@vibeship/devtools
Version:
Comprehensive markdown-based project management system with AI capabilities for Next.js applications
985 lines (978 loc) • 28 kB
JavaScript
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
// src/config/defaults.ts
var defaultConfig = {
// File scanning
scanPaths: ["./docs", "./README.md"],
include: ["**/*.md", "**/*.mdx"],
exclude: ["**/node_modules/**", "**/.next/**", "**/.git/**", "**/dist/**", "**/build/**"],
// Features
features: {
tasks: true,
ai: false,
realtime: true,
commandPalette: true,
fileEditing: false,
markdownPreview: true
},
// Security
security: {
authentication: false,
rateLimit: true,
cors: true,
blockedPatterns: [
"**/.env*",
"**/*.key",
"**/*.pem",
"**/*.p12",
"**/*.pfx",
"**/secrets/**",
"**/credentials/**"
]
},
// Task patterns
taskPatterns: {
todo: true,
fixme: true,
hack: true,
note: true
},
// UI configuration
ui: {
theme: "system",
position: "bottom-right",
defaultSize: {
width: "400px",
height: "600px"
},
hotkey: "cmd+shift+k",
showInProduction: false
},
// API configuration
api: {
basePath: "/api/vibeship",
version: "v1",
documentation: true,
timeout: 3e4
// 30 seconds
},
// Cache configuration
cache: {
enabled: true,
directory: ".vibeship/cache",
maxSize: 52428800,
// 50MB
ttl: 36e5,
// 1 hour
strategy: "lru"
}
};
var developmentConfig = {
features: {
...defaultConfig.features,
fileEditing: true
},
security: {
...defaultConfig.security,
authentication: false,
rateLimitConfig: {
windowMs: 6e4,
maxRequests: 1e3
// More lenient in development
}
},
ui: {
...defaultConfig.ui,
showInProduction: true
// Allow in dev mode
},
cache: {
...defaultConfig.cache,
ttl: 3e5
// 5 minutes in dev
}
};
var productionConfig = {
features: {
...defaultConfig.features,
fileEditing: false
// Never allow file editing in production
},
security: {
...defaultConfig.security,
authentication: true,
rateLimit: true,
rateLimitConfig: {
windowMs: 6e4,
maxRequests: 100,
tiers: {
anonymous: { windowMs: 6e4, maxRequests: 20 },
authenticated: { windowMs: 6e4, maxRequests: 100 },
premium: { windowMs: 6e4, maxRequests: 1e3 }
}
},
corsConfig: {
allowedOrigins: (origin) => {
const allowedDomains = process.env.ALLOWED_DOMAINS?.split(",") || [];
return allowedDomains.some((domain) => origin.includes(domain));
},
credentials: true,
maxAge: 86400
}
},
ui: {
...defaultConfig.ui,
showInProduction: false
},
cache: {
...defaultConfig.cache,
maxSize: 104857600,
// 100MB in production
ttl: 72e5
// 2 hours in production
}
};
var testConfig = {
scanPaths: ["./test-docs"],
security: {
...defaultConfig.security,
authentication: false,
rateLimit: false
},
cache: {
...defaultConfig.cache,
enabled: false
// Disable cache in tests
},
ui: {
...defaultConfig.ui,
showInProduction: true
}
};
function getEnvironmentDefaults() {
const env = "development";
switch (env) {
case "production":
return productionConfig;
case "test":
return testConfig;
case "development":
default:
return developmentConfig;
}
}
// src/config/schema.ts
import { z } from "zod";
var CustomTaskPatternSchema = z.object({
name: z.string().min(1, "Pattern name is required"),
pattern: z.union([z.string(), z.instanceof(RegExp)]),
priority: z.enum(["low", "medium", "high"]).optional(),
color: z.string().optional()
});
var TaskPatternsSchema = z.object({
todo: z.boolean(),
fixme: z.boolean(),
hack: z.boolean(),
note: z.boolean(),
warning: z.boolean().optional(),
optimize: z.boolean().optional(),
custom: z.array(CustomTaskPatternSchema).optional()
});
var FeatureFlagsSchema = z.object({
tasks: z.boolean(),
ai: z.boolean(),
realtime: z.boolean(),
commandPalette: z.boolean(),
fileEditing: z.boolean(),
markdownPreview: z.boolean()
});
var AuthProviderSchema = z.object({
id: z.string(),
type: z.enum(["oauth", "oidc", "saml"]),
clientId: z.string(),
clientSecret: z.string().optional(),
issuer: z.string().optional()
});
var AuthConfigSchema = z.object({
jwtSecret: z.string().optional(),
apiKey: z.string().optional(),
session: z.object({
secret: z.string(),
maxAge: z.number().optional()
}).optional(),
providers: z.array(AuthProviderSchema).optional()
});
var RateLimitConfigSchema = z.object({
windowMs: z.number().positive(),
maxRequests: z.number().positive(),
skipSuccessfulRequests: z.boolean().optional(),
skipFailedRequests: z.boolean().optional(),
tiers: z.object({
anonymous: z.object({
windowMs: z.number().positive(),
maxRequests: z.number().positive()
}).optional(),
authenticated: z.object({
windowMs: z.number().positive(),
maxRequests: z.number().positive()
}).optional(),
premium: z.object({
windowMs: z.number().positive(),
maxRequests: z.number().positive()
}).optional()
}).optional()
});
var CORSConfigSchema = z.object({
allowedOrigins: z.union([
z.array(z.string()),
z.string(),
z.function().args(z.string()).returns(z.boolean())
]),
allowedMethods: z.array(z.string()).optional(),
allowedHeaders: z.array(z.string()).optional(),
exposedHeaders: z.array(z.string()).optional(),
credentials: z.boolean().optional(),
maxAge: z.number().optional()
});
var SecurityConfigSchema = z.object({
authentication: z.boolean(),
auth: AuthConfigSchema.optional(),
rateLimit: z.boolean(),
rateLimitConfig: RateLimitConfigSchema.optional(),
cors: z.boolean(),
corsConfig: CORSConfigSchema.optional(),
allowedPaths: z.array(z.string()).optional(),
blockedPatterns: z.array(z.string()).optional()
});
var UIConfigSchema = z.object({
theme: z.enum(["light", "dark", "system"]).optional(),
position: z.enum(["top-left", "top-right", "bottom-left", "bottom-right"]).optional(),
defaultSize: z.object({
width: z.union([z.number(), z.string()]).optional(),
height: z.union([z.number(), z.string()]).optional()
}).optional(),
hotkey: z.string().optional(),
showInProduction: z.boolean().optional(),
customCSS: z.string().optional()
});
var APIConfigSchema = z.object({
basePath: z.string(),
version: z.string().optional(),
documentation: z.boolean().optional(),
middleware: z.array(z.string()).optional(),
timeout: z.number().positive().optional()
});
var CacheConfigSchema = z.object({
enabled: z.boolean(),
directory: z.string(),
maxSize: z.number().positive(),
ttl: z.number().positive(),
strategy: z.enum(["lru", "fifo", "lfu"])
});
var ExperimentalConfigSchema = z.object({
markdownExtensions: z.boolean().optional(),
customTaskProviders: z.boolean().optional(),
plugins: z.boolean().optional(),
pluginConfigs: z.record(z.any()).optional()
});
var VibeshipConfigSchema = z.object({
scanPaths: z.array(z.string()).min(1, "At least one scan path is required"),
include: z.array(z.string()).min(1, "At least one include pattern is required"),
exclude: z.array(z.string()),
features: FeatureFlagsSchema,
security: SecurityConfigSchema,
taskPatterns: TaskPatternsSchema,
ui: UIConfigSchema,
api: APIConfigSchema,
cache: CacheConfigSchema,
experimental: ExperimentalConfigSchema.optional()
});
var PartialVibeshipConfigSchema = VibeshipConfigSchema.deepPartial();
function validateConfig(config) {
try {
const result = VibeshipConfigSchema.parse(config);
return { success: true, data: result };
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.errors.map((err) => {
const path = err.path.join(".");
const message = err.message;
return `${path}: ${message}`;
});
return { success: false, errors };
}
return {
success: false,
errors: ["Invalid configuration format"]
};
}
}
function validatePartialConfig(config) {
try {
const result = PartialVibeshipConfigSchema.parse(config);
return { success: true, data: result };
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.errors.map((err) => {
const path = err.path.join(".");
const message = err.message;
return `${path}: ${message}`;
});
return { success: false, errors };
}
return {
success: false,
errors: ["Invalid configuration format"]
};
}
}
function isValidConfig(config) {
return VibeshipConfigSchema.safeParse(config).success;
}
// src/config/loader.ts
import { existsSync, readFileSync } from "fs";
import { join, resolve, extname } from "path";
import { pathToFileURL } from "url";
// src/config/merger.ts
function deepMerge(target, ...sources) {
if (!sources.length) return target;
const source = sources.shift();
if (!source) return target;
const output = { ...target };
Object.keys(source).forEach((key) => {
const targetValue = output[key];
const sourceValue = source[key];
if (sourceValue === void 0) {
return;
}
if (sourceValue === null) {
output[key] = null;
return;
}
if (isObject(targetValue) && isObject(sourceValue)) {
output[key] = deepMerge(
targetValue,
sourceValue
);
} else if (Array.isArray(sourceValue)) {
output[key] = [...sourceValue];
} else {
output[key] = sourceValue;
}
});
return deepMerge(output, ...sources);
}
function isObject(value) {
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp);
}
function mergeConfigurations(defaultConfig2, environmentDefaults, environmentOverrides, userConfig) {
return deepMerge(
defaultConfig2,
environmentDefaults,
environmentOverrides,
userConfig
);
}
function applyEnvironmentOverrides(config) {
const overrides = {};
if (process.env.VIBECODE_AUTH_SECRET) {
overrides.security = {
...overrides.security,
auth: {
...overrides.security?.auth,
jwtSecret: process.env.VIBECODE_AUTH_SECRET
}
};
}
if (process.env.VIBECODE_API_KEY) {
overrides.security = {
...overrides.security,
auth: {
...overrides.security?.auth,
apiKey: process.env.VIBECODE_API_KEY
}
};
}
if (process.env.VIBECODE_ALLOWED_ORIGINS) {
const origins = process.env.VIBECODE_ALLOWED_ORIGINS.split(",").map((s) => s.trim());
overrides.security = {
...overrides.security,
corsConfig: {
...overrides.security?.corsConfig,
allowedOrigins: origins
}
};
}
if (process.env.VIBECODE_RATE_LIMIT) {
const [windowMs, maxRequests] = process.env.VIBECODE_RATE_LIMIT.split(",").map(Number);
if (windowMs && maxRequests) {
overrides.security = {
...overrides.security,
rateLimitConfig: {
...overrides.security?.rateLimitConfig,
windowMs,
maxRequests
}
};
}
}
if (process.env.VIBECODE_CACHE_ENABLED !== void 0) {
overrides.cache = {
...overrides.cache,
enabled: process.env.VIBECODE_CACHE_ENABLED === "true"
};
}
if (process.env.VIBECODE_AI_PROVIDER) {
overrides.features = {
...overrides.features,
ai: true
};
}
const featureFlags = [
"VIBECODE_FEATURE_TASKS",
"VIBECODE_FEATURE_AI",
"VIBECODE_FEATURE_REALTIME",
"VIBECODE_FEATURE_COMMAND_PALETTE",
"VIBECODE_FEATURE_FILE_EDITING",
"VIBECODE_FEATURE_MARKDOWN_PREVIEW"
];
featureFlags.forEach((flag) => {
if (process.env[flag] !== void 0) {
const featureName = flag.replace("VIBECODE_FEATURE_", "").toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
overrides.features = {
...overrides.features,
[featureName]: process.env[flag] === "true"
};
}
});
return deepMerge(config, overrides);
}
function freezeConfig(config) {
return deepFreeze(config);
}
function deepFreeze(obj) {
Object.freeze(obj);
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = obj[prop];
if (value && typeof value === "object" && !Object.isFrozen(value)) {
deepFreeze(value);
}
});
return obj;
}
function createConfigPatch(baseConfig, newConfig) {
const patch = {};
Object.keys(newConfig).forEach((key) => {
const baseValue = baseConfig[key];
const newValue = newConfig[key];
if (JSON.stringify(baseValue) !== JSON.stringify(newValue)) {
patch[key] = newValue;
}
});
return patch;
}
function isPatchSafe(patch) {
const dangerousPaths = ["/", "..", "~", "$HOME"];
if (patch.scanPaths && Array.isArray(patch.scanPaths)) {
for (const path of patch.scanPaths) {
if (path && dangerousPaths.some((dangerous) => path.includes(dangerous))) {
return false;
}
}
}
if (patch.security?.allowedPaths && Array.isArray(patch.security.allowedPaths)) {
for (const path of patch.security.allowedPaths) {
if (path && dangerousPaths.some((dangerous) => path.includes(dangerous))) {
return false;
}
}
}
if (patch.security?.blockedPatterns) {
const criticalPatterns = ["**/.env*", "**/*.key", "**/*.pem"];
for (const pattern of criticalPatterns) {
if (!patch.security.blockedPatterns.includes(pattern)) {
return false;
}
}
}
return true;
}
// src/config/loader.ts
var CONFIG_FILE_NAMES = [
"vibeship.config.ts",
"vibeship.config.js",
"vibeship.config.mjs",
"vibeship.config.cjs",
"vibeship.config.json",
".vibeshiprc.json",
".vibeshiprc"
];
async function loadConfig(options = {}) {
const {
configPath,
rootDir = process.cwd(),
applyEnvOverrides = true,
validate = true,
freeze = true
} = options;
const configFile = configPath || findConfigFile(rootDir);
let userConfig = {};
if (configFile) {
userConfig = await loadConfigFile(configFile);
if (validate) {
const validation = validatePartialConfig(userConfig);
if (!validation.success) {
throw new Error(
`Invalid configuration in ${configFile}:
${validation.errors?.join("\n")}`
);
}
}
}
const environmentDefaults = getEnvironmentDefaults();
let config = mergeConfigurations(
defaultConfig,
environmentDefaults,
{},
// Environment overrides will be applied separately
userConfig
);
if (applyEnvOverrides) {
config = applyEnvironmentOverrides(config);
}
if (validate) {
const validation = validateConfig(config);
if (!validation.success) {
throw new Error(
`Invalid final configuration:
${validation.errors?.join("\n")}`
);
}
config = validation.data;
}
if (freeze) {
config = freezeConfig(config);
}
return config;
}
function findConfigFile(rootDir) {
for (const fileName of CONFIG_FILE_NAMES) {
const filePath = join(rootDir, fileName);
if (existsSync(filePath)) {
return filePath;
}
}
let currentDir = rootDir;
for (let i = 0; i < 3; i++) {
const parentDir = resolve(currentDir, "..");
if (parentDir === currentDir) break;
for (const fileName of CONFIG_FILE_NAMES) {
const filePath = join(parentDir, fileName);
if (existsSync(filePath)) {
return filePath;
}
}
currentDir = parentDir;
}
return void 0;
}
async function loadConfigFile(filePath) {
const ext = extname(filePath);
switch (ext) {
case ".ts":
case ".mjs":
return loadTypeScriptConfig(filePath);
case ".js":
case ".cjs":
return loadJavaScriptConfig(filePath);
case ".json":
case "":
return loadJsonConfig(filePath);
default:
throw new Error(`Unsupported configuration file format: ${ext}`);
}
}
async function loadTypeScriptConfig(filePath) {
const supportsTS = await checkTypeScriptSupport();
if (supportsTS) {
const fileUrl2 = pathToFileURL(filePath).href;
const module2 = await import(fileUrl2);
return extractConfigFromModule(module2);
}
try {
await tryRegisterLoader("tsx/cjs");
} catch {
try {
await tryRegisterLoader("ts-node/register");
} catch {
throw new Error(
"TypeScript configuration files require either:\n1. Running with --loader tsx or --loader ts-node/esm\n2. Having tsx or ts-node installed\n3. Using a .js configuration file instead"
);
}
}
const fileUrl = pathToFileURL(filePath).href;
const module = await import(fileUrl);
return extractConfigFromModule(module);
}
async function loadJavaScriptConfig(filePath) {
const fileUrl = pathToFileURL(filePath).href;
const module = await import(fileUrl);
return extractConfigFromModule(module);
}
function loadJsonConfig(filePath) {
const content = readFileSync(filePath, "utf-8");
try {
return JSON.parse(content);
} catch (error) {
throw new Error(`Invalid JSON in configuration file ${filePath}: ${error}`);
}
}
function extractConfigFromModule(module) {
if (module.default) {
if (typeof module.default === "function") {
return module.default();
}
return module.default;
}
if (module.config) {
if (typeof module.config === "function") {
return module.config();
}
return module.config;
}
if (typeof module === "function") {
return module();
}
if (typeof module === "object" && module !== null) {
return module;
}
throw new Error("Configuration file must export a configuration object");
}
async function checkTypeScriptSupport() {
if (process.env.TSX || process.env.TS_NODE_DEV) {
return true;
}
const nodeVersion = process.version;
const major = parseInt(nodeVersion.split(".")[0].substring(1));
if (major >= 20 && process.execArgv.includes("--experimental-strip-types")) {
return true;
}
return false;
}
async function tryRegisterLoader(loader) {
try {
await import(loader);
} catch (error) {
throw new Error(`Failed to load ${loader}`);
}
}
function defineConfig(config) {
return config;
}
async function watchConfig(options) {
const { onChange, ...loadOptions } = options;
const configFile = options.configPath || findConfigFile(options.rootDir || process.cwd());
if (!configFile) {
const config = await loadConfig(loadOptions);
onChange(config);
return () => {
};
}
let currentConfig = await loadConfig(loadOptions);
onChange(currentConfig);
const { watch } = await import("fs");
const watcher = watch(configFile, async (eventType) => {
if (eventType === "change") {
try {
delete __require.cache[__require.resolve(configFile)];
const newConfig = await loadConfig(loadOptions);
if (JSON.stringify(newConfig) !== JSON.stringify(currentConfig)) {
currentConfig = newConfig;
onChange(newConfig);
}
} catch (error) {
console.error("Error reloading configuration:", error);
}
}
});
return () => {
watcher.close();
};
}
var cachedConfig = null;
var cacheKey = null;
async function getConfig(options = {}) {
const key = JSON.stringify(options);
if (cachedConfig && cacheKey === key) {
return cachedConfig;
}
cachedConfig = await loadConfig(options);
cacheKey = key;
return cachedConfig;
}
function clearConfigCache() {
cachedConfig = null;
cacheKey = null;
}
// src/config/migration.ts
var MIGRATIONS = [
{
version: "1.0.0",
description: "Migrate legacy devtools config to vibecode config",
shouldApply: (config) => {
return config.devtools && !config.scanPaths;
},
migrate: (config) => {
const { devtools, ...rest } = config;
return {
...rest,
scanPaths: devtools.scanPaths || ["./docs"],
features: {
tasks: devtools.enableTasks !== false,
ai: devtools.enableAI === true,
realtime: devtools.enableRealtime !== false,
commandPalette: devtools.enableCommandPalette !== false,
fileEditing: devtools.enableFileEditing === true,
markdownPreview: devtools.enableMarkdownPreview !== false
},
ui: {
theme: devtools.theme || "system",
position: devtools.position || "bottom-right",
hotkey: devtools.hotkey || "ctrl+shift+d",
showInProduction: devtools.showInProduction === true
}
};
}
},
{
version: "1.1.0",
description: "Migrate old security config structure",
shouldApply: (config) => {
return config.auth && !config.security?.auth;
},
migrate: (config) => {
const { auth, cors, rateLimit, ...rest } = config;
return {
...rest,
security: {
...rest.security,
authentication: !!auth,
auth: auth ? {
jwtSecret: auth.jwtSecret,
apiKey: auth.apiKey,
session: auth.session,
providers: auth.providers
} : void 0,
cors: cors !== false,
corsConfig: cors && typeof cors === "object" ? cors : void 0,
rateLimit: rateLimit !== false,
rateLimitConfig: rateLimit && typeof rateLimit === "object" ? rateLimit : void 0
}
};
}
},
{
version: "1.2.0",
description: "Migrate task patterns from arrays to objects",
shouldApply: (config) => {
return config.taskPatterns && Array.isArray(config.taskPatterns);
},
migrate: (config) => {
const patterns = config.taskPatterns;
return {
...config,
taskPatterns: {
todo: patterns.includes("TODO") || patterns.includes("todo"),
fixme: patterns.includes("FIXME") || patterns.includes("fixme"),
hack: patterns.includes("HACK") || patterns.includes("hack"),
note: patterns.includes("NOTE") || patterns.includes("note"),
warning: patterns.includes("WARNING") || patterns.includes("warning"),
optimize: patterns.includes("OPTIMIZE") || patterns.includes("optimize")
}
};
}
},
{
version: "1.3.0",
description: "Migrate cache config from string to object",
shouldApply: (config) => {
return typeof config.cache === "string" || typeof config.cache === "boolean";
},
migrate: (config) => {
const cacheValue = config.cache;
return {
...config,
cache: {
enabled: cacheValue !== false && cacheValue !== "false",
directory: typeof cacheValue === "string" ? cacheValue : ".vibecode/cache",
maxSize: 52428800,
// 50MB
ttl: 36e5,
// 1 hour
strategy: "lru"
}
};
}
},
{
version: "1.4.0",
description: "Migrate API config from string to object",
shouldApply: (config) => {
return typeof config.api === "string";
},
migrate: (config) => {
const apiValue = config.api;
return {
...config,
api: {
basePath: apiValue.startsWith("/") ? apiValue : `/api/${apiValue}`,
version: "v1",
documentation: true,
timeout: 3e4
}
};
}
}
];
function migrateConfig(config) {
const result = {
migrated: false,
appliedMigrations: [],
warnings: [],
config: { ...config }
};
for (const migration of MIGRATIONS) {
if (migration.shouldApply(result.config)) {
try {
const migratedConfig = migration.migrate(result.config);
if (migration.validate && !migration.validate(migratedConfig)) {
result.warnings.push(
`Migration ${migration.version} validation failed: ${migration.description}`
);
continue;
}
const validation = validatePartialConfig(migratedConfig);
if (!validation.success) {
result.warnings.push(
`Migration ${migration.version} produced invalid config: ${validation.errors?.join(", ")}`
);
continue;
}
result.config = migratedConfig;
result.migrated = true;
result.appliedMigrations.push(migration.version);
console.log(`Applied migration ${migration.version}: ${migration.description}`);
} catch (error) {
result.warnings.push(
`Migration ${migration.version} failed: ${error instanceof Error ? error.message : String(error)}`
);
}
}
}
return result;
}
function needsMigration(config) {
return MIGRATIONS.some((migration) => migration.shouldApply(config));
}
function getAvailableMigrations(config) {
return MIGRATIONS.filter((migration) => migration.shouldApply(config));
}
function createConfigBackup(config, backupPath) {
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
const backupName = backupPath || `vibecode.config.backup.${timestamp}.json`;
const { writeFileSync } = __require("fs");
writeFileSync(backupName, JSON.stringify(config, null, 2));
return backupName;
}
async function interactiveMigration(config, options = {}) {
const { prompt, createBackup = true, backupPath } = options;
const availableMigrations = getAvailableMigrations(config);
if (availableMigrations.length === 0) {
return {
migrated: false,
appliedMigrations: [],
warnings: [],
config
};
}
console.log("\nAvailable migrations:");
for (const migration of availableMigrations) {
console.log(` ${migration.version}: ${migration.description}`);
}
const shouldMigrate = prompt ? await prompt(`Apply ${availableMigrations.length} migration(s)?`) : true;
if (!shouldMigrate) {
return {
migrated: false,
appliedMigrations: [],
warnings: ["Migration cancelled by user"],
config
};
}
if (createBackup) {
const backupFile = createConfigBackup(config, backupPath);
console.log(`Configuration backup created: ${backupFile}`);
}
return migrateConfig(config);
}
function rollbackConfig(backupPath) {
const { readFileSync: readFileSync2, existsSync: existsSync2 } = __require("fs");
if (!existsSync2(backupPath)) {
throw new Error(`Backup file not found: ${backupPath}`);
}
const backupContent = readFileSync2(backupPath, "utf-8");
return JSON.parse(backupContent);
}
function cleanupBackups(maxAge = 30 * 24 * 60 * 60 * 1e3) {
const { readdirSync, statSync, unlinkSync } = __require("fs");
const { join: join2 } = __require("path");
const currentDir = process.cwd();
const files = readdirSync(currentDir);
const backupFiles = files.filter((file) => file.startsWith("vibecode.config.backup."));
const now = Date.now();
for (const file of backupFiles) {
const filePath = join2(currentDir, file);
const stats = statSync(filePath);
if (now - stats.mtime.getTime() > maxAge) {
unlinkSync(filePath);
console.log(`Cleaned up old backup: ${file}`);
}
}
}
// src/config/index.ts
import { z as z2 } from "zod";
export {
PartialVibeshipConfigSchema,
VibeshipConfigSchema,
applyEnvironmentOverrides,
cleanupBackups,
clearConfigCache,
createConfigBackup,
createConfigPatch,
deepMerge,
defaultConfig,
defineConfig,
developmentConfig,
freezeConfig,
getAvailableMigrations,
getConfig,
getEnvironmentDefaults,
interactiveMigration,
isPatchSafe,
isValidConfig,
loadConfig,
mergeConfigurations,
migrateConfig,
needsMigration,
productionConfig,
rollbackConfig,
testConfig,
validateConfig,
validatePartialConfig,
watchConfig,
z2 as z
};
//# sourceMappingURL=config.mjs.map