dd-trace 6.8.0 → 6.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/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +9 -3
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +38 -28
- package/ci/test-optimization-validation/generated-test-contract.js +8 -4
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +300 -50
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +40 -20
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +59 -5
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +140 -42
- package/index.d.ts +140 -1
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +8 -5
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/src/utils.js +16 -1
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +81 -5
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/cucumber.js +124 -47
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +629 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +199 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +62 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +37 -6
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +980 -234
- package/packages/datadog-instrumentations/src/mocha/main.js +108 -10
- package/packages/datadog-instrumentations/src/mocha/utils.js +66 -50
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +25 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -18
- package/packages/datadog-instrumentations/src/mysql.js +46 -16
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +209 -11
- package/packages/datadog-instrumentations/src/playwright.js +173 -79
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +85 -13
- package/packages/datadog-instrumentations/src/vitest-main.js +528 -72
- package/packages/datadog-instrumentations/src/vitest-util.js +106 -12
- package/packages/datadog-instrumentations/src/vitest-worker.js +382 -40
- package/packages/datadog-instrumentations/src/webdriverio.js +212 -22
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +51 -47
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +6 -22
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +5 -3
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +832 -4
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-next/src/index.js +51 -21
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-openai-agents/src/integration.js +278 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +66 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +103 -27
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +228 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +9 -0
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +27 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +21 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +5 -0
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +16 -5
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +18 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/manager.js +5 -1
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +33 -25
- package/packages/dd-trace/src/llmobs/experiments/util.js +4 -2
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +149 -68
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +6 -0
- package/packages/dd-trace/src/plugins/util/git.js +6 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +2 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +3 -62
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/test.js +397 -74
- package/packages/dd-trace/src/plugins/util/url.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +76 -3
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
const {
|
|
6
|
+
dispatchesAcquireSynchronously,
|
|
7
|
+
takePoolWaitTime,
|
|
8
|
+
wrapPoolClusterQueryMethod,
|
|
9
|
+
wrapPoolGetConnection,
|
|
10
|
+
wrapPoolQueryMethod,
|
|
11
|
+
} = require('./helpers/pool-acquire')
|
|
5
12
|
|
|
6
13
|
addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connection => {
|
|
7
14
|
const startCh = channel('apm:mysql:query:start')
|
|
@@ -17,6 +24,11 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
|
|
|
17
24
|
const conf = this.config
|
|
18
25
|
const ctx = { sql, conf }
|
|
19
26
|
|
|
27
|
+
const waitTime = takePoolWaitTime(this)
|
|
28
|
+
if (waitTime !== undefined) {
|
|
29
|
+
ctx.poolWaitTime = waitTime
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
return startCh.runStores(ctx, () => {
|
|
21
33
|
if (args[0].sql) {
|
|
22
34
|
args[0].sql = ctx.sql
|
|
@@ -36,7 +48,7 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
|
|
|
36
48
|
}
|
|
37
49
|
ctx.result = result
|
|
38
50
|
|
|
39
|
-
return finishCh.runStores(ctx, cb, this,
|
|
51
|
+
return finishCh.runStores(ctx, cb, this, ...arguments)
|
|
40
52
|
})
|
|
41
53
|
} else {
|
|
42
54
|
res.once('end', () => finishCh.publish(ctx))
|
|
@@ -61,20 +73,24 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
|
|
|
61
73
|
const connectionFinishCh = channel('apm:mysql:connection:finish')
|
|
62
74
|
const startPoolQueryCh = channel('datadog:mysql:pool:query:start')
|
|
63
75
|
const finishPoolQueryCh = channel('datadog:mysql:pool:query:finish')
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
const acquireStartCh = channel('apm:mysql:pool:acquire:start')
|
|
77
|
+
const acquireFinishCh = channel('apm:mysql:pool:acquire:finish')
|
|
78
|
+
const deferredPoolAcquire = !dispatchesAcquireSynchronously(
|
|
79
|
+
Pool.prototype.query,
|
|
80
|
+
Object.assign(Object.create(Pool.prototype), { config: { connectionConfig: {} } }),
|
|
81
|
+
'getConnection',
|
|
82
|
+
['SELECT 1', () => {}]
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
shimmer.wrap(Pool.prototype, 'getConnection', getConnection => wrapPoolGetConnection(getConnection, {
|
|
86
|
+
connectionStartCh,
|
|
87
|
+
connectionFinishCh,
|
|
88
|
+
acquireStartCh,
|
|
89
|
+
acquireFinishCh,
|
|
90
|
+
reentersQueuedCallbacks: true,
|
|
91
|
+
}, deferredPoolAcquire))
|
|
92
|
+
|
|
93
|
+
shimmer.wrap(Pool.prototype, 'query', query => wrapPoolQueryMethod(function (...args) {
|
|
78
94
|
if (!startPoolQueryCh.hasSubscribers) {
|
|
79
95
|
return query.apply(this, args)
|
|
80
96
|
}
|
|
@@ -99,7 +115,21 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
|
|
|
99
115
|
|
|
100
116
|
return retval
|
|
101
117
|
})
|
|
102
|
-
})
|
|
118
|
+
}, connectionStartCh, deferredPoolAcquire))
|
|
103
119
|
|
|
104
120
|
return Pool
|
|
105
121
|
})
|
|
122
|
+
|
|
123
|
+
// A `canRetry` failover re-invokes `query` with the same Query object. Key the acquire state by that
|
|
124
|
+
// object so a retry remains part of the query even if a future mysql version defers it.
|
|
125
|
+
addHook({ name: 'mysql', file: 'lib/PoolNamespace.js', versions: ['>=2'] }, PoolNamespace => {
|
|
126
|
+
const channels = {
|
|
127
|
+
connectionStartCh: channel('apm:mysql:connection:start'),
|
|
128
|
+
connectionFinishCh: channel('apm:mysql:connection:finish'),
|
|
129
|
+
acquireStartCh: channel('apm:mysql:pool:acquire:start'),
|
|
130
|
+
acquireFinishCh: channel('apm:mysql:pool:acquire:finish'),
|
|
131
|
+
}
|
|
132
|
+
shimmer.wrap(PoolNamespace.prototype, 'query', query => wrapPoolClusterQueryMethod(query, channels))
|
|
133
|
+
|
|
134
|
+
return PoolNamespace
|
|
135
|
+
})
|
|
@@ -5,10 +5,55 @@ const { errorMonitor } = require('node:events')
|
|
|
5
5
|
const shimmer = require('../../datadog-shimmer')
|
|
6
6
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
7
7
|
const { channel, addHook } = require('./helpers/instrument')
|
|
8
|
+
const {
|
|
9
|
+
dispatchesAcquireSynchronously,
|
|
10
|
+
takePoolWaitTime,
|
|
11
|
+
wrapPoolClusterGetConnection,
|
|
12
|
+
wrapPoolClusterMethod,
|
|
13
|
+
wrapPoolGetConnection,
|
|
14
|
+
wrapPoolQueryMethod,
|
|
15
|
+
} = require('./helpers/pool-acquire')
|
|
8
16
|
|
|
9
17
|
/** @type {WeakMap<object, Function>} */
|
|
10
18
|
const wrappedOnResult = new WeakMap()
|
|
11
19
|
|
|
20
|
+
/** @type {WeakSet<object>} */
|
|
21
|
+
const flagWrappedNamespaces = new WeakSet()
|
|
22
|
+
|
|
23
|
+
const connectionStartCh = channel('apm:mysql2:connection:start')
|
|
24
|
+
const connectionFinishCh = channel('apm:mysql2:connection:finish')
|
|
25
|
+
const acquireStartCh = channel('apm:mysql2:pool:acquire:start')
|
|
26
|
+
const acquireFinishCh = channel('apm:mysql2:pool:acquire:finish')
|
|
27
|
+
const poolAcquireChannels = {
|
|
28
|
+
connectionStartCh,
|
|
29
|
+
connectionFinishCh,
|
|
30
|
+
acquireStartCh,
|
|
31
|
+
acquireFinishCh,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Bracket a pool-cluster namespace's internal acquires and key retry state by its stable callback.
|
|
36
|
+
* @param {{ query?: Function, execute?: Function, getConnection?: Function }} poolNamespace
|
|
37
|
+
*/
|
|
38
|
+
function flagWrapNamespace (poolNamespace) {
|
|
39
|
+
if (poolNamespace == null || flagWrappedNamespaces.has(poolNamespace)) return
|
|
40
|
+
flagWrappedNamespaces.add(poolNamespace)
|
|
41
|
+
|
|
42
|
+
if (typeof poolNamespace.query === 'function') {
|
|
43
|
+
shimmer.wrap(poolNamespace, 'query', query => wrapPoolClusterMethod(query, connectionStartCh))
|
|
44
|
+
}
|
|
45
|
+
if (typeof poolNamespace.execute === 'function') {
|
|
46
|
+
shimmer.wrap(poolNamespace, 'execute', execute => wrapPoolClusterMethod(execute, connectionStartCh))
|
|
47
|
+
}
|
|
48
|
+
if (typeof poolNamespace.getConnection === 'function') {
|
|
49
|
+
shimmer.wrap(
|
|
50
|
+
poolNamespace,
|
|
51
|
+
'getConnection',
|
|
52
|
+
getConnection => wrapPoolClusterGetConnection(getConnection, poolAcquireChannels)
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
12
57
|
/**
|
|
13
58
|
* @param {unknown} sql
|
|
14
59
|
* @returns {string|undefined}
|
|
@@ -43,6 +88,11 @@ function wrapConnection (Connection, version) {
|
|
|
43
88
|
const ctx = {}
|
|
44
89
|
|
|
45
90
|
if (isQuery) {
|
|
91
|
+
const waitTime = takePoolWaitTime(this)
|
|
92
|
+
if (waitTime !== undefined) {
|
|
93
|
+
ctx.poolWaitTime = waitTime
|
|
94
|
+
}
|
|
95
|
+
|
|
46
96
|
command.execute = wrapExecute(command, command.execute, ctx, this.config)
|
|
47
97
|
|
|
48
98
|
return commandAddCh.runStores(ctx, addCommand, this, ...arguments)
|
|
@@ -212,22 +262,41 @@ function wrapConnection (Connection, version) {
|
|
|
212
262
|
* by the queued query attach to the caller rather than the previous query that freed the connection.
|
|
213
263
|
*
|
|
214
264
|
* @param {Function} Pool
|
|
265
|
+
* @param {boolean} deferredPoolAcquire
|
|
215
266
|
* @returns {Function}
|
|
216
267
|
*/
|
|
217
|
-
function wrapGetConnection (Pool) {
|
|
218
|
-
|
|
219
|
-
|
|
268
|
+
function wrapGetConnection (Pool, deferredPoolAcquire) {
|
|
269
|
+
shimmer.wrap(
|
|
270
|
+
Pool.prototype,
|
|
271
|
+
'getConnection',
|
|
272
|
+
getConnection => wrapPoolGetConnection(getConnection, poolAcquireChannels, deferredPoolAcquire)
|
|
273
|
+
)
|
|
220
274
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
arguments[0] = function (...args) {
|
|
224
|
-
return connectionFinishCh.runStores(ctx, cb, this, ...args)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
connectionStartCh.publish(ctx)
|
|
275
|
+
return Pool
|
|
276
|
+
}
|
|
228
277
|
|
|
229
|
-
|
|
230
|
-
|
|
278
|
+
/**
|
|
279
|
+
* mysql2 >=3.11.5 keeps the outer-query abort at the connection level, so the pool only needs the
|
|
280
|
+
* acquire wrap plus the pool-query flag around `query` / `execute`.
|
|
281
|
+
*
|
|
282
|
+
* @param {Function} Pool
|
|
283
|
+
* @returns {Function}
|
|
284
|
+
*/
|
|
285
|
+
function wrapBasePool (Pool) {
|
|
286
|
+
const deferredQueryAcquire = defersPoolAcquire(Pool, 'query')
|
|
287
|
+
const deferredExecuteAcquire = defersPoolAcquire(Pool, 'execute')
|
|
288
|
+
wrapGetConnection(Pool, deferredQueryAcquire || deferredExecuteAcquire)
|
|
289
|
+
|
|
290
|
+
shimmer.wrap(
|
|
291
|
+
Pool.prototype,
|
|
292
|
+
'query',
|
|
293
|
+
query => wrapPoolQueryMethod(query, connectionStartCh, deferredQueryAcquire)
|
|
294
|
+
)
|
|
295
|
+
shimmer.wrap(
|
|
296
|
+
Pool.prototype,
|
|
297
|
+
'execute',
|
|
298
|
+
execute => wrapPoolQueryMethod(execute, connectionStartCh, deferredExecuteAcquire)
|
|
299
|
+
)
|
|
231
300
|
|
|
232
301
|
return Pool
|
|
233
302
|
}
|
|
@@ -240,10 +309,12 @@ function wrapGetConnection (Pool) {
|
|
|
240
309
|
function wrapPool (Pool, version) {
|
|
241
310
|
const startOuterQueryCh = channel('datadog:mysql2:outerquery:start')
|
|
242
311
|
const shouldEmitEndAfterQueryAbort = satisfies(version, '>=1.3.3')
|
|
312
|
+
const deferredQueryAcquire = defersPoolAcquire(Pool, 'query')
|
|
313
|
+
const deferredExecuteAcquire = defersPoolAcquire(Pool, 'execute')
|
|
243
314
|
|
|
244
|
-
wrapGetConnection(Pool)
|
|
315
|
+
wrapGetConnection(Pool, deferredQueryAcquire || deferredExecuteAcquire)
|
|
245
316
|
|
|
246
|
-
shimmer.wrap(Pool.prototype, 'query', query => function (sql, values, cb) {
|
|
317
|
+
shimmer.wrap(Pool.prototype, 'query', query => wrapPoolQueryMethod(function (sql, values, cb) {
|
|
247
318
|
if (!startOuterQueryCh.hasSubscribers) return query.apply(this, arguments)
|
|
248
319
|
|
|
249
320
|
const resolvedSql = resolveSqlString(sql)
|
|
@@ -279,9 +350,9 @@ function wrapPool (Pool, version) {
|
|
|
279
350
|
}
|
|
280
351
|
|
|
281
352
|
return query.apply(this, arguments)
|
|
282
|
-
})
|
|
353
|
+
}, connectionStartCh, deferredQueryAcquire))
|
|
283
354
|
|
|
284
|
-
shimmer.wrap(Pool.prototype, 'execute', execute => function (sql, values, cb) {
|
|
355
|
+
shimmer.wrap(Pool.prototype, 'execute', execute => wrapPoolQueryMethod(function (sql, values, cb) {
|
|
285
356
|
if (!startOuterQueryCh.hasSubscribers) return execute.apply(this, arguments)
|
|
286
357
|
|
|
287
358
|
const resolvedSql = resolveSqlString(sql)
|
|
@@ -304,11 +375,25 @@ function wrapPool (Pool, version) {
|
|
|
304
375
|
}
|
|
305
376
|
|
|
306
377
|
return execute.apply(this, arguments)
|
|
307
|
-
})
|
|
378
|
+
}, connectionStartCh, deferredExecuteAcquire))
|
|
308
379
|
|
|
309
380
|
return Pool
|
|
310
381
|
}
|
|
311
382
|
|
|
383
|
+
/**
|
|
384
|
+
* @param {Function} Pool
|
|
385
|
+
* @param {'query'|'execute'} method
|
|
386
|
+
* @returns {boolean}
|
|
387
|
+
*/
|
|
388
|
+
function defersPoolAcquire (Pool, method) {
|
|
389
|
+
return !dispatchesAcquireSynchronously(
|
|
390
|
+
Pool.prototype[method],
|
|
391
|
+
Object.assign(Object.create(Pool.prototype), { config: { connectionConfig: {} } }),
|
|
392
|
+
'getConnection',
|
|
393
|
+
['SELECT 1', () => {}]
|
|
394
|
+
)
|
|
395
|
+
}
|
|
396
|
+
|
|
312
397
|
/**
|
|
313
398
|
* @param {Function} PoolCluster
|
|
314
399
|
* @returns {Function}
|
|
@@ -319,6 +404,7 @@ function wrapPoolCluster (PoolCluster) {
|
|
|
319
404
|
|
|
320
405
|
shimmer.wrap(PoolCluster.prototype, 'of', of => function (...args) {
|
|
321
406
|
const poolNamespace = of.apply(this, args)
|
|
407
|
+
flagWrapNamespace(poolNamespace)
|
|
322
408
|
|
|
323
409
|
if (startOuterQueryCh.hasSubscribers && !wrappedPoolNamespaces.has(poolNamespace)) {
|
|
324
410
|
shimmer.wrap(poolNamespace, 'query', query => function (sql, values, cb) {
|
|
@@ -404,7 +490,7 @@ addHook(
|
|
|
404
490
|
// mysql2 >=3.11.5 moved the pool onto BasePool in lib/base/pool.js.
|
|
405
491
|
addHook(
|
|
406
492
|
{ name: 'mysql2', file: 'lib/base/pool.js', versions: ['>=3.11.5'] },
|
|
407
|
-
/** @type {(moduleExports: unknown, version: string) => unknown} */ (
|
|
493
|
+
/** @type {(moduleExports: unknown, version: string) => unknown} */ (wrapBasePool)
|
|
408
494
|
)
|
|
409
495
|
|
|
410
496
|
// PoolNamespace.prototype.query does not exist in mysql2<2.3.0
|
|
@@ -412,3 +498,18 @@ addHook(
|
|
|
412
498
|
{ name: 'mysql2', file: 'lib/pool_cluster.js', versions: ['2.3.0 - 3.11.4'] },
|
|
413
499
|
/** @type {(moduleExports: unknown, version: string) => unknown} */ (wrapPoolCluster)
|
|
414
500
|
)
|
|
501
|
+
|
|
502
|
+
// mysql2 >=3.11.5 keeps the outer-query abort at the connection level, so a cluster namespace only
|
|
503
|
+
// needs the pool-query flag so its internal query/execute acquire does not open an acquire span.
|
|
504
|
+
addHook(
|
|
505
|
+
{ name: 'mysql2', file: 'lib/pool_cluster.js', versions: ['>=3.11.5'] },
|
|
506
|
+
/** @type {(moduleExports: unknown, version: string) => unknown} */ (PoolCluster => {
|
|
507
|
+
shimmer.wrap(PoolCluster.prototype, 'of', of => function () {
|
|
508
|
+
const poolNamespace = of.apply(this, arguments)
|
|
509
|
+
flagWrapNamespace(poolNamespace)
|
|
510
|
+
return poolNamespace
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
return PoolCluster
|
|
514
|
+
})
|
|
515
|
+
)
|
|
@@ -15,6 +15,7 @@ const queryParsedChannel = channel('apm:next:query-parsed')
|
|
|
15
15
|
|
|
16
16
|
const requests = new WeakSet()
|
|
17
17
|
const nodeNextRequestsToNextRequests = new WeakMap()
|
|
18
|
+
const requestErrors = new WeakMap()
|
|
18
19
|
|
|
19
20
|
// Next.js <= 14.2.6
|
|
20
21
|
const MIDDLEWARE_HEADER = 'x-middleware-invoke'
|
|
@@ -213,10 +214,8 @@ function wrapServeStatic (serveStatic) {
|
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
function finish (ctx, result, err) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
errorChannel.publish(ctx)
|
|
219
|
-
}
|
|
217
|
+
publishError(ctx.req, ctx, err)
|
|
218
|
+
requestErrors.delete(ctx.req)
|
|
220
219
|
|
|
221
220
|
const maybeNextRequest = nodeNextRequestsToNextRequests.get(ctx.req)
|
|
222
221
|
if (maybeNextRequest) {
|
|
@@ -226,6 +225,27 @@ function finish (ctx, result, err) {
|
|
|
226
225
|
finishChannel.publish(ctx)
|
|
227
226
|
}
|
|
228
227
|
|
|
228
|
+
function publishError (req, ctx, error) {
|
|
229
|
+
if (!error) return
|
|
230
|
+
|
|
231
|
+
req = req.originalRequest || req
|
|
232
|
+
let errors = requestErrors.get(req)
|
|
233
|
+
if (errors?.has(error)) return
|
|
234
|
+
|
|
235
|
+
if (!errors) {
|
|
236
|
+
errors = new Set()
|
|
237
|
+
requestErrors.set(req, errors)
|
|
238
|
+
}
|
|
239
|
+
errors.add(error)
|
|
240
|
+
|
|
241
|
+
if (ctx) {
|
|
242
|
+
ctx.error = error
|
|
243
|
+
errorChannel.publish(ctx)
|
|
244
|
+
} else {
|
|
245
|
+
errorChannel.publish({ error })
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
229
249
|
// also wrapped in dist/server/future/route-handlers/app-route-route-handler.js
|
|
230
250
|
// in versions below 13.3.0 that support middleware,
|
|
231
251
|
// however, it is not provided as a class function or exported property
|
|
@@ -244,15 +264,11 @@ addHook({
|
|
|
244
264
|
return NextRequestAdapter
|
|
245
265
|
})
|
|
246
266
|
|
|
247
|
-
// From
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// bundled. The bundler/experimental part of the name is matched with a pattern rather than
|
|
253
|
-
// enumerated, so a variant next adds later is picked up without a code change.
|
|
254
|
-
const patchedAppRouteModules = new WeakSet()
|
|
255
|
-
|
|
267
|
+
// From Next 15.4.1, route modules execute through precompiled runtime bundles that bypass the
|
|
268
|
+
// classic server hooks above. Match bundler and experimental filename variants without enumerating
|
|
269
|
+
// them so App Routes, Pages APIs, and App Pages reuse the existing Next request lifecycle.
|
|
270
|
+
const patchedRouteModules = new WeakSet()
|
|
271
|
+
const COMPILED_RUNTIME_PATH = 'dist/compiled/next-server/'
|
|
256
272
|
function wrapOnRequestError (onRequestError) {
|
|
257
273
|
return function (req, error) {
|
|
258
274
|
if (error) {
|
|
@@ -262,21 +278,137 @@ function wrapOnRequestError (onRequestError) {
|
|
|
262
278
|
}
|
|
263
279
|
}
|
|
264
280
|
|
|
265
|
-
function
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
281
|
+
function getRoutePage (routeModule, fallbackPage) {
|
|
282
|
+
const definition = routeModule?.definition
|
|
283
|
+
if (typeof definition?.pathname === 'string') {
|
|
284
|
+
return { page: definition.pathname, isFilesystemPath: false }
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (typeof definition?.page === 'string') {
|
|
288
|
+
return { page: definition.page, isFilesystemPath: true }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return { page: fallbackPage, isFilesystemPath: false }
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function publishRoutePage (ctx, routeModule, fallbackPage, isAppPath) {
|
|
295
|
+
if (!ctx || !pageLoadChannel.hasSubscribers) return
|
|
296
|
+
|
|
297
|
+
const pageData = getRoutePage(routeModule, fallbackPage)
|
|
298
|
+
if (pageData.page) {
|
|
299
|
+
pageLoadChannel.publish(isAppPath ? { ...pageData, isAppPath: true } : pageData)
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function wrapAppRouteHandle (handle) {
|
|
304
|
+
return function (req, context) {
|
|
305
|
+
if (!startChannel.hasSubscribers && !queryParsedChannel.hasSubscribers) {
|
|
306
|
+
return handle.apply(this, arguments)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const res = { statusCode: 500 }
|
|
310
|
+
nodeNextRequestsToNextRequests.set(req, req)
|
|
311
|
+
|
|
312
|
+
return instrument(req, res, ctx => {
|
|
313
|
+
publishRoutePage(ctx, this, undefined, true)
|
|
314
|
+
|
|
315
|
+
return handle.apply(this, arguments).then(response => {
|
|
316
|
+
if (ctx) ctx.res.statusCode = response?.status || 200
|
|
317
|
+
return response
|
|
318
|
+
})
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function instrumentRouteModule (RouteModule, method, wrapper, handleErrors) {
|
|
324
|
+
const proto = RouteModule?.prototype
|
|
325
|
+
if (!proto || patchedRouteModules.has(RouteModule)) return
|
|
326
|
+
|
|
327
|
+
patchedRouteModules.add(RouteModule)
|
|
328
|
+
if (typeof proto[method] === 'function') {
|
|
329
|
+
shimmer.wrap(proto, method, wrapper)
|
|
330
|
+
}
|
|
331
|
+
if (handleErrors && typeof proto.onRequestError === 'function') {
|
|
270
332
|
shimmer.wrap(proto, 'onRequestError', wrapOnRequestError)
|
|
271
333
|
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function instrumentAppRouteRuntime (runtime) {
|
|
337
|
+
instrumentRouteModule(runtime.AppRouteRouteModule, 'handle', wrapAppRouteHandle, true)
|
|
272
338
|
return runtime
|
|
273
339
|
}
|
|
274
340
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
341
|
+
function wrapPagesApiRender (render) {
|
|
342
|
+
return function (req, res, context = {}) {
|
|
343
|
+
if (!startChannel.hasSubscribers && !queryParsedChannel.hasSubscribers) {
|
|
344
|
+
return render.apply(this, arguments)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return instrument(req, res, ctx => {
|
|
348
|
+
publishRoutePage(ctx, this, context.page, false)
|
|
349
|
+
|
|
350
|
+
const { onError } = context
|
|
351
|
+
return render.call(this, req, res, {
|
|
352
|
+
...context,
|
|
353
|
+
onError: function (error) {
|
|
354
|
+
publishError(req, ctx, error)
|
|
355
|
+
return onError?.apply(this, arguments)
|
|
356
|
+
},
|
|
357
|
+
})
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function instrumentPagesApiRuntime (runtime) {
|
|
363
|
+
const PagesAPIRouteModule = runtime.PagesAPIRouteModule || runtime.default
|
|
364
|
+
instrumentRouteModule(PagesAPIRouteModule, 'render', wrapPagesApiRender, false)
|
|
365
|
+
return runtime
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function wrapAppPageRender (render) {
|
|
369
|
+
return function (req, res, context = {}) {
|
|
370
|
+
if (!startChannel.hasSubscribers && !queryParsedChannel.hasSubscribers) {
|
|
371
|
+
return render.apply(this, arguments)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return instrument(req, res, ctx => {
|
|
375
|
+
publishRoutePage(ctx, this, context.page, true)
|
|
376
|
+
|
|
377
|
+
return render.apply(this, arguments).then(result => {
|
|
378
|
+
const statusCode = result?.metadata?.statusCode
|
|
379
|
+
if (ctx && typeof statusCode === 'number') {
|
|
380
|
+
ctx.res.statusCode = statusCode
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return result
|
|
384
|
+
}, error => {
|
|
385
|
+
if (ctx && (typeof ctx.res.statusCode !== 'number' || ctx.res.statusCode < 400)) {
|
|
386
|
+
ctx.res.statusCode = 500
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
throw error
|
|
390
|
+
})
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function instrumentAppPageRuntime (runtime) {
|
|
396
|
+
const AppPageRouteModule = runtime.AppPageRouteModule || runtime.default
|
|
397
|
+
instrumentRouteModule(AppPageRouteModule, 'render', wrapAppPageRender, true)
|
|
398
|
+
return runtime
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
for (const [runtime, instrumentRuntime] of [
|
|
402
|
+
['app-route', instrumentAppRouteRuntime],
|
|
403
|
+
['pages-api', instrumentPagesApiRuntime],
|
|
404
|
+
['app-page', instrumentAppPageRuntime],
|
|
405
|
+
]) {
|
|
406
|
+
addHook({
|
|
407
|
+
name: 'next',
|
|
408
|
+
versions: ['>=15.4.1'],
|
|
409
|
+
filePattern: String.raw`${COMPILED_RUNTIME_PATH}${runtime}[\w-]*\.runtime\.(?:dev|prod)\.js$`,
|
|
410
|
+
}, instrumentRuntime)
|
|
411
|
+
}
|
|
280
412
|
|
|
281
413
|
addHook({
|
|
282
414
|
name: 'next',
|
|
@@ -210,10 +210,24 @@ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, expor
|
|
|
210
210
|
return exports
|
|
211
211
|
})
|
|
212
212
|
|
|
213
|
+
/**
|
|
214
|
+
* @typedef {{
|
|
215
|
+
* methodName: string,
|
|
216
|
+
* args: unknown[],
|
|
217
|
+
* basePath?: string,
|
|
218
|
+
* result?: Record<string, unknown>,
|
|
219
|
+
* error?: unknown,
|
|
220
|
+
* }} OpenAiContext
|
|
221
|
+
*/
|
|
222
|
+
|
|
213
223
|
/**
|
|
214
224
|
* For streamed responses, we need to accumulate all of the content in
|
|
215
225
|
* the chunks, and let the combined content be the final response.
|
|
216
226
|
* This way, spans look the same as when not streamed.
|
|
227
|
+
*
|
|
228
|
+
* @param {{ headers: unknown, url: string }} response
|
|
229
|
+
* @param {{ method: string }} options
|
|
230
|
+
* @param {OpenAiContext} ctx
|
|
217
231
|
*/
|
|
218
232
|
function wrapStreamIterator (response, options, ctx) {
|
|
219
233
|
return function (itr) {
|
|
@@ -5,6 +5,12 @@ const { addHook } = require('./helpers/instrument')
|
|
|
5
5
|
/** @type {((pattern: string | RegExp) => RegExp | undefined) | undefined} */
|
|
6
6
|
let compileToRegexp
|
|
7
7
|
|
|
8
|
+
/** @type {((pattern: string) => { tokens: object[] } | undefined) | undefined} */
|
|
9
|
+
let parseTokens
|
|
10
|
+
|
|
11
|
+
/** @type {((route: string) => ((url: string) => object | undefined) | undefined) | undefined} */
|
|
12
|
+
let makeMatcher
|
|
13
|
+
|
|
8
14
|
addHook({ name: 'path-to-regexp', versions: ['*'] }, moduleExports => {
|
|
9
15
|
// 0.1.x and 6.x: `module.exports = (path, ...) => RegExp`.
|
|
10
16
|
// 7.x: `module.exports = { pathToRegexp(path, ...) => RegExp }`.
|
|
@@ -29,6 +35,47 @@ addHook({ name: 'path-to-regexp', versions: ['*'] }, moduleExports => {
|
|
|
29
35
|
return moduleExports
|
|
30
36
|
})
|
|
31
37
|
|
|
38
|
+
// 8.x only: earlier majors also expose `parse`/`match`, but with incompatible shapes — 7.x returns
|
|
39
|
+
// `{ tokens }` too, yet its tokens are bare strings rather than typed nodes. Gating on the version
|
|
40
|
+
// keeps those from installing adapters the consumers would misread.
|
|
41
|
+
addHook({ name: 'path-to-regexp', versions: ['>=8'] }, moduleExports => {
|
|
42
|
+
const { parse, match } = moduleExports
|
|
43
|
+
|
|
44
|
+
if (typeof parse === 'function' && typeof match === 'function') {
|
|
45
|
+
parseTokens = pattern => {
|
|
46
|
+
let result
|
|
47
|
+
try {
|
|
48
|
+
result = parse(pattern)
|
|
49
|
+
} catch {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(result?.tokens)) return result
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
makeMatcher = route => {
|
|
56
|
+
let matcher
|
|
57
|
+
try {
|
|
58
|
+
// Callers read which params matched, never their values: skipping decode is faster and
|
|
59
|
+
// stops a malformed escape ('%ZZ') from throwing URIError, which would read as "no match".
|
|
60
|
+
matcher = match(route, { decode: false })
|
|
61
|
+
} catch {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
return url => {
|
|
65
|
+
let result
|
|
66
|
+
try {
|
|
67
|
+
result = matcher(url)
|
|
68
|
+
} catch {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
return result ? result.params : undefined
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return moduleExports
|
|
77
|
+
})
|
|
78
|
+
|
|
32
79
|
/**
|
|
33
80
|
* Returns whatever path-to-regexp compile adapter the host most recently
|
|
34
81
|
* loaded. Capture this once at addHook fire time so each express/router
|
|
@@ -41,4 +88,23 @@ function getCompileToRegexp () {
|
|
|
41
88
|
return compileToRegexp
|
|
42
89
|
}
|
|
43
90
|
|
|
44
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Returns the host's path-to-regexp `parse` adapter (8.x token tree), or `undefined` when the
|
|
93
|
+
* host has not loaded an 8.x path-to-regexp (e.g. Express 4 ships 0.1.x, which has no `parse`).
|
|
94
|
+
* @returns {((pattern: string) => { tokens: object[] } | undefined) | undefined}
|
|
95
|
+
*/
|
|
96
|
+
function getParse () {
|
|
97
|
+
return parseTokens
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the host's path-to-regexp 8.x `match` adapter: a factory `route => (url => params)` that
|
|
102
|
+
* compiles a route once and returns a matcher yielding the captured params (or undefined on no
|
|
103
|
+
* match / unusable route). `undefined` when the host has not loaded an 8.x path-to-regexp.
|
|
104
|
+
* @returns {((route: string) => ((url: string) => object | undefined) | undefined) | undefined}
|
|
105
|
+
*/
|
|
106
|
+
function getMatch () {
|
|
107
|
+
return makeMatcher
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = { getCompileToRegexp, getParse, getMatch }
|