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

automerge

Package Overview
Dependencies
Maintainers
2
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

automerge - npm Package Compare versions

Comparing version 0.7.1 to 0.7.2

.travis.yml

25

CHANGELOG.md

@@ -11,3 +11,18 @@ # Changelog

## [0.7.2] — 2018-04-17
### Changed
- [#83]: Changed `_objectId` property on Automerge map objects to be non-enumerable ([@EthanRBrown], [@ept])
- [#84]: Changed `_conflicts`, `_state`, and `_actorId` to be non-enumerable properties ([@ept])
### Fixed
- [#77]: Fixed exception when a list element is inserted and updated in the same change callback
([@mmcgrana], [@ept])
- [#78]: Better error message when trying to use an unsupported datatype ([@ept])
## [0.7.1] — 2018-02-26
### Fixed
- [#69]: `Automerge.load` generates random actorId if none specified ([@saranrapjs])

@@ -95,3 +110,5 @@ - [#64]: `Automerge.applyChanges()` allows changes to be applied out-of-order ([@jimpick], [@ept])

[Unreleased]: https://github.com/automerge/automerge/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/automerge/automerge/compare/v0.7.2...HEAD
[0.7.2]: https://github.com/automerge/automerge/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/automerge/automerge/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/automerge/automerge/compare/v0.6.0...v0.7.0

@@ -106,2 +123,6 @@ [0.6.0]: https://github.com/automerge/automerge/compare/v0.5.0...v0.6.0

[#84]: https://github.com/automerge/automerge/pull/84
[#83]: https://github.com/automerge/automerge/pull/83
[#78]: https://github.com/automerge/automerge/issues/78
[#77]: https://github.com/automerge/automerge/pull/77
[#69]: https://github.com/automerge/automerge/pull/69

@@ -125,7 +146,9 @@ [#64]: https://github.com/automerge/automerge/pull/64

[@aslakhellesoy]: https://github.com/aslakhellesoy
[@EthanRBrown]: https://github.com/EthanRBrown
[@jeffpeterson]: https://github.com/jeffpeterson
[@jimpick]: https://github.com/jimpick
[@ept]: https://github.com/ept
[@mmcgrana]: https://github.com/mmcgrana
[@mmmm1998]: https://github.com/mmmm1998
[@pvh]: https://github.com/pvh
[@saranrapjs]: https://github.com/saranrapjs

@@ -0,0 +0,0 @@ Automerge internal data structures

@@ -0,0 +0,0 @@ module.exports = function(config) {

25

package.json
{
"name": "automerge",
"version": "0.7.1",
"version": "0.7.2",
"description": "Data structures for building collaborative applications",

@@ -14,20 +14,21 @@ "main": "src/automerge.js",

"dependencies": {
"immutable": "^3.8.1",
"immutable": "^3.8.2",
"transit-immutable-js": "^0.7.0",
"transit-js": "^0.8.846",
"uuid": "^3.1.0"
"transit-js": "^0.8.861",
"uuid": "^3.2.1"
},
"devDependencies": {
"browserify": "^14.4.0",
"browserify": "^14.5.0",
"jsverify": "^0.8.3",
"karma": "^1.7.0",
"karma-browserify": "^5.1.1",
"karma": "^1.7.1",
"karma-browserify": "^5.2.0",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.0.1",
"karma-firefox-launcher": "^1.1.0",
"karma-mocha": "^1.3.0",
"mocha": "^3.4.2",
"sinon": "^3.2.1",
"watchify": "^3.9.0",
"webpack": "^3.0.0"
"karma-sauce-launcher": "^1.2.0",
"mocha": "^3.5.3",
"sinon": "^3.3.0",
"watchify": "^3.11.0",
"webpack": "^3.11.0"
}
}

@@ -5,2 +5,5 @@ # Automerge

[![Build Status](https://travis-ci.org/automerge/automerge.svg?branch=master)](https://travis-ci.org/automerge/automerge)
[![Browser Test Status](https://saucelabs.com/buildstatus/automerge)](https://saucelabs.com/open_sauce/user/automerge)
Automerge is a library of data structures for building collaborative applications in JavaScript.

@@ -37,3 +40,3 @@

* If the state was concurrently changed on different devices, Automerge automatically merges the
* If the state was changed concurrently on different devices, Automerge automatically merges the
changes together cleanly, so that everybody ends up in the same state, and no changes are lost.

@@ -46,7 +49,9 @@

* **Network-agnostic**. Automerge is a pure data structure library that does not care what kind of
* **Network-agnostic**. Automerge is a pure data structure library that does not care about what kind of
network you use: client/server, peer-to-peer, Bluetooth, carrier pigeon, whatever, anything goes.
Bindings to particular networking technologies are handled by separate libraries. For example, see
[MPL](https://github.com/automerge/mpl) for an implementation that uses Automerge in a
peer-to-peer model using [WebRTC](https://webrtc.org/).
peer-to-peer model using [WebRTC](https://webrtc.org/), and
[Hypermerge](https://github.com/automerge/hypermerge) is a peer-to-peer networking layer that uses
[Hypercore](https://github.com/mafintosh/hypercore), part of the [Dat project](https://datproject.org/).
* **Immutable state**. An Automerge object is an immutable snapshot of the application state at one

@@ -68,3 +73,3 @@ point in time. Whenever you make a change, or merge in a change that came from the network, you

* **Fairly portable**. We're not yet making an effort to support old platforms, but we have tested
Automerge in Node.js, Chrome, Firefox, and [Electron](https://electron.atom.io/).
Automerge in Node.js, Chrome, Firefox, Safari, MS Edge, and [Electron](https://electron.atom.io/).

@@ -92,5 +97,9 @@

The following code samples give a quick overview of how to use Automerge.
For an example of a real-life application built upon Automerge, check out
[Trellis](https://github.com/automerge/trellis), a project management tool.
For examples of real-life applications built upon Automerge, check out:
* [Trellis](https://github.com/automerge/trellis), a project management tool
in the style of [Trello](https://trello.com/).
* [Pixelpusher](https://github.com/automerge/pixelpusher), a pixel art editor
([blog post](https://medium.com/@pvh/pixelpusher-real-time-peer-to-peer-collaboration-with-react-7c7bc8ecbf74)).
```js

@@ -352,7 +361,7 @@ // This is how you load Automerge in Node. In a browser, simply including the

})
val changes = Automerge.getChanges(currentDoc, newDoc)
let changes = Automerge.getChanges(currentDoc, newDoc)
network.broadcast(JSON.stringify(changes))
// On another node
val changes = JSON.parse(network.receive())
let changes = JSON.parse(network.receive())
newDoc = Automerge.applyChanges(currentDoc, changes)

@@ -359,0 +368,0 @@ ```

@@ -0,0 +0,0 @@ const { List, fromJS } = require('immutable')

@@ -60,4 +60,4 @@ const { Map, List, fromJS } = require('immutable')

if (typeof value === 'undefined') {
return deleteField(state, objectId, key)
if (!['object', 'boolean', 'number', 'string'].includes(typeof value)) {
throw new TypeError('Unsupported type of value: ' + (typeof value))
} else if (isObject(value)) {

@@ -64,0 +64,0 @@ const [newState, newId] = createNestedObjects(state, value)

@@ -0,0 +0,0 @@ const { Map, fromJS } = require('immutable')

@@ -0,0 +0,0 @@ const { Map, Set } = require('immutable')

@@ -11,3 +11,7 @@ const { Map, List, Set } = require('immutable')

if (edit.action === 'create') {
return opSet.setIn(['cache', edit.obj], Object.freeze({_objectId: edit.obj}))
const object = {}
Object.defineProperty(object, '_objectId', {value: edit.obj})
Object.defineProperty(object, '_conflicts', {value: Object.freeze({})})
Object.freeze(object)
return opSet.setIn(['cache', edit.obj], object)
}

@@ -17,3 +21,5 @@

const conflicts = Object.assign({}, oldObject._conflicts)
const object = Object.assign(Object.create({_conflicts: conflicts}), oldObject)
const object = Object.assign({}, oldObject)
Object.defineProperty(object, '_objectId', {value: oldObject._objectId})
Object.defineProperty(object, '_conflicts', {value: conflicts})

@@ -38,3 +44,4 @@ if (edit.action === 'set') {

Object.freeze(conflicts)
return opSet.setIn(['cache', edit.obj], Object.freeze(object))
if (edit.obj !== OpSet.ROOT_ID) Object.freeze(object)
return opSet.setIn(['cache', edit.obj], object)
}

@@ -45,3 +52,5 @@

const conflicts = Object.assign({}, oldObject._conflicts)
const object = Object.assign(Object.create({_conflicts: conflicts}), oldObject)
const object = Object.assign({}, oldObject)
Object.defineProperty(object, '_objectId', {value: oldObject._objectId})
Object.defineProperty(object, '_conflicts', {value: conflicts})
const value = opSet.getIn(['cache', ref.get('value')])

@@ -68,3 +77,4 @@ let changed = false

Object.freeze(conflicts)
opSet = opSet.setIn(['cache', ref.get('obj')], Object.freeze(object))
if (ref.get('obj') !== OpSet.ROOT_ID) Object.freeze(object)
opSet = opSet.setIn(['cache', ref.get('obj')], object)
}

@@ -196,5 +206,6 @@ return opSet

if (isRoot || objType === 'makeMap') {
const conflicts = OpSet.getObjectConflicts(opSet, objectId, this)
obj = Object.create({_conflicts: Object.freeze(conflicts.toJS())})
obj = {}
const conflicts = OpSet.getObjectConflicts(opSet, objectId, this).toJS()
Object.defineProperty(obj, '_objectId', {value: objectId})
Object.defineProperty(obj, '_conflicts', {value: Object.freeze(conflicts)})
for (let field of OpSet.getObjectFields(opSet, objectId)) {

@@ -214,3 +225,3 @@ obj[field] = OpSet.getObjectField(opSet, objectId, field, this)

Object.freeze(obj)
if (!isRoot) Object.freeze(obj)
if (this.cache) this.cache[objectId] = obj

@@ -228,4 +239,5 @@ return obj

function rootObject(state, rootObj) {
Object.assign(Object.getPrototypeOf(rootObj), {_state: state, _actorId: state.get('actorId')})
Object.freeze(Object.getPrototypeOf(rootObj))
Object.defineProperty(rootObj, '_state', {value: state})
Object.defineProperty(rootObj, '_actorId', {value: state.get('actorId')})
Object.freeze(rootObj)
return rootObj

@@ -241,6 +253,7 @@ }

function applyChanges(root, changes, incremental) {
let opSet = root._state.get('opSet'), diffs = [], diff
let opSet = root._state.get('opSet'), diffs = []
for (let change of changes) {
[opSet, diff] = OpSet.addChange(opSet, change)
let [newOpSet, diff] = OpSet.addChange(opSet, change)
diffs.push(...diff)
opSet = newOpSet
}

@@ -253,7 +266,9 @@

if (newRoot === root) {
newRoot = Object.assign(Object.create({_conflicts: root._conflicts}), root)
newRoot = Object.assign({}, root)
Object.defineProperty(newRoot, '_objectId', {value: root._objectId})
Object.defineProperty(newRoot, '_conflicts', {value: root._conflicts})
opSet = opSet.setIn(['cache', OpSet.ROOT_ID], newRoot)
}
} else {
[opSet, newRoot] = materialize(opSet)
;[opSet, newRoot] = materialize(opSet)
}

@@ -260,0 +275,0 @@ return rootObject(root._state.set('opSet', opSet), newRoot)

@@ -20,3 +20,3 @@ const { Map, List, Set } = require('immutable')

const conflicts = OpSet.getObjectConflicts(opSet, objectId, this)
obj = Map().set('_conflicts', conflicts)
obj = Map().set('_conflicts', conflicts).set('_objectId', objectId)

@@ -23,0 +23,0 @@ for (let field of OpSet.getObjectFields(opSet, objectId)) {

@@ -266,3 +266,5 @@ const { Map, List, Set } = require('immutable')

if (action === 'set' || action === 'del' || action === 'link') {
ops = ops.filter(prev => prev.get('obj') != objectId || prev.get('key') != key)
ops = ops.filter(prev =>
prev.get('obj') != objectId || prev.get('key') != key ||
(prev.get('action') !== 'set' && prev.get('action') !== 'del' && prev.get('action') !== 'link'))
}

@@ -399,7 +401,5 @@ ops = ops.push(op)

.toSet()
.add('_objectId')
}
function getObjectField(opSet, objectId, key, context) {
if (key === '_objectId') return objectId
if (!validFieldName(key)) return undefined

@@ -406,0 +406,0 @@ const ops = getFieldOps(opSet, objectId, key)

@@ -131,3 +131,3 @@ const { List, fromJS } = require('immutable')

has (target, key) {
return (key === '_type') || (key === '_state') || (key === '_actorId') || (key === '_conflicts') ||
return ['_type', '_state', '_actorId', '_objectId', '_conflicts'].includes(key) ||
OpSet.getObjectFields(target.context.state.get('opSet'), target.objectId).has(key)

@@ -134,0 +134,0 @@ },

@@ -0,0 +0,0 @@ const { Map } = require('immutable')

@@ -0,0 +0,0 @@ const { SkipList } = require('./skip_list')

@@ -0,0 +0,0 @@ const { Map, Set, fromJS } = require('immutable')

@@ -214,5 +214,5 @@ const assert = require('assert')

assert.deepEqual(nodes[1].getDoc('doc1'),
{_objectId: doc1._objectId, doc1: 'doc1', one: 'one', two: 'two'})
{doc1: 'doc1', one: 'one', two: 'two'})
assert.deepEqual(nodes[1].getDoc('doc1'),
{_objectId: doc1._objectId, doc1: 'doc1', one: 'one', two: 'two'})
{doc1: 'doc1', one: 'one', two: 'two'})
})

@@ -306,6 +306,6 @@

assert.deepEqual(nodes[1].getDoc('doc1'), {_objectId: doc1._objectId, list: ['hello']})
assert.deepEqual(nodes[2].getDoc('doc1'), {_objectId: doc1._objectId, list: ['hello']})
assert.deepEqual(nodes[3].getDoc('doc1'), {_objectId: doc1._objectId, list: ['hello']})
assert.deepEqual(nodes[1].getDoc('doc1'), {list: ['hello']})
assert.deepEqual(nodes[2].getDoc('doc1'), {list: ['hello']})
assert.deepEqual(nodes[3].getDoc('doc1'), {list: ['hello']})
})
})

@@ -0,0 +0,0 @@ const assert = require('assert')

@@ -0,0 +0,0 @@ const assert = require('assert')

const assert = require('assert')
const sinon = require('sinon')
const Immutable = require('immutable')
const Automerge = require('../src/Automerge')
const Automerge = require('../src/automerge')

@@ -6,0 +6,0 @@ describe('Automerge.initImmutable()', () => {

@@ -12,2 +12,3 @@ const assert = require('assert')

assert.strictEqual(doc._objectId, ROOT_ID)
assert.strictEqual('_objectId' in doc, true)
})

@@ -21,2 +22,3 @@ })

assert.strictEqual(Automerge.init('customActorId')._actorId, 'customActorId')
assert.strictEqual('_actorId' in doc, true)
})

@@ -50,10 +52,7 @@ })

Automerge.change(Automerge.init(), doc => {
assert.deepEqual(Object.keys(doc), ['_objectId'])
assert.deepEqual(Object.keys(doc), [])
doc.key1 = 'value1'
equalsOneOf(Object.keys(doc), ['_objectId', 'key1'], ['key1', '_objectId'])
assert.deepEqual(Object.keys(doc), ['key1'])
doc.key2 = 'value2'
equalsOneOf(Object.keys(doc),
['_objectId', 'key1', 'key2'], ['_objectId', 'key2', 'key1'],
['key1', '_objectId', 'key2'], ['key2', '_objectId', 'key1'],
['key1', 'key2', '_objectId'], ['key2', 'key1', '_objectId'])
equalsOneOf(Object.keys(doc), ['key1', 'key2'], ['key2', 'key1'])
})

@@ -64,23 +63,25 @@ })

Automerge.change(Automerge.init(), doc => {
assert.deepEqual(Object.getOwnPropertyNames(doc), ['_objectId'])
assert.deepEqual(Object.getOwnPropertyNames(doc), [])
doc.key1 = 'value1'
equalsOneOf(Object.getOwnPropertyNames(doc), ['_objectId', 'key1'], ['key1', '_objectId'])
assert.deepEqual(Object.getOwnPropertyNames(doc), ['key1'])
doc.key2 = 'value2'
equalsOneOf(Object.getOwnPropertyNames(doc),
['_objectId', 'key1', 'key2'], ['_objectId', 'key2', 'key1'],
['key1', '_objectId', 'key2'], ['key2', '_objectId', 'key1'],
['key1', 'key2', '_objectId'], ['key2', 'key1', '_objectId'])
equalsOneOf(Object.getOwnPropertyNames(doc), ['key1', 'key2'], ['key2', 'key1'])
})
})
it('should support bulk assignment with Object.assign()', () => {
Automerge.change(Automerge.init(), doc => {
Object.assign(doc, {key1: 'value1', key2: 'value2'})
assert.deepEqual(doc, {key1: 'value1', key2: 'value2'})
})
})
it('should support JSON.stringify()', () => {
Automerge.change(Automerge.init(), doc => {
assert.deepEqual(JSON.stringify(doc), '{"_objectId":"00000000-0000-0000-0000-000000000000"}')
assert.deepEqual(JSON.stringify(doc), '{}')
doc.key1 = 'value1'
equalsOneOf(JSON.stringify(doc),
'{"_objectId":"00000000-0000-0000-0000-000000000000","key1":"value1"}',
'{"key1":"value1","_objectId":"00000000-0000-0000-0000-000000000000"}')
assert.deepEqual(JSON.stringify(doc), '{"key1":"value1"}')
doc.key2 = 'value2'
assert.deepEqual(JSON.parse(JSON.stringify(doc)), {
_objectId: ROOT_ID, key1: 'value1', key2: 'value2'
key1: 'value1', key2: 'value2'
})

@@ -92,13 +93,13 @@ })

Automerge.change(Automerge.init(), doc => {
assert.deepEqual(doc._inspect, {_objectId: ROOT_ID})
assert.deepEqual(Automerge.inspect(doc), {_objectId: ROOT_ID})
assert.deepEqual(doc._inspect, {})
assert.deepEqual(Automerge.inspect(doc), {})
doc.key1 = 'value1'
assert.deepEqual(doc._inspect, {_objectId: ROOT_ID, key1: 'value1'})
assert.deepEqual(Automerge.inspect(doc), {_objectId: ROOT_ID, key1: 'value1'})
assert.deepEqual(doc._inspect, {key1: 'value1'})
assert.deepEqual(Automerge.inspect(doc), {key1: 'value1'})
doc.key2 = 'value2'
assert.deepEqual(doc._inspect, {
_objectId: ROOT_ID, key1: 'value1', key2: 'value2'
key1: 'value1', key2: 'value2'
})
assert.deepEqual(Automerge.inspect(doc), {
_objectId: ROOT_ID, key1: 'value1', key2: 'value2'
key1: 'value1', key2: 'value2'
})

@@ -172,3 +173,3 @@ })

assert.deepEqual(JSON.parse(JSON.stringify(doc)), {
_objectId: ROOT_ID, list: [1, 2, 3], empty: []
list: [1, 2, 3], empty: []
})

@@ -182,6 +183,6 @@ assert.deepEqual(JSON.stringify(doc.list), '[1,2,3]')

assert.deepEqual(doc._inspect, {
_objectId: ROOT_ID, list: [1, 2, 3], empty: []
list: [1, 2, 3], empty: []
})
assert.deepEqual(Automerge.inspect(doc), {
_objectId: ROOT_ID, list: [1, 2, 3], empty: []
list: [1, 2, 3], empty: []
})

@@ -188,0 +189,0 @@ })

@@ -0,0 +0,0 @@ const assert = require('assert')

@@ -14,3 +14,3 @@ const assert = require('assert')

it('should initially be an empty map', () => {
assert.deepEqual(s1, { _objectId: ROOT_ID })
assert.deepEqual(s1, {})
})

@@ -39,9 +39,7 @@

assert.deepEqual(doc, {
_objectId: ROOT_ID, first: 'one', second: 'two'
first: 'one', second: 'two'
})
})
assert.deepEqual(s1, {_objectId: ROOT_ID})
assert.deepEqual(s2, {
_objectId: ROOT_ID, first: 'one', second: 'two'
})
assert.deepEqual(s1, {})
assert.deepEqual(s2, {first: 'one', second: 'two'})
})

@@ -78,4 +76,4 @@

})
assert.deepEqual(s1, {_objectId: ROOT_ID})
assert.deepEqual(s2, {_objectId: ROOT_ID, counter: 3})
assert.deepEqual(s1, {})
assert.deepEqual(s2, {counter: 3})
})

@@ -114,5 +112,15 @@

})
assert.deepEqual(s1, {_objectId: ROOT_ID, one: 1})
assert.deepEqual(s2, {_objectId: ROOT_ID, two: 2})
assert.deepEqual(s1, {one: 1})
assert.deepEqual(s2, {two: 2})
})
it('should work with Object.assign merges', () => {
s1 = Automerge.change(s1, doc1 => {
doc1.stuff = {foo: 'bar', baz: 'blur'}
})
s1 = Automerge.change(s1, doc1 => {
doc1.stuff = Object.assign({}, doc1.stuff, {baz: 'updated!'})
})
assert.deepEqual(s1, {stuff: {foo: 'bar', baz: 'updated!'}})
})
})

@@ -126,3 +134,3 @@

assert.strictEqual(s1.zip, 'zap')
assert.deepEqual(s1, {_objectId: ROOT_ID, foo: 'bar', zip: 'zap'})
assert.deepEqual(s1, {foo: 'bar', zip: 'zap'})
})

