feat: full database clone feature in api-cli

This commit is contained in:
2023-10-20 15:07:52 +02:00
parent 06b8ca109e
commit f618725598
3 changed files with 45 additions and 28 deletions

View File

@@ -0,0 +1,5 @@
---
'@openstapps/api-cli': minor
---
Add "\*" option to copy command that allows for a full database clone

View File

@@ -20,6 +20,12 @@ npm run build
node ./lib/cli.js e2e http://localhost:3000 node ./lib/cli.js e2e http://localhost:3000
``` ```
Example to clone the full database
```shell
node app.js copy "*" https://mobile.app.uni-frankfurt.de http://localhost:3000 100
```
### Program arguments ### Program arguments
```shell ```shell

View File

@@ -15,12 +15,11 @@
import {SCThingType} from '@openstapps/core'; import {SCThingType} from '@openstapps/core';
import {Logger} from '@openstapps/logger'; import {Logger} from '@openstapps/logger';
import {Command} from 'commander'; import {Command} from 'commander';
import {readFileSync} from 'fs'; import {URL} from 'url';
import path from 'path';
import {fileURLToPath, URL} from 'url';
import waitOn from 'wait-on'; import waitOn from 'wait-on';
import {HttpClient} from '@openstapps/api'; import {HttpClient} from '@openstapps/api';
import {copy} from './copy.js'; import {copy} from './copy.js';
import {version} from '../package.json';
// eslint-disable-next-line unicorn/prevent-abbreviations // eslint-disable-next-line unicorn/prevent-abbreviations
import {e2eRun} from './e2e.js'; import {e2eRun} from './e2e.js';
@@ -28,11 +27,6 @@ process.on('unhandledRejection', async error => {
await Logger.error('unhandledRejection', error); await Logger.error('unhandledRejection', error);
}); });
// eslint-disable-next-line unicorn/prefer-module
const packageJson = JSON.parse(
readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'package.json')).toString(),
);
const client = new HttpClient(); const client = new HttpClient();
const commander = new Command(); const commander = new Command();
const helpAndExit = (help: string) => { const helpAndExit = (help: string) => {
@@ -43,7 +37,7 @@ const helpAndExit = (help: string) => {
commander commander
.command('e2e <to>') .command('e2e <to>')
.version(packageJson.version) .version(version)
.description( .description(
'Run in end to end test mode. Indexing and afterwards retrieving all test files from @openstapp/core to the backend', 'Run in end to end test mode. Indexing and afterwards retrieving all test files from @openstapp/core to the backend',
) )
@@ -87,15 +81,14 @@ commander
commander commander
.command('copy <type> <from> <to> <batchSize>') .command('copy <type> <from> <to> <batchSize>')
.version(packageJson.version) .version(version)
.description('Copy data from one instance to another') .description('Copy data from one instance to another')
.option( .option(
'-s, --bulkSource <bulkSource>', '-s, --bulkSource <bulkSource>',
'The source identifier for the bulk to use with the target instance [copy]', 'The source identifier for the bulk to use with the target instance [copy]',
'copy', 'copy',
) )
// TODO: remove .option('-a, --appVersion <version>', 'The App version to use [unset by default]', version)
.option('-a, --appVersion <version>', 'The App version to use [unset by default]')
.allowUnknownOption(false) .allowUnknownOption(false)
.action(async (type, from, to, batchSize, copyCommand) => { .action(async (type, from, to, batchSize, copyCommand) => {
// validate type // validate type
@@ -123,23 +116,36 @@ commander
helpAndExit(copyCommand.helpInformation()); helpAndExit(copyCommand.helpInformation());
} }
Logger.info(`Copying ${type} objects from ${fromURL} to ${toURL}`); /**
* Copy a single type from one backend to another
*/
async function copySingleType(type: string) {
Logger.info(`Copying ${type} objects from ${fromURL} to ${toURL}`);
copy(client, { await copy(client, {
batchSize: Number.parseInt(batchSize, 10), batchSize: Number.parseInt(batchSize, 10),
from: fromURL, from: fromURL,
source: copyCommand.bulkSource, source: copyCommand.bulkSource,
to: toURL, to: toURL,
type: type as SCThingType, type: type as SCThingType,
version: copyCommand.appVersion, version: copyCommand.appVersion,
}).then( });
() => { Logger.ok('done');
Logger.ok('Done'); }
},
error => { if (type === '*') {
throw error; const types = Object.values(SCThingType);
}, for (const [i, type] of types.entries()) {
); Logger.info(`Copying ${type} (${i + 1} / ${types.length})`);
try {
await copySingleType(type);
} catch (error) {
await Logger.error(error);
}
}
} else {
await copySingleType(type);
}
}); });
commander.parse(process.argv); commander.parse(process.argv);