<commit_before># Buttercup core library

A NodeJS password vault.

[![Buttercup](https://buttercup.pw/buttercup.svg)](https://buttercup.pw) [![npm version](https://badge.fury.io/js/buttercup.svg)](https://badge.fury.io/js/buttercup) ![node min version](https://img.shields.io/badge/node-%3E%3D%204.4-lightgrey.svg) [![security](https://img.shields.io/badge/Security-As%20you%20wish-green.svg)](https://www.npmjs.com/package/buttercup) [![encryption](https://img.shields.io/badge/Encryption-AES%20256%20CBC-red.svg)](https://tools.ietf.org/html/rfc3602) [![Join the chat at https://gitter.im/buttercup-pw/buttercup-core](https://badges.gitter.im/buttercup-pw/buttercup-core.svg)](https://gitter.im/buttercup-pw/buttercup-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[![Build Status](https://travis-ci.org/buttercup-pw/buttercup-core.svg?branch=master)](https://travis-ci.org/buttercup-pw/buttercup-core) [![Code Climate](https://codeclimate.com/github/buttercup-pw/buttercup-core/badges/gpa.svg)](https://codeclimate.com/github/buttercup-pw/buttercup-core)

[![NPM](https://nodei.co/npm/buttercup.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/buttercup/)
[![NPM](https://nodei.co/npm-dl/buttercup.png?months=3)](https://nodei.co/npm/buttercup/)

**Please be aware** that breaking changes _will occur_ during 0.* (alpha) development. Until 1.0 is released, assume that every minor version contains breaking changes to encryption, structure and API.

## This library

This repository holds the core system functionality:

 - Archive reading/writing
 - Encryption/decryption
 - Low-level processing and manipulation
 - Archive format handling

## About

Buttercup manages credentials in an encrypted archive. The archive utilises a delta-based (history) archive description method to load and save data. This allows for more robust saving and loading whilst protecting against external file changes by allowing some degree of merging.

## Features

 - AES 256 bit CBC encryption (w/ HMAC-sha256)
 - Archive change delta tracking
 - WebDAV/ownCloud remote file support
 - Text compression with GZIP

## Usage

Buttercup can be easily used as a component, allowing for powerful and secure data storage within projects.

You can read the [API documentation here](doc/api.md), and the [change-log here](CHANGELOG.md). Please read our [contribution style guide](CONTRIBUTING.md) before making any issues or pull-requests.

### Creating, saving and loading

Create an archive and a data source: The datasource is where the archive will be written to.

```
var Buttercup = require("buttercup");

var archive = new Buttercup.Archive(),
    datasource = new Buttercup.FileDatasource("~/myArchive.bcup");

datasource.save(archive, "my secure password");
```

Using the same system, you can also load an archive:

```
var Buttercup = require("buttercup");

var datasource = new Buttercup.OwnCloudDatasource(
    "http://www.mycloud.com",
    "/personal/security/passwords.bcup",
    "inigo",
    "montoya1987"
);

// `load()` returns a promise
datasource.load("my archive password").then(function(archive) {
    // `archive` is the archive, loaded from remote. Saving on this datasource will
    // write back to the remote.
});
```

### Using a workspace

Workspaces are designed to help manage the necessary archive management tasks that come from creating a user-friendly password management application. Features like remote update merging need to be handled internally, and so the workspace helps manage such complex tasks.

In reality, the workspace is just a container:

```
var Buttercup = require("buttercup");

var workspace = new Buttercup.Workspace(),
    archive = new Buttercup.Archive(),
    datasource = new Buttercup.FileDatasource("~/myArchive.bcup");

datasource
    .load("password")
    .then(function(archive) {
        workspace
            .setArchive(archive)
            .setDatasource(datasource)
            .setPassword("<PASSWORD>");
    });
```

The workspace can handle some complex operations like merge conflicts - for instance, if a user has an archive open, and remotely the archive is modified, the workspace can help perform a merge between the two.

_A merge is quite basic, in that the remote commands (that differ) are run first, and then the local run next. All deletion commands that could cause conflicts are stripped, so the resulting merge will still contain items that were deleted in the differing portions before the merge._

```
// Check for differences
workspace.archiveDiffersFromDatasource()
    .then(function(differs) {
        if (differs) {
            // Merge differences first
            return workspace.mergeFromDatasource();
        }
    })
    .then(function() {
        // Save the archive
        workspace.save();
    });
```

Merging is especially helpful for situations where archives can be modified at any time, such as with cloud storage.

### Searching for things

You can search within archives for certain entries or groups:
```
archive
    .findEntriesByProperty("title", /^Home-[a-z]+$/i)
    .forEach(function(entry) {
        // Do something with entry
    });

archive
    .findGroupsByTitle("banking")
    .forEach(function(group) {});
```
<commit_msg>Workspace save doc<commit_after># Buttercup core library

A NodeJS password vault.

[![Buttercup](https://buttercup.pw/buttercup.svg)](https://buttercup.pw) [![npm version](https://badge.fury.io/js/buttercup.svg)](https://badge.fury.io/js/buttercup) ![node min version](https://img.shields.io/badge/node-%3E%3D%204.4-lightgrey.svg) [![security](https://img.shields.io/badge/Security-As%20you%20wish-green.svg)](https://www.npmjs.com/package/buttercup) [![encryption](https://img.shields.io/badge/Encryption-AES%20256%20CBC-red.svg)](https://tools.ietf.org/html/rfc3602) [![Join the chat at https://gitter.im/buttercup-pw/buttercup-core](https://badges.gitter.im/buttercup-pw/buttercup-core.svg)](https://gitter.im/buttercup-pw/buttercup-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[![Build Status](https://travis-ci.org/buttercup-pw/buttercup-core.svg?branch=master)](https://travis-ci.org/buttercup-pw/buttercup-core) [![Code Climate](https://codeclimate.com/github/buttercup-pw/buttercup-core/badges/gpa.svg)](https://codeclimate.com/github/buttercup-pw/buttercup-core)

[![NPM](https://nodei.co/npm/buttercup.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/buttercup/)
[![NPM](https://nodei.co/npm-dl/buttercup.png?months=3)](https://nodei.co/npm/buttercup/)

**Please be aware** that breaking changes _will occur_ during 0.* (alpha) development. Until 1.0 is released, assume that every minor version contains breaking changes to encryption, structure and API.

## This library

This repository holds the core system functionality:

 - Archive reading/writing
 - Encryption/decryption
 - Low-level processing and manipulation
 - Archive format handling

## About

Buttercup manages credentials in an encrypted archive. The archive utilises a delta-based (history) archive description method to load and save data. This allows for more robust saving and loading whilst protecting against external file changes by allowing some degree of merging.

## Features

 - AES 256 bit CBC encryption (w/ HMAC-sha256)
 - Archive change delta tracking
 - WebDAV/ownCloud remote file support
 - Text compression with GZIP

## Usage

Buttercup can be easily used as a component, allowing for powerful and secure data storage within projects.

You can read the [API documentation here](doc/api.md), and the [change-log here](CHANGELOG.md). Please read our [contribution style guide](CONTRIBUTING.md) before making any issues or pull-requests.

### Creating, saving and loading

Create an archive and a data source: The datasource is where the archive will be written to.

```
var Buttercup = require("buttercup");

var archive = new Buttercup.Archive(),
    datasource = new Buttercup.FileDatasource("~/myArchive.bcup");

datasource.save(archive, "my secure password");
```

Using the same system, you can also load an archive:

```
var Buttercup = require("buttercup");

var datasource = new Buttercup.OwnCloudDatasource(
    "http://www.mycloud.com",
    "/personal/security/passwords.bcup",
    "inigo",
    "montoya1987"
);

// `load()` returns a promise
datasource.load("my archive password").then(function(archive) {
    // `archive` is the archive, loaded from remote. Saving on this datasource will
    // write back to the remote.
});
```

### Using a workspace

Workspaces are designed to help manage the necessary archive management tasks that come from creating a user-friendly password management application. Features like remote update merging need to be handled internally, and so the workspace helps manage such complex tasks.

In reality, the workspace is just a container:

```
var Buttercup = require("buttercup");

var workspace = new Buttercup.Workspace(),
    archive = new Buttercup.Archive(),
    datasource = new Buttercup.FileDatasource("~/myArchive.bcup");

datasource
    .load("password")
    .then(function(archive) {
        workspace
            .setArchive(archive)
            .setDatasource(datasource)
            .setPassword("<PASSWORD>");
    });
```

The workspace can handle some complex operations like merge conflicts - for instance, if a user has an archive open, and remotely the archive is modified, the workspace can help perform a merge between the two.

_A merge is quite basic, in that the remote commands (that differ) are run first, and then the local run next. All deletion commands that could cause conflicts are stripped, so the resulting merge will still contain items that were deleted in the differing portions before the merge._

```
// Check for differences
workspace.archiveDiffersFromDatasource()
    .then(function(differs) {
        if (differs) {
            // Merge differences first
            return workspace.mergeFromDatasource();
        }
    })
    .then(function() {
        // Save the archive
        return workspace.save();
    });
```

Merging is especially helpful for situations where archives can be modified at any time, such as with cloud storage.

### Searching for things

You can search within archives for certain entries or groups:
```
archive
    .findEntriesByProperty("title", /^Home-[a-z]+$/i)
    .forEach(function(entry) {
        // Do something with entry
    });

archive
    .findGroupsByTitle("banking")
    .forEach(function(group) {});
```

{'fraction_non_alphanumeric': 0.11878191791185928, 'fraction_numerical': 0.006620011348590883, 'mean_word_length': 4.245535714285714, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 40, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5156580', 'n_tokens_mistral': 3220, 'n_tokens_neox': 3035, 'n_words': 945}