@@ -136,3 +144,3 @@

assert.strictEqual(s1.answer, 42)
assert.deepEqual(s1, {_objectId: ROOT_ID, foo: 'bar', answer: 42})
assert.deepEqual(s1, {foo: 'bar', answer: 42})
})

@@ -145,3 +153,3 @@

assert.strictEqual(s1.something, null)
assert.deepEqual(s1, {_objectId: ROOT_ID, something: null})
assert.deepEqual(s1, {something: null})
})

@@ -168,2 +176,11 @@

})
it('should not allow assignment of unsupported datatypes', () => {
Automerge.change(s1, doc => {
assert.throws(() => { doc.foo = undefined }, /Unsupported type of value: undefined/)
assert.throws(() => { doc.foo = {prop: undefined} }, /Unsupported type of value: undefined/)
assert.throws(() => { doc.foo = () => {} }, /Unsupported type of value: function/)
assert.throws(() => { doc.foo = Symbol('foo') }, /Unsupported type of value: symbol/)
})
})
})

@@ -176,7 +193,2 @@

assert.notEqual(s1.nested._objectId, ROOT_ID)
assert.deepEqual(s1, {
_objectId: ROOT_ID,
nested: {_objectId: s1.nested._objectId}
})
assert.deepEqual(s1.nested, {_objectId: s1.nested._objectId})
})

