integreat 0.7.45 → 0.7.46
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/lib/integreat.js +1 -1
- package/lib/service/index.js +204 -153
- package/package.json +3 -3
package/lib/integreat.js
CHANGED
package/lib/service/index.js
CHANGED
|
@@ -2,51 +2,72 @@ const EventEmitter = require('events')
|
|
|
2
2
|
const { compose, identity } = require('ramda')
|
|
3
3
|
const prepareEndpoints = require('../endpoints')
|
|
4
4
|
const requestFromAction = require('./requestFromAction')
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
beforeService,
|
|
7
|
+
sendToService,
|
|
8
|
+
afterService,
|
|
9
|
+
respondToUnknownAction,
|
|
10
|
+
} = require('./send')
|
|
6
11
|
const createError = require('../utils/createError')
|
|
7
12
|
|
|
8
|
-
const lookup = (id, resource) => (typeof id === 'string'
|
|
13
|
+
const lookup = (id, resource) => (typeof id === 'string' ? resource[id] : id)
|
|
9
14
|
|
|
10
15
|
const normalizeAction = async (action, adapter) => {
|
|
11
|
-
const normalized = await adapter.normalize(
|
|
16
|
+
const normalized = await adapter.normalize(
|
|
17
|
+
{ status: 'ok', data: action.payload.data },
|
|
18
|
+
{ endpoint: {} }
|
|
19
|
+
)
|
|
12
20
|
return { ...action, payload: { ...action.payload, data: normalized.data } }
|
|
13
21
|
}
|
|
14
22
|
|
|
15
|
-
const receiveRequestFromAction = (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const receiveRequestFromAction = (
|
|
24
|
+
{ type, payload: { data, ...params }, meta: { ident } },
|
|
25
|
+
endpoint
|
|
26
|
+
) => ({
|
|
27
|
+
action: type,
|
|
28
|
+
params: {
|
|
29
|
+
...endpoint.options.actionPayload,
|
|
30
|
+
...params,
|
|
31
|
+
},
|
|
32
|
+
endpoint: endpoint.options,
|
|
33
|
+
access: { ident },
|
|
34
|
+
})
|
|
25
35
|
|
|
26
36
|
const receiveAfterArgs = (action, request, endpoint) => ({
|
|
27
37
|
request,
|
|
28
|
-
response:
|
|
38
|
+
response: { status: 'ok', data: action.payload.data },
|
|
29
39
|
requestMapper: endpoint.requestMapper,
|
|
30
40
|
responseMapper: endpoint.responseMapper,
|
|
31
|
-
mappings: endpoint.mappings
|
|
41
|
+
mappings: endpoint.mappings,
|
|
32
42
|
})
|
|
33
43
|
|
|
34
|
-
const receiveBeforeArgs = (
|
|
35
|
-
|
|
44
|
+
const receiveBeforeArgs = (
|
|
45
|
+
{ data, status, error },
|
|
46
|
+
request,
|
|
47
|
+
{ payload: { data: _, ...params } },
|
|
48
|
+
endpoint
|
|
49
|
+
) => ({
|
|
50
|
+
request: {
|
|
51
|
+
...request,
|
|
52
|
+
data,
|
|
53
|
+
params: { ...request.params, ...params, status, error },
|
|
54
|
+
},
|
|
36
55
|
requestMapper: endpoint.requestMapper,
|
|
37
56
|
responseMapper: endpoint.responseMapper,
|
|
38
|
-
mappings: endpoint.mappings
|
|
57
|
+
mappings: endpoint.mappings,
|
|
39
58
|
})
|
|
40
59
|
|
|
60
|
+
const removeIdAndSetGid = ({ id, ...meta }) => ({ ...meta, gid: id })
|
|
61
|
+
|
|
41
62
|
const createNextAction = (action, { options }, mappedResponse) => ({
|
|
42
63
|
type: options.actionType,
|
|
43
64
|
payload: {
|
|
44
65
|
type: action.payload.type,
|
|
45
66
|
...options.actionPayload,
|
|
46
67
|
...mappedResponse.params,
|
|
47
|
-
...(
|
|
68
|
+
...(mappedResponse.data ? { data: mappedResponse.data } : {}),
|
|
48
69
|
},
|
|
49
|
-
meta: { ...action.meta, ...options.actionMeta }
|
|
70
|
+
meta: removeIdAndSetGid({ ...action.meta, ...options.actionMeta }),
|
|
50
71
|
})
|
|
51
72
|
|
|
52
73
|
const wrapResponse = (response) => ({ response })
|
|
@@ -57,145 +78,175 @@ const wrapResponse = (response) => ({ response })
|
|
|
57
78
|
* @param {Object} resources - Object with mappings, adapters, auths, and plurals
|
|
58
79
|
* @returns {Object} The created service
|
|
59
80
|
*/
|
|
60
|
-
const service =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
setupMapping = identity
|
|
66
|
-
} = {}) => ({
|
|
67
|
-
id: serviceId,
|
|
68
|
-
adapter,
|
|
69
|
-
auth = null,
|
|
70
|
-
meta = null,
|
|
71
|
-
options = {},
|
|
72
|
-
endpoints = [],
|
|
73
|
-
mappings: mappingsDef = {}
|
|
74
|
-
}) => {
|
|
75
|
-
if (!serviceId) {
|
|
76
|
-
throw new TypeError('Can\'t create service without an id.')
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
adapter = lookup(adapter, adapters)
|
|
80
|
-
if (!adapter) {
|
|
81
|
-
throw new TypeError(`Can't create service '${serviceId}' without an adapter.`)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
endpoints = prepareEndpoints({ endpoints, options, mappings: mappingsDef }, { adapter, transformers, setupMapping })
|
|
85
|
-
auth = lookup(auth, auths) || {}
|
|
86
|
-
let connection = null
|
|
87
|
-
const emitter = new EventEmitter()
|
|
88
|
-
|
|
89
|
-
const sendOptions = {
|
|
90
|
-
serviceId,
|
|
81
|
+
const service =
|
|
82
|
+
({
|
|
83
|
+
adapters = {},
|
|
84
|
+
auths = {},
|
|
85
|
+
transformers = {},
|
|
91
86
|
schemas,
|
|
87
|
+
setupMapping = identity,
|
|
88
|
+
} = {}) =>
|
|
89
|
+
({
|
|
90
|
+
id: serviceId,
|
|
92
91
|
adapter,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
auth = null,
|
|
93
|
+
meta = null,
|
|
94
|
+
options = {},
|
|
95
|
+
endpoints = [],
|
|
96
|
+
mappings: mappingsDef = {},
|
|
97
|
+
}) => {
|
|
98
|
+
if (!serviceId) {
|
|
99
|
+
throw new TypeError("Can't create service without an id.")
|
|
100
|
+
}
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
adapter = lookup(adapter, adapters)
|
|
103
|
+
if (!adapter) {
|
|
104
|
+
throw new TypeError(
|
|
105
|
+
`Can't create service '${serviceId}' without an adapter.`
|
|
106
|
+
)
|
|
107
|
+
}
|
|
103
108
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
endpoints = prepareEndpoints(
|
|
110
|
+
{ endpoints, options, mappings: mappingsDef },
|
|
111
|
+
{ adapter, transformers, setupMapping }
|
|
112
|
+
)
|
|
113
|
+
auth = lookup(auth, auths) || {}
|
|
114
|
+
let connection = null
|
|
115
|
+
const emitter = new EventEmitter()
|
|
116
|
+
|
|
117
|
+
const sendOptions = {
|
|
118
|
+
serviceId,
|
|
119
|
+
schemas,
|
|
120
|
+
adapter,
|
|
121
|
+
authenticator: auth.authenticator,
|
|
122
|
+
authOptions: auth.options,
|
|
123
|
+
setAuthentication: (authentication) => {
|
|
124
|
+
auth.authentication = authentication
|
|
125
|
+
},
|
|
126
|
+
setConnection: (conn) => {
|
|
127
|
+
connection = conn
|
|
128
|
+
},
|
|
129
|
+
serviceOptions: options,
|
|
130
|
+
emit: emitter.emit.bind(emitter),
|
|
131
|
+
}
|
|
110
132
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
133
|
+
const beforeServiceFn = beforeService(sendOptions)
|
|
134
|
+
const afterServiceFn = afterService(sendOptions)
|
|
135
|
+
|
|
136
|
+
const sendFn = compose(
|
|
137
|
+
afterServiceFn,
|
|
138
|
+
sendToService(sendOptions),
|
|
139
|
+
beforeServiceFn,
|
|
140
|
+
respondToUnknownAction(sendOptions)
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
// Create the service instance
|
|
144
|
+
return {
|
|
145
|
+
id: serviceId,
|
|
146
|
+
adapter,
|
|
147
|
+
meta,
|
|
148
|
+
endpoints: endpoints.list,
|
|
149
|
+
on: emitter.on.bind(emitter),
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The given action is prepared, authenticated, and mapped, before it is
|
|
153
|
+
* sent to the service via the adapter. The response from the adapter is then
|
|
154
|
+
* mapped, authenticated, and returned.
|
|
155
|
+
*
|
|
156
|
+
* The prepared and authenticated request is also returned.
|
|
157
|
+
*
|
|
158
|
+
* @param {Object} action - Action object to map and send to the service
|
|
159
|
+
* @returns {Object} Object with the sent request and the received response
|
|
160
|
+
*/
|
|
161
|
+
async send(action) {
|
|
162
|
+
const endpoint = endpoints.match(action)
|
|
163
|
+
if (!endpoint) {
|
|
164
|
+
return {
|
|
165
|
+
response: createError(
|
|
166
|
+
`No endpoint matching request to service '${serviceId}'.`,
|
|
167
|
+
'noaction'
|
|
168
|
+
),
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const validateRes = endpoint.validate(action)
|
|
173
|
+
if (validateRes !== null) {
|
|
174
|
+
return { response: validateRes }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const {
|
|
178
|
+
requestMapper,
|
|
179
|
+
responseMapper,
|
|
180
|
+
mapResponseWithType = true,
|
|
181
|
+
mappings,
|
|
182
|
+
} = endpoint
|
|
183
|
+
|
|
184
|
+
return sendFn({
|
|
185
|
+
request: requestFromAction(action, { endpoint, schemas }),
|
|
186
|
+
authentication: auth.authentication,
|
|
187
|
+
requestMapper,
|
|
188
|
+
responseMapper,
|
|
189
|
+
mapResponseWithType,
|
|
190
|
+
mappings,
|
|
191
|
+
connection,
|
|
192
|
+
})
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The given action is prepared, authenticated, and mapped – as coming
|
|
197
|
+
* _from_ the service. It is then made into an action and dispatched.
|
|
198
|
+
* The response from the action is mapped, authenticated, and returned – for
|
|
199
|
+
* going _to_ the service.
|
|
200
|
+
*
|
|
201
|
+
* @param {Object} action - Action object to map from the service
|
|
202
|
+
* @param {Object} dispatch - A dispatch function
|
|
203
|
+
* @returns {Object} Object with the received response
|
|
204
|
+
*/
|
|
205
|
+
async receive(action, dispatch) {
|
|
206
|
+
action = await normalizeAction(action, adapter)
|
|
207
|
+
const endpoint = endpoints.match(action)
|
|
208
|
+
if (!endpoint) {
|
|
209
|
+
return wrapResponse(
|
|
210
|
+
createError(
|
|
211
|
+
`No endpoint matching request to service '${serviceId}'.`,
|
|
212
|
+
'noaction'
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const validateRes = endpoint.validate(action)
|
|
218
|
+
if (validateRes !== null) {
|
|
219
|
+
return wrapResponse(validateRes)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!endpoint.options || !endpoint.options.actionType) {
|
|
223
|
+
return wrapResponse(
|
|
224
|
+
createError(
|
|
225
|
+
`The matching endpoint on service '${serviceId}' did not specify an action type`,
|
|
226
|
+
'noaction'
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const request = receiveRequestFromAction(action, endpoint)
|
|
232
|
+
const mapped = await afterServiceFn(
|
|
233
|
+
receiveAfterArgs(action, request, endpoint)
|
|
234
|
+
)
|
|
235
|
+
const nextAction = createNextAction(action, endpoint, mapped.response)
|
|
236
|
+
|
|
237
|
+
const response = await dispatch(nextAction)
|
|
238
|
+
|
|
239
|
+
const serialized = await beforeServiceFn(
|
|
240
|
+
receiveBeforeArgs(response, request, nextAction, endpoint)
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return wrapResponse({
|
|
244
|
+
...response,
|
|
245
|
+
...(serialized.request.data ? { data: serialized.request.data } : {}),
|
|
246
|
+
access: serialized.request.access,
|
|
247
|
+
})
|
|
248
|
+
},
|
|
197
249
|
}
|
|
198
250
|
}
|
|
199
|
-
}
|
|
200
251
|
|
|
201
252
|
module.exports = service
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "integreat",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.46",
|
|
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,12 +46,12 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@sindresorhus/is": "^1.2.0",
|
|
49
|
-
"debug": "^4.
|
|
49
|
+
"debug": "^4.4.0",
|
|
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
|
-
"nanoid": "^3.3.
|
|
54
|
+
"nanoid": "^3.3.11",
|
|
55
55
|
"p-limit": "^2.3.0",
|
|
56
56
|
"p-progress": "^0.5.1",
|
|
57
57
|
"ramda": "^0.27.2",
|