import { PluginMetaLoader } from '@squeebot/core/lib/plugin'; import { takeChecksum } from '@squeebot/core/lib/util'; import fs from 'fs-extra'; import path from 'path'; import tar from 'tar'; import { defaultEnvironment } from '../default/environment.default'; import { execute } from '../execute'; import { REPOSITORY_SCHEMA } from './constants'; import { deploy } from './deploy'; /** * Build repository ready for deployment * @param location Repository location * @param out Create output files for deployment (false - only compile tsc in-place) * @param doDeploy Deployment name * @param onlyDeploy Deploy only without building */ export async function buildRepository( location?: string, out = true, doDeploy?: string, onlyDeploy = false ): Promise { if (!location) { location = process.cwd(); } location = path.resolve(process.cwd(), location); const outDir = path.join(location, '.out'); // Check for repository metadata const buildMetaFile = path.join(location, 'squeebot.repo.json'); if (!await fs.pathExists(buildMetaFile)) { throw new Error(`${location} is not a valid squeebot repository development environment!`); } // Read repository metadata const meta = await fs.readJson(buildMetaFile); const env = defaultEnvironment(location); env.pluginsPath = location; if (!meta.name) { throw new Error(`${location} is not a valid squeebot repository development environment!`); } console.log('Detected repository "%s"!', meta.name); if (onlyDeploy) { if (!await fs.pathExists(outDir)) { throw new Error('You need to build before deploying!'); } else { return deploy(meta.name, location, outDir, doDeploy as string); } } // Run typescript build if (meta.typescript) { console.log('Running build task..'); await execute(['npm', 'run', 'build'], location); } console.log('Detecting plugins in this environment..'); const loader = new PluginMetaLoader(env); const plugins = await loader.loadAll(false); console.log('Found the following plugins:', plugins.map((plugin) => { return `${plugin.name}@${plugin.version}`; }).join(', ')); const savedList = plugins.map((plugin) => ({ name: plugin.name, version: plugin.version, })); meta.plugins = savedList; await fs.writeJson(buildMetaFile, meta, { spaces: 2 }); if (!out) { console.log('Done!'); return; } await fs.remove(outDir); await fs.ensureDir(outDir); console.log('Copying plugins'); for (const plugin of plugins) { const src = path.join(location, plugin.name); const dst = path.join(outDir, plugin.name); await fs.copy(src, dst); } if (meta.typescript) { console.log('Stripping TypeScript source files'); for (const plugin of plugins) { const plOut = path.join(outDir, plugin.name); const listAllFiles = await fs.readdir(plOut); for (const f of listAllFiles) { if (f.match(/(\.d)?\.ts$/i) != null) { await fs.remove(path.join(plOut, f)); } } } } console.log('Copying configuration schemas'); for (const plugin of plugins) { const plOut = path.join(outDir, plugin.name); const schemaFile = path.join(plOut, 'schema.json'); const outSchemaFile = path.join(outDir, `${plugin.name}.schema.json`); if (await fs.pathExists(schemaFile)) { await fs.copy(schemaFile, outSchemaFile); } } console.log('Creating tarballs'); for (const plugin of plugins) { const plOut = path.join(outDir, plugin.name); const fileName = `${plOut}.plugin.tgz`; await tar.c({ gzip: true, file: fileName, C: outDir, }, [plugin.name]); // Create checksum of tarball const checksum = await takeChecksum(fileName); const metaPlugin = meta.plugins.find((item: { name: string }) => item.name === plugin.name); if (metaPlugin && checksum) { metaPlugin.checksum = checksum; } } console.log('Creating repository index'); await fs.writeJSON(path.join(outDir, 'repository.json'), { created: Math.floor(Date.now() / 1000), name: meta.name, plugins: meta.plugins, $schema: REPOSITORY_SCHEMA, }); if (doDeploy == null) { console.log('Done!'); return; } deploy(meta.name, location, outDir, doDeploy); }