@@ -192,7 +204,4 @@

})
assert.deepEqual(s1, {
_objectId: ROOT_ID,
nested: {_objectId: s1.nested._objectId, foo: 'bar', one: 1}
})
assert.deepEqual(s1.nested, {_objectId: s1.nested._objectId, foo: 'bar', one: 1})
assert.deepEqual(s1, {nested: {foo: 'bar', one: 1}})
assert.deepEqual(s1.nested, {foo: 'bar', one: 1})
assert.strictEqual(s1.nested.foo, 'bar')

@@ -208,7 +217,4 @@ assert.strictEqual(s1.nested['foo'], 'bar')

})
assert.deepEqual(s1, {
_objectId: ROOT_ID,
textStyle: {_objectId: s1.textStyle._objectId, bold: false, fontSize: 12}
})
assert.deepEqual(s1.textStyle, {_objectId: s1.textStyle._objectId, bold: false, fontSize: 12})
assert.deepEqual(s1, {textStyle: {bold: false, fontSize: 12}})
assert.deepEqual(s1.textStyle, {bold: false, fontSize: 12})
assert.strictEqual(s1.textStyle.bold, false)

@@ -226,5 +232,3 @@ assert.strictEqual(s1.textStyle.fontSize, 12)

assert.strictEqual(s1.textStyle.fontSize, 14)
assert.deepEqual(s1.textStyle, {
_objectId: s1.textStyle._objectId, typeface: 'Optima', bold: false, fontSize: 14
})
assert.deepEqual(s1.textStyle, {typeface: 'Optima', bold: false, fontSize: 14})
})

