integreat 0.7.33 → 0.7.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,66 +4,124 @@ const pLimit = require('p-limit')
4
4
  const action = require('../utils/createAction')
5
5
  const createError = require('../utils/createError')
6
6
 
7
- const createTransformAction = ({ action: type, ...payload }, data, { ident, project }) =>
8
- action(type, { ...payload, data }, { ident, project })
9
-
10
- const makeErrorString = (results) => results
11
- .map((result, index) => (result.status === 'ok') ? null : `[${index}]: ${result.error}`)
12
- .filter(Boolean)
13
- .join('\n')
7
+ const createTransformAction = (
8
+ { action: type, ...payload },
9
+ data,
10
+ { ident, project }
11
+ ) => action(type, { ...payload, data }, { ident, project })
12
+
13
+ const makeErrorString = (results) =>
14
+ results
15
+ .map((result, index) =>
16
+ result.status === 'ok' ? null : `[${index}]: ${result.error}`
17
+ )
18
+ .filter(Boolean)
19
+ .join('\n')
14
20
 
15
21
  const addDeltaToDate = (date, delta) =>
16
22
  delta ? new Date(date.getTime() + delta) : date
17
23
 
18
24
  const generateUpdatedAfter = (updatedAfter, afterDelta) => ({
19
25
  updatedAfter: addDeltaToDate(updatedAfter, afterDelta),
20
- updatedSince: addDeltaToDate(updatedAfter, 1)
26
+ updatedSince: addDeltaToDate(updatedAfter, 1),
21
27
  })
22
28
 
