@workspace-fs/core
Version:
Multi-project workspace manager for Firesystem with support for multiple sources
201 lines (175 loc) • 4.3 kB
text/typescript
import type { ProjectSource } from "../types";
/**
* Validates and builds source configurations with credentials
*/
export class SourceConfigBuilder {
/**
* Build IndexedDB source config
*/
static indexedDB(dbName?: string): ProjectSource {
return {
type: "indexeddb",
config: {
dbName: dbName || `firesystem-${Date.now()}`,
},
};
}
/**
* Build Memory source config
*/
static memory(initialData?: any): ProjectSource {
return {
type: "memory",
config: {
initialData,
},
};
}
/**
* Build S3 source config
*/
static s3(config: {
bucket: string;
prefix?: string;
region?: string;
credentials?: {
accessKeyId: string;
secretAccessKey: string;
};
}): ProjectSource {
const source: ProjectSource = {
type: "s3",
config: {
bucket: config.bucket,
prefix: config.prefix || "",
region: config.region || "us-east-1",
},
};
// Add auth if credentials provided
if (config.credentials) {
source.auth = {
type: "token",
credentials: config.credentials,
};
}
return source;
}
/**
* Build GitHub source config
*/
static github(config: {
owner: string;
repo: string;
branch?: string;
path?: string;
token?: string;
}): ProjectSource {
const source: ProjectSource = {
type: "github",
config: {
owner: config.owner,
repo: config.repo,
branch: config.branch || "main",
path: config.path || "/",
},
};
if (config.token) {
source.auth = {
type: "bearer",
credentials: { token: config.token },
};
}
return source;
}
/**
* Build API source config
*/
static api(config: {
baseUrl: string;
projectEndpoint?: string;
headers?: Record<string, string>;
apiKey?: string;
}): ProjectSource {
const source: ProjectSource = {
type: "api",
config: {
baseUrl: config.baseUrl,
projectEndpoint: config.projectEndpoint || "/projects",
headers: config.headers,
},
};
if (config.apiKey) {
source.auth = {
type: "token",
credentials: { apiKey: config.apiKey },
};
}
return source;
}
/**
* Validate source configuration
*/
static validate(source: ProjectSource): { valid: boolean; errors: string[] } {
const errors: string[] = [];
switch (source.type) {
case "indexeddb":
if (!source.config.dbName) {
errors.push("IndexedDB source requires dbName");
}
break;
case "s3":
if (!source.config.bucket) {
errors.push("S3 source requires bucket");
}
// For validation, we don't require credentials - they can be provided at runtime
break;
case "github":
if (!source.config.owner || !source.config.repo) {
errors.push("GitHub source requires owner and repo");
}
break;
case "api":
if (!source.config.baseUrl) {
errors.push("API source requires baseUrl");
}
break;
case "memory":
// Memory source has no required fields
break;
default:
errors.push(`Unknown source type: ${source.type}`);
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Sanitize source for export (remove credentials)
*/
static sanitize(source: ProjectSource): ProjectSource {
const sanitized = { ...source };
// Remove auth completely
delete sanitized.auth;
// Clean specific fields based on type
switch (source.type) {
case "s3":
// Keep only bucket and prefix
sanitized.config = {
bucket: source.config.bucket,
prefix: source.config.prefix,
};
break;
case "api":
// Remove headers that might contain auth
const { headers, ...restConfig } = source.config;
sanitized.config = restConfig;
break;
// For other types (memory, indexeddb, github), preserve config as-is
default:
// No special sanitization needed for other types
break;
}
return sanitized;
}
}