@@ -239,11 +243,3 @@

})
assert.deepEqual(s1, {
_objectId: ROOT_ID, a: {
_objectId: s1.a._objectId, b: {
_objectId: s1.a.b._objectId, c: {
_objectId: s1.a.b.c._objectId, d: {
_objectId: s1.a.b.c.d._objectId, e: {
_objectId: s1.a.b.c.d.e._objectId, f: {
_objectId: s1.a.b.c.d.e.f._objectId,
g: 'h', i: 'j'}}}}}}})
assert.deepEqual(s1, {a: { b: { c: { d: { e: { f: { g: 'h', i: 'j'}}}}}}})
assert.strictEqual(s1.a.b.c.d.e.f.g, 'h')

@@ -261,8 +257,8 @@ assert.strictEqual(s1.a.b.c.d.e.f.i, 'j')

assert.deepEqual(s1.myPet, {
_objectId: s1.myPet._objectId, species: 'dog', legs: 4, breed: 'dachshund'
species: 'dog', legs: 4, breed: 'dachshund'
})
assert.strictEqual(s1.myPet.breed, 'dachshund')
assert.deepEqual(s2.myPet, {
_objectId: s2.myPet._objectId, species: 'koi', variety: '紅白',
colors: {_objectId: s2.myPet.colors._objectId, red: true, white: true, black: false}
species: 'koi', variety: '紅白',
colors: {red: true, white: true, black: false}
})

