@catalystlabs/awm
Version:
Appwrite Migration Tool - Schema management and code generation for Appwrite databases
194 lines (167 loc) • 6.42 kB
JavaScript
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';
import os from 'os';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
cyan: '\x1b[36m'
};
async function checkAppwriteCLI() {
try {
execSync('appwrite --version', { stdio: 'pipe' });
return true;
} catch {
return false;
}
}
async function checkAppwriteProject() {
try {
// Check if appwrite.config.json exists (created by appwrite init project)
await fs.access(path.join(process.cwd(), 'appwrite.config.json'));
return true;
} catch {
return false;
}
}
async function getAppwriteConfig() {
try {
const configPath = path.join(os.homedir(), '.appwrite', 'prefs.json');
const configContent = await fs.readFile(configPath, 'utf-8');
const config = JSON.parse(configContent);
return {
endpoint: config.endpoint || 'http://localhost/v1',
projectId: config.projectId || null
};
} catch {
return null;
}
}
export async function initProject() {
console.log(`\n${colors.cyan}🚀 Initializing AWM in your project...${colors.reset}\n`);
// Check for Appwrite CLI
const hasAppwriteCLI = await checkAppwriteCLI();
if (!hasAppwriteCLI) {
console.log(`${colors.yellow}⚠️ Appwrite CLI not found${colors.reset}`);
console.log(`${colors.dim} Install it with: npm install -g appwrite-cli${colors.reset}\n`);
} else {
console.log(`${colors.green}✓${colors.reset} Appwrite CLI detected\n`);
}
// Check for Appwrite project initialization
const hasAppwriteProject = await checkAppwriteProject();
if (!hasAppwriteProject && hasAppwriteCLI) {
console.log(`${colors.yellow}⚠️ No Appwrite project found${colors.reset}`);
console.log(`${colors.dim} Initialize with: appwrite init project${colors.reset}\n`);
} else if (hasAppwriteProject) {
console.log(`${colors.green}✓${colors.reset} Appwrite project initialized\n`);
}
// Get Appwrite config if available
const appwriteConfig = await getAppwriteConfig();
let defaultConfig = {
projectId: "your-project-id",
endpoint: "http://localhost/v1",
databaseId: "your-database",
schemaPath: "schema/appwrite.schema"
};
if (appwriteConfig) {
console.log(`${colors.green}✓${colors.reset} Found Appwrite CLI configuration\n`);
defaultConfig.endpoint = appwriteConfig.endpoint;
if (appwriteConfig.projectId) {
defaultConfig.projectId = appwriteConfig.projectId;
}
}
// Create schema directory if it doesn't exist
const schemaDir = path.join(process.cwd(), 'schema');
try {
await fs.access(schemaDir);
console.log(`${colors.green}✓${colors.reset} Schema directory exists\n`);
} catch {
await fs.mkdir(schemaDir, { recursive: true });
console.log(`${colors.green}✓${colors.reset} Created schema directory\n`);
}
// Create types directory if it doesn't exist
const typesDir = path.join(process.cwd(), 'types');
try {
await fs.access(typesDir);
console.log(`${colors.green}✓${colors.reset} Types directory exists\n`);
} catch {
await fs.mkdir(typesDir, { recursive: true });
console.log(`${colors.green}✓${colors.reset} Created types directory\n`);
}
const files = {
'.env.example': await fs.readFile(path.join(__dirname, '.env.example'), 'utf-8'),
'schema/appwrite.schema': await fs.readFile(path.join(__dirname, 'appwrite.schema.example'), 'utf-8'),
'.awm.json': JSON.stringify(defaultConfig, null, 2)
};
const created = [];
const skipped = [];
for (const [filename, content] of Object.entries(files)) {
const targetPath = path.join(process.cwd(), filename);
try {
// Check if file exists
await fs.access(targetPath);
skipped.push(filename);
} catch {
// Ensure parent directory exists
const parentDir = path.dirname(targetPath);
await fs.mkdir(parentDir, { recursive: true });
// File doesn't exist, create it
await fs.writeFile(targetPath, content);
created.push(filename);
}
}
// Add .awm-state.db to .gitignore
try {
const gitignorePath = path.join(process.cwd(), '.gitignore');
let gitignore = '';
try {
gitignore = await fs.readFile(gitignorePath, 'utf-8');
} catch {
// .gitignore doesn't exist
}
if (!gitignore.includes('.awm-state.db')) {
gitignore += '\n# AWM state database\n.awm-state.db\n.awm-state.db-journal\n';
await fs.writeFile(gitignorePath, gitignore);
created.push('.gitignore (updated)');
}
} catch (error) {
console.warn(`${colors.yellow}Warning: Could not update .gitignore${colors.reset}`);
}
// Print results
if (created.length > 0) {
console.log(`${colors.green}✅ Created files:${colors.reset}`);
created.forEach(file => console.log(` - ${file}`));
}
if (skipped.length > 0) {
console.log(`\n${colors.yellow}⏭️ Skipped existing files:${colors.reset}`);
skipped.forEach(file => console.log(` - ${file}`));
}
console.log(`
${colors.bright}Next steps:${colors.reset}`);
if (!hasAppwriteCLI) {
console.log(`1. ${colors.cyan}Install Appwrite CLI:${colors.reset} npm install -g appwrite-cli`);
}
if (!hasAppwriteProject && hasAppwriteCLI) {
console.log(`2. ${colors.cyan}Initialize Appwrite project:${colors.reset} appwrite init project`);
}
console.log(`3. Edit ${colors.cyan}.env.example${colors.reset} with your Appwrite credentials`);
console.log(`4. Rename it to ${colors.cyan}.env${colors.reset}`);
console.log(`5. Customize ${colors.cyan}schema/appwrite.schema${colors.reset} for your database`);
console.log(`6. Run ${colors.cyan}awm plan${colors.reset} to preview changes`);
console.log(`7. Run ${colors.cyan}awm apply${colors.reset} to create collections`);
console.log(`8. Run ${colors.cyan}awm relationships${colors.reset} to add relationships`);
console.log(`9. Run ${colors.cyan}awm generate${colors.reset} to create TypeScript types`);
console.log(`
${colors.dim}For more information, see the README or run 'awm --help'${colors.reset}
`);
}
// Export for use as module
export default initProject;