# Sync JavaScript SDK 0.7 Release Notes

This document outlines the changes between the 0.6.2 and 0.7.0 versions of the twilio-sync.js library. Documentation for 0.7.0 release: [https://media.twiliocdn.com/sdk/js/sync/releases/0.7.0/docs](https://media.twiliocdn.com/sdk/js/sync/releases/0.7.0/docs)

**To include via CDN:**

```html
<script type="text/javascript" src="https://media.twiliocdn.com/sdk/js/sync/releases/0.7.0/twilio-sync.min.js"></script>
```

**Via NPM:**

```bash
npm install --save twilio-sync@0.7.0
```

## Non-functional changes

The documentation page for the SDK has been improved, including links to useful resources and code snippets for all methods and event handlers in the SDK.

New APIs

### 1. OpenOptions

The client.document(), client.list(), client.map(), client.stream() methods now take in an optional OpenOptions object, which allows for more granular control over how the SDK handles opening nonexistent objects. Refer to [documentation](https://media.twiliocdn.com/sdk/js/sync/releases/0.7.0/docs/Client.html#OpenOptions) for more details.

### 2. TTL

It is now possible to specify a TTL for Documents and List/Map Items on creation, update, and via a dedicated setTtl(ttlInSeconds) method.

## Breaking changes

1. **The conditional flag was removed** from the document.set(newValue, conditional) method.
2. **The document.get() method was removed.** Use document.value instead.
3. **"thingHappened" and "thingHappenedRemotely" events were merged** for all objects:
   * `thingHappenedRemotely` events were removed
   * `thingHappened` events now include a Boolean isLocal property for determining the locality of the event:
     * `isLocal == true`: the event was triggered by the current endpoint (i.e., the current SDK instance)
     * `isLocal == false`: the event was triggered by a different endpoint (i.e., a different SDK instance)

**SDK version 0.6**

```javascript
map.on('itemUpdatedRemotely', function(item) {
  console.log('Remote update:', item);
});
```

**SDK version 0.7**

```javascript
map.on('itemUpdated', function(args) {
  if (!args.isLocal) {
    let item = args.item;
    console.log('Remote update:', item);
  }
});
```

4. **The `collectionRemoved` event for Lists and Maps** was renamed to **`removed`** .

**SDK version 0.6**

```javascript
list.on('collectionRemoved', function(isLocal) {
  console.log('isLocal:', isLocal);
});

map.on('collectionRemoved', function(isLocal) {
  console.log('isLocal:', isLocal);
});
```

**SDK version 0.7**

```javascript
list.on('removed', function(args) {
  console.log('args.isLocal:', args.isLocal);
});

map.on('removed', function(args) {
  console.log('args.isLocal:', args.isLocal);
});
```

**5. Update squashing**

For Documents and List/Map Items, it is no longer guaranteed that *every* state update via set(), mutate(), update() is observable by subscribers. Convergence is guaranteed only to *latest* state.

Given the following example:

**SDK client 1**

```javascript
client.document('MyDoc')
  .then(doc => {
    let promise1 = doc.set({ state: 1 });
    let promise2 = doc.set({ state: 2 });
    let promise3 = doc.set({ state: 3 });
  });
```

**SDK client 2**

```javascript
client.document('MyDoc')
  .then(doc => {
    doc.on('updated', function(newState) {
    console.log('Document updated:', newState);
  });
});
```

Console output from **SDK client 2** :

**In SDK version 0.6**

```javascript
Document updated: { state: 1 }
Document updated: { state: 2 }
Document updated: { state: 3 }
```

**In SDK version 0.7**

```javascript
Document updated: { state: 1 }
Document updated: { state: 3 }
```

The underlying reason is that when the 0.6 SDK triggered a request to the Sync backend for every set() call, the 0.7 SDK *may* squash successive set() calls into one, and making a request to the Sync backend only with the latest state. This means that subscribers also receive an updated event *only for the latest state*.

With the example above, to ensure that subscribers receive *all* state updates in v0.7, the set/update/mutate method should be called after the previous one has completed:

```javascript
var doc; client.document("MyDoc")
  .then((document) => {
    doc = document;
    let promise1 = doc.set({ state: 1 });
    return promise1;
  })
  .then(() => {
    let promise2 = doc.set({ state: 2 });
    return promise2;
  })
  .then(() => {
    let promise3 = doc.set({ state: 3 });
    return promise3;
  });
```

## Bug fixes

1. Validate the requested page size to be correct on the client
2. Make object subscription cancellation handling more robust.
3. Enable abandoning requested data mutations gracefully, when the mutator function returns null.