@@ -277,3 +273,3 @@ assert.strictEqual(s2.myPet.breed, undefined)

s1 = Automerge.change(s1, doc => doc.color = {red: 255, green: 127, blue: 0})
assert.deepEqual(s1.color, {_objectId: s1.color._objectId, red: 255, green: 127, blue: 0})
assert.deepEqual(s1.color, {red: 255, green: 127, blue: 0})
s1 = Automerge.change(s1, doc => doc.color = '#ff7f00')

@@ -300,3 +296,3 @@ assert.strictEqual(s1.color, '#ff7f00')

assert.strictEqual(s1.textStyle.bold, undefined)
assert.deepEqual(s1.textStyle, {_objectId: s1.textStyle._objectId, typeface: 'Optima', fontSize: 12})
assert.deepEqual(s1.textStyle, {typeface: 'Optima', fontSize: 12})
})

@@ -310,3 +306,3 @@

assert.strictEqual(s1.textStyle, undefined)
assert.deepEqual(s1, {_objectId: ROOT_ID, title: 'Hello'})
assert.deepEqual(s1, {title: 'Hello'})
})

@@ -328,3 +324,3 @@

s1 = Automerge.change(s1, doc => doc.noodles.insertAt(1, 'ramen'))
assert.deepEqual(s1, {_objectId: ROOT_ID, noodles: ['udon', 'ramen', 'soba']})
assert.deepEqual(s1, {noodles: ['udon', 'ramen', 'soba']})
assert.deepEqual(s1.noodles, ['udon', 'ramen', 'soba'])

