lorehub
Version:
Capture and surface the collective wisdom of your codebase
146 lines • 6.73 kB
JavaScript
import React, { useState, useEffect } from 'react';
import { render, Box, Text } from 'ink';
import { Database } from '../../db/database.js';
import { getDbPath } from '../utils/db-config.js';
import { Progress } from '../components/Progress.js';
import { ErrorMessage } from '../components/ErrorMessage.js';
import fs from 'fs/promises';
import path from 'path';
function Import({ inputFile, merge = false }) {
const [status, setStatus] = useState('loading');
const [error, setError] = useState(null);
const [importedCount, setImportedCount] = useState(0);
const [totalCount, setTotalCount] = useState(0);
const [summary, setSummary] = useState(null);
useEffect(() => {
async function performImport() {
try {
// Read and parse import file
const resolvedPath = path.resolve(inputFile);
const fileContent = await fs.readFile(resolvedPath, 'utf-8');
let importData;
try {
importData = JSON.parse(fileContent);
}
catch (err) {
throw new Error('Invalid JSON format. Please ensure the file is a valid LoreHub export.');
}
// Validate import data
if (!importData.version || !importData.realms || !importData.lores) {
throw new Error('Invalid import file format. Missing required fields.');
}
setTotalCount(importData.realms.length + importData.lores.length);
setStatus('importing');
const dbPath = getDbPath();
const db = new Database(dbPath);
// Clear existing data if not merging
if (!merge) {
// Get all existing realms and delete their lores
const existingRealms = db.listRealms();
for (const realm of existingRealms) {
const lores = db.listLoresByRealm(realm.id);
for (const lore of lores) {
db.deleteLore(lore.id);
}
}
}
// Import realms
const realmIdMap = new Map(); // old ID -> new ID
let importedRealms = 0;
for (const realm of importData.realms) {
setImportedCount(prev => prev + 1);
// Check if realm already exists
let existingRealm = db.findRealmByPath(realm.path);
if (existingRealm && merge) {
// Update existing realm
realmIdMap.set(realm.id, existingRealm.id);
}
else {
// Create new realm
const newRealm = db.createRealm({
name: realm.name,
path: realm.path,
gitRemote: realm.gitRemote === null ? undefined : realm.gitRemote,
isMonorepo: realm.isMonorepo,
provinces: realm.provinces,
});
realmIdMap.set(realm.id, newRealm.id);
importedRealms++;
}
}
// Import lores
let importedLores = 0;
for (const lore of importData.lores) {
setImportedCount(prev => prev + 1);
const newRealmId = realmIdMap.get(lore.realmId);
if (!newRealmId) {
console.warn(`Skipping lore: realm ${lore.realmId} not found`);
continue;
}
const loreInput = {
realmId: newRealmId,
content: lore.content,
type: lore.type,
status: lore.status,
confidence: lore.confidence,
why: lore.why === null ? undefined : lore.why,
provinces: lore.provinces,
sigils: lore.sigils,
origin: lore.origin,
};
try {
await db.createLore(loreInput);
importedLores++;
}
catch (err) {
console.warn(`Failed to import lore: ${err}`);
}
}
db.close();
setSummary({ realms: importedRealms, lores: importedLores });
setStatus('success');
}
catch (err) {
setError(err instanceof Error ? err : new Error('Import failed'));
setStatus('error');
}
}
performImport();
}, [inputFile, merge]);
if (status === 'loading') {
return React.createElement(Progress, { message: "Reading import file..." });
}
if (status === 'importing') {
return (React.createElement(Progress, { message: "Importing data...", current: importedCount, total: totalCount }));
}
if (status === 'error' && error) {
return (React.createElement(ErrorMessage, { error: error, context: "Import", suggestions: [
'Check if the import file exists and is readable',
'Ensure the file is a valid LoreHub export (JSON format)',
'Use --merge flag to add to existing data instead of replacing',
] }));
}
if (status === 'success' && summary) {
return (React.createElement(Box, { flexDirection: "column" },
React.createElement(Text, { color: "green", bold: true }, "\u2713 Import completed successfully!"),
React.createElement(Text, null,
"Imported from: ",
path.resolve(inputFile)),
React.createElement(Box, { marginTop: 1 },
React.createElement(Text, null,
"\u2022 Realms: ",
summary.realms)),
React.createElement(Box, null,
React.createElement(Text, null,
"\u2022 Lores: ",
summary.lores)),
merge && (React.createElement(Box, { marginTop: 1 },
React.createElement(Text, { dimColor: true }, "Mode: Merge (existing data preserved)")))));
}
return null;
}
export async function renderImport(options) {
const { waitUntilExit } = render(React.createElement(Import, { ...options }));
await waitUntilExit();
}
//# sourceMappingURL=import.js.map