integreat 0.7.35 → 0.7.39

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.
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export as namespace integreat
2
2
  export = integreat
3
3
 
4
- declare function integreat (
4
+ declare function integreat(
5
5
  defs: integreat.Definitions,
6
6
  resources: integreat.Resources,
7
7
  middlewares?: integreat.Middleware[]
@@ -20,58 +20,63 @@ declare namespace integreat {
20
20
  }
21
21
 
22
22
  export interface Ident {
23
- id?: string,
23
+ id?: string
24
24
  root?: boolean
25
25
  }
26
26
 
27
27
  export interface Meta {
28
- queue?: boolean,
29
- ident?: Ident,
28
+ queue?: boolean | number
29
+ ident?: Ident
30
30
  [key: string]: unknown
31
31
  }
32
32
 
33
33
  export interface Action<P = Payload> {
34
- type: string,
35
- payload: P,
34
+ type: string
35
+ payload: P
36
36
  meta?: Meta
37
37
  }
38
38
 
39
39
  export type ActionHandlerResources = {
40
40
  dispatch: Dispatch
41
+ setProgress: (progress: number) => void
41
42
  }
42
43
 
43
44
  export interface Instance {
44
- version: string,
45
- schemas: object,
46
- services: object,
47
- identType: string,
45
+ version: string
46
+ schemas: object
47
+ services: object
48
+ identType: string
48
49
 
49
- dispatch: Dispatch,
50
- on: (eventName: string, serviceId: string, listener: (request: Request, response: Response) => void) => void
50
+ dispatch: Dispatch
51
+ on: (
52
+ eventName: string,
53
+ serviceId: string,
54
+ listener: (request: Request, response: Response) => void
55
+ ) => void
51
56
  }
52
57
 
53
58
  export interface IdentDefinitions {
54
59
  type: string
55
60
  props?: {
56
- id?: string,
57
- roles?: string,
61
+ id?: string
62
+ roles?: string
58
63
  tokens?: string
59
64
  }
60
65
  }
61
66
 
62
67
  export interface Definitions {
63
- schemas: object[],
64
- services: object[],
65
- mappings: object[],
66
- auths?: object[],
68
+ schemas: object[]
69
+ services: object[]
70
+ mappings: object[]
71
+ auths?: object[]
67
72
  ident?: IdentDefinitions
68
73
  }
69
74
 
70
75
  export interface Resources {
71
- adapters: any,
72
- authenticators?: any,
73
- transformers?: any,
74
- filters?: any,
76
+ adapters: any
77
+ authenticators?: any
78
+ transformers?: any
79
+ filters?: any
75
80
  actions?: any
76
81
  }
77
82
 
@@ -80,9 +85,9 @@ declare namespace integreat {
80
85
  }
81
86
 
82
87
  export interface Queue {
83
- queue: object,
84
- setDispatch: (dispatch: Dispatch) => Promise<void>,
85
- middleware: Middleware,
88
+ queue: object
89
+ setDispatch: (dispatch: Dispatch) => Promise<void>
90
+ middleware: Middleware
86
91
  schedule: (schedule: object) => Promise<Response>
87
92
  }
88
93
 
@@ -97,10 +102,10 @@ declare namespace integreat {
97
102
  }
98
103
 
99
104
  type Relationship = {
100
- id: string | null | undefined,
101
- type: string,
102
- attributes?: Attributes,
103
- relationships?: Relationships,
105
+ id: string | null | undefined
106
+ type: string
107
+ attributes?: Attributes
108
+ relationships?: Relationships
104
109
  meta?: object
105
110
  }
106
111
 
@@ -109,30 +114,30 @@ declare namespace integreat {
109
114
  }
110
115
 
111
116
  export type Data = {
112
- id: string | null | undefined,
113
- type: string,
114
- attributes: Attributes,
117
+ id: string | null | undefined
118
+ type: string
119
+ attributes: Attributes
115
120
  relationships: Relationships
116
121
  }
117
122
 
118
123
  interface Request<T = Data[] | Data | null> {
119
- action: string,
124
+ action: string
120
125
  params?: {
121
126
  [param: string]: any
122
- },
127
+ }
123
128
  endpoint?: {
124
129
  [option: string]: any
125
130
  }
126
- data: T,
127
- auth?: object | boolean,
131
+ data: T
132
+ auth?: object | boolean
128
133
  access?: { ident: Ident }
129
134
  }
130
135
 
131
136
  interface Response<T = Data[]> {
132
- status: string,
133
- data?: T,
134
- error?: string,
135
- responses?: Response[],
137
+ status: string
138
+ data?: T
139
+ error?: string
140
+ responses?: Response[]
136
141
  access?: object
137
142
  }
138
143
  }