@@ -339,3 +335,3 @@ assert.strictEqual(s1.noodles[0], 'udon')

s1 = Automerge.change(s1, doc => doc.noodles = ['udon', 'ramen', 'soba'])
assert.deepEqual(s1, {_objectId: ROOT_ID, noodles: ['udon', 'ramen', 'soba']})
assert.deepEqual(s1, {noodles: ['udon', 'ramen', 'soba']})
assert.deepEqual(s1.noodles, ['udon', 'ramen', 'soba'])

@@ -412,11 +408,11 @@ assert.strictEqual(s1.noodles[0], 'udon')

s1 = Automerge.change(s1, doc => doc.noodles[0].dishes.push('miso'))
assert.deepEqual(s1, {_objectId: ROOT_ID, noodles: [
{_objectId: s1.noodles[0]._objectId, type: 'ramen', dishes: ['tonkotsu', 'shoyu', 'miso']},
{_objectId: s1.noodles[1]._objectId, type: 'udon', dishes: ['tempura udon']}
assert.deepEqual(s1, {noodles: [
{type: 'ramen', dishes: ['tonkotsu', 'shoyu', 'miso']},
{type: 'udon', dishes: ['tempura udon']}
]})
assert.deepEqual(s1.noodles[0], {
_objectId: s1.noodles[0]._objectId, type: 'ramen', dishes: ['tonkotsu', 'shoyu', 'miso']
type: 'ramen', dishes: ['tonkotsu', 'shoyu', 'miso']
})
assert.deepEqual(s1.noodles[1], {
_objectId: s1.noodles[1]._objectId, type: 'udon', dishes: ['tempura udon']
type: 'udon', dishes: ['tempura udon']
})

@@ -439,3 +435,2 @@ })

assert.deepEqual(s1, {
_objectId: ROOT_ID,
noodles: ['wonton', 'pho'],

@@ -455,3 +450,3 @@ japaneseNoodles: ['udon', 'soba', 'ramen']

s1 = Automerge.change(s1, doc => doc.noodles[1] = {type: 'soba', options: ['hot', 'cold']})
assert.deepEqual(s1.noodles, ['udon', {_objectId: s1.noodles[1]._objectId, type: 'soba', options: ['hot', 'cold']}, 'ramen'])
assert.deepEqual(s1.noodles, ['udon', {type: 'soba', options: ['hot', 'cold']}, 'ramen'])
s1 = Automerge.change(s1, doc => doc.noodles[1] = ['hot soba', 'cold soba'])

@@ -463,2 +458,10 @@ assert.deepEqual(s1.noodles, ['udon', ['hot soba', 'cold soba'], 'ramen'])

it('should allow list creation and assignment in the same change callback', () => {
s1 = Automerge.change(Automerge.init(), doc => {
doc.letters = ['a', 'b', 'c']
doc.letters[1] = 'd'
})
assert.strictEqual(s1.letters[1], 'd')
})
it('should handle arbitrary-depth nesting', () => {

@@ -476,3 +479,2 @@ s1 = Automerge.change(s1, doc => doc.maze = [[[[[[[['noodles', ['here']]]]]]]]])

assert.deepEqual(s1, {
_objectId: ROOT_ID,
japaneseNoodles: ['udon', 'soba', 'ramen'],

@@ -503,3 +505,3 @@ theBestNoodles: ['udon', 'soba', 'ramen']

assert.strictEqual(s3.hello, 'world')
assert.deepEqual(s3, {_objectId: ROOT_ID, foo: 'bar', hello: 'world' })
assert.deepEqual(s3, {foo: 'bar', hello: 'world' })
assert.deepEqual(s3._conflicts, {})

@@ -513,6 +515,6 @@ })

if (s1._actorId > s2._actorId) {
assert.deepEqual(s3, {_objectId: ROOT_ID, field: 'one'})
assert.deepEqual(s3, {field: 'one'})
assert.deepEqual(s3._conflicts, {field: {[s2._actorId]: 'two'}})
} else {
assert.deepEqual(s3, {_objectId: ROOT_ID, field: 'two'})
assert.deepEqual(s3, {field: 'two'})
assert.deepEqual(s3._conflicts, {field: {[s1._actorId]: 'one'}})

@@ -542,8 +544,8 @@ }

s1 = Automerge.merge(Automerge.merge(s1, s2), s3)
equalsOneOf(s1.field, 'string', ['list'], {_objectId: s3.field._objectId, thing: 'map'})
equalsOneOf(s1.field, 'string', ['list'], {thing: 'map'})
if (s1.field === 'string') {
assert.deepEqual(s1._conflicts, {field: {[s2._actorId]: ['list'], [s3._actorId]: {_objectId: s3.field._objectId, thing: 'map'}}})
assert.deepEqual(s1._conflicts, {field: {[s2._actorId]: ['list'], [s3._actorId]: {thing: 'map'}}})
} else if (Automerge.equals(s1.field, ['list'])) {
assert.deepEqual(s1._conflicts, {field: {[s1._actorId]: 'string', [s3._actorId]: {_objectId: s3.field._objectId, thing: 'map'}}})
} else if (Automerge.equals(s1.field, {_objectId: s3.field._objectId, thing: 'map'})) {
assert.deepEqual(s1._conflicts, {field: {[s1._actorId]: 'string', [s3._actorId]: {thing: 'map'}}})
} else if (Automerge.equals(s1.field, {thing: 'map'})) {
assert.deepEqual(s1._conflicts, {field: {[s1._actorId]: 'string', [s2._actorId]: ['list']}})

@@ -560,5 +562,5 @@ } else {

s3 = Automerge.merge(s1, s2)
equalsOneOf(s3.field, 'string', {_objectId: s2.field._objectId, innerKey: 42})
equalsOneOf(s3.field, 'string', {innerKey: 42})
if (s3.field === 'string') {
assert.deepEqual(s3._conflicts, {field: {[s2._actorId]: {_objectId: s2.field._objectId, innerKey: 42}}})
assert.deepEqual(s3._conflicts, {field: {[s2._actorId]: {innerKey: 42}}})
} else {

@@ -578,7 +580,7 @@ assert.deepEqual(s3._conflicts, {field: {[s1._actorId]: 'string'}})

if (s1._actorId > s2._actorId) {
assert.deepEqual(s3.list, [{_objectId: s1.list[0]._objectId, map1: true, key: 1}])
assert.deepEqual(s3.list._conflicts, [{[s2._actorId]: {_objectId: s2.list[0]._objectId, map2: true, key: 2}}])
assert.deepEqual(s3.list, [{map1: true, key: 1}])
assert.deepEqual(s3.list._conflicts, [{[s2._actorId]: {map2: true, key: 2}}])
} else {
assert.deepEqual(s3.list, [{_objectId: s2.list[0]._objectId, map2: true, key: 2}])
assert.deepEqual(s3.list._conflicts, [{[s1._actorId]: {_objectId: s1.list[0]._objectId, map1: true, key: 1}}])
assert.deepEqual(s3.list, [{map2: true, key: 2}])
assert.deepEqual(s3.list._conflicts, [{[s1._actorId]: {map1: true, key: 1}}])
}

@@ -592,9 +594,9 @@ })

equalsOneOf(s3.config,
{_objectId: s1.config._objectId, background: 'blue'},
{_objectId: s2.config._objectId, logo_url: 'logo.png'}
{background: 'blue'},
{logo_url: 'logo.png'}
)
if (s3.config.background === 'blue') {
assert.deepEqual(s3._conflicts.config, {[s2._actorId]: {_objectId: s2.config._objectId, logo_url: 'logo.png'}})
assert.deepEqual(s3._conflicts.config, {[s2._actorId]: {logo_url: 'logo.png'}})
} else {
assert.deepEqual(s3._conflicts.config, {[s1._actorId]: {_objectId: s1.config._objectId, background: 'blue'}})
assert.deepEqual(s3._conflicts.config, {[s1._actorId]: {background: 'blue'}})
}

@@ -608,6 +610,6 @@ })

s3 = Automerge.change(s3, doc => doc.field = 'three')
assert.deepEqual(s3, {_objectId: ROOT_ID, field: 'three'})
assert.deepEqual(s3, {field: 'three'})
assert.deepEqual(s3._conflicts, {})
s2 = Automerge.merge(s2, s3)
assert.deepEqual(s2, {_objectId: ROOT_ID, field: 'three'})
assert.deepEqual(s2, {field: 'three'})
assert.deepEqual(s2._conflicts, {})

@@ -622,6 +624,3 @@ })

s3 = Automerge.merge(s1, s2)
assert.deepEqual(s3, {
_objectId: ROOT_ID,
list: ['one', 'two', 'three', 'four']
})
assert.deepEqual(s3, {list: ['one', 'two', 'three', 'four']})
assert.deepEqual(s3._conflicts, {})

@@ -648,5 +647,5 @@ })

