@insforge/sdk
Version:
TypeScript SDK for InsForge Backend-as-a-Service platform
1,107 lines (1,098 loc) • 31.8 kB
JavaScript
// src/types.ts
var InsForgeError = class _InsForgeError extends Error {
constructor(message, statusCode, error, nextActions) {
super(message);
this.name = "InsForgeError";
this.statusCode = statusCode;
this.error = error;
this.nextActions = nextActions;
}
static fromApiError(apiError) {
return new _InsForgeError(
apiError.message,
apiError.statusCode,
apiError.error,
apiError.nextActions
);
}
};
// src/lib/http-client.ts
var HttpClient = class {
constructor(config) {
this.userToken = null;
this.baseUrl = config.baseUrl || "http://localhost:7130";
this.fetch = config.fetch || (globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
this.anonKey = config.anonKey;
this.defaultHeaders = {
...config.headers
};
if (!this.fetch) {
throw new Error(
"Fetch is not available. Please provide a fetch implementation in the config."
);
}
}
buildUrl(path, params) {
const url = new URL(path, this.baseUrl);
if (params) {
Object.entries(params).forEach(([key, value]) => {
if (key === "select") {
let normalizedValue = value.replace(/\s+/g, " ").trim();
normalizedValue = normalizedValue.replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\(\s+/g, "(").replace(/\s+\)/g, ")").replace(/,\s+(?=[^()]*\))/g, ",");
url.searchParams.append(key, normalizedValue);
} else {
url.searchParams.append(key, value);
}
});
}
return url.toString();
}
async request(method, path, options = {}) {
const { params, headers = {}, body, ...fetchOptions } = options;
const url = this.buildUrl(path, params);
const requestHeaders = {
...this.defaultHeaders
};
const authToken = this.userToken || this.anonKey;
if (authToken) {
requestHeaders["Authorization"] = `Bearer ${authToken}`;
}
let processedBody;
if (body !== void 0) {
if (typeof FormData !== "undefined" && body instanceof FormData) {
processedBody = body;
} else {
if (method !== "GET") {
requestHeaders["Content-Type"] = "application/json;charset=UTF-8";
}
processedBody = JSON.stringify(body);
}
}
Object.assign(requestHeaders, headers);
const response = await this.fetch(url, {
method,
headers: requestHeaders,
body: processedBody,
...fetchOptions
});
if (response.status === 204) {
return void 0;
}
let data;
const contentType = response.headers.get("content-type");
if (contentType?.includes("json")) {
data = await response.json();
} else {
data = await response.text();
}
if (!response.ok) {
if (data && typeof data === "object" && "error" in data) {
if (!data.statusCode && !data.status) {
data.statusCode = response.status;
}
const error = InsForgeError.fromApiError(data);
Object.keys(data).forEach((key) => {
if (key !== "error" && key !== "message" && key !== "statusCode") {
error[key] = data[key];
}
});
throw error;
}
throw new InsForgeError(
`Request failed: ${response.statusText}`,
response.status,
"REQUEST_FAILED"
);
}
return data;
}
get(path, options) {
return this.request("GET", path, options);
}
post(path, body, options) {
return this.request("POST", path, { ...options, body });
}
put(path, body, options) {
return this.request("PUT", path, { ...options, body });
}
patch(path, body, options) {
return this.request("PATCH", path, { ...options, body });
}
delete(path, options) {
return this.request("DELETE", path, options);
}
setAuthToken(token) {
this.userToken = token;
}
getHeaders() {
const headers = { ...this.defaultHeaders };
const authToken = this.userToken || this.anonKey;
if (authToken) {
headers["Authorization"] = `Bearer ${authToken}`;
}
return headers;
}
};
// src/lib/token-manager.ts
var TOKEN_KEY = "insforge-auth-token";
var USER_KEY = "insforge-auth-user";
var TokenManager = class {
constructor(storage) {
if (storage) {
this.storage = storage;
} else if (typeof window !== "undefined" && window.localStorage) {
this.storage = window.localStorage;
} else {
const store = /* @__PURE__ */ new Map();
this.storage = {
getItem: (key) => store.get(key) || null,
setItem: (key, value) => {
store.set(key, value);
},
removeItem: (key) => {
store.delete(key);
}
};
}
}
saveSession(session) {
this.storage.setItem(TOKEN_KEY, session.accessToken);
this.storage.setItem(USER_KEY, JSON.stringify(session.user));
}
getSession() {
const token = this.storage.getItem(TOKEN_KEY);
const userStr = this.storage.getItem(USER_KEY);
if (!token || !userStr) {
return null;
}
try {
const user = JSON.parse(userStr);
return { accessToken: token, user };
} catch {
this.clearSession();
return null;
}
}
getAccessToken() {
const token = this.storage.getItem(TOKEN_KEY);
return typeof token === "string" ? token : null;
}
clearSession() {
this.storage.removeItem(TOKEN_KEY);
this.storage.removeItem(USER_KEY);
}
};
// src/modules/database-postgrest.ts
import { PostgrestClient } from "@supabase/postgrest-js";
function createInsForgePostgrestFetch(httpClient, tokenManager) {
return async (input, init) => {
const url = typeof input === "string" ? input : input.toString();
const urlObj = new URL(url);
const tableName = urlObj.pathname.slice(1);
const insforgeUrl = `${httpClient.baseUrl}/api/database/records/${tableName}${urlObj.search}`;
const token = tokenManager.getAccessToken();
const httpHeaders = httpClient.getHeaders();
const authToken = token || httpHeaders["Authorization"]?.replace("Bearer ", "");
const headers = new Headers(init?.headers);
if (authToken && !headers.has("Authorization")) {
headers.set("Authorization", `Bearer ${authToken}`);
}
const response = await fetch(insforgeUrl, {
...init,
headers
});
return response;
};
}
var Database = class {
constructor(httpClient, tokenManager) {
this.postgrest = new PostgrestClient("http://dummy", {
fetch: createInsForgePostgrestFetch(httpClient, tokenManager),
headers: {}
});
}
/**
* Create a query builder for a table
*
* @example
* // Basic query
* const { data, error } = await client.database
* .from('posts')
* .select('*')
* .eq('user_id', userId);
*
* // With count (Supabase style!)
* const { data, error, count } = await client.database
* .from('posts')
* .select('*', { count: 'exact' })
* .range(0, 9);
*
* // Just get count, no data
* const { count } = await client.database
* .from('posts')
* .select('*', { count: 'exact', head: true });
*
* // Complex queries with OR
* const { data } = await client.database
* .from('posts')
* .select('*, users!inner(*)')
* .or('status.eq.active,status.eq.pending');
*
* // All features work:
* - Nested selects
* - Foreign key expansion
* - OR/AND/NOT conditions
* - Count with head
* - Range pagination
* - Upserts
*/
from(table) {
return this.postgrest.from(table);
}
};
// src/modules/auth.ts
var Auth = class {
constructor(http, tokenManager) {
this.http = http;
this.tokenManager = tokenManager;
this.database = new Database(http, tokenManager);
this.detectOAuthCallback();
}
/**
* Automatically detect and handle OAuth callback parameters in the URL
* This runs on initialization to seamlessly complete the OAuth flow
* Matches the backend's OAuth callback response (backend/src/api/routes/auth.ts:540-544)
*/
detectOAuthCallback() {
if (typeof window === "undefined") return;
try {
const params = new URLSearchParams(window.location.search);
const accessToken = params.get("access_token");
const userId = params.get("user_id");
const email = params.get("email");
const name = params.get("name");
if (accessToken && userId && email) {
const session = {
accessToken,
user: {
id: userId,
email,
name: name || "",
// These fields are not provided by backend OAuth callback
// They'll be populated when calling getCurrentUser()
emailVerified: false,
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
}
};
this.tokenManager.saveSession(session);
this.http.setAuthToken(accessToken);
const url = new URL(window.location.href);
url.searchParams.delete("access_token");
url.searchParams.delete("user_id");
url.searchParams.delete("email");
url.searchParams.delete("name");
if (params.has("error")) {
url.searchParams.delete("error");
}
window.history.replaceState({}, document.title, url.toString());
}
} catch (error) {
console.debug("OAuth callback detection skipped:", error);
}
}
/**
* Sign up a new user
*/
async signUp(request) {
try {
const response = await this.http.post("/api/auth/users", request);
const session = {
accessToken: response.accessToken,
user: response.user
};
this.tokenManager.saveSession(session);
this.http.setAuthToken(response.accessToken);
return {
data: response,
error: null
};
} catch (error) {
if (error instanceof InsForgeError) {
return { data: null, error };
}
return {
data: null,
error: new InsForgeError(
error instanceof Error ? error.message : "An unexpected error occurred during sign up",
500,
"UNEXPECTED_ERROR"
)
};
}
}
/**
* Sign in with email and password
*/
async signInWithPassword(request) {
try {
const response = await this.http.post("/api/auth/sessions", request);
const session = {
accessToken: response.accessToken,
user: response.user
};
this.tokenManager.saveSession(session);
this.http.setAuthToken(response.accessToken);
return {
data: response,
error: null
};
} catch (error) {
if (error instanceof InsForgeError) {
return { data: null, error };
}
return {
data: null,
error: new InsForgeError(
"An unexpected error occurred during sign in",
500,
"UNEXPECTED_ERROR"
)
};
}
}
/**
* Sign in with OAuth provider
*/
async signInWithOAuth(options) {
try {
const { provider, redirectTo, skipBrowserRedirect } = options;
const params = redirectTo ? { redirect_uri: redirectTo } : void 0;
const endpoint = `/api/auth/oauth/${provider}`;
const response = await this.http.get(endpoint, { params });
if (typeof window !== "undefined" && !skipBrowserRedirect) {
window.location.href = response.authUrl;
return { data: {}, error: null };
}
return {
data: {
url: response.authUrl,
provider
},
error: null
};
} catch (error) {
if (error instanceof InsForgeError) {
return { data: {}, error };
}
return {
data: {},
error: new InsForgeError(
"An unexpected error occurred during OAuth initialization",
500,
"UNEXPECTED_ERROR"
)
};
}
}
/**
* Sign out the current user
*/
async signOut() {
try {
this.tokenManager.clearSession();
this.http.setAuthToken(null);
return { error: null };
} catch (error) {
return {
error: new InsForgeError(
"Failed to sign out",
500,
"SIGNOUT_ERROR"
)
};
}
}
/**
* Get the current user with full profile information
* Returns both auth info (id, email, role) and profile data (nickname, avatar_url, bio, etc.)
*/
async getCurrentUser() {
try {
const session = this.tokenManager.getSession();
if (!session?.accessToken) {
return { data: null, error: null };
}
this.http.setAuthToken(session.accessToken);
const authResponse = await this.http.get("/api/auth/sessions/current");
const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
if (profileError && profileError.code !== "PGRST116") {
return { data: null, error: profileError };
}
return {
data: {
user: authResponse.user,
profile
},
error: null
};
} catch (error) {
if (error instanceof InsForgeError && error.statusCode === 401) {
await this.signOut();
return { data: null, error: null };
}
if (error instanceof InsForgeError) {
return { data: null, error };
}
return {
data: null,
error: new InsForgeError(
"An unexpected error occurred while fetching user",
500,
"UNEXPECTED_ERROR"
)
};
}
}
/**
* Get any user's profile by ID
* Returns profile information from the users table (nickname, avatar_url, bio, etc.)
*/
async getProfile(userId) {
const { data, error } = await this.database.from("users").select("*").eq("id", userId).single();
if (error && error.code === "PGRST116") {
return { data: null, error: null };
}
return { data, error };
}
/**
* Get the current session (only session data, no API call)
* Returns the stored JWT token and basic user info from local storage
*/
getCurrentSession() {
try {
const session = this.tokenManager.getSession();
if (session?.accessToken) {
this.http.setAuthToken(session.accessToken);
return { data: { session }, error: null };
}
return { data: { session: null }, error: null };
} catch (error) {
if (error instanceof InsForgeError) {
return { data: { session: null }, error };
}
return {
data: { session: null },
error: new InsForgeError(
"An unexpected error occurred while getting session",
500,
"UNEXPECTED_ERROR"
)
};
}
}
/**
* Set/Update the current user's profile
* Updates profile information in the users table (nickname, avatar_url, bio, etc.)
*/
async setProfile(profile) {
const session = this.tokenManager.getSession();
if (!session?.user?.id) {
return {
data: null,
error: new InsForgeError(
"No authenticated user found",
401,
"UNAUTHENTICATED"
)
};
}
const { data, error } = await this.database.from("users").update(profile).eq("id", session.user.id).select().single();
return { data, error };
}
};
// src/modules/storage.ts
var StorageBucket = class {
constructor(bucketName, http) {
this.bucketName = bucketName;
this.http = http;
}
/**
* Upload a file with a specific key
* Uses the upload strategy from backend (direct or presigned)
* @param path - The object key/path
* @param file - File or Blob to upload
*/
async upload(path, file) {
try {
const strategyResponse = await this.http.post(
`/api/storage/buckets/${this.bucketName}/upload-strategy`,
{
filename: path,
contentType: file.type || "application/octet-stream",
size: file.size
}
);
if (strategyResponse.method === "presigned") {
return await this.uploadWithPresignedUrl(strategyResponse, file);
}
if (strategyResponse.method === "direct") {
const formData = new FormData();
formData.append("file", file);
const response = await this.http.request(
"PUT",
`/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`,
{
body: formData,
headers: {
// Don't set Content-Type, let browser set multipart boundary
}
}
);
return { data: response, error: null };
}
throw new InsForgeError(
`Unsupported upload method: ${strategyResponse.method}`,
500,
"STORAGE_ERROR"
);
} catch (error) {
return {
data: null,
error: error instanceof InsForgeError ? error : new InsForgeError(
"Upload failed",
500,
"STORAGE_ERROR"
)
};
}
}
/**
* Upload a file with auto-generated key
* Uses the upload strategy from backend (direct or presigned)
* @param file - File or Blob to upload
*/
async uploadAuto(file) {
try {
const filename = file instanceof File ? file.name : "file";
const strategyResponse = await this.http.post(
`/api/storage/buckets/${this.bucketName}/upload-strategy`,
{
filename,
contentType: file.type || "application/octet-stream",
size: file.size
}
);
if (strategyResponse.method === "presigned") {
return await this.uploadWithPresignedUrl(strategyResponse, file);
}
if (strategyResponse.method === "direct") {
const formData = new FormData();
formData.append("file", file);
const response = await this.http.request(
"POST",
`/api/storage/buckets/${this.bucketName}/objects`,
{
body: formData,
headers: {
// Don't set Content-Type, let browser set multipart boundary
}
}
);
return { data: response, error: null };
}
throw new InsForgeError(
`Unsupported upload method: ${strategyResponse.method}`,
500,
"STORAGE_ERROR"
);
} catch (error) {
return {
data: null,
error: error instanceof InsForgeError ? error : new InsForgeError(
"Upload failed",
500,
"STORAGE_ERROR"
)
};
}
}
/**
* Internal method to handle presigned URL uploads
*/
async uploadWithPresignedUrl(strategy, file) {
try {
const formData = new FormData();
if (strategy.fields) {
Object.entries(strategy.fields).forEach(([key, value]) => {
formData.append(key, value);
});
}
formData.append("file", file);
const uploadResponse = await fetch(strategy.uploadUrl, {
method: "POST",
body: formData
});
if (!uploadResponse.ok) {
throw new InsForgeError(
`Upload to storage failed: ${uploadResponse.statusText}`,
uploadResponse.status,
"STORAGE_ERROR"
);
}
if (strategy.confirmRequired && strategy.confirmUrl) {
const confirmResponse = await this.http.post(
strategy.confirmUrl,
{
size: file.size,
contentType: file.type || "application/octet-stream"
}
);
return { data: confirmResponse, error: null };
}
return {
data: {
key: strategy.key,
bucket: this.bucketName,
size: file.size,
mimeType: file.type || "application/octet-stream",
uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
url: this.getPublicUrl(strategy.key)
},
error: null
};
} catch (error) {
throw error instanceof InsForgeError ? error : new InsForgeError(
"Presigned upload failed",
500,
"STORAGE_ERROR"
);
}
}
/**
* Download a file
* Uses the download strategy from backend (direct or presigned)
* @param path - The object key/path
* Returns the file as a Blob
*/
async download(path) {
try {
const strategyResponse = await this.http.post(
`/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}/download-strategy`,
{ expiresIn: 3600 }
);
const downloadUrl = strategyResponse.url;
const headers = {};
if (strategyResponse.method === "direct") {
Object.assign(headers, this.http.getHeaders());
}
const response = await fetch(downloadUrl, {
method: "GET",
headers
});
if (!response.ok) {
try {
const error = await response.json();
throw InsForgeError.fromApiError(error);
} catch {
throw new InsForgeError(
`Download failed: ${response.statusText}`,
response.status,
"STORAGE_ERROR"
);
}
}
const blob = await response.blob();
return { data: blob, error: null };
} catch (error) {
return {
data: null,
error: error instanceof InsForgeError ? error : new InsForgeError(
"Download failed",
500,
"STORAGE_ERROR"
)
};
}
}
/**
* Get public URL for a file
* @param path - The object key/path
*/
getPublicUrl(path) {
return `${this.http.baseUrl}/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`;
}
/**
* List objects in the bucket
* @param prefix - Filter by key prefix
* @param search - Search in file names
* @param limit - Maximum number of results (default: 100, max: 1000)
* @param offset - Number of results to skip
*/
async list(options) {
try {
const params = {};
if (options?.prefix) params.prefix = options.prefix;
if (options?.search) params.search = options.search;
if (options?.limit) params.limit = options.limit.toString();
if (options?.offset) params.offset = options.offset.toString();
const response = await this.http.get(
`/api/storage/buckets/${this.bucketName}/objects`,
{ params }
);
return { data: response, error: null };
} catch (error) {
return {
data: null,
error: error instanceof InsForgeError ? error : new InsForgeError(
"List failed",
500,
"STORAGE_ERROR"
)
};
}
}
/**
* Delete a file
* @param path - The object key/path
*/
async remove(path) {
try {
const response = await this.http.delete(
`/api/storage/buckets/${this.bucketName}/objects/${encodeURIComponent(path)}`
);
return { data: response, error: null };
} catch (error) {
return {
data: null,
error: error instanceof InsForgeError ? error : new InsForgeError(
"Delete failed",
500,
"STORAGE_ERROR"
)
};
}
}
};
var Storage = class {
constructor(http) {
this.http = http;
}
/**
* Get a bucket instance for operations
* @param bucketName - Name of the bucket
*/
from(bucketName) {
return new StorageBucket(bucketName, this.http);
}
};
// src/modules/ai.ts
var AI = class {
constructor(http) {
this.http = http;
this.chat = new Chat(http);
this.images = new Images(http);
}
};
var Chat = class {
constructor(http) {
this.completions = new ChatCompletions(http);
}
};
var ChatCompletions = class {
constructor(http) {
this.http = http;
}
/**
* Create a chat completion - OpenAI-like response format
*
* @example
* ```typescript
* // Non-streaming
* const completion = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Hello!' }]
* });
* console.log(completion.choices[0].message.content);
*
* // With images
* const response = await client.ai.chat.completions.create({
* model: 'gpt-4-vision',
* messages: [{
* role: 'user',
* content: 'What is in this image?',
* images: [{ url: 'https://example.com/image.jpg' }]
* }]
* });
*
* // Streaming - returns async iterable
* const stream = await client.ai.chat.completions.create({
* model: 'gpt-4',
* messages: [{ role: 'user', content: 'Tell me a story' }],
* stream: true
* });
*
* for await (const chunk of stream) {
* if (chunk.choices[0]?.delta?.content) {
* process.stdout.write(chunk.choices[0].delta.content);
* }
* }
* ```
*/
async create(params) {
const backendParams = {
model: params.model,
messages: params.messages,
temperature: params.temperature,
maxTokens: params.maxTokens,
topP: params.topP,
stream: params.stream
};
if (params.stream) {
const headers = this.http.getHeaders();
headers["Content-Type"] = "application/json";
const response2 = await this.http.fetch(
`${this.http.baseUrl}/api/ai/chat/completion`,
{
method: "POST",
headers,
body: JSON.stringify(backendParams)
}
);
if (!response2.ok) {
const error = await response2.json();
throw new Error(error.error || "Stream request failed");
}
return this.parseSSEStream(response2, params.model);
}
const response = await this.http.post(
"/api/ai/chat/completion",
backendParams
);
const content = response.text || "";
return {
id: `chatcmpl-${Date.now()}`,
object: "chat.completion",
created: Math.floor(Date.now() / 1e3),
model: response.metadata?.model,
choices: [
{
index: 0,
message: {
role: "assistant",
content
},
finish_reason: "stop"
}
],
usage: response.metadata?.usage || {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0
}
};
}
/**
* Parse SSE stream into async iterable of OpenAI-like chunks
*/
async *parseSSEStream(response, model) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
if (line.startsWith("data: ")) {
const dataStr = line.slice(6).trim();
if (dataStr) {
try {
const data = JSON.parse(dataStr);
if (data.chunk || data.content) {
yield {
id: `chatcmpl-${Date.now()}`,
object: "chat.completion.chunk",
created: Math.floor(Date.now() / 1e3),
model,
choices: [
{
index: 0,
delta: {
content: data.chunk || data.content
},
finish_reason: data.done ? "stop" : null
}
]
};
}
if (data.done) {
reader.releaseLock();
return;
}
} catch (e) {
console.warn("Failed to parse SSE data:", dataStr);
}
}
}
}
}
} finally {
reader.releaseLock();
}
}
};
var Images = class {
constructor(http) {
this.http = http;
}
/**
* Generate images - OpenAI-like response format
*
* @example
* ```typescript
* // Text-to-image
* const response = await client.ai.images.generate({
* model: 'dall-e-3',
* prompt: 'A sunset over mountains',
* });
* console.log(response.images[0].url);
*
* // Image-to-image (with input images)
* const response = await client.ai.images.generate({
* model: 'stable-diffusion-xl',
* prompt: 'Transform this into a watercolor painting',
* images: [
* { url: 'https://example.com/input.jpg' },
* // or base64-encoded Data URI:
* { url: 'data:image/jpeg;base64,/9j/4AAQ...' }
* ]
* });
* ```
*/
async generate(params) {
const response = await this.http.post(
"/api/ai/image/generation",
params
);
let data = [];
if (response.images && response.images.length > 0) {
data = response.images.map((img) => ({
b64_json: img.imageUrl.replace(/^data:image\/\w+;base64,/, ""),
content: response.text
}));
} else if (response.text) {
data = [{ content: response.text }];
}
return {
created: Math.floor(Date.now() / 1e3),
data,
...response.metadata?.usage && {
usage: {
total_tokens: response.metadata.usage.totalTokens || 0,
input_tokens: response.metadata.usage.promptTokens || 0,
output_tokens: response.metadata.usage.completionTokens || 0
}
}
};
}
};
// src/modules/functions.ts
var Functions = class {
constructor(http) {
this.http = http;
}
/**
* Invokes an Edge Function
* @param slug The function slug to invoke
* @param options Request options
*/
async invoke(slug, options = {}) {
try {
const { method = "POST", body, headers = {} } = options;
const path = `/functions/${slug}`;
const data = await this.http.request(
method,
path,
{ body, headers }
);
return { data, error: null };
} catch (error) {
return {
data: null,
error
// Pass through the full error object with all properties
};
}
}
};
// src/client.ts
var InsForgeClient = class {
constructor(config = {}) {
this.http = new HttpClient(config);
this.tokenManager = new TokenManager(config.storage);
if (config.edgeFunctionToken) {
this.http.setAuthToken(config.edgeFunctionToken);
this.tokenManager.saveSession({
accessToken: config.edgeFunctionToken,
user: {}
// Will be populated by getCurrentUser()
});
}
const existingSession = this.tokenManager.getSession();
if (existingSession?.accessToken) {
this.http.setAuthToken(existingSession.accessToken);
}
this.auth = new Auth(
this.http,
this.tokenManager
);
this.database = new Database(this.http, this.tokenManager);
this.storage = new Storage(this.http);
this.ai = new AI(this.http);
this.functions = new Functions(this.http);
}
/**
* Get the underlying HTTP client for custom requests
*
* @example
* ```typescript
* const httpClient = client.getHttpClient();
* const customData = await httpClient.get('/api/custom-endpoint');
* ```
*/
getHttpClient() {
return this.http;
}
/**
* Future modules will be added here:
* - database: Database operations
* - storage: File storage operations
* - functions: Serverless functions
* - tables: Table management
* - metadata: Backend metadata
*/
};
// src/index.ts
function createClient(config) {
return new InsForgeClient(config);
}
var index_default = InsForgeClient;
export {
AI,
Auth,
Database,
Functions,
HttpClient,
InsForgeClient,
InsForgeError,
Storage,
StorageBucket,
TokenManager,
createClient,
index_default as default
};
//# sourceMappingURL=index.mjs.map