lib/actions/sync.js
async function sync ({ payload, meta = {} }, { dispatch }) {
  debug('Action: SYNC')
  const fromParams = await generateFromParams(payload, meta, dispatch)
  const toParams = generateToParams(payload, fromParams)

  const lastSyncedAt = new Date()

  const results = await Promise.all(
    fromParams.map(getFromService(dispatch, payload.type, meta))
  )

  if (results.some((result) => result.status !== 'ok')) {
    return (results.length === 1) ? results[0] : createError(makeErrorString(results))
  }

  const data = flatten(results.map((result) => result.data)).filter(Boolean)

  if (data.length === 0 && payload.syncNoData !== true) {
    return createError(`No items to update from service '${fromParams[0].service}'`, 'noaction')
  }

  return Promise.all([
    ...createSetMetas(fromParams, lastSyncedAt, meta.ident, dispatch),
    dispatch(action('SET', { data, ...toParams }, { ...meta, queue: true }))
  ])
    .then((responses) => {
      return { status: 'ok', data: responses }
    })
}
async function sync ({ payload, meta = {} }, { dispatch }) {
  debug('Action: SYNC')
  const fromParams = await generateFromParams(payload, meta, dispatch)
  const toParams = generateToParams(payload, fromParams)

  const lastSyncedAt = new Date()

  const results = await Promise.all(
    fromParams.map(getFromService(dispatch, payload.type, meta))
  )

  if (results.some((result) => result.status !== 'ok')) {
    return (results.length === 1) ? results[0] : createError(makeErrorString(results))
  }

  const data = flatten(results.map((result) => result.data)).filter(Boolean)

  if (data.length === 0 && payload.syncNoData !== true) {
    return createError(`No items to update from service '${fromParams[0].service}'`, 'noaction')
  }

  return Promise.all([
    ...createSetMetas(fromParams, lastSyncedAt, meta.ident, dispatch),
    dispatch(action('SET', { data, ...toParams }, { ...meta, queue: true }))
  ])
    .then((responses) => {
      return { status: 'ok', data: responses }
    })
}
Action to sync from one service to another.

`retrieve` indicates which items to retrieve. The default is `all`, which
will retrieve all items from the `get` endpoint. Set `retrieve` to `updated`
to retrieve only items that are updated after the  `lastSyncedAt` date for
the `from` service. This is done by passing the `lastSyncedAt` date as a
parameter named `updatedAfter` to the `get` endpoint, and by actively
filter away any items received with `updatedAt` earlier than `lastSyncedAt`.

The `lastSyncedAt` metadata will be set on the `from` service when items
are retrieved and updated.

@param {Object} payload - Action payload (from, to, type, and retrieve)
@param {Object} resources - Dispatch function
@returns {Promise} Promise of the action result