@@ -267,21 +267,15 @@ async function transformData(
267
267
  useIndividualTransform
268
268
  ) {
269
269
  if (useIndividualTransform) {
270
- const responses = await Promise.all(
270
+ return await Promise.all(
271
271
  data
272
272
  .map((item) =>
273
273
  dispatch(createTransformAction(transformParams, item, meta))
274
274
  )
275
275
  .map((p) => pLimit(1)(() => p))
276
276
  )
277
- return responses.flatMap((response, index) =>
278
- response.status === 'ok' ? response.data : data[index]
279
- )
280
277
  } else {
281
- const transformResponse = await dispatch(
282
- createTransformAction(transformParams, data, meta)
283
- )
284
- return transformResponse.status === 'ok' ? transformResponse.data : data
278
+ return [await dispatch(createTransformAction(transformParams, data, meta))]
285
279
  }
286
280
  }
287
281
 
@@ -344,7 +338,7 @@ async function sync({ payload, meta = {} }, { dispatch, getService }) {
344
338
 
345
339
  // Dispatch transform action
346
340
  if (transformParams) {
347
- data = await transformData(
341
+ const transformResults = await transformData(
348
342
  data,
349
343
  dispatch,
350
344
  transformParams,
@@ -352,6 +346,16 @@ async function sync({ payload, meta = {} }, { dispatch, getService }) {
352
346
  payload.useIndividualTransform
353
347
  )
354
348
 
349
+ if (transformResults.some((result) => result.status !== 'ok')) {
350
+ return transformResults.length === 1
351
+ ? transformResults[0]
352
+ : createError(makeErrorString(transformResults))
353
+ }
354
+
355
+ data = flatten(transformResults.map((result) => result.data)).filter(
356
+ Boolean
357
+ )
358
+
355
359
  if (data.length === 0 && payload.syncNoData !== true) {
356
360
  return createError(
357
361
  `No items to update from service '${fromParams[0].service}' after transform action`,
@@ -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.35'
8
+ const version = '0.7.39'
9
9
 
10
10
  /**
11
11
  * Return an Integreat instance with a dispatch method.
@@ -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)
@@ -2,8 +2,8 @@ const is = require('@sindresorhus/is')
2
2
 
3
3
  const generateErrorResponse = (status, error, access, authError) => ({
4
4
  status,
5
- error: (authError) ? `${error}: ${authError}` : error,
6
- access: { ...access, status: 'refused', scheme: 'service' }
5
+ error: authError ? `${error}: ${authError}` : error,
6
+ access: { ...access, status: 'refused', scheme: 'service' },
7
7
  })
8
8
 
9
9
  const responseFromAuthentication = (authentication, response, { access }) => {
@@ -11,18 +11,38 @@ const responseFromAuthentication = (authentication, response, { access }) => {
11
11
  case 'granted':
12
12
  return undefined
13
13
  case 'refused':
14
- return generateErrorResponse('noaccess', 'Authentication was refused', access)
14
+ return generateErrorResponse(
15
+ 'noaccess',
16
+ 'Authentication was refused',
17
+ access
18
+ )
15
19
  case 'error':
16
20
  case 'timeout':
17
- return generateErrorResponse('autherror', 'Could not authenticate', access, authentication.error)
21
+ return generateErrorResponse(
22
+ 'autherror',
23
+ 'Could not authenticate',
24
+ access,
25
+ authentication.error
26
+ )
18
27
  }
19
28
 
20
- return generateErrorResponse('autherror', 'Could not authenticate - unknown status from authenticator', access)
29
+ return generateErrorResponse(
30
+ 'autherror',
31
+ 'Could not authenticate - unknown status from authenticator',
32
+ access
33
+ )
21
34
  }
22
35
 
23
- const requestFromAuthentication = (authentication, authenticator, adapter, request) => {
36
+ const requestFromAuthentication = (
37
+ authentication,
38
+ authenticator,
39
+ adapter,
40
+ request,
41
+ authOptions
42
+ ) => {
24
43
  if (authentication.status === 'granted') {
25
- const fn = authenticator[adapter.authentication]
44
+ const method = authOptions.overrideAdapterMethod || adapter.authentication
45
+ const fn = authenticator[method]
26
46
  if (is.function(fn)) {
27
47
  const auth = fn(authentication)
28
48
  return { ...request, auth }
@@ -32,7 +52,12 @@ const requestFromAuthentication = (authentication, authenticator, adapter, reque
32
52
  return { ...request, auth: null }
33
53
  }
34
54
 
35
- const doAuthenticate = async (authenticator, authOptions, request, retries = 1) => {
55
+ const doAuthenticate = async (
56
+ authenticator,
57
+ authOptions,
58
+ request,
59
+ retries = 1
60
+ ) => {
36
61
  const authentication = await authenticator.authenticate(authOptions, request)
37
62
 
38
63
  if (authentication.status === 'timeout' && retries > 0) {
@@ -42,28 +67,53 @@ const doAuthenticate = async (authenticator, authOptions, request, retries = 1)
42
67
  return authentication
43
68
  }
44
69
 
45
- function authenticate ({ authenticator, authOptions, setAuthentication = () => {}, adapter }) {
46
- return (authenticator && authenticator.authenticate)
70
+ function authenticate({
71
+ authenticator,
72
+ authOptions,
73
+ setAuthentication = () => {},
74
+ adapter,
75
+ }) {
76
+ return authenticator && authenticator.authenticate
47
77
  ? async (args) => {
48
- const { authentication, response, request } = args
78
+ const { authentication, response, request } = args
49
79
 
50
- if (authentication && authenticator.isAuthenticated(authentication)) {
51
- return {
52
- ...args,
53
- request: requestFromAuthentication(authentication, authenticator, adapter, request)
80
+ if (authentication && authenticator.isAuthenticated(authentication)) {
81
+ return {
82
+ ...args,
83
+ request: requestFromAuthentication(
84
+ authentication,
85
+ authenticator,
86
+ adapter,
87
+ request,
88
+ authOptions
89
+ ),
90
+ }
54
91
  }
55
- }
56
92
 
57
- const nextAuthentication = await doAuthenticate(authenticator, authOptions, request)
58
- setAuthentication(nextAuthentication)
93
+ const nextAuthentication = await doAuthenticate(
94
+ authenticator,
95
+ authOptions,
96
+ request
97
+ )
98
+ setAuthentication(nextAuthentication)
59
99
 
60
- return {
61
- ...args,
62
- authentication: nextAuthentication,
63
- response: responseFromAuthentication(nextAuthentication, response, request),
64
- request: requestFromAuthentication(nextAuthentication, authenticator, adapter, request)
100
+ return {
101
+ ...args,
102
+ authentication: nextAuthentication,
103
+ response: responseFromAuthentication(
104
+ nextAuthentication,
105
+ response,
106
+ request
107
+ ),
108
+ request: requestFromAuthentication(
109
+ nextAuthentication,
110
+ authenticator,
111
+ adapter,
112
+ request,
113
+ authOptions
114
+ ),
115
+ }
65
116
  }
66
- }
67
117
  : async (args) => args
68
118
  }
69
119
 
@@ -5,13 +5,19 @@ const mergeWithParams = (response, params) => ({
5
5
  ...response,
6
6
  params: {
7
7
  ...params,
8
- ...response.params
9
- }
8
+ ...response.params,
9
+ },
10
10
  })
11
11
 
12
12
  const mapWithEndpoint = (responseMapper, response, params, actionType) => {
13
- if (responseMapper || actionType.startsWith('GET') || actionType === 'REQUEST') {
14
- return (responseMapper) ? responseMapper(mergeWithParams(response, params)) || {} : response
13
+ if (
14
+ responseMapper ||
15
+ actionType.startsWith('GET') ||
16
+ actionType === 'REQUEST'
17
+ ) {
18
+ return responseMapper
19
+ ? responseMapper(mergeWithParams(response, params)) || {}
20
+ : response
15
21
  } else {
16
22
  return {}
17
23
  }
@@ -25,8 +31,14 @@ const mapWithEndpoint = (responseMapper, response, params, actionType) => {
25
31
  * @param {Object} options - mappings, params, onlyMappedValues, and endpoint
26
32
  * @returns {Object[]} Array of mapped items
27
33
  */
28
- function mapFromService () {
29
- return ({ response, request, responseMapper, mappings, mapResponseWithType = true }) => {
34
+ function mapFromService() {
35
+ return ({
36
+ response,
37
+ request,
38
+ responseMapper,
39
+ mappings,
40
+ mapResponseWithType = true,
41
+ }) => {
30
42
  const type = request.params.type || Object.keys(mappings)
31
43
  const { onlyMappedValues, unmapped = false } = request.params
32
44
 
@@ -34,28 +46,38 @@ function mapFromService () {
34
46
  return response
35
47
  }
36
48
 
37
- const {
38
- data,
39
- status = response.status,
40
- error,
41
- paging,
42
- params
43
- } = mapWithEndpoint(responseMapper, response, request.params, request.action)
49
+ const { data, status, error, paging, params } = mapWithEndpoint(
50
+ responseMapper,
51
+ response,
52
+ request.params,
53
+ request.action
54
+ )
55
+
44
56
  const responseError = [response.error, error].filter(Boolean).join(' | ')
57
+ const responseStatus =
58
+ response.status !== 'ok'
59
+ ? response.status
60
+ : status || (responseError ? 'error' : 'ok')
45
61
 
46
62
  const ret = {
47
63
  ...response,
48
- status: response.status === 'ok' ? status : response.status,
49
- ...(status !== 'ok' && responseError ? { error: responseError } : {}),
50
- ...((paging) ? { paging } : {}),
51
- ...((params) ? { params } : {}),
52
- ...(status === 'ok' || data ? { data: data === null ? undefined : data } : {})
64
+ status: responseStatus,
65
+ ...(responseError ? { error: responseError } : {}),
66
+ ...(paging ? { paging } : {}),
67
+ ...(params ? { params } : {}),
68
+ ...(responseStatus === 'ok' || data
69
+ ? { data: data === null ? undefined : data }
70
+ : {}),
53
71
  }
54
72
 
55
- if (status === 'ok' && data && mapResponseWithType) {
56
- const mapType = (type) => (mappings[type])
57
- ? mappings[type].fromService({ ...request, data }, { onlyMappedValues })
58
- : []
73
+ if (ret.status === 'ok' && data && mapResponseWithType) {
74
+ const mapType = (type) =>
75
+ mappings[type]
76
+ ? mappings[type].fromService(
77
+ { ...request, data },
78
+ { onlyMappedValues }
79
+ )
80
+ : []
59
81
  ret.data = flatten(mapAny(mapType, type))
60
82
  }
61
83
 
@@ -6,9 +6,9 @@ const getPluralType = (type, schemas) =>
6
6
  * @param {Object} request - The request object to complete
7
7
  * @returns {Object} The completed request object
8
8
  */
9
- function requestFromAction (
9
+ function requestFromAction(
10
10
  { type: action, payload, meta = {} },
11
- { endpoint, schemas = {} } = {}
11
+ { endpoint, schemas = {}, auth } = {}
12
12
  ) {
13
13
  const { data, ...params } = payload
14
14
  const { ident = null, id } = meta
@@ -19,11 +19,12 @@ function requestFromAction (
19
19
  params,
20
20
  data,
21
21
  endpoint: (endpoint && endpoint.options) || null,
22
+ auth,
22
23
  access: { ident },
23
24
  meta: {
24
25
  id,
25
- typePlural
26
- }
26
+ typePlural,
27
+ },
27
28
  }
28
29
  }
29
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "integreat",
3
- "version": "0.7.35",
3
+ "version": "0.7.39",
4
4
  "description": "Node.js integration layer",
5
5
  "author": "Kjell-Morten Bratsberg Thorsen <post@kjellmorten.no> (http://kjellmorten.no/)",
6
6
  "license": "ISC",
@@ -46,13 +46,14 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@sindresorhus/is": "^1.2.0",
49
- "debug": "^4.3.2",
49
+ "debug": "^4.3.3",
50
50
  "got": "^9.6.0",
51
51
  "later": "^1.2.0",
52
52
  "map-any": "^0.2.1",
53
53
  "map-transform": "^0.3.12",
54
54
  "p-limit": "^2.3.0",
55
- "ramda": "^0.27.1",
55
+ "p-progress": "^0.5.1",
56
+ "ramda": "^0.27.2",
56
57
  "uuid": "^3.4.0"
57
58
  },
58
59
  "devDependencies": {
@@ -61,9 +62,9 @@
61
62
  "coveralls": "^3.1.1",
62
63
  "dotenv": "^10.0.0",
63
64
  "integreat-adapter-json": "^0.2.1",
64
- "nock": "^13.1.2",
65
+ "nock": "^13.2.4",
65
66
  "nyc": "^15.1.0",
66
- "prettier": "^2.3.2",
67
+ "prettier": "^2.5.1",
67
68
  "sinon": "^11.1.2"
68
69
  }
69
70
  }