@puls-atlas/cli
Version:
The Puls Atlas CLI tool for managing Atlas projects
138 lines (136 loc) • 5.17 kB
JavaScript
import path from 'path';
import fs from 'fs';
import inquirer from 'inquirer';
import { exec, logger, sanitizeCollection, writeCollectionMapping } from '../../../utils/index.js';
import { manageRequest } from './manageRequest.js';
import deploy from '../../deploy/index.js';
const onWriteTemplate = collection => {
const sanitizedName = sanitizeCollection(collection);
return `\
import { functions, bigquery } from '@limebooth/atlas-cloud-functions';
import * as collections from '../collections/index.js';
export default functions.firestore
.document('${collection}/{docId}')
.onWrite(async event => bigquery.insertDocumentOnWrite(collections['${sanitizedName}'], event));
`;
};
export const initializeCollection = async (projectId, options) => {
const {
collection
} = options.collection ? {
collection: options.collection
} : await inquirer.prompt([{
type: 'input',
name: 'collection',
message: 'Give the collection path to export:'
}]);
const spinner = logger.spinner(`Initializing collection \`${collection}\`...`);
const {
results
} = await manageRequest(projectId, {
collection,
mode: 'config'
}).then(response => response.json());
if (!results?.config) {
throw new Error('No configuration returned from cloud function.');
}
const {
config
} = results;
const sanitizedName = sanitizeCollection(collection);
const collectionsDir = path.join(process.cwd(), 'functions', 'atlas-export', 'src', 'collections');
if (!fs.existsSync(collectionsDir)) {
fs.mkdirSync(collectionsDir, {
recursive: true
});
}
const formattedConfig = JSON.stringify(config, null, 4);
const collectionFilePath = path.join(collectionsDir, `${sanitizedName}.js`);
const configContent = `
/* eslint-disable quote-props */
/* eslint-disable quotes */
// Auto-generated configuration for ${collection}
export default ${formattedConfig};
`;
fs.writeFileSync(collectionFilePath, configContent);
const indexFilePath = path.join(collectionsDir, 'index.js');
let indexContent = fs.readFileSync(indexFilePath, 'utf-8');
if (!indexContent.includes(`export { default as ${sanitizedName} }`)) {
indexContent += `export { default as ${sanitizedName} } from './${sanitizedName}.js';\n`;
}
fs.writeFileSync(indexFilePath, indexContent);
const syncDir = path.join(process.cwd(), 'functions', 'atlas-export', 'src', 'sync');
if (!fs.existsSync(syncDir)) {
fs.mkdirSync(syncDir, {
recursive: true
});
}
const syncFilePath = path.join(syncDir, `${sanitizedName}.js`);
const syncContent = onWriteTemplate(collection);
fs.writeFileSync(syncFilePath, syncContent);
const syncIndexFilePath = path.join(syncDir, 'index.js');
let syncIndexContent = fs.readFileSync(syncIndexFilePath, 'utf-8');
if (!syncIndexContent.includes(`export { default as ${sanitizedName} }`)) {
syncIndexContent += `export { default as ${sanitizedName} } from './${sanitizedName}.js';\n`;
}
fs.writeFileSync(syncIndexFilePath, syncIndexContent);
writeCollectionMapping(sanitizedName, collection);
spinner.succeed(`Collection \`${collection}\` initialized successfully.\n`);
logger.info(`Configuration saved to: ${collectionFilePath}`);
logger.info(`Sync function saved to: ${syncFilePath}\n`);
logger.info('It is recommend to check the newly generated configuration and validate the schema.');
const openEditor = options.allYes ? false : await inquirer.prompt([{
type: 'confirm',
name: 'openEditor',
message: 'Would you like to open the configuration in your editor?'
}]).then(({
openEditor
}) => openEditor);
if (openEditor) {
const subCmd = exec(`${process.env.EDITOR || 'code'} ${collectionFilePath}`, {});
await new Promise(resolve => {
subCmd.on('error', error => {
logger.error(error);
resolve();
});
subCmd.on('exit', resolve);
});
}
const doDeploy = options.allYes ?? (await inquirer.prompt([{
type: 'confirm',
name: 'doDeploy',
message: 'Continue with deploying to Firebase functions?'
}]).then(({
doDeploy
}) => doDeploy));
if (doDeploy) {
return deploy.functions(['atlasExport'], {
codebase: 'atlas-export',
projectId
});
}
const {
createTable
} = await inquirer.prompt([{
type: 'confirm',
name: 'createTable',
message: 'Would you like to create the BigQuery table now (runs manage function in reset mode)?',
default: true
}]);
if (createTable) {
const tableSpinner = logger.spinner(`Creating BigQuery table for collection \`${collection}\`...`);
const response = await manageRequest(projectId, {
collection,
mode: 'reset'
});
const result = await response.json();
if (response.ok) {
tableSpinner.succeed(`BigQuery table created successfully for collection \`${collection}\`.`);
logger.info('Table is now ready to receive data from Firestore.');
} else {
tableSpinner.fail(`Failed to create BigQuery table: ${result.error || 'Unknown error'}`);
throw new Error(result.error || 'Failed to create BigQuery table');
}
}
return Promise.resolve();
};