dd-trace 2.8.0 → 2.10.0
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/ci/init.js +22 -6
- package/ci/jest/env.js +19 -7
- package/ext/tags.d.ts +1 -0
- package/ext/tags.js +2 -1
- package/index.d.ts +4 -2
- package/package.json +5 -5
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/aws-sdk.js +5 -4
- package/packages/datadog-instrumentations/src/fastify.js +84 -92
- package/packages/datadog-instrumentations/src/graphql.js +352 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +14 -14
- package/packages/datadog-instrumentations/src/koa.js +10 -7
- package/packages/datadog-instrumentations/src/tedious.js +1 -1
- package/packages/datadog-plugin-graphql/src/index.js +123 -412
- package/packages/datadog-plugin-graphql/src/resolve.js +125 -0
- package/packages/datadog-plugin-http/src/client.js +10 -7
- package/packages/datadog-plugin-http2/src/server.js +3 -1
- package/packages/datadog-plugin-jest/src/util.js +13 -1
- package/packages/datadog-plugin-mysql/src/index.js +18 -7
- package/packages/dd-trace/src/appsec/index.js +3 -3
- package/packages/dd-trace/src/config.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/plugin_manager.js +21 -0
- package/packages/dd-trace/src/plugins/util/test.js +3 -0
- package/packages/dd-trace/src/plugins/util/web.js +3 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/startup-log.js +1 -1
- package/packages/dd-trace/src/telemetry.js +1 -1
- package/scripts/install_plugin_modules.js +2 -4
- package/packages/dd-trace/lib/version.js +0 -1
|
@@ -1,260 +1,177 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const documentSources = new WeakMap()
|
|
9
|
-
const patchedTypes = new WeakSet()
|
|
10
|
-
const patchedResolvers = new WeakSet()
|
|
6
|
+
const log = require('../../dd-trace/src/log')
|
|
7
|
+
const GraphQLResolvePlugin = require('./resolve')
|
|
11
8
|
|
|
12
9
|
let tools
|
|
10
|
+
class GraphQLPlugin extends Plugin {
|
|
11
|
+
static get name () {
|
|
12
|
+
return 'graphql'
|
|
13
|
+
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return function executeWithTrace () {
|
|
17
|
-
const args = normalizeArgs(arguments, tracer, config, defaultFieldResolver)
|
|
18
|
-
const schema = args.schema
|
|
19
|
-
const document = args.document
|
|
20
|
-
const source = documentSources.get(document)
|
|
21
|
-
const contextValue = args.contextValue
|
|
22
|
-
const operation = getOperation(document, args.operationName)
|
|
23
|
-
|
|
24
|
-
if (contexts.has(contextValue)) {
|
|
25
|
-
return execute.apply(this, arguments)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (schema) {
|
|
29
|
-
wrapFields(schema._queryType, tracer, config)
|
|
30
|
-
wrapFields(schema._mutationType, tracer, config)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const span = startExecutionSpan(tracer, config, operation, args)
|
|
34
|
-
const context = { source, span, fields: {} }
|
|
15
|
+
constructor (...args) {
|
|
16
|
+
super(...args)
|
|
35
17
|
|
|
36
|
-
|
|
18
|
+
/** Execute Subs */
|
|
37
19
|
|
|
38
|
-
|
|
39
|
-
|
|
20
|
+
// resolve plugin separated for disabling purposes
|
|
21
|
+
this.resolve = new GraphQLResolvePlugin(...args)
|
|
40
22
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
23
|
+
this.addSub('apm:graphql:execute:start', ({ operation, args, docSource }) => {
|
|
24
|
+
const store = storage.getStore()
|
|
25
|
+
const span = startSpan('execute', this.config, this.tracer, store)
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
27
|
+
// process add tags
|
|
28
|
+
addExecutionTags(span, this.config, operation, args.document)
|
|
29
|
+
addDocumentTags(span, args.document, this.config, docSource)
|
|
30
|
+
addVariableTags(this.config, span, args.variableValues)
|
|
53
31
|
|
|
54
|
-
analyticsSampler.sample(span, config.measured, true)
|
|
32
|
+
analyticsSampler.sample(span, this.config.measured, true)
|
|
55
33
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
document = parse.apply(this, arguments)
|
|
59
|
-
const operation = getOperation(document)
|
|
34
|
+
this.enter(span, store)
|
|
35
|
+
})
|
|
60
36
|
|
|
61
|
-
|
|
37
|
+
this.addSub('apm:graphql:execute:error', this.addError)
|
|
62
38
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
39
|
+
this.addSub('apm:graphql:execute:finish', ({ res, args }) => {
|
|
40
|
+
const span = storage.getStore().span
|
|
41
|
+
this.config.hooks.execute(span, args, res)
|
|
42
|
+
span.finish()
|
|
43
|
+
})
|
|
66
44
|
|
|
67
|
-
|
|
45
|
+
/** Parser Subs */
|
|
68
46
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
throw e
|
|
73
|
-
} finally {
|
|
74
|
-
config.hooks.parse(span, source, document)
|
|
75
|
-
finish(span)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
47
|
+
this.addSub('apm:graphql:parser:start', () => {
|
|
48
|
+
const store = storage.getStore()
|
|
49
|
+
const span = startSpan('parse', this.config, this.tracer, store)
|
|
80
50
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const span = startSpan(tracer, config, 'validate')
|
|
51
|
+
analyticsSampler.sample(span, this.config.measured, true)
|
|
52
|
+
this.enter(span, store)
|
|
53
|
+
})
|
|
85
54
|
|
|
86
|
-
|
|
55
|
+
this.addSub('apm:graphql:parser:finish', ({ source, document, docSource }) => {
|
|
56
|
+
const span = storage.getStore().span
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
58
|
+
const tags = {}
|
|
59
|
+
if (this.config.source && document) {
|
|
60
|
+
tags['graphql.source'] = docSource
|
|
91
61
|
}
|
|
92
62
|
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
errors = validate.apply(this, arguments)
|
|
63
|
+
span.addTags(tags)
|
|
96
64
|
|
|
97
|
-
|
|
65
|
+
this.config.hooks.parse(span, source, document)
|
|
98
66
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
setError(span, e)
|
|
102
|
-
throw e
|
|
103
|
-
} finally {
|
|
104
|
-
config.hooks.validate(span, document, errors)
|
|
105
|
-
finish(span)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
67
|
+
span.finish()
|
|
68
|
+
})
|
|
110
69
|
|
|
111
|
-
|
|
112
|
-
if (!type || !type._fields || patchedTypes.has(type)) {
|
|
113
|
-
return
|
|
114
|
-
}
|
|
70
|
+
this.addSub('apm:graphql:parser:error', this.addError)
|
|
115
71
|
|
|
116
|
-
|
|
72
|
+
/** Validate Subs */
|
|
117
73
|
|
|
118
|
-
|
|
119
|
-
|
|
74
|
+
this.addSub('apm:graphql:validate:start', ({ docSource, document }) => {
|
|
75
|
+
const store = storage.getStore()
|
|
76
|
+
const span = startSpan('validate', this.config, this.tracer, store)
|
|
120
77
|
|
|
121
|
-
|
|
122
|
-
wrapFieldType(field, tracer, config)
|
|
123
|
-
})
|
|
124
|
-
}
|
|
78
|
+
analyticsSampler.sample(span, this.config.measured, true)
|
|
125
79
|
|
|
126
|
-
|
|
127
|
-
|
|
80
|
+
if (document && document.loc) {
|
|
81
|
+
const tags = {}
|
|
82
|
+
if (this.config.source && document) {
|
|
83
|
+
tags['graphql.source'] = docSource
|
|
84
|
+
}
|
|
128
85
|
|
|
129
|
-
|
|
130
|
-
}
|
|
86
|
+
span.addTags(tags)
|
|
87
|
+
}
|
|
131
88
|
|
|
132
|
-
|
|
133
|
-
|
|
89
|
+
this.enter(span, store)
|
|
90
|
+
})
|
|
134
91
|
|
|
135
|
-
|
|
92
|
+
this.addSub('apm:graphql:validate:finish', ({ document, errors }) => {
|
|
93
|
+
const span = storage.getStore().span
|
|
94
|
+
this.config.hooks.validate(span, document, errors)
|
|
95
|
+
span.finish()
|
|
96
|
+
})
|
|
136
97
|
|
|
137
|
-
|
|
138
|
-
unwrappedType = unwrappedType.ofType
|
|
98
|
+
this.addSub('apm:graphql:validate:error', this.addError)
|
|
139
99
|
}
|
|
140
100
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
function wrapResolve (resolve, tracer, config) {
|
|
145
|
-
if (typeof resolve !== 'function' || patchedResolvers.has(resolve)) return resolve
|
|
101
|
+
configure (config) {
|
|
102
|
+
const validated = validateConfig(config)
|
|
146
103
|
|
|
147
|
-
|
|
148
|
-
?
|
|
149
|
-
|
|
104
|
+
// this will disable resolve subscribers if `config.depth` is set to 0
|
|
105
|
+
const resolveConfig = validated.depth === 0 ? false : validated
|
|
106
|
+
this.resolve.configure(resolveConfig)
|
|
150
107
|
|
|
151
|
-
|
|
152
|
-
const context = contexts.get(contextValue)
|
|
153
|
-
|
|
154
|
-
if (!context) return resolve.apply(this, arguments)
|
|
155
|
-
|
|
156
|
-
const path = responsePathAsArray(info && info.path)
|
|
157
|
-
|
|
158
|
-
if (config.depth >= 0) {
|
|
159
|
-
const depth = path.filter(item => typeof item === 'string').length
|
|
160
|
-
|
|
161
|
-
if (config.depth < depth) {
|
|
162
|
-
const parent = getParentField(tracer, context, path)
|
|
163
|
-
|
|
164
|
-
return call(resolve, parent.span, this, arguments)
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const field = assertField(tracer, config, context, info, path)
|
|
169
|
-
|
|
170
|
-
return call(resolve, field.span, this, arguments, err => updateField(field, err))
|
|
108
|
+
return super.configure(validated)
|
|
171
109
|
}
|
|
172
|
-
|
|
173
|
-
patchedResolvers.add(resolveWithTrace)
|
|
174
|
-
|
|
175
|
-
return resolveWithTrace
|
|
176
110
|
}
|
|
177
111
|
|
|
178
|
-
|
|
179
|
-
const scope = span.tracer().scope()
|
|
180
|
-
|
|
181
|
-
callback = callback || (() => {})
|
|
112
|
+
// config validator helpers
|
|
182
113
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
)
|
|
191
|
-
} else {
|
|
192
|
-
callback(null, result)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return result
|
|
196
|
-
} catch (e) {
|
|
197
|
-
callback(e)
|
|
198
|
-
throw e
|
|
199
|
-
}
|
|
114
|
+
function validateConfig (config) {
|
|
115
|
+
return Object.assign({}, config, {
|
|
116
|
+
depth: getDepth(config),
|
|
117
|
+
variables: getVariablesFilter(config),
|
|
118
|
+
collapse: config.collapse === undefined || !!config.collapse,
|
|
119
|
+
hooks: getHooks(config)
|
|
120
|
+
})
|
|
200
121
|
}
|
|
201
122
|
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return field
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
span: context.span
|
|
123
|
+
function getDepth (config) {
|
|
124
|
+
if (typeof config.depth === 'number') {
|
|
125
|
+
return config.depth
|
|
126
|
+
} else if (config.hasOwnProperty('depth')) {
|
|
127
|
+
log.error('Expected `depth` to be a integer.')
|
|
213
128
|
}
|
|
129
|
+
return -1
|
|
214
130
|
}
|
|
215
131
|
|
|
216
|
-
function
|
|
217
|
-
|
|
132
|
+
function getVariablesFilter (config) {
|
|
133
|
+
if (typeof config.variables === 'function') {
|
|
134
|
+
return config.variables
|
|
135
|
+
} else if (config.variables instanceof Array) {
|
|
136
|
+
return variables => pick(variables, config.variables)
|
|
137
|
+
} else if (config.hasOwnProperty('variables')) {
|
|
138
|
+
log.error('Expected `variables` to be an array or function.')
|
|
139
|
+
}
|
|
140
|
+
return null
|
|
218
141
|
}
|
|
219
142
|
|
|
220
|
-
function
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
return args[0]
|
|
227
|
-
}
|
|
143
|
+
function getHooks (config) {
|
|
144
|
+
const noop = () => { }
|
|
145
|
+
const execute = (config.hooks && config.hooks.execute) || noop
|
|
146
|
+
const parse = (config.hooks && config.hooks.parse) || noop
|
|
147
|
+
const validate = (config.hooks && config.hooks.validate) || noop
|
|
228
148
|
|
|
229
|
-
|
|
230
|
-
args[3] = args[3] || {} // contextValue
|
|
231
|
-
args[6] = wrapResolve(args[6] || defaultFieldResolver, tracer, config) // fieldResolver
|
|
232
|
-
args.length = Math.max(args.length, 7)
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
schema: args[0],
|
|
236
|
-
document: args[1],
|
|
237
|
-
rootValue: args[2],
|
|
238
|
-
contextValue: args[3],
|
|
239
|
-
variableValues: args[4],
|
|
240
|
-
operationName: args[5],
|
|
241
|
-
fieldResolver: args[6]
|
|
242
|
-
}
|
|
149
|
+
return { execute, parse, validate }
|
|
243
150
|
}
|
|
244
151
|
|
|
245
|
-
|
|
246
|
-
const span = startSpan(tracer, config, 'execute')
|
|
152
|
+
// non-lodash pick
|
|
247
153
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
154
|
+
function pick (obj, selectors) {
|
|
155
|
+
return Object.fromEntries(Object.entries(obj).filter(([key]) => selectors.includes(key)))
|
|
156
|
+
}
|
|
251
157
|
|
|
252
|
-
|
|
158
|
+
// span-related
|
|
253
159
|
|
|
254
|
-
|
|
160
|
+
function startSpan (name, conf, tracer, store, options) {
|
|
161
|
+
const service = conf.service || tracer._service
|
|
162
|
+
const childOf = store ? store.span : store
|
|
163
|
+
options = options || {}
|
|
164
|
+
return tracer.startSpan(`graphql.${name}`, {
|
|
165
|
+
childOf: options.childOf || childOf,
|
|
166
|
+
startTime: options.startTime,
|
|
167
|
+
tags: {
|
|
168
|
+
'service.name': service,
|
|
169
|
+
'span.type': 'graphql'
|
|
170
|
+
}
|
|
171
|
+
})
|
|
255
172
|
}
|
|
256
173
|
|
|
257
|
-
function addExecutionTags (span, config, operation, document
|
|
174
|
+
function addExecutionTags (span, config, operation, document) {
|
|
258
175
|
const type = operation && operation.operation
|
|
259
176
|
const name = operation && operation.name && operation.name.value
|
|
260
177
|
const tags = {
|
|
@@ -272,17 +189,17 @@ function addExecutionTags (span, config, operation, document, operationName) {
|
|
|
272
189
|
span.addTags(tags)
|
|
273
190
|
}
|
|
274
191
|
|
|
275
|
-
function addDocumentTags (span, document, config) {
|
|
192
|
+
function addDocumentTags (span, document, config, docSource) {
|
|
276
193
|
const tags = {}
|
|
277
194
|
|
|
278
195
|
if (config.source && document) {
|
|
279
|
-
tags['graphql.source'] =
|
|
196
|
+
tags['graphql.source'] = docSource
|
|
280
197
|
}
|
|
281
198
|
|
|
282
199
|
span.addTags(tags)
|
|
283
200
|
}
|
|
284
201
|
|
|
285
|
-
function addVariableTags (
|
|
202
|
+
function addVariableTags (config, span, variableValues) {
|
|
286
203
|
const tags = {}
|
|
287
204
|
|
|
288
205
|
if (variableValues && config.variables) {
|
|
@@ -295,155 +212,6 @@ function addVariableTags (tracer, config, span, variableValues) {
|
|
|
295
212
|
span.addTags(tags)
|
|
296
213
|
}
|
|
297
214
|
|
|
298
|
-
function startSpan (tracer, config, name, options) {
|
|
299
|
-
options = options || {}
|
|
300
|
-
|
|
301
|
-
return tracer.startSpan(`graphql.${name}`, {
|
|
302
|
-
childOf: options.childOf || tracer.scope().active(),
|
|
303
|
-
startTime: options.startTime,
|
|
304
|
-
tags: {
|
|
305
|
-
'service.name': getService(tracer, config),
|
|
306
|
-
'span.type': 'graphql'
|
|
307
|
-
}
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function startResolveSpan (tracer, config, childOf, path, info, { source }) {
|
|
312
|
-
const span = startSpan(tracer, config, 'resolve', { childOf })
|
|
313
|
-
const document = source
|
|
314
|
-
const fieldNode = info.fieldNodes.find(fieldNode => fieldNode.kind === 'Field')
|
|
315
|
-
|
|
316
|
-
analyticsSampler.sample(span, config.measured)
|
|
317
|
-
|
|
318
|
-
span.addTags({
|
|
319
|
-
'resource.name': `${info.fieldName}:${info.returnType}`,
|
|
320
|
-
'graphql.field.name': info.fieldName,
|
|
321
|
-
'graphql.field.path': path.join('.'),
|
|
322
|
-
'graphql.field.type': info.returnType.name
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
if (fieldNode) {
|
|
326
|
-
if (config.source && document && fieldNode.loc) {
|
|
327
|
-
span.setTag('graphql.source', document.substring(fieldNode.loc.start, fieldNode.loc.end))
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (config.variables && fieldNode.arguments) {
|
|
331
|
-
const variables = config.variables(info.variableValues)
|
|
332
|
-
|
|
333
|
-
fieldNode.arguments
|
|
334
|
-
.filter(arg => arg.value && arg.value.kind === 'Variable')
|
|
335
|
-
.filter(arg => arg.value.name && variables[arg.value.name.value])
|
|
336
|
-
.map(arg => arg.value.name.value)
|
|
337
|
-
.forEach(name => {
|
|
338
|
-
span.setTag(`graphql.variables.${name}`, variables[name])
|
|
339
|
-
})
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return span
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function setError (span, error) {
|
|
347
|
-
if (error) {
|
|
348
|
-
span.setTag('error', error)
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function finish (span, finishTime) {
|
|
353
|
-
span.finish(finishTime)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function finishResolvers ({ fields }) {
|
|
357
|
-
Object.keys(fields).reverse().forEach(key => {
|
|
358
|
-
const field = fields[key]
|
|
359
|
-
|
|
360
|
-
setError(field.span, field.error)
|
|
361
|
-
finish(field.span, field.finishTime)
|
|
362
|
-
})
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function updateField (field, error) {
|
|
366
|
-
// TODO: update this to also work with no-op spans without a hack
|
|
367
|
-
field.finishTime = field.span._getTime ? field.span._getTime() : 0
|
|
368
|
-
field.error = field.error || error
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function withCollapse (responsePathAsArray) {
|
|
372
|
-
return function () {
|
|
373
|
-
return responsePathAsArray.apply(this, arguments)
|
|
374
|
-
.map(segment => typeof segment === 'number' ? '*' : segment)
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function assertField (tracer, config, context, info, path) {
|
|
379
|
-
const pathString = path.join('.')
|
|
380
|
-
const fields = context.fields
|
|
381
|
-
|
|
382
|
-
let field = fields[pathString]
|
|
383
|
-
|
|
384
|
-
if (!field) {
|
|
385
|
-
const parent = getParentField(tracer, context, path)
|
|
386
|
-
|
|
387
|
-
field = fields[pathString] = {
|
|
388
|
-
parent,
|
|
389
|
-
span: startResolveSpan(tracer, config, parent.span, path, info, context),
|
|
390
|
-
error: null
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return field
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function getService (tracer, config) {
|
|
398
|
-
return config.service || tracer._service
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function getOperation (document, operationName) {
|
|
402
|
-
if (!document || !Array.isArray(document.definitions)) {
|
|
403
|
-
return
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const definitions = document.definitions.filter(def => def)
|
|
407
|
-
const types = ['query', 'mutation', 'subscription']
|
|
408
|
-
|
|
409
|
-
if (operationName) {
|
|
410
|
-
return definitions
|
|
411
|
-
.filter(def => types.indexOf(def.operation) !== -1)
|
|
412
|
-
.find(def => operationName === (def.name && def.name.value))
|
|
413
|
-
} else {
|
|
414
|
-
return definitions.find(def => types.indexOf(def.operation) !== -1)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function validateConfig (config) {
|
|
419
|
-
return Object.assign({}, config, {
|
|
420
|
-
depth: getDepth(config),
|
|
421
|
-
variables: getVariablesFilter(config),
|
|
422
|
-
collapse: config.collapse === undefined || !!config.collapse,
|
|
423
|
-
hooks: getHooks(config)
|
|
424
|
-
})
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function getDepth (config) {
|
|
428
|
-
if (typeof config.depth === 'number') {
|
|
429
|
-
return config.depth
|
|
430
|
-
} else if (config.hasOwnProperty('depth')) {
|
|
431
|
-
log.error('Expected `depth` to be a integer.')
|
|
432
|
-
}
|
|
433
|
-
return -1
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function getVariablesFilter (config) {
|
|
437
|
-
if (typeof config.variables === 'function') {
|
|
438
|
-
return config.variables
|
|
439
|
-
} else if (config.variables instanceof Array) {
|
|
440
|
-
return variables => pick(variables, config.variables)
|
|
441
|
-
} else if (config.hasOwnProperty('variables')) {
|
|
442
|
-
log.error('Expected `variables` to be an array or function.')
|
|
443
|
-
}
|
|
444
|
-
return null
|
|
445
|
-
}
|
|
446
|
-
|
|
447
215
|
function getSignature (document, operationName, operationType, calculate) {
|
|
448
216
|
if (calculate !== false && tools !== false) {
|
|
449
217
|
try {
|
|
@@ -463,61 +231,4 @@ function getSignature (document, operationName, operationType, calculate) {
|
|
|
463
231
|
return [operationType, operationName].filter(val => val).join(' ')
|
|
464
232
|
}
|
|
465
233
|
|
|
466
|
-
|
|
467
|
-
const flattened = []
|
|
468
|
-
let curr = path
|
|
469
|
-
while (curr) {
|
|
470
|
-
flattened.push(curr.key)
|
|
471
|
-
curr = curr.prev
|
|
472
|
-
}
|
|
473
|
-
return flattened.reverse()
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
function getHooks (config) {
|
|
477
|
-
const noop = () => {}
|
|
478
|
-
const execute = (config.hooks && config.hooks.execute) || noop
|
|
479
|
-
const parse = (config.hooks && config.hooks.parse) || noop
|
|
480
|
-
const validate = (config.hooks && config.hooks.validate) || noop
|
|
481
|
-
|
|
482
|
-
return { execute, parse, validate }
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
module.exports = [
|
|
486
|
-
{
|
|
487
|
-
name: 'graphql',
|
|
488
|
-
file: 'execution/execute.js',
|
|
489
|
-
versions: ['>=0.10'],
|
|
490
|
-
patch (execute, tracer, config) {
|
|
491
|
-
this.wrap(execute, 'execute', createWrapExecute(
|
|
492
|
-
tracer,
|
|
493
|
-
validateConfig(config),
|
|
494
|
-
execute.defaultFieldResolver
|
|
495
|
-
))
|
|
496
|
-
},
|
|
497
|
-
unpatch (execute) {
|
|
498
|
-
this.unwrap(execute, 'execute')
|
|
499
|
-
}
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
name: 'graphql',
|
|
503
|
-
file: 'language/parser.js',
|
|
504
|
-
versions: ['>=0.10'],
|
|
505
|
-
patch (parser, tracer, config) {
|
|
506
|
-
this.wrap(parser, 'parse', createWrapParse(tracer, validateConfig(config)))
|
|
507
|
-
},
|
|
508
|
-
unpatch (parser) {
|
|
509
|
-
this.unwrap(parser, 'parse')
|
|
510
|
-
}
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
name: 'graphql',
|
|
514
|
-
file: 'validation/validate.js',
|
|
515
|
-
versions: ['>=0.10'],
|
|
516
|
-
patch (validate, tracer, config) {
|
|
517
|
-
this.wrap(validate, 'validate', createWrapValidate(tracer, validateConfig(config)))
|
|
518
|
-
},
|
|
519
|
-
unpatch (validate) {
|
|
520
|
-
this.unwrap(validate, 'validate')
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
]
|
|
234
|
+
module.exports = GraphQLPlugin
|