23
- const setUpdatedParams = (dispatch, dontSetUntil, afterDelta, untilDelta, metaKey, ident) => async (params) => {
24
- const { status, data, error } = await dispatch(
25
- action('GET_META', { service: params.service, metaKey, keys: 'lastSyncedAt' }, { ident })
26
- )
29
+ const setUpdatedParams =
30
+ (dispatch, dontSetUntil, afterDelta, untilDelta, metaKey, ident) =>
31
+ async (params) => {
32
+ const { status, data, error } = await dispatch(
33
+ action(
34
+ 'GET_META',
35
+ { service: params.service, metaKey, keys: 'lastSyncedAt' },
36
+ { ident }
37
+ )
38
+ )
27
39
 
28
- if (status === 'ok' && data && data.meta && data.meta.lastSyncedAt) {
29
- return {
30
- ...params,
31
- ...generateUpdatedAfter(data.meta.lastSyncedAt, afterDelta),
32
- updatedUntil: dontSetUntil ? undefined : addDeltaToDate(new Date(), untilDelta)
40
+ if (status === 'ok' && data && data.meta && data.meta.lastSyncedAt) {
41
+ return {
42
+ ...params,
43
+ ...generateUpdatedAfter(data.meta.lastSyncedAt, afterDelta),
44
+ updatedUntil: dontSetUntil
45
+ ? undefined
46
+ : addDeltaToDate(new Date(), untilDelta),
47
+ }
48
+ } else {
49
+ debug(
50
+ 'SYNC: Could not get meta for service %s. Error: %s %s',
51
+ params.service,
52
+ status,
53
+ error
54
+ )
33
55
  }
34
- } else {
35
- debug('SYNC: Could not get meta for service %s. Error: %s %s', params.service, status, error)
56
+ return params
36
57
  }
37
- return params
38
- }
39
58
 
40
- const generateParamsWithUpdatedDates = async (params, dispatch, ident, updatedAfter, updatedUntil, afterDelta, untilDelta, metaKey) => {
59
+ const generateParamsWithUpdatedDates = async (
60
+ params,
61
+ dispatch,
62
+ ident,
63
+ updatedAfter,
64
+ updatedUntil,
65
+ afterDelta,
66
+ untilDelta,
67
+ metaKey
68
+ ) => {
41
69
  if (updatedAfter) {
42
70
  return params.map((params) => ({
43
71
  ...params,
44
72
  ...generateUpdatedAfter(new Date(updatedAfter), afterDelta),
45
- updatedUntil: updatedUntil === 'open'
46
- ? undefined
47
- : addDeltaToDate(updatedUntil ? new Date(updatedUntil) : new Date(), untilDelta)
73
+ updatedUntil:
74
+ updatedUntil === 'open'
75
+ ? undefined
76
+ : addDeltaToDate(
77
+ updatedUntil ? new Date(updatedUntil) : new Date(),
78
+ untilDelta
79
+ ),
48
80
  }))
49
81
  } else {
50
82
  return Promise.all(
51
- params.map(setUpdatedParams(dispatch, updatedUntil === 'open', afterDelta, untilDelta, metaKey, ident))
83
+ params.map(
84
+ setUpdatedParams(
85
+ dispatch,
86
+ updatedUntil === 'open',
87
+ afterDelta,
88
+ untilDelta,
89
+ metaKey,
90
+ ident
91
+ )
92
+ )
52
93
  )
53
94
  }
54
95
  }
55
96
 
56
97
  const paramsFromStringOrObject = (params) =>
57
- (typeof params === 'string') ? { service: params } : params
98
+ typeof params === 'string' ? { service: params } : params
58
99
 
59
100
  const generateFromParams = async (
60
- { retrieve, from, updatedAfter, updatedUntil, afterDelta, untilDelta, metaKey },
101
+ {
102
+ retrieve,
103
+ from,
104
+ updatedAfter,
105
+ updatedUntil,
106
+ afterDelta,
107
+ untilDelta,
108
+ metaKey,
109
+ },
61
110
  { ident },
62
111
  dispatch
63
112
  ) => {
64
113
  const fromParams = [].concat(from).map(paramsFromStringOrObject)
65
114
  if (retrieve === 'updated') {
66
- return generateParamsWithUpdatedDates(fromParams, dispatch, ident, updatedAfter, updatedUntil, afterDelta, untilDelta, metaKey)
115
+ return generateParamsWithUpdatedDates(
116
+ fromParams,
117
+ dispatch,
118
+ ident,
119
+ updatedAfter,
120
+ updatedUntil,
121
+ afterDelta,
122
+ untilDelta,
123
+ metaKey
124
+ )
67
125
  } else {
68
126
  return fromParams
69
127
  }
@@ -89,15 +147,15 @@ const generateTransformParams = ({ transform }, { service, type }) => {
89
147
  const generateToParams = ({ to, type }, fromParams) => {
90
148
  const { updatedAfter, updatedUntil } = fromParams[0]
91
149
  return {
92
- ...((typeof to === 'string') ? { service: to } : to),
150
+ ...(typeof to === 'string' ? { service: to } : to),
93
151
  type,
94
152
  updatedAfter,
95
- updatedUntil
153
+ updatedUntil,
96
154
  }
97
155
  }
98
156
 
99
157
  const filterDataOnUpdatedDates = (data, updatedAfter, updatedUntil) =>
100
- (Array.isArray(data) && data.length > 0 && (updatedAfter || updatedUntil))
158
+ Array.isArray(data) && data.length > 0 && (updatedAfter || updatedUntil)
101
159
  ? data.filter(isWithinUpdateWindow(updatedAfter, updatedUntil))
102
160
  : data
103
161
 
@@ -106,66 +164,124 @@ const isWithinUpdateWindow = (updatedAfter, updatedUntil) => (item) =>
106
164
  (!updatedAfter || item.attributes.updatedAt > updatedAfter) &&
107
165
  (!updatedUntil || item.attributes.updatedAt <= updatedUntil)
108
166
 
109
- const getFromService = (dispatch, type, noFilter = false, { project, ident }) =>
167
+ const getFromService =
168
+ (dispatch, type, noFilter = false, { project, ident }) =>
110
169
  async ({ action: fromAction = 'GET', ...fromParams }) => {
111
- const response = await dispatch(action(fromAction, { type, ...fromParams }, { project, ident }))
170
+ const response = await dispatch(
171
+ action(fromAction, { type, ...fromParams }, { project, ident })
172
+ )
112
173
  if (response.status !== 'ok') {
113
- return createError(`Could not get items from service '${fromParams.service}'. Reason: ${response.status} ${response.error}`)
174
+ return createError(
175
+ `Could not get items from service '${fromParams.service}'. Reason: ${response.status} ${response.error}`
176
+ )
114
177
  }
115
178
 
116
179
  return {
117
180
  status: 'ok',
118
- data: noFilter ? response.data : filterDataOnUpdatedDates(response.data, fromParams.updatedAfter, fromParams.updatedUntil)
181
+ data: noFilter
182
+ ? response.data
183
+ : filterDataOnUpdatedDates(
184
+ response.data,
185
+ fromParams.updatedAfter,
186
+ fromParams.updatedUntil
187
+ ),
119
188
  }
120
189
  }
121
190
 
122
- function isConfiguredWithMeta (serviceId, getService) {
191
+ function isConfiguredWithMeta(serviceId, getService) {
123
192
  const service = getService(null, serviceId)
124
193
  return !!(service && service.meta)
125
194
  }
126
195
 
127
- const createSetMetas = (fromParams, lastSyncedAt, metaKey, ident, dispatch, getService) => fromParams
128
- .reduce((services, params) =>
129
- (
130
- params.service &&
131
- !services.includes(params.service) &&
132
- isConfiguredWithMeta(params.service, getService)
196
+ const createSetMetas = (
197
+ fromParams,
198
+ lastSyncedAt,
199
+ metaKey,
200
+ ident,
201
+ dispatch,
202
+ getService
203
+ ) =>
204
+ fromParams
205
+ .reduce(
206
+ (services, params) =>
207
+ params.service &&
208
+ !services.includes(params.service) &&
209
+ isConfiguredWithMeta(params.service, getService)
210
+ ? [...services, params.service]
211
+ : services,
212
+ []
213
+ )
214
+ .map((service) =>
215
+ dispatch(
216
+ action(
217
+ 'SET_META',
218
+ { service, metaKey, meta: { lastSyncedAt } },
219
+ { ident }
220
+ )
221
+ )
133
222
  )
134
- ? [...services, params.service] : services,
135
- [])
136
- .map((service) =>
137
- dispatch(action('SET_META', { service, metaKey, meta: { lastSyncedAt } }, { ident })))
138
223
 
139
224
  const createSetActions = (toAction, data, toParams, meta, useIndividualSet) =>
140
225
  useIndividualSet
141
- ? data.map(item => action(toAction, { data: item, ...toParams }, meta))
226
+ ? data.map((item) => action(toAction, { data: item, ...toParams }, meta))
142
227
  : [action(toAction, { data, ...toParams }, meta)]
143
228
 
144
- const createDoneAction = (data, { action: type = 'SET', ...params }, { ident, project }) => ({
229
+ const createDoneAction = (
230
+ data,
231
+ { action: type = 'SET', ...params },
232
+ { ident, project }
233
+ ) => ({
145
234
  type,
146
235
  payload: { ...params, data },
147
- meta: { ident, project }
236
+ meta: { ident, project },
148
237
  })
149
238
 
150
239
  const isError = (response) =>
151
240
  !['ok', 'queued', 'noaction'].includes(response.status)
152
241
 
153
- const getLastSyncedAt = (fromParams, data, setLastSyncedAtFromData = false) =>
154
- setLastSyncedAtFromData
155
- ? data.map(item => item.attributes.updatedAt).reduce((latest, date) => latest > date ? latest : date)
156
- : (fromParams[0] && fromParams[0].updatedUntil) // TODO: Pick the latest date, not just the first
157
-
158
- async function transformData (data, dispatch, transformParams, meta, useIndividualTransform) {
242
+ function getLastSyncedAt(
243
+ fromParams,
244
+ data,
245
+ setLastSyncedAtFromData = false,
246
+ untilDelta = 0
247
+ ) {
248
+ if (setLastSyncedAtFromData) {
249
+ return data
250
+ .map((item) => item.attributes.updatedAt)
251
+ .reduce((latest, date) => (latest > date ? latest : date))
252
+ } else if (fromParams[0]) {
253
+ const lastSyncedAt = fromParams
254
+ .map((param) => param.updatedUntil)
255
+ .sort((a, b) =>
256
+ a instanceof Date && b instanceof Date ? a.getTime() - b.getTime() : 0
257
+ )[0]
258
+ return addDeltaToDate(lastSyncedAt, untilDelta * -1) // Subtract delta to get the actual updatedUntil date
259
+ }
260
+ return undefined
261
+ }
262
+ async function transformData(
263
+ data,
264
+ dispatch,
265
+ transformParams,
266
+ meta,
267
+ useIndividualTransform
268
+ ) {
159
269
  if (useIndividualTransform) {
160
270
  const responses = await Promise.all(
161
271
  data
162
- .map(item => dispatch(createTransformAction(transformParams, item, meta)))
163
- .map(p => pLimit(1)(() => p))
272
+ .map((item) =>
273
+ dispatch(createTransformAction(transformParams, item, meta))
274
+ )
275
+ .map((p) => pLimit(1)(() => p))
276
+ )
277
+ return responses.flatMap((response, index) =>
278
+ response.status === 'ok' ? response.data : data[index]
164
279
  )
165
- return responses.flatMap((response, index) => response.status === 'ok' ? response.data : data[index])
166
280
  } else {
167
- const transformResponse = await dispatch(createTransformAction(transformParams, data, meta))
168
- return (transformResponse.status === 'ok') ? transformResponse.data : data
281
+ const transformResponse = await dispatch(
282
+ createTransformAction(transformParams, data, meta)
283
+ )
284
+ return transformResponse.status === 'ok' ? transformResponse.data : data
169
285
  }
170
286
  }
171
287
 
@@ -186,36 +302,61 @@ async function transformData (data, dispatch, transformParams, meta, useIndividu
186
302
  * @param {Object} resources - Dispatch function
187
303
  * @returns {Promise} Promise of the action result
188
304
  */
189
- async function sync ({ payload, meta = {} }, { dispatch, getService }) {
305
+ async function sync({ payload, meta = {} }, { dispatch, getService }) {
190
306
  debug('Action: SYNC')
191
307
  const fromParams = await generateFromParams(payload, meta, dispatch)
192
- const { action: toAction = 'SET', ...toParams } = generateToParams(payload, fromParams)
308
+ const { action: toAction = 'SET', ...toParams } = generateToParams(
309
+ payload,
310
+ fromParams
311
+ )
193
312
  const transformParams = generateTransformParams(payload, toParams)
194
313
  const { queueSet = true, metaKey, useIndividualSet = false } = payload
195
314
  const doneParams = generateDoneParams(payload)
196
315
 
197
316
  const results = await Promise.all(
198
- fromParams.map(getFromService(dispatch, payload.type, payload.noFilter, meta))
317
+ fromParams.map(
318
+ getFromService(dispatch, payload.type, payload.noFilter, meta)
319
+ )
199
320
  )
200
321
 
201
322
  if (results.some((result) => result.status !== 'ok')) {
202
- return (results.length === 1) ? results[0] : createError(makeErrorString(results))
323
+ return results.length === 1
324
+ ? results[0]
325
+ : createError(makeErrorString(results))
203
326
  }
204
327
 
205
328
  let data = flatten(results.map((result) => result.data)).filter(Boolean)
206
329
 
207
330
  if (data.length === 0 && payload.syncNoData !== true) {
208
- return createError(`No items to update from service '${fromParams[0].service}'`, 'noaction')
331
+ return createError(
332
+ `No items to update from service '${fromParams[0].service}'`,
333
+ 'noaction'
334
+ )
209
335
  }
210
336
 
211
- const lastSyncedAt = getLastSyncedAt(fromParams, data, payload.setLastSyncedAtFromData) || new Date()
337
+ const lastSyncedAt =
338
+ getLastSyncedAt(
339
+ fromParams,
340
+ data,
341
+ payload.setLastSyncedAtFromData,
342
+ payload.untilDelta
343
+ ) || new Date()
212
344
 
213
345
  // Dispatch transform action
214
346
  if (transformParams) {
215
- data = await transformData(data, dispatch, transformParams, meta, payload.useIndividualTransform)
347
+ data = await transformData(
348
+ data,
349
+ dispatch,
350
+ transformParams,
351
+ meta,
352
+ payload.useIndividualTransform
353
+ )
216
354
 
217
355
  if (data.length === 0 && payload.syncNoData !== true) {
218
- return createError(`No items to update from service '${fromParams[0].service}' after transform action`, 'noaction')
356
+ return createError(
357
+ `No items to update from service '${fromParams[0].service}' after transform action`,
358
+ 'noaction'
359
+ )
219
360
  }
220
361
  }
221
362
 
@@ -236,10 +377,11 @@ async function sync ({ payload, meta = {} }, { dispatch, getService }) {
236
377
  )
237
378
 
238
379
  // Dispatch set actions
239
- const responses = await Promise.all([
240
- ...setMetaActions,
241
- ...setActions.map(dispatch)
242
- ].map(p => pLimit(1)(() => p)))
380
+ const responses = await Promise.all(
381
+ [...setMetaActions, ...setActions.map(dispatch)].map((p) =>
382
+ pLimit(1)(() => p)
383
+ )
384
+ )
243
385
 
244
386
  // Get responses, excluding set meta actions
245
387
  const setResponses = responses.slice(setMetaActions.length)
@@ -258,7 +400,9 @@ async function sync ({ payload, meta = {} }, { dispatch, getService }) {
258
400
  return {
259
401
  status: errors.length ? 'error' : 'ok',
260
402
  data: setResponses,
261
- ...(errors.length ? { error: `${errors.length} of ${setResponses.length} actions failed` } : {})
403
+ ...(errors.length
404
+ ? { error: `${errors.length} of ${setResponses.length} actions failed` }
405
+ : {}),
262
406
  }
263
407
  }
264
408
 
@@ -12,7 +12,7 @@ const optionsAuth = {
12
12
  * @param {Object} options - An options object
13
13
  * @returns {Object} An authentication object
14
14
  */
15
- async authenticate (options) {
15
+ async authenticate(options) {
16
16
  return { status: 'granted', ...options }
17
17
  },
18
18
 
@@ -23,7 +23,7 @@ const optionsAuth = {
23
23
  * @param {Object} authentication - The object returned from `authenticate()`
24
24
  * @returns {boolean} `true` if already authenticated, otherwise `false`
25
25
  */
26
- isAuthenticated (authentication) {
26
+ isAuthenticated(authentication) {
27
27
  return !!(authentication && authentication.status === 'granted')
28
28
  },
29
29
 
@@ -35,8 +35,8 @@ const optionsAuth = {
35
35
  * @param {Object} authentication - The object returned from `authenticate()`
36
36
  * @returns {Object} Auth object
37
37
  */
38
- asObject ({ status, ...options }) {
39
- return (status === 'granted') ? options : {}
38
+ asObject({ status, ...options }) {
39
+ return status === 'granted' ? options : {}
40
40
  },
41
41
 
42
42
  /**
@@ -45,9 +45,9 @@ const optionsAuth = {
45
45
  * @param {Object} authentication - The object returned from `authenticate()`
46
46
  * @returns {Object} Headers object
47
47
  */
48
- asHttpHeaders (authentication) {
49
- return {}
50
- }
48
+ asHttpHeaders({ status, ...options }) {
49
+ return status === 'granted' ? options : {}
50
+ },
51
51
  }
52
52
 
53
53
  module.exports = optionsAuth
package/lib/dispatch.js CHANGED
@@ -1,7 +1,13 @@
1
1
  const debug = require('debug')('great')
2
+ const PProgress = require('p-progress')
2
3
  const setupGetService = require('./utils/getService')
3
4
 
4
- const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))
5
+ const compose = (...fns) =>
6
+ fns.reduce(
7
+ (f, g) =>
8
+ (...args) =>
9
+ f(g(...args))
10
+ )
5
11
 
6
12
  const handleAction = (action, resources, actionHandlers) => {
7
13
  if (action) {
@@ -13,7 +19,7 @@ const handleAction = (action, resources, actionHandlers) => {
13
19
  }
14
20
  }
15
21
 
16
- return { status: 'noaction' }
22
+ return PProgress.resolve({ status: 'noaction' })
17
23
  }
18
24
 
19
25
  /**
@@ -22,26 +28,44 @@ const handleAction = (action, resources, actionHandlers) => {
22
28
  * @param {Object} resources - Object with actions, schemas, services, and middlewares
23
29
  * @returns {function} Dispatch function, accepting an action as only argument
24
30
  */
25
- function setupDispatch ({ actions: actionHandlers = {}, schemas = {}, services = {}, middlewares = [], identOptions = {} }) {
31
+ function setupDispatch({
32
+ actions: actionHandlers = {},
33
+ schemas = {},
34
+ services = {},
35
+ middlewares = [],
36
+ identOptions = {},
37
+ }) {
26
38
  const getService = setupGetService(schemas, services)
39
+ const middlewareFn =
40
+ middlewares.length > 0
41
+ ? compose(...middlewares)
42
+ : (next) => async (action) => next(action)
27
43
 
28
- let dispatch = async (action) => {
29
- debug('Dispatch: %o', action)
30
- return handleAction(
31
- action,
32
- {
33
- schemas,
34
- services,
35
- dispatch,
36
- identOptions,
37
- getService
38
- },
39
- actionHandlers
40
- )
41
- }
44
+ const dispatch = (action) => {
45
+ return new PProgress(async (resolve, reject, setProgress) => {
46
+ debug('Dispatch: %o', action)
42
47
 
43
- if (middlewares.length > 0) {
44
- dispatch = compose(...middlewares)(dispatch)
48
+ try {
49
+ resolve(
50
+ middlewareFn((action) =>
51
+ handleAction(
52
+ action,
53
+ {
54
+ schemas,
55
+ services,
56
+ dispatch,
57
+ identOptions,
58
+ getService,
59
+ setProgress,
60
+ },
61
+ actionHandlers
62
+ )
63
+ )(action)
64
+ )
65
+ } catch (err) {
66
+ reject(err)
67
+ }
68
+ })
45
69
  }
46
70
 
47
71
  return dispatch
package/lib/integreat.js CHANGED
@@ -5,7 +5,7 @@ const setupMapping = require('./mapping')
5
5
  const setupDispatch = require('./dispatch')
6
6
  const builtinActions = require('./actions')
7
7
 
8
- const version = '0.7.33'
8
+ const version = '0.7.37'
9
9
 
10
10
  /**
11
11
  * Return an Integreat instance with a dispatch method.
@@ -16,20 +16,20 @@ const version = '0.7.33'
16
16
  * @param {Array} middlewares - Array of middlewares
17
17
  * @returns {Object} Integration object with the dispatch method
18
18
  */
19
- function integreat (
19
+ function integreat(
20
20
  {
21
21
  schemas: typeDefs,
22
22
  services: serviceDefs,
23
23
  mappings = [],
24
24
  auths: authDefs = [],
25
- ident: identOptions = {}
25
+ ident: identOptions = {},
26
26
  },
27
27
  {
28
28
  adapters = {},
29
29
  authenticators = {},
30
30
  filters = {},
31
31
  transformers = {},
32
- actions = {}
32
+ actions = {},
33
33
  } = {},
34
34
  middlewares = []
35
35
  ) {
@@ -41,38 +41,46 @@ function integreat (
41
41
  actions = { ...builtinActions, ...actions }
42
42
 
43
43
  // Setup schemas object from type defs
44
- const schemas = R.compose(
45
- R.indexBy(R.prop('id')),
46
- R.map(schema)
47
- )(typeDefs)
44
+ const schemas = R.compose(R.indexBy(R.prop('id')), R.map(schema))(typeDefs)
48
45
 
49
- const pluralTypes = Object.keys(schemas)
50
- .reduce((plurals, type) => ({ ...plurals, [schemas[type].plural]: type }), {})
46
+ const pluralTypes = Object.keys(schemas).reduce(
47
+ (plurals, type) => ({ ...plurals, [schemas[type].plural]: type }),
48
+ {}
49
+ )
51
50
 
52
51
  // Setup auths object from auth defs
53
- const auths = authDefs
54
- .reduce((auths, def) => (def)
55
- ? {
56
- ...auths,
57
- [def.id]: {
58
- authenticator: authenticators[def && def.authenticator],
59
- options: def.options,
60
- authentication: null
61
- }
62
- }
63
- : auths,
64
- {})
52
+ const auths = authDefs.reduce(
53
+ (auths, def) =>
54
+ def
55
+ ? {
56
+ ...auths,
57
+ [def.id]: {
58
+ authenticator: authenticators[def && def.authenticator],
59
+ options: def.options,
60
+ authentication: null,
61
+ },
62
+ }
63
+ : auths,
64
+ {}
65
+ )
65
66
 
66
67
  // Setup services object from service defs.
67
68
  const services = R.compose(
68
69
  R.indexBy(R.prop('id')),
69
- R.map(createService({
70
- adapters,
71
- auths,
72
- transformers,
73
- schemas,
74
- setupMapping: setupMapping({ filters, transformers, schemas, mappings })
75
- }))
70
+ R.map(
71
+ createService({
72
+ adapters,
73
+ auths,
74
+ transformers,
75
+ schemas,
76
+ setupMapping: setupMapping({
77
+ filters,
78
+ transformers,
79
+ schemas,
80
+ mappings,
81
+ }),
82
+ })
83
+ )
76
84
  )(serviceDefs)
77
85
 
78
86
  // Return Integreat instance
@@ -93,14 +101,14 @@ function integreat (
93
101
  services,
94
102
  schemas,
95
103
  middlewares,
96
- identOptions
104
+ identOptions,
97
105
  }),
98
106
 
99
107
  /**
100
108
  * Adds the `listener` function to the service's emitter for events with the
101
109
  * given `eventName` name.
102
110
  */
103
- on (eventName, serviceId, listener) {
111
+ on(eventName, serviceId, listener) {
104
112
  const service = services[serviceId]
105
113
  if (service && service.on) {
106
114
  service.on(eventName, listener)
@@ -110,9 +118,9 @@ function integreat (
110
118
  /**
111
119
  * Return schema type from its plural form.
112
120
  */
113
- typeFromPlural (plural) {
121
+ typeFromPlural(plural) {
114
122
  return pluralTypes[plural]
115
- }
123
+ },
116
124
  }
117
125
  }
118
126
 
@@ -1,33 +1,60 @@
1
1
  const { compose, map, mergeDeepWith } = require('ramda')
2
- const { mapTransform, transform, filter, set, fwd, rev, functions } = require('map-transform')
2
+ const {
3
+ mapTransform,
4
+ transform,
5
+ filter,
6
+ set,
7
+ fwd,
8
+ rev,
9
+ functions,
10
+ } = require('map-transform')
3
11
  const is = require('@sindresorhus/is')
4
- const { preparePipeline, prepareRevPipeline } = require('../utils/preparePipeline')
5
- const { normalizeFieldMapping } = require('./normalize')
12
+ const {
13
+ preparePipeline,
14
+ prepareRevPipeline,
15
+ } = require('../utils/preparePipeline')
16
+ const { normalizeFieldMapping, pathToPipeline } = require('./normalize')
6
17
 
7
18
  const { compare } = functions
8
19
 
9
20
  const hasFieldMappings = (id, attributes, relationships) =>
10
- id || Object.keys(attributes).length > 0 || Object.keys(relationships).length > 0
21
+ id ||
22
+ Object.keys(attributes).length > 0 ||
23
+ Object.keys(relationships).length > 0
11
24
 
12
25
  const prepareRelationship = (normalize, createPipeline) => (relationship) =>
13
- (relationship.mapping) ? createPipeline(relationship.mapping, undefined, relationship.path).pipeline : normalize(relationship)
26
+ relationship.mapping
27
+ ? createPipeline(relationship.mapping, undefined, relationship.path)
28
+ .pipeline
29
+ : normalize(relationship)
14
30
 
15
- function prepareMapping ({ attributes: { id = null, type = null, ...attributes } = {}, relationships = {}, toService = {} }, transformers, createPipeline) {
31
+ function prepareMapping(
32
+ {
33
+ attributes: { id = null, type = null, ...attributes } = {},
34
+ relationships = {},
35
+ toService = {},
36
+ },
37
+ transformers,
38
+ createPipeline
39
+ ) {
16
40
  if (hasFieldMappings(id, attributes, relationships)) {
17
41
  const normalize = normalizeFieldMapping(transformers)
18
42
  return {
19
- id: (id) ? normalize(id) : null,
20
- type: (type) ? rev(type) : null,
43
+ id: id ? normalize(id) : null,
44
+ type: type ? rev(type) : null,
21
45
  attributes: map(normalize, attributes),
22
- relationships: map(prepareRelationship(normalize, createPipeline), relationships),
23
- ...map(normalize, toService)
46
+ relationships: map(
47
+ prepareRelationship(normalize, createPipeline),
48
+ relationships
49
+ ),
50
+ ...map(normalize, toService),
24
51
  }
25
52
  } else {
26
53
  return {
27
54
  id: 'id',
28
55
  type: rev('type'),
29
56
  attributes: 'attributes',
30
- relationships: 'relationships'
57
+ relationships: 'relationships',
31
58
  }
32
59
  }
33
60
  }
@@ -39,29 +66,38 @@ const createCompareFilter = ([path, value]) => {
39
66
  return []
40
67
  }
41
68
  }
42
- const prepareQualifier = (qualifier) => (qualifier) ? createCompareFilter(qualifier.split('=')) : []
69
+ const prepareQualifier = (qualifier) =>
70
+ qualifier ? createCompareFilter(qualifier.split('=')) : []
43
71
 
44
- const prepareTypeQualifier = ({ attributes = {}, relationships = {}, type }) => (is.emptyObject(attributes) && is.emptyObject(relationships))
45
- ? [filter(compare({ path: 'type', match: type }))]
46
- : []
72
+ const prepareTypeQualifier = ({ attributes = {}, relationships = {}, type }) =>
73
+ is.emptyObject(attributes) && is.emptyObject(relationships)
74
+ ? [filter(compare({ path: 'type', match: type }))]
75
+ : []
47
76
 
48
- const concatOrRight = (left, right) => (Array.isArray(left)) ? left.concat(right) : right
77
+ const concatOrRight = (left, right) =>
78
+ Array.isArray(left) ? left.concat(right) : right
49
79
 
50
- const ensureArray = (data) => (Array.isArray(data)) ? data : ((data) ? [data] : [])
80
+ const ensureArray = (data) => (Array.isArray(data) ? data : data ? [data] : [])
51
81
 
52
- const overrideMappingProps = (mapping, overrideType, prependPath) => (mapping)
53
- ? {
54
- ...mapping,
55
- type: overrideType || mapping.type,
56
- path: [prependPath, mapping.path].filter(Boolean).join('.')
57
- }
58
- : undefined
82
+ const joinPaths = (...paths) => paths.filter(Boolean).join('.')
83
+
84
+ const overrideMappingProps = (mapping, overrideType, prependPath) =>
85
+ mapping
86
+ ? {
87
+ ...mapping,
88
+ type: overrideType || mapping.type,
89
+ path: Array.isArray(prependPath)
90
+ ? prependPath.map((path) => joinPaths(path, mapping.path))
91
+ : joinPaths(prependPath, mapping.path),
92
+ }
93
+ : undefined
59
94
 
60
- const lookupMapping = (mapping, mappings) => (mappings[mapping]) ? { ...mappings[mapping], id: mapping } : null
95
+ const lookupMapping = (mapping, mappings) =>
96
+ mappings[mapping] ? { ...mappings[mapping], id: mapping } : null
61
97
 
62
98
  const expandMapping = (mapping, mappings, overrideType, prependPath) =>
63
99
  overrideMappingProps(
64
- (typeof mapping === 'string') ? lookupMapping(mapping, mappings) : mapping,
100
+ typeof mapping === 'string' ? lookupMapping(mapping, mappings) : mapping,
65
101
  overrideType,
66
102
  prependPath
67
103
  )
@@ -87,7 +123,7 @@ const createPipelines = (mapping, transformers, filters) => {
87
123
  transform: transformDef = null,
88
124
  transformTo: transformToDef = null,
89
125
  filterFrom = null,
90
- filterTo = null
126
+ filterTo = null,
91
127
  } = mapping
92
128
 
93
129
  const transformPipeline = preparePipeline(transformDef, transformers)
@@ -100,15 +136,19 @@ const createPipelines = (mapping, transformers, filters) => {
100
136
  transformers
101
137
  ).map(transformRev),
102
138
  filterFrom: preparePipeline(filterFrom, filters).map(filterFwd),
103
- filterTo: preparePipeline(filterTo, filters).map(filterRev)
139
+ filterTo: preparePipeline(filterTo, filters).map(filterRev),
104
140
  }
105
141
  }
106
142
 
107
- const concatPipeline = (mapping, schema, { createPipelineFn, transformers, filters }) => {
143
+ const concatPipeline = (
144
+ mapping,
145
+ schema,
146
+ { createPipelineFn, transformers, filters }
147
+ ) => {
108
148
  const pipelines = createPipelines(mapping, transformers, filters)
109
149
 
110
150
  return [
111
- mapping.path,
151
+ ...pathToPipeline(mapping.path),
112
152
  ...prepareQualifier(mapping.qualifier),
113
153
  ...prepareTypeQualifier(mapping),
114
154
  prepareMapping(mapping, transformers, createPipelineFn),
@@ -117,7 +157,7 @@ const concatPipeline = (mapping, schema, { createPipelineFn, transformers, filte
117
157
  ...pipelines.transformRev,
118
158
  ...pipelines.filterFrom,
119
159
  ...pipelines.filterTo,
120
- filter(item => typeof item !== 'undefined')
160
+ filter((item) => typeof item !== 'undefined'),
121
161
  ]
122
162
  }
123
163
 
@@ -133,7 +173,7 @@ const createPipeline = (filters, transformers, schemas, mappings) => {
133
173
  const pipeline = concatPipeline(mapping, schema, {
134
174
  createPipelineFn,
135
175
  transformers,
136
- filters
176
+ filters,
137
177
  })
138
178
 
139
179
  return { id, type, schema, pipeline }
@@ -147,29 +187,33 @@ const createPipeline = (filters, transformers, schemas, mappings) => {
147
187
  * @param {Object} resources - filters, transformers, and schemas
148
188
  * @returns {Object} Item mapping def
149
189
  */
150
- function mapping ({
190
+ function mapping({
151
191
  filters,
152
192
  transformers,
153
193
  schemas = {},
154
- mappings: mappingsArr = []
194
+ mappings: mappingsArr = [],
155
195
  } = {}) {
156
196
  const mappings = mappingsArr.reduce(
157
197
  (mappings, def) => ({ ...mappings, [def.id]: def }),
158
198
  {}
159
199
  )
160
- const createPipelineFn = createPipeline(filters, transformers, schemas, mappings)
200
+ const createPipelineFn = createPipeline(
201
+ filters,
202
+ transformers,
203
+ schemas,
204
+ mappings
205
+ )
161
206
 
162
207
  return (mapping, overrideType) => {
163
- const { id, type, schema, pipeline } = createPipelineFn(mapping, overrideType)
208
+ const { id, type, schema, pipeline } = createPipelineFn(
209
+ mapping,
210
+ overrideType
211
+ )
164
212
  if (!pipeline) {
165
213
  return null
166
214
  }
167
215
 
168
- const mapper = mapTransform([
169
- fwd('data'),
170
- ...pipeline,
171
- rev(set('data'))
172
- ])
216
+ const mapper = mapTransform([fwd('data'), ...pipeline, rev(set('data'))])
173
217
 
174
218
  return {
175
219
  id,
@@ -182,11 +226,11 @@ function mapping ({
182
226
  * @param {Object} options - onlyMappedValues
183
227
  * @returns {Object} Target item
184
228
  */
185
- fromService (data, { onlyMappedValues = true } = {}) {
229
+ fromService(data, { onlyMappedValues = true } = {}) {
186
230
  return data
187
231
  ? ensureArray(
188
- (onlyMappedValues) ? mapper.onlyMappedValues(data) : mapper(data)
189
- )
232
+ onlyMappedValues ? mapper.onlyMappedValues(data) : mapper(data)
233
+ )
190
234
  : []
191
235
  },
192
236
 
@@ -196,7 +240,7 @@ function mapping ({
196
240
  * @param {Object} target - Optional object to map to data on
197
241
  * @returns {Object} Mapped data
198
242
  */
199
- toService (data, target = null) {
243
+ toService(data, target = null) {
200
244
  const mapped = mapper.rev.onlyMappedValues(data)
201
245
  return (
202
246
  (target
@@ -205,7 +249,7 @@ function mapping ({
205
249
  : mergeDeepWith(concatOrRight, target, mapped)
206
250
  : mapped) || null
207
251
  )
208
- }
252
+ },
209
253
  }
210
254
  }
211
255
  }
@@ -1,45 +1,66 @@
1
1
  const { compose, map } = require('ramda')
2
2
  const is = require('@sindresorhus/is')
3
3
  const { transform, fwd, rev, value, fixed, set, alt } = require('map-transform')
4
- const { preparePipeline, prepareRevPipeline } = require('../utils/preparePipeline')
4
+ const {
5
+ preparePipeline,
6
+ prepareRevPipeline,
7
+ } = require('../utils/preparePipeline')
5
8
 
6
9
  const pathPipelineSetAlts = ([primary, ...alts]) => [
7
10
  primary,
8
- ...alts.map(compose(fwd, alt))
11
+ ...alts.map(compose(fwd, alt)),
9
12
  ]
10
13
 
11
- const pathToPipeline = (path) => is.array(path)
12
- ? pathPipelineSetAlts(path)
13
- : [path]
14
+ const pathToPipeline = (path) =>
15
+ is.array(path) ? pathPipelineSetAlts(path) : [path]
14
16
 
15
17
  const createSubMapping = (sub, transformers, switchTransforms) =>
16
- (switchTransforms && typeof sub === 'string')
18
+ switchTransforms && typeof sub === 'string'
17
19
  ? set(sub)
18
20
  : normalizeFieldMapping(transformers, switchTransforms)(sub)
19
21
 
20
- const createFieldPipeline = ({
21
- path,
22
- transform: transformDef = [],
23
- transformTo: transformToDef = null,
24
- default: defValue,
25
- const: constValue,
26
- sub
27
- }, transformers, switchTransforms) => {
22
+ const createFieldPipeline = (
23
+ {
24
+ path,
25
+ transform: transformDef = [],
26
+ transformTo: transformToDef = null,
27
+ default: defValue,
28
+ const: constValue,
29
+ sub,
30
+ },
31
+ transformers,
32
+ switchTransforms
33
+ ) => {
28
34
  const transformPipeline = preparePipeline(transformDef, transformers)
29
- const revTransformPipeline = prepareRevPipeline(transformToDef, transformPipeline, transformers)
35
+ const revTransformPipeline = prepareRevPipeline(
36
+ transformToDef,
37
+ transformPipeline,
38
+ transformers
39
+ )
30
40
  return [
31
41
  ...pathToPipeline(path),
32
- (typeof constValue !== 'undefined') ? fixed(constValue) : null,
33
- (typeof defValue !== 'undefined') ? alt(value(defValue)) : null,
34
- (sub && switchTransforms) ? createSubMapping(sub, transformers, switchTransforms) : null,
35
- ...((switchTransforms) ? revTransformPipeline : transformPipeline).map(compose(fwd, transform)),
36
- ...((switchTransforms) ? transformPipeline : revTransformPipeline).map(compose(rev, transform)),
37
- (sub && !switchTransforms) ? createSubMapping(sub, transformers, switchTransforms) : null
42
+ typeof constValue !== 'undefined' ? fixed(constValue) : null,
43
+ typeof defValue !== 'undefined' ? alt(value(defValue)) : null,
44
+ sub && switchTransforms
45
+ ? createSubMapping(sub, transformers, switchTransforms)
46
+ : null,
47
+ ...(switchTransforms ? revTransformPipeline : transformPipeline).map(
48
+ compose(fwd, transform)
49
+ ),
50
+ ...(switchTransforms ? transformPipeline : revTransformPipeline).map(
51
+ compose(rev, transform)
52
+ ),
53
+ sub && !switchTransforms
54
+ ? createSubMapping(sub, transformers, switchTransforms)
55
+ : null,
38
56
  ].filter(Boolean)
39
57
  }
40
- const normalizeFieldMapping = (transformers = {}, switchTransforms = false) => (def) => (is.string(def) || is.array(def))
41
- ? pathToPipeline(def)
42
- : createFieldPipeline(def, transformers, switchTransforms)
58
+ const normalizeFieldMapping =
59
+ (transformers = {}, switchTransforms = false) =>
60
+ (def) =>
61
+ is.string(def) || is.array(def)
62
+ ? pathToPipeline(def)
63
+ : createFieldPipeline(def, transformers, switchTransforms)
43
64
 
44
65
  const normalizeMapping = (mapping, transformers = {}) =>
45
66
  map(normalizeFieldMapping(transformers), mapping)
@@ -50,5 +71,6 @@ const normalizeMappingWithSwitchedTransforms = (mapping, transformers = {}) =>
50
71
  module.exports = {
51
72
  normalizeMapping,
52
73
  normalizeFieldMapping,
53
- normalizeMappingWithSwitchedTransforms
74
+ normalizeMappingWithSwitchedTransforms,
75
+ pathToPipeline,
54
76
  }
@@ -3,30 +3,41 @@ const createError = require('../utils/createError')
3
3
 
4
4
  const prepareMetaForQueue = ({ queue, ...rest }) => ({
5
5
  ...rest,
6
- queuedAt: Date.now()
6
+ queuedAt: Date.now(),
7
7
  })
8
8
 
9
9
  const prepareForQueue = (action) => ({
10
10
  ...action,
11
- meta: prepareMetaForQueue(action.meta)
11
+ meta: prepareMetaForQueue(action.meta),
12
12
  })
13
13
 
14
14
  const enqueue = async (queue, action) => {
15
15
  const { meta } = action
16
16
  const queuedAction = prepareForQueue(action)
17
- const timestamp = (typeof meta.queue === 'boolean') ? null : meta.queue
17
+ const timestamp = typeof meta.queue === 'boolean' ? null : meta.queue
18
18
  const actionId = meta.id || null
19
19
 
20
20
  let id
21
21
  try {
22
22
  id = await queue.push(queuedAction, timestamp, actionId)
23
23
  } catch (error) {
24
- debug('Error from queue when pushing %o with timestamp %s. Error: %s', queuedAction, timestamp, error)
24
+ debug(
25
+ 'Error from queue when pushing %o with timestamp %s. Error: %s',
26
+ queuedAction,
27
+ timestamp,
28
+ error
29
+ )
25
30
  return createError(`Could not push to queue. ${error}`)
26
31
  }
27
32
 
28
- debug('Pushed to queue with timestamp %s and id \'%s\': %o', timestamp, id, queuedAction)
29
- return { status: 'queued', data: { id } }
33
+ debug(
34
+ "Pushed to queue with timestamp %s and id '%s': %o",
35
+ timestamp,
36
+ id,
37
+ queuedAction
38
+ )
39
+ const queuedStatus = action.meta.queuedStatus || 'queued'
40
+ return { status: queuedStatus, data: { id } }
30
41
  }
31
42
 
32
43
  module.exports = enqueue
@@ -17,12 +17,15 @@ const enqueueNext = (queue, action) => {
17
17
  const nextTime = getNextTime(action)
18
18
 
19
19
  if (nextTime) {
20
- const nextAction = { ...action, meta: { ...action.meta, queue: nextTime.getTime() } }
20
+ const nextAction = {
21
+ ...action,
22
+ meta: { ...action.meta, queue: nextTime.getTime() },
23
+ }
21
24
  return enqueue(queue, nextAction)
22
25
  }
23
26
  }
24
27
 
25
- function middleware (next, queue) {
28
+ function middleware(next, queue) {
26
29
  return async (action) => {
27
30
  if (action.meta && action.meta.queue) {
28
31
  return enqueue(queue, action)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "integreat",
3
- "version": "0.7.33",
3
+ "version": "0.7.37",
4
4
  "description": "Node.js integration layer",
5
5
  "author": "Kjell-Morten Bratsberg Thorsen <post@kjellmorten.no> (http://kjellmorten.no/)",
6
6
  "license": "ISC",
@@ -13,12 +13,11 @@
13
13
  "main": "index.js",
14
14
  "types": "index.d.ts",
15
15
  "scripts": {
16
- "test": "npm run lint && NODE_ENV=test nyc --reporter=text-summary ava",
16
+ "test": "NODE_ENV=test nyc --reporter=text-summary ava",
17
17
  "test:inspect": "node --inspect node_modules/ava/profile.js",
18
18
  "dev": "NODE_ENV=test ava --watch",
19
19
  "coverage": "nyc report --reporter=text-lcov | coveralls",
20
- "nyc:report": "nyc report --reporter=text --reporter=html",
21
- "lint": "standard"
20
+ "nyc:report": "nyc report --reporter=text --reporter=html"
22
21
  },
23
22
  "ava": {
24
23
  "babel": true,
@@ -47,24 +46,25 @@
47
46
  },
48
47
  "dependencies": {
49
48
  "@sindresorhus/is": "^1.2.0",
50
- "debug": "^4.3.2",
49
+ "debug": "^4.3.3",
51
50
  "got": "^9.6.0",
52
51
  "later": "^1.2.0",
53
52
  "map-any": "^0.2.1",
54
- "map-transform": "^0.3.11",
53
+ "map-transform": "^0.3.12",
55
54
  "p-limit": "^2.3.0",
55
+ "p-progress": "^0.5.1",
56
56
  "ramda": "^0.27.1",
57
57
  "uuid": "^3.4.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@ava/babel": "^1.0.1",
61
- "ava": "3.3.0",
62
- "coveralls": "^3.1.0",
63
- "dotenv": "^8.2.0",
60
+ "@ava/babel": "^2.0.0",
61
+ "ava": "3.15.0",
62
+ "coveralls": "^3.1.1",
63
+ "dotenv": "^10.0.0",
64
64
  "integreat-adapter-json": "^0.2.1",
65
- "nock": "^12.0.3",
65
+ "nock": "^13.2.1",
66
66
  "nyc": "^15.1.0",
67
- "sinon": "^9.2.4",
68
- "standard": "^14.3.4"
67
+ "prettier": "^2.5.1",
68
+ "sinon": "^11.1.2"
69
69
  }
70
70
  }