s3 = Automerge.merge(s1, s2)
assert.deepEqual(s1, {_objectId: ROOT_ID})
assert.deepEqual(s2, {_objectId: ROOT_ID, bestBird: 'magpie'})
assert.deepEqual(s3, {_objectId: ROOT_ID, bestBird: 'magpie'})
assert.deepEqual(s1, {})
assert.deepEqual(s2, {bestBird: 'magpie'})
assert.deepEqual(s3, {bestBird: 'magpie'})
assert.deepEqual(s3._conflicts, {})

@@ -676,5 +675,3 @@ })

assert.deepEqual(s1.animals, {
_objectId: s1.animals._objectId,
birds: {
_objectId: s1.animals.birds._objectId,
pink: 'flamingo', brown: 'sparrow', black: 'starling'

@@ -684,4 +681,4 @@ },

})
assert.deepEqual(s2.animals, {_objectId: s1.animals._objectId, mammals: ['badger']})
assert.deepEqual(s3.animals, {_objectId: s1.animals._objectId, mammals: ['badger']})
assert.deepEqual(s2.animals, {mammals: ['badger']})
assert.deepEqual(s3.animals, {mammals: ['badger']})
})

@@ -743,3 +740,3 @@

let s = Automerge.load(Automerge.save(Automerge.init()))
assert.deepEqual(s, {_objectId: ROOT_ID})
assert.deepEqual(s, {})
})

