Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@cloudant/couchbackup

Package Overview
Dependencies
Maintainers
0
Versions
493
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cloudant/couchbackup - npm Package Compare versions

Comparing version 2.10.3-SNAPSHOT-240 to 2.10.3-SNAPSHOT-241

includes/attachmentMappings.js

17

app.js

@@ -100,3 +100,5 @@ // Copyright © 2017, 2024 IBM Corp. All rights reserved.

{ key: 'mode', type: 'enum', values: ['full', 'shallow'] },
{ key: 'resume', type: 'boolean' }
{ key: 'resume', type: 'boolean' },
{ key: 'quiet', type: 'boolean' },
{ key: 'attachments', type: 'boolean' }
];

@@ -193,2 +195,10 @@

async function attachmentWarnings(opts) {
if (opts && opts.attachments) {
console.warn('WARNING: The "attachments" option is provided as-is and is not supported. ' +
'This option is for Apache CouchDB only and is experimental. ' +
'Do not use this option with IBM Cloudant.');
}
}
/**

@@ -206,3 +216,4 @@ * Validate arguments.

validateURL(url, isIAM),
validateOptions(opts)
validateOptions(opts),
attachmentWarnings(opts)
];

@@ -332,3 +343,3 @@ if (isBackup) {

debug('Will write backup file header.');
metadataToWrite = `${JSON.stringify({ name: pkg.name, version: pkg.version, mode: opts.mode })}\n`;
metadataToWrite = `${JSON.stringify({ name: pkg.name, version: pkg.version, mode: opts.mode, attachments: opts.attachments })}\n`;
}

@@ -335,0 +346,0 @@ return new Promise((resolve, reject) => {

3

bin/couchbackup.bin.js

@@ -40,3 +40,4 @@ #!/usr/bin/env node

iamApiKey: program.iamApiKey,
iamTokenUrl: program.iamTokenUrl
iamTokenUrl: program.iamTokenUrl,
attachments: program.attachments
};

@@ -43,0 +44,0 @@

@@ -35,3 +35,4 @@ #!/usr/bin/env node

iamApiKey: program.iamApiKey,
iamTokenUrl: program.iamTokenUrl
iamTokenUrl: program.iamTokenUrl,
attachments: program.attachments
};

@@ -38,0 +39,0 @@

@@ -1,2 +0,2 @@

// Copyright © 2023 IBM Corp. All rights reserved.
// Copyright © 2023, 2024 IBM Corp. All rights reserved.
//

@@ -31,2 +31,5 @@ // Licensed under the Apache License, Version 2.0 (the "License");

const opts = { db: dbClient.dbName, limit: options.bufferSize, includeDocs: true };
if (options.attachments === true) {
opts.attachments = true;
}
do {

@@ -33,0 +36,0 @@ if (startKey) opts.startKey = startKey;

@@ -18,2 +18,3 @@ // Copyright © 2017, 2024 IBM Corp. All rights reserved.

const { pipeline } = require('node:stream/promises');
const { Attachments } = require('./attachmentMappings.js');
const { Backup } = require('./backupMappings.js');

@@ -91,3 +92,3 @@ const { BackupError } = require('./error.js');

.then((srcStreams) => {
const backup = new Backup(dbClient);
const backup = new Backup(dbClient, options);
const postWrite = (backupBatch) => {

@@ -99,2 +100,3 @@ total += backupBatch.docs.length;

const mappingStreams = [];
const destinationStreams = [];

@@ -114,4 +116,6 @@ if (options.mode === 'shallow') {

// full mode needs to fetch spooled changes and writes a backup file then finally a log file
mappingStreams.push(...[
new MappingStream(backup.pendingToFetched, options.parallelism) // fetch the batches at the configured concurrency
]);
destinationStreams.push(...[
new MappingStream(backup.pendingToFetched, options.parallelism), // fetch the batches at the configured concurrency
new WritableWithPassThrough(

@@ -133,4 +137,11 @@ 'backup', // name for logging

if (options.attachments) {
mappingStreams.push(
new MappingStream(new Attachments().encode, options.parallelism)
);
}
return pipeline(
...srcStreams, // the source streams from the previous block (all docs async generator for shallow or for full either spool changes or resumed log)
...mappingStreams, // map from source to destination content
...destinationStreams // the appropriate destination streams for the mode

@@ -137,0 +148,0 @@ );

@@ -1,2 +0,2 @@

// Copyright © 2017, 2023 IBM Corp. All rights reserved.
// Copyright © 2017, 2024 IBM Corp. All rights reserved.
//

@@ -174,4 +174,5 @@ // Licensed under the Apache License, Version 2.0 (the "License");

class Backup {
constructor(dbClient) {
constructor(dbClient, options) {
this.dbClient = dbClient;
this.options = options;
}

@@ -211,7 +212,11 @@

try {
const response = await this.dbClient.service.postBulkGet({
const bulkGetOpts = {
db: this.dbClient.dbName,
revs: true,
docs: backupBatch.docs
});
};
if (this.options.attachments) {
bulkGetOpts.attachments = true;
}
const response = await this.dbClient.service.postBulkGet(bulkGetOpts);

@@ -218,0 +223,0 @@ mappingDebug(`Good server response for batch ${backupBatch.batch}.`);

@@ -1,2 +0,2 @@

// Copyright © 2017, 2023 IBM Corp. All rights reserved.
// Copyright © 2017, 2024 IBM Corp. All rights reserved.
//

@@ -25,2 +25,3 @@ // Licensed under the Apache License, Version 2.0 (the "License");

return {
attachments: false,
parallelism: 5,

@@ -114,2 +115,7 @@ bufferSize: 500,

}
// if we are instructed to be quiet
if (typeof process.env.COUCH_ATTACHMENTS !== 'undefined' && process.env.COUCH_ATTACHMENTS === 'true') {
opts.attachments = true;
}
}

@@ -116,0 +122,0 @@

@@ -1,2 +0,2 @@

// Copyright © 2017, 2023 IBM Corp. All rights reserved.
// Copyright © 2017, 2024 IBM Corp. All rights reserved.
//

@@ -30,3 +30,5 @@ // Licensed under the Apache License, Version 2.0 (the "License");

HTTPFatalError: 40,
BulkGetError: 50
BulkGetError: 50,
AttachmentsNotEnabledError: 60,
AttachmentsMetadataAbsent: 61
};

@@ -33,0 +35,0 @@

@@ -36,2 +36,4 @@ // Copyright © 2017, 2024 IBM Corp. All rights reserved.

.usage('[options...]')
.option('-a, --attachments',
cliutils.getUsage('*EXPERIMENTAL/UNSUPPORTED*: enable backup of attachments', defaults.attachments))
.option('-b, --buffer-size <n>',

@@ -101,2 +103,4 @@ cliutils.getUsage('number of documents fetched at once', defaults.bufferSize),

.usage('[options...]')
.option('-a, --attachments',
cliutils.getUsage('*EXPERIMENTAL/UNSUPPORTED*: enable restore of attachments', defaults.attachments))
.option('-b, --buffer-size <n>',

@@ -103,0 +107,0 @@ cliutils.getUsage('number of documents restored at once', defaults.bufferSize),

@@ -17,4 +17,5 @@ // Copyright © 2017, 2024 IBM Corp. All rights reserved.

const debug = require('debug')('couchbackup:restore');
const { Liner } = require('../includes/liner.js');
const { Restore } = require('../includes/restoreMappings.js');
const { Attachments } = require('./attachmentMappings.js');
const { Liner } = require('./liner.js');
const { Restore } = require('./restoreMappings.js');
const { BatchingStream, MappingStream } = require('./transforms.js');

@@ -34,3 +35,3 @@ const { Writable } = require('node:stream');

module.exports = function(dbClient, options, readstream, ee) {
const restore = new Restore(dbClient);
const restore = new Restore(dbClient, options);
const start = new Date().getTime(); // restore start time

@@ -53,3 +54,3 @@ let total = 0; // the total restored

return pipeline(
const batchPreparationStreams = [
readstream, // the backup file

@@ -59,5 +60,20 @@ new Liner(), // line by line

new BatchingStream(options.bufferSize, true), // make new arrays of the correct buffer size
new MappingStream(restore.docsToRestoreBatch), // make a restore batch
new MappingStream(restore.docsToRestoreBatch) // make a restore batch
];
const mappingStreams = [];
const restoreStreams = [
new MappingStream(restore.pendingToRestored, options.parallelism), // do the restore at the desired level of concurrency
output // emit restored events
];
if (options.attachments) {
mappingStreams.push(
new MappingStream(new Attachments().decode, options.parallelism)
);
}
return pipeline(
...batchPreparationStreams,
...mappingStreams,
...restoreStreams
).then(() => {

@@ -64,0 +80,0 @@ return { total };

@@ -1,2 +0,2 @@

// Copyright © 2017, 2023 IBM Corp. All rights reserved.
// Copyright © 2017, 2024 IBM Corp. All rights reserved.
//

@@ -31,4 +31,5 @@ // Licensed under the Apache License, Version 2.0 (the "License");

constructor(dbClient) {
constructor(dbClient, options) {
this.dbClient = dbClient;
this.options = options;
this.batchCounter = 0;

@@ -69,3 +70,3 @@ }

// First line is metadata.
mappingDebug(`Parsed backup file metadata ${lineAsJson.name} ${lineAsJson.version} ${lineAsJson.mode}.`);
mappingDebug(`Parsed backup file metadata ${lineAsJson.name} ${lineAsJson.version} ${lineAsJson.mode} ${lineAsJson.attachments}.`);
// This identifies a version of 2.10.0 or newer that wrote the backup file.

@@ -78,2 +79,12 @@ // Set the mode that was used for the backup file.

// Later we may add other version/feature specific toggles here.
if (lineAsJson.attachments === true) {
if (!this.options.attachments) {
// Error out if trying to restore attachments without the option
throw new BackupError('AttachmentsNotEnabledError', 'To restore a backup file with attachments, enable the attachments option.');
}
} else {
if (this.options.attachments) {
throw new BackupError('AttachmentsMetadataAbsent', 'Cannot restore with attachments because the backup file was not created with the attachments option.');
}
}
} else if (lineAsJson.marker && lineAsJson.marker === marker) {

@@ -80,0 +91,0 @@ mappingDebug(`Resume marker on line ${backupLine.lineNumber} of backup file.`);

{
"name": "@cloudant/couchbackup",
"version": "2.10.3-SNAPSHOT-240",
"version": "2.10.3-SNAPSHOT-241",
"description": "CouchBackup - command-line backup utility for Cloudant/CouchDB",

@@ -5,0 +5,0 @@ "homepage": "https://github.com/IBM/couchbackup",

@@ -25,3 +25,3 @@ # CouchBackup

* **`couchbackup` does not do CouchDB replication as such, it simply streams through a database's `_changes` feed, and uses `POST /db/_bulk_get` to fetch the documents, storing the documents it finds on disk.**
* **`couchbackup` does not support backing up or restoring databases containing documents with attachments. The recommendation is to store attachments directly in an object store. DO NOT USE THIS TOOL FOR DATABASES CONTAINING ATTACHMENTS.** [Note](#note-on-attachments)
* **`couchbackup` does not support backing up or restoring databases containing documents with attachments. The recommendation is to store attachments directly in an object store. The "attachments" option is provided as-is and is not supported. This option is for Apache CouchDB only and is experimental. DO NOT USE THIS OPTION WITH IBM Cloudant backups.** [Note](#note-on-attachments)

@@ -232,2 +232,3 @@ ## Installation

`https://iam.cloud.ibm.com/identity/token`, but can be overridden if necessary using the `CLOUDANT_IAM_TOKEN_URL` environment variable.
* `COUCH_ATTACHMENTS` - _EXPERIMENTAL & UNSUPPORTED_ (see [Note](#note-on-attachments)) if `true` will include attachments as part of the backup or restore process.
* `DEBUG` - if set to `couchbackup`, all debug messages print on `stderr` during a backup or restore process

@@ -251,2 +252,3 @@

* `--quiet` - same as `COUCH_QUIET`
* `--attachments` - _EXPERIMENTAL & UNSUPPORTED_ (see [Note](#note-on-attachments)) same as `COUCH_ATTACHMENTS`

@@ -295,2 +297,3 @@ ## Using programmatically

retrieving IAM tokens.
* `attachments`: _EXPERIMENTAL & UNSUPPORTED_ (see [Note](#note-on-attachments)), see `CLOUDANT_ATTACHMENTS`.

@@ -359,2 +362,3 @@ When the backup completes or fails the callback functions gets called with

retrieving IAM tokens.
* `attachments`: _EXPERIMENTAL & UNSUPPORTED_ (see [Note](#note-on-attachments)), see `CLOUDANT_ATTACHMENTS`.

@@ -444,8 +448,20 @@ When the restore completes or fails the callback functions gets called with

* `13`: restore target database is not new and empty.
* `60`: `attachments` option used for backup, but wasn't used for restore.
* `61`: `attachments` option used for restore, but wasn't used for backup.
## Note on attachments
TLDR; If you backup a database that has attachments `couchbackup` cannot restore it.
TLDR; If you backup a database that has attachments without using the `attachments` option `couchbackup` can't restore it.
As documented above `couchbackup` does not support backing up or restoring databases containing documents with attachments.
The recommendation is to store attachments directly in an object store with a link in the JSON document instead of using the
native attachment API.
### With experimental `attachments` option
The `attachments` option is provided as-is and is not supported. This option is for Apache CouchDB only and is experimental. Do not use this option with IBM Cloudant backups.
### Without experimental `attachments` option
Backing up a database that includes documents with attachments appears to complete successfully. However, the attachment

@@ -455,4 +471,1 @@ content is not downloaded and the backup file contains attachment metadata. So attempts to

in the restored database.
The recommendation is to store attachments directly in an object store with a link in the JSON document instead of using the
native attachment API.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc