@blinkmobile/json-as-files

convert between files and JSON strings, maintaining certain values as separate files

Stats

StarsIssuesVersionUpdatedCreatedSize
@blinkmobile/json-as-files
001.2.15 years ago6 years agoMinified + gzip package size for @blinkmobile/json-as-files in KB

Readme

json-as-files Travis CI Status npm AppVeyor Status

convert between files and JSON strings, maintaining certain values as separate files

Why?

We have a use case where we wish to serialise JSON data to files, but certain values within that JSON would be more convenient to keep separate. This project keeps all values in the same JSON file by default, but allows you to split certain values out into their own files.

For example, if you have Markdown content within a JSON structure, this project allows you to maintain it as a separate ".md" file. That way, your editor can help you with Markdown-specific highlighting, etc.

How?

Just replace a value in your JSON Object with a "$file" reference: { "$file": "foo.txt" }. Make sure you keep a "foo.txt" file with the desired contents.

During JSON file reads, we find these references, and replace them with the contents of the referenced file.

Usage

basic examples

const { readData, writeData } = require('@blinkmobile/json-as-files');

readData({ filePath: '/path/to/object.json' })
.then((object) => { /* ... */ });

writeData({ filePath: '/path/to/object.json', data: { /* ... */ } })
.then(() => { /* ... */ });

read example with "$file"

object.json:

{
  "title": "short and sweet",
  "content": { "$file": "content.txt"}
}

content.txt:

Too long / inconvenient to include in the primary JSON file.

JavaScript:

readData({ filePath: '/path/to/object.json' })
.then((data) => {
  console.assert(data.title === 'short and sweet');
  console.assert(data.content === 'Too long / inconvenient to include in the primary JSON file.');
});

write example with "$file"

object.json (already on disk):

{
  "title": "short and sweet",
  "content": { "$file": "content.txt"}
}

content.txt may or may not exist beforehand

JavaScript:

writeData({
  data: {
    title: 'new title',
    content: 'new content'
  },
  filePath: '/path/to/object.json'
})
.then(() => {
  // avoid ...Sync() methods in production, please!
  console.assert(fs.existsSync('/path/to/object.json'));
  console.assert(fs.existsSync('/path/to/content.txt'));

  return readData({ filePath: '/path/to/object.json' })
})
.then((data) => {
  console.assert(data.title === 'new title');
  console.assert(data.content === 'new content');
});

write example with "$file" template

object.json and content.txt may or may not exist beforehand

JavaScript:

writeData({
  data: {
    title: 'new title',
    content: 'new content'
  },
  filePath: '/path/to/object.json',
  template: {
    title: 'short and sweet',
    content: { $file: 'content.txt' }
  }
})
.then(() => {
  // avoid ...Sync() methods in production, please!
  console.assert(fs.existsSync('/path/to/object.json'));
  console.assert(fs.existsSync('/path/to/content.txt'));

  return readData({ filePath: '/path/to/object.json' })
})
.then((data) => {
  console.assert(data.title === 'new title');
  console.assert(data.content === 'new content');
});

API

findReferences()

findReferences (data: Object) => Promise[FoundReference[]]

Scan a data structure to locate references. Used internally.

FoundReference

interface FoundReference {
  path: String[], // property path to the reference within the parent structure
  target: String, // for "$file" references, this is a filename or path
  type: String, // only "$file" has been implemented so far
}

isFileInReferences()

isFileReference (refs: FoundReference[], dataPath: String, filePath: String)
  => Boolean

We scanned a data structure for references (see findReferences()). Is this file included in those references?

isFileReference()

isFileReference (value: Any) => Boolean

Does this value conform to our definition of a "file reference"?

readData()

readData (options: ReadOptions, callback?: Function)
  => Promise[Object|Array]

Read data from the provided filePath and other files relative to it.

ReadOptions

interface ReadOptions {
  filePath: String
}

writeData()

writeData (options: WriteOptions, callback?: Function)
  => Promise

Write data to the provided filePath and other files relative to it. Internal uses planWriteData() and writePlan().

Reads pre-existing destination file (if any) to preserve past references (if any). If "template" option is provided, then bypass this check.

WriteOptions

interface WriteOptions {
  filePath: String,
  data?: Any,
  template?: Any
}

planWriteData()

planWriteData (options: WriteOptions, callback?: Function)
  => Promise[PlannedWrite[]]

Like writeData(), but do not perform actual writes. Prepare a list of planned write operations instead.

PlannedWrite

interface PlannedWrite {
  targetPath: String,
  value: Any
}

writePlan()

writePlan (options: WritePlanOptions)
  => Promise

Execute a list of planned write operations, writing to target files. If plannedWrite.value is not already a String, then JSON.stringify() first.

WritePlanOptions

interface WritePlanOptions {
  plan: PlannedWrite[]
}

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.