@puls-atlas/cli
Version:
The Puls Atlas CLI tool for managing Atlas projects
110 lines • 3.52 kB
JavaScript
import inquirer from 'inquirer';
import { Firestore } from '@google-cloud/firestore';
import { logger, readCollectionMappings } from '../../../utils/index.js';
import { manageRequest } from './manageRequest.js';
import deploy from '../../deploy/index.js';
const EXPORT_ACTIONS = ['Backfill', 'Reset', 'Migrate'];
const insertUntilDone = (projectId, collection, state) => {
const {
totalDocs,
exported = 0,
spinner
} = state;
return manageRequest(projectId, {
collection,
mode: 'insert',
limit: 10000,
startAfter: state.last
}).then(async response => {
if (!response.ok) {
throw new Error(await response.text());
}
return response.json();
}).then(({
result
}) => {
if (!result.success) {
throw new Error(JSON.stringify(result));
}
if (result.last) {
spinner.succeed(`Exported ${result.exported + exported} / ${totalDocs} documents.`);
const newSpinner = logger.spinner('Backfill in progress');
return insertUntilDone(projectId, collection, {
totalDocs,
spinner: newSpinner,
last: result.last,
exported: result.exported + exported
});
}
spinner.succeed('All documents have been exported.');
return 'DONE';
});
};
export const manageCollection = async (projectId, options) => {
const collectionMap = readCollectionMappings();
const {
collection
} = options.collection ? {
collection: options.collection
} : await inquirer.prompt([{
type: 'select',
name: 'collection',
message: 'Which collection do you want to manage?',
choices: Object.entries(collectionMap).map(([, entry]) => entry.collectionName)
}]);
const firestore = new Firestore({
projectId
});
const totalDocs = await firestore.collection(collection).count().get().then(result => result.data().count).catch(() => {
throw new Error('Collection does not exist!');
});
const {
mode
} = options.mode ? {
mode: options.mode
} : await inquirer.prompt([{
type: 'select',
name: 'mode',
message: `Which action do you want to perform on ${collection}?`,
choices: EXPORT_ACTIONS
}]);
if (!(collection in collectionMap)) {
spinner.fail(`Collection ${collection} is not initialized. Create the export for the collection first`);
return;
}
switch (mode) {
case 'Backfill':
{
const spinner = logger.spinner(`${mode} in progress`);
return insertUntilDone(projectId, collectionMap[collection].sanitizedName, {
totalDocs,
spinner
}).finally(() => spinner.stop());
}
case 'Reset':
case 'Migrate':
{
const doDeploy = options.allYes ?? (await inquirer.prompt([{
type: 'confirm',
message: 'Would you like to deploy the cloud functions first? (this might be needed if you changed any config or schema)',
name: 'doDeploy'
}]).then(({
doDeploy
}) => doDeploy));
if (doDeploy) {
await deploy.functions(['atlasExport']);
}
const spinner = logger.spinner(`${mode} in progress`);
return manageRequest(projectId, {
collection: collectionMap[collection].sanitizedName,
mode: mode.toLowerCase()
}).then(() => {
spinner.succeed(`${mode} completed successfully`);
}).catch(error => {
spinner.fail(`${mode} failed got: ${error.message}`);
});
}
default:
spinner.fail('Unknown mode');
}
};