@@ -763,5 +760,3 @@

let s2 = Automerge.load(Automerge.save(s1))
assert.deepEqual(s2, {_objectId: ROOT_ID, todos: [
{title: 'water plants', done: false, _objectId: s1.todos[0]._objectId}
]})
assert.deepEqual(s2, {todos: [{title: 'water plants', done: false}]})
})

@@ -800,9 +795,6 @@

assert.deepEqual(Automerge.getHistory(s).map(state => state.snapshot), [
{_objectId: ROOT_ID,
config: {_objectId: s.config._objectId, background: 'blue'}},
{_objectId: ROOT_ID,
config: {_objectId: s.config._objectId, background: 'blue'},
{config: {background: 'blue'}},
{config: {background: 'blue'},
birds: ['mallard']},
{_objectId: ROOT_ID,
config: {_objectId: s.config._objectId, background: 'blue'},
{config: {background: 'blue'},
birds: ['oystercatcher', 'mallard']}])

@@ -929,3 +921,3 @@ })

let s3 = Automerge.applyChanges(Automerge.init(), [changes[1]])
assert.deepEqual(s3, {_objectId: ROOT_ID})
assert.deepEqual(s3, {})
assert.deepEqual(Automerge.getMissingDeps(s3), {[s1._actorId]: 1})

@@ -932,0 +924,0 @@ s3 = Automerge.applyChanges(s3, [changes[0]])

@@ -0,0 +0,0 @@ const assert = require('assert')

@@ -0,0 +0,0 @@ const assert = require('assert')

@@ -0,0 +0,0 @@ var path = require('path');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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