dd-trace 5.72.0 → 5.74.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/LICENSE-3rdparty.csv +3 -0
- package/index.d.ts +49 -0
- package/package.json +11 -6
- package/packages/datadog-core/src/utils/src/set.js +5 -1
- package/packages/datadog-esbuild/index.js +112 -36
- package/packages/datadog-esbuild/src/utils.js +198 -0
- package/packages/datadog-instrumentations/src/azure-service-bus.js +49 -22
- package/packages/datadog-instrumentations/src/cookie-parser.js +2 -0
- package/packages/datadog-instrumentations/src/express-session.js +1 -0
- package/packages/datadog-instrumentations/src/express.js +82 -0
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +238 -0
- package/packages/datadog-instrumentations/src/jest.js +60 -14
- package/packages/datadog-instrumentations/src/mocha/utils.js +3 -4
- package/packages/datadog-instrumentations/src/playwright.js +110 -56
- package/packages/datadog-instrumentations/src/router.js +63 -6
- package/packages/datadog-instrumentations/src/ws.js +3 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +24 -14
- package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +60 -12
- package/packages/datadog-plugin-express/src/code_origin.js +2 -0
- package/packages/datadog-plugin-jest/src/index.js +53 -18
- package/packages/datadog-plugin-ws/src/close.js +2 -2
- package/packages/datadog-plugin-ws/src/producer.js +1 -1
- package/packages/datadog-plugin-ws/src/receiver.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +9 -1
- package/packages/dd-trace/src/appsec/reporter.js +2 -3
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +5 -0
- package/packages/dd-trace/src/config-helper.js +3 -1
- package/packages/dd-trace/src/config.js +437 -446
- package/packages/dd-trace/src/config_defaults.js +5 -12
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +8 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +11 -12
- package/packages/dd-trace/src/llmobs/sdk.js +20 -4
- package/packages/dd-trace/src/llmobs/tagger.js +12 -0
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +7 -127
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +19 -134
- package/packages/dd-trace/src/opentelemetry/otlp/metrics.proto +720 -0
- package/packages/dd-trace/src/opentelemetry/otlp/metrics_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +177 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +163 -0
- package/packages/dd-trace/src/opentelemetry/{protos → otlp}/protobuf_loader.js +24 -6
- package/packages/dd-trace/src/plugins/util/ci.js +3 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +16 -1
- package/packages/dd-trace/src/supported-configurations.json +2 -0
- package/packages/dd-trace/src/telemetry/endpoints.js +27 -1
- package/packages/dd-trace/src/telemetry/index.js +16 -13
- package/scripts/preinstall.js +3 -1
- package/version.js +2 -1
- /package/packages/dd-trace/src/opentelemetry/{protos → otlp}/common.proto +0 -0
- /package/packages/dd-trace/src/opentelemetry/{protos → otlp}/logs.proto +0 -0
- /package/packages/dd-trace/src/opentelemetry/{protos → otlp}/logs_service.proto +0 -0
- /package/packages/dd-trace/src/opentelemetry/{protos → otlp}/resource.proto +0 -0
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -50,6 +50,7 @@ dev,@stylistic/eslint-plugin,MIT,Copyright OpenJS Foundation and other contribut
|
|
|
50
50
|
dev,axios,MIT,Copyright 2014-present Matt Zabriskie
|
|
51
51
|
dev,benchmark,MIT,Copyright 2010-2016 Mathias Bynens Robert Kieffer John-David Dalton
|
|
52
52
|
dev,body-parser,MIT,Copyright 2014 Jonathan Ong 2014-2015 Douglas Christopher Wilson
|
|
53
|
+
dev,bun,MIT,Copyright contributors
|
|
53
54
|
dev,chai,MIT,Copyright 2017 Chai.js Assertion Library
|
|
54
55
|
dev,eslint,MIT,Copyright JS Foundation and other contributors https://js.foundation
|
|
55
56
|
dev,eslint-plugin-cypress,MIT,Copyright (c) 2019 Cypress.io
|
|
@@ -64,6 +65,8 @@ dev,globals,MIT,Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://si
|
|
|
64
65
|
dev,graphql,MIT,Copyright 2015 Facebook Inc.
|
|
65
66
|
dev,jszip,MIT,Copyright 2015-2016 Stuart Knightley and contributors
|
|
66
67
|
dev,mocha,MIT,Copyright 2011-2018 JS Foundation and contributors https://js.foundation
|
|
68
|
+
dev,mocha-multi-reporters,MIT,Copyright 2015-2019 Yousaf Nabi and Stanley Ng
|
|
69
|
+
dev,mocha-junit-reporter,MIT, Copyright 2015 Michael Allen
|
|
67
70
|
dev,multer,MIT,Copyright 2014 Hage Yaapa
|
|
68
71
|
dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
|
|
69
72
|
dev,nyc,ISC,Copyright 2015 Contributors
|
package/index.d.ts
CHANGED
|
@@ -134,6 +134,11 @@ interface Tracer extends opentracing.Tracer {
|
|
|
134
134
|
|
|
135
135
|
dogstatsd: tracer.DogStatsD;
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Data Streams manual checkpointer API.
|
|
139
|
+
*/
|
|
140
|
+
dataStreamsCheckpointer: tracer.DataStreamsCheckpointer;
|
|
141
|
+
|
|
137
142
|
/**
|
|
138
143
|
* LLM Observability SDK
|
|
139
144
|
*/
|
|
@@ -1026,6 +1031,29 @@ declare namespace tracer {
|
|
|
1026
1031
|
flush(): void
|
|
1027
1032
|
}
|
|
1028
1033
|
|
|
1034
|
+
/**
|
|
1035
|
+
* Manual Data Streams Monitoring checkpointer API.
|
|
1036
|
+
*/
|
|
1037
|
+
export interface DataStreamsCheckpointer {
|
|
1038
|
+
/**
|
|
1039
|
+
* Sets a produce checkpoint and injects the DSM context into the provided carrier.
|
|
1040
|
+
* @param type The streaming technology (e.g., kafka, kinesis, sns).
|
|
1041
|
+
* @param target The target of data (topic, exchange, stream name).
|
|
1042
|
+
* @param carrier The carrier object to inject DSM context into.
|
|
1043
|
+
*/
|
|
1044
|
+
setProduceCheckpoint (type: string, target: string, carrier: any): void;
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Sets a consume checkpoint and extracts DSM context from the provided carrier.
|
|
1048
|
+
* @param type The streaming technology (e.g., kafka, kinesis, sns).
|
|
1049
|
+
* @param source The source of data (topic, exchange, stream name).
|
|
1050
|
+
* @param carrier The carrier object to extract DSM context from.
|
|
1051
|
+
* @param manualCheckpoint Whether this checkpoint was manually set. Defaults to true.
|
|
1052
|
+
* @returns The DSM context associated with the current pathway.
|
|
1053
|
+
*/
|
|
1054
|
+
setConsumeCheckpoint (type: string, source: string, carrier: any, manualCheckpoint?: boolean): any;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1029
1057
|
export interface EventTrackingV2 {
|
|
1030
1058
|
/**
|
|
1031
1059
|
* Links a successful login event to the current trace. Will link the passed user to the current trace with Appsec.setUser() internally.
|
|
@@ -2938,6 +2966,15 @@ declare namespace tracer {
|
|
|
2938
2966
|
*/
|
|
2939
2967
|
submitEvaluation (spanContext: llmobs.ExportedLLMObsSpan, options: llmobs.EvaluationOptions): void
|
|
2940
2968
|
|
|
2969
|
+
|
|
2970
|
+
/**
|
|
2971
|
+
* Annotates all spans, including auto-instrumented spans, with the provided tags created in the context of the callback function.
|
|
2972
|
+
* @param options The annotation context options.
|
|
2973
|
+
* @param fn The callback over which to apply the annotation context options.
|
|
2974
|
+
* @returns The result of the function.
|
|
2975
|
+
*/
|
|
2976
|
+
annotationContext<T> (options: llmobs.AnnotationContextOptions, fn: () => T): T
|
|
2977
|
+
|
|
2941
2978
|
/**
|
|
2942
2979
|
* Flushes any remaining spans and evaluation metrics to LLM Observability.
|
|
2943
2980
|
*/
|
|
@@ -3099,6 +3136,18 @@ declare namespace tracer {
|
|
|
3099
3136
|
tags?: { [key: string]: any }
|
|
3100
3137
|
}
|
|
3101
3138
|
|
|
3139
|
+
interface AnnotationContextOptions {
|
|
3140
|
+
/**
|
|
3141
|
+
* Dictionary of JSON serializable key-value tag pairs to set or update on the LLMObs span regarding the span's context.
|
|
3142
|
+
*/
|
|
3143
|
+
tags?: { [key: string]: any },
|
|
3144
|
+
|
|
3145
|
+
/**
|
|
3146
|
+
* Set to override the span name for any spans annotated within the returned context.
|
|
3147
|
+
*/
|
|
3148
|
+
name?: string,
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3102
3151
|
/**
|
|
3103
3152
|
* An object containing the span ID and trace ID of interest
|
|
3104
3153
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.74.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
"test:trace:core:ci": "npm run test:trace:core -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/**/*.js\"",
|
|
33
33
|
"test:trace:guardrails": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/guardrails/**/*.spec.js\"",
|
|
34
34
|
"test:trace:guardrails:ci": "nyc --no-clean --include \"packages/dd-trace/src/guardrails/**/*.js\" -- npm run test:trace:guardrails",
|
|
35
|
+
"test:esbuild": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-esbuild/test/**/*.spec.js\"",
|
|
36
|
+
"test:esbuild:ci": "nyc --no-clean --include \"packages/datadog-esbuild/test/**/*.js\" -- npm run test:esbuild",
|
|
35
37
|
"test:instrumentations": "mocha -r 'packages/dd-trace/test/setup/mocha.js' \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\"",
|
|
36
38
|
"test:instrumentations:ci": "yarn services && nyc --no-clean --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS)).js\" --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS))/**/*.js\" -- npm run test:instrumentations",
|
|
37
39
|
"test:instrumentations:misc": "mocha -r 'packages/dd-trace/test/setup/mocha.js' 'packages/datadog-instrumentations/test/*/**/*.spec.js'",
|
|
@@ -44,7 +46,7 @@
|
|
|
44
46
|
"test:llmobs:sdk:ci": "nyc --no-clean --include \"packages/dd-trace/src/llmobs/**/*.js\" -- npm run test:llmobs:sdk",
|
|
45
47
|
"test:llmobs:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/llmobs/plugins/@($(echo $PLUGINS))/*.spec.js\"",
|
|
46
48
|
"test:llmobs:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/src/llmobs/**/*.js\" -- npm run test:llmobs:plugins",
|
|
47
|
-
"test:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test
|
|
49
|
+
"test:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/@($(echo ${SPEC:-'*'})).spec.js\"",
|
|
48
50
|
"test:plugins:ci": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins",
|
|
49
51
|
"test:plugins:ci:flaky": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins -- --bail --retries 2",
|
|
50
52
|
"test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
|
|
@@ -120,10 +122,10 @@
|
|
|
120
122
|
],
|
|
121
123
|
"dependencies": {
|
|
122
124
|
"@datadog/libdatadog": "0.7.0",
|
|
123
|
-
"@datadog/native-appsec": "10.
|
|
125
|
+
"@datadog/native-appsec": "10.3.0",
|
|
124
126
|
"@datadog/native-iast-taint-tracking": "4.0.0",
|
|
125
127
|
"@datadog/native-metrics": "3.1.1",
|
|
126
|
-
"@datadog/openfeature-node-server": "0.1.0-preview.
|
|
128
|
+
"@datadog/openfeature-node-server": "0.1.0-preview.12",
|
|
127
129
|
"@datadog/pprof": "5.11.1",
|
|
128
130
|
"@datadog/sketches-js": "2.1.1",
|
|
129
131
|
"@datadog/wasm-js-rewriter": "4.0.1",
|
|
@@ -158,7 +160,7 @@
|
|
|
158
160
|
},
|
|
159
161
|
"peerDependencies": {
|
|
160
162
|
"@openfeature/core": "^1.9.0",
|
|
161
|
-
"@openfeature/server-sdk": "~1.
|
|
163
|
+
"@openfeature/server-sdk": "~1.20.0"
|
|
162
164
|
},
|
|
163
165
|
"peerDependenciesMeta": {
|
|
164
166
|
"@openfeature/core": {
|
|
@@ -174,7 +176,7 @@
|
|
|
174
176
|
"@eslint/js": "^9.29.0",
|
|
175
177
|
"@msgpack/msgpack": "^3.1.2",
|
|
176
178
|
"@openfeature/core": "^1.8.1",
|
|
177
|
-
"@openfeature/server-sdk": "~1.
|
|
179
|
+
"@openfeature/server-sdk": "~1.20.0",
|
|
178
180
|
"@stylistic/eslint-plugin": "^5.0.0",
|
|
179
181
|
"@types/chai": "^4.3.16",
|
|
180
182
|
"@types/mocha": "^10.0.10",
|
|
@@ -184,6 +186,7 @@
|
|
|
184
186
|
"axios": "^1.12.2",
|
|
185
187
|
"benchmark": "^2.1.4",
|
|
186
188
|
"body-parser": "^2.2.0",
|
|
189
|
+
"bun": "1.3.1",
|
|
187
190
|
"chai": "^4.5.0",
|
|
188
191
|
"eslint": "^9.29.0",
|
|
189
192
|
"eslint-plugin-cypress": "^5.1.0",
|
|
@@ -198,6 +201,8 @@
|
|
|
198
201
|
"graphql": "*",
|
|
199
202
|
"jszip": "^3.10.1",
|
|
200
203
|
"mocha": "^11.6.0",
|
|
204
|
+
"mocha-junit-reporter": "^2.2.1",
|
|
205
|
+
"mocha-multi-reporters": "^1.5.1",
|
|
201
206
|
"multer": "^2.0.2",
|
|
202
207
|
"nock": "^13.5.6",
|
|
203
208
|
"nyc": "^15.1.0",
|
|
@@ -5,7 +5,11 @@ module.exports = function set (object, path, value) {
|
|
|
5
5
|
while (true) {
|
|
6
6
|
const nextIndex = path.indexOf('.', index + 1)
|
|
7
7
|
if (nextIndex === -1) {
|
|
8
|
-
|
|
8
|
+
if (index === -1) {
|
|
9
|
+
object[path] = value
|
|
10
|
+
} else {
|
|
11
|
+
object[path.slice(index + 1)] = value
|
|
12
|
+
}
|
|
9
13
|
return
|
|
10
14
|
}
|
|
11
15
|
object = object[path.slice(index + 1, nextIndex)] ??= {}
|
|
@@ -8,6 +8,12 @@ const extractPackageAndModulePath = require(
|
|
|
8
8
|
'../datadog-instrumentations/src/helpers/extract-package-and-module-path.js'
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
+
const { pathToFileURL, fileURLToPath } = require('url')
|
|
12
|
+
const { processModule, isESMFile } = require('./src/utils.js')
|
|
13
|
+
|
|
14
|
+
const ESM_INTERCEPTED_SUFFIX = '._dd_esbuild_intercepted'
|
|
15
|
+
const INTERNAL_ESM_INTERCEPTED_PREFIX = '/_dd_esm_internal_/'
|
|
16
|
+
|
|
11
17
|
let rewriter
|
|
12
18
|
|
|
13
19
|
for (const hook of Object.values(hooks)) {
|
|
@@ -30,7 +36,6 @@ for (const instrumentation of Object.values(instrumentations)) {
|
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
const INSTRUMENTED = Object.keys(instrumentations)
|
|
34
39
|
const RAW_BUILTINS = require('module').builtinModules
|
|
35
40
|
const CHANNEL = 'dd-trace:bundler:load'
|
|
36
41
|
const path = require('path')
|
|
@@ -47,14 +52,6 @@ for (const builtin of RAW_BUILTINS) {
|
|
|
47
52
|
const DEBUG = !!process.env.DD_TRACE_DEBUG
|
|
48
53
|
const DD_IAST_ENABLED = process.env.DD_IAST_ENABLED?.toLowerCase() === 'true' || process.env.DD_IAST_ENABLED === '1'
|
|
49
54
|
|
|
50
|
-
// We don't want to handle any built-in packages
|
|
51
|
-
// Those packages will still be handled via RITM
|
|
52
|
-
// Attempting to instrument them would fail as they have no package.json file
|
|
53
|
-
for (const pkg of INSTRUMENTED) {
|
|
54
|
-
if (builtins.has(pkg) || pkg.startsWith('node:')) continue
|
|
55
|
-
modulesOfInterest.add(pkg)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
55
|
module.exports.name = 'datadog-esbuild'
|
|
59
56
|
|
|
60
57
|
function isESMBuild (build) {
|
|
@@ -115,7 +112,16 @@ module.exports.setup = function (build) {
|
|
|
115
112
|
${isSourceMapEnabled ? `globalThis.__DD_ESBUILD_BASEPATH = '${require('../dd-trace/src/util').ddBasePath}';` : ''}
|
|
116
113
|
${build.initialOptions.banner.js}`
|
|
117
114
|
}
|
|
118
|
-
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
require.resolve('@openfeature/core')
|
|
118
|
+
} catch (error) {
|
|
119
|
+
build.initialOptions.external ??= []
|
|
120
|
+
build.initialOptions.external.push('@openfeature/core')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const esmBuild = isESMBuild(build)
|
|
124
|
+
if (esmBuild) {
|
|
119
125
|
if (!build.initialOptions.banner.js.includes('import { createRequire as $dd_createRequire } from \'module\'')) {
|
|
120
126
|
build.initialOptions.banner.js = `import { createRequire as $dd_createRequire } from 'module';
|
|
121
127
|
import { fileURLToPath as $dd_fileURLToPath } from 'url';
|
|
@@ -149,6 +155,9 @@ ${build.initialOptions.banner.js}`
|
|
|
149
155
|
console.warn('Warning: No git metadata available - skipping injection')
|
|
150
156
|
}
|
|
151
157
|
|
|
158
|
+
// first time is intercepted, proxy should be created, next time the original should be loaded
|
|
159
|
+
const interceptedESMModules = new Set()
|
|
160
|
+
|
|
152
161
|
build.onResolve({ filter: /.*/ }, args => {
|
|
153
162
|
if (externalModules.has(args.path)) {
|
|
154
163
|
// Internal Node.js packages will still be instrumented via require()
|
|
@@ -167,7 +176,7 @@ ${build.initialOptions.banner.js}`
|
|
|
167
176
|
|
|
168
177
|
let fullPathToModule
|
|
169
178
|
try {
|
|
170
|
-
fullPathToModule = dotFriendlyResolve(args.path, args.resolveDir)
|
|
179
|
+
fullPathToModule = dotFriendlyResolve(args.path, args.resolveDir, args.kind === 'import-statement')
|
|
171
180
|
} catch (err) {
|
|
172
181
|
if (DEBUG) {
|
|
173
182
|
console.warn(`Warning: Unable to find "${args.path}".` +
|
|
@@ -197,8 +206,25 @@ ${build.initialOptions.banner.js}`
|
|
|
197
206
|
if (args.namespace === 'file' && (
|
|
198
207
|
modulesOfInterest.has(args.path) || modulesOfInterest.has(`${extracted.pkg}/${extracted.path}`))
|
|
199
208
|
) {
|
|
209
|
+
// Internal module like http/fs is imported and the build output is ESM
|
|
210
|
+
if (internal && args.kind === 'import-statement' && esmBuild && !interceptedESMModules.has(fullPathToModule)) {
|
|
211
|
+
fullPathToModule = `${INTERNAL_ESM_INTERCEPTED_PREFIX}${fullPathToModule}${ESM_INTERCEPTED_SUFFIX}`
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
path: fullPathToModule,
|
|
215
|
+
pluginData: {
|
|
216
|
+
pkg: extracted?.pkg,
|
|
217
|
+
path: extracted?.path,
|
|
218
|
+
full: fullPathToModule,
|
|
219
|
+
raw: args.path,
|
|
220
|
+
pkgOfInterest: true,
|
|
221
|
+
kind: args.kind,
|
|
222
|
+
internal,
|
|
223
|
+
isESM: true
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
200
227
|
// The file namespace is used when requiring files from disk in userland
|
|
201
|
-
|
|
202
228
|
let pathToPackageJson
|
|
203
229
|
try {
|
|
204
230
|
// we can't use require.resolve('pkg/package.json') as ESM modules don't make the file available
|
|
@@ -220,6 +246,11 @@ ${build.initialOptions.banner.js}`
|
|
|
220
246
|
|
|
221
247
|
const packageJson = JSON.parse(fs.readFileSync(pathToPackageJson).toString())
|
|
222
248
|
|
|
249
|
+
const isESM = isESMFile(fullPathToModule, pathToPackageJson, packageJson)
|
|
250
|
+
if (isESM && !interceptedESMModules.has(fullPathToModule)) {
|
|
251
|
+
fullPathToModule += ESM_INTERCEPTED_SUFFIX
|
|
252
|
+
}
|
|
253
|
+
|
|
223
254
|
if (DEBUG) console.log(`RESOLVE: ${args.path}@${packageJson.version}`)
|
|
224
255
|
|
|
225
256
|
// https://esbuild.github.io/plugins/#on-resolve-arguments
|
|
@@ -232,13 +263,15 @@ ${build.initialOptions.banner.js}`
|
|
|
232
263
|
full: fullPathToModule,
|
|
233
264
|
raw: args.path,
|
|
234
265
|
pkgOfInterest: true,
|
|
235
|
-
|
|
266
|
+
kind: args.kind,
|
|
267
|
+
internal,
|
|
268
|
+
isESM
|
|
236
269
|
}
|
|
237
270
|
}
|
|
238
271
|
}
|
|
239
272
|
})
|
|
240
273
|
|
|
241
|
-
build.onLoad({ filter: /.*/ }, args => {
|
|
274
|
+
build.onLoad({ filter: /.*/ }, async args => {
|
|
242
275
|
if (args.pluginData?.pkgOfInterest) {
|
|
243
276
|
const data = args.pluginData
|
|
244
277
|
|
|
@@ -249,26 +282,63 @@ ${build.initialOptions.banner.js}`
|
|
|
249
282
|
: data.pkg
|
|
250
283
|
|
|
251
284
|
// Read the content of the module file of interest
|
|
252
|
-
|
|
285
|
+
let contents
|
|
286
|
+
|
|
287
|
+
if (data.isESM) {
|
|
288
|
+
if (args.path.endsWith(ESM_INTERCEPTED_SUFFIX)) {
|
|
289
|
+
args.path = args.path.slice(0, -1 * ESM_INTERCEPTED_SUFFIX.length)
|
|
290
|
+
|
|
291
|
+
if (data.internal) {
|
|
292
|
+
args.path = args.path.slice(INTERNAL_ESM_INTERCEPTED_PREFIX.length)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
interceptedESMModules.add(args.path)
|
|
296
|
+
|
|
297
|
+
const setters = await processModule({
|
|
298
|
+
path: args.path,
|
|
299
|
+
internal: data.internal,
|
|
300
|
+
context: { format: 'module' }
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
const iitmPath = require.resolve('import-in-the-middle/lib/register.js')
|
|
304
|
+
const toRegister = data.internal ? args.path : pathToFileURL(args.path)
|
|
305
|
+
// Mimic a Module object (https://tc39.es/ecma262/#sec-module-namespace-objects).
|
|
306
|
+
contents = `
|
|
307
|
+
import { register } from ${JSON.stringify(iitmPath)};
|
|
308
|
+
import * as namespace from ${JSON.stringify(args.path)};
|
|
309
|
+
const _ = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
|
|
310
|
+
const set = {};
|
|
311
|
+
const get = {};
|
|
312
|
+
|
|
313
|
+
${Array.from(setters.values()).join(';\n')};
|
|
314
|
+
|
|
315
|
+
register(${JSON.stringify(toRegister)}, _, set, get, ${JSON.stringify(data.raw)});
|
|
316
|
+
`
|
|
317
|
+
} else {
|
|
318
|
+
contents = fs.readFileSync(args.path, 'utf8')
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
const fileCode = fs.readFileSync(args.path, 'utf8')
|
|
322
|
+
contents = `
|
|
323
|
+
(function() {
|
|
324
|
+
${fileCode}
|
|
325
|
+
})(...arguments);
|
|
326
|
+
{
|
|
327
|
+
const dc = require('dc-polyfill');
|
|
328
|
+
const ch = dc.channel('${CHANNEL}');
|
|
329
|
+
const mod = module.exports
|
|
330
|
+
const payload = {
|
|
331
|
+
module: mod,
|
|
332
|
+
version: '${data.version}',
|
|
333
|
+
package: '${data.pkg}',
|
|
334
|
+
path: '${pkgPath}'
|
|
335
|
+
};
|
|
336
|
+
ch.publish(payload);
|
|
337
|
+
module.exports = payload.module;
|
|
338
|
+
}
|
|
339
|
+
`
|
|
340
|
+
}
|
|
253
341
|
|
|
254
|
-
const contents = `
|
|
255
|
-
(function() {
|
|
256
|
-
${fileCode}
|
|
257
|
-
})(...arguments);
|
|
258
|
-
{
|
|
259
|
-
const dc = require('dc-polyfill');
|
|
260
|
-
const ch = dc.channel('${CHANNEL}');
|
|
261
|
-
const mod = module.exports
|
|
262
|
-
const payload = {
|
|
263
|
-
module: mod,
|
|
264
|
-
version: '${data.version}',
|
|
265
|
-
package: '${data.pkg}',
|
|
266
|
-
path: '${pkgPath}'
|
|
267
|
-
};
|
|
268
|
-
ch.publish(payload);
|
|
269
|
-
module.exports = payload.module;
|
|
270
|
-
}
|
|
271
|
-
`
|
|
272
342
|
// https://esbuild.github.io/plugins/#on-load-results
|
|
273
343
|
return {
|
|
274
344
|
contents,
|
|
@@ -276,7 +346,6 @@ ${build.initialOptions.banner.js}`
|
|
|
276
346
|
resolveDir: path.dirname(args.path)
|
|
277
347
|
}
|
|
278
348
|
}
|
|
279
|
-
|
|
280
349
|
if (DD_IAST_ENABLED && args.pluginData?.applicationFile) {
|
|
281
350
|
const ext = path.extname(args.path).toLowerCase()
|
|
282
351
|
const isJs = /^\.(js|mjs|cjs)$/.test(ext)
|
|
@@ -295,12 +364,19 @@ ${build.initialOptions.banner.js}`
|
|
|
295
364
|
}
|
|
296
365
|
|
|
297
366
|
// @see https://github.com/nodejs/node/issues/47000
|
|
298
|
-
function dotFriendlyResolve (path, directory) {
|
|
367
|
+
function dotFriendlyResolve (path, directory, usesImportStatement) {
|
|
299
368
|
if (path === '.') {
|
|
300
369
|
path = './'
|
|
301
370
|
} else if (path === '..') {
|
|
302
371
|
path = '../'
|
|
303
372
|
}
|
|
373
|
+
let conditions
|
|
374
|
+
if (usesImportStatement) {
|
|
375
|
+
conditions = new Set(['import', 'node'])
|
|
376
|
+
}
|
|
304
377
|
|
|
305
|
-
|
|
378
|
+
if (path.startsWith('file://')) {
|
|
379
|
+
path = fileURLToPath(path)
|
|
380
|
+
}
|
|
381
|
+
return require.resolve(path, { paths: [directory], conditions })
|
|
306
382
|
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// The content of this file is copied from the `import-in-the-middle` package with minor modifications (https://www.npmjs.com/package/import-in-the-middle)
|
|
4
|
+
const { pathToFileURL, fileURLToPath } = require('node:url')
|
|
5
|
+
const fs = require('node:fs')
|
|
6
|
+
const path = require('node:path')
|
|
7
|
+
const { NODE_MAJOR, NODE_MINOR } = require('../../../version.js')
|
|
8
|
+
|
|
9
|
+
const getExportsImporting = (url) => import(url).then(Object.keys)
|
|
10
|
+
const getExports = NODE_MAJOR >= 20 || (NODE_MAJOR === 18 && NODE_MINOR >= 19)
|
|
11
|
+
? require('import-in-the-middle/lib/get-exports.js')
|
|
12
|
+
: getExportsImporting
|
|
13
|
+
|
|
14
|
+
function isStarExportLine (line) {
|
|
15
|
+
return /^\* from /.test(line)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isBareSpecifier (specifier) {
|
|
19
|
+
// Relative and absolute paths are not bare specifiers.
|
|
20
|
+
if (
|
|
21
|
+
specifier.startsWith('.') ||
|
|
22
|
+
specifier.startsWith('/')) {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Valid URLs are not bare specifiers. (file:, http:, node:, etc.)
|
|
27
|
+
|
|
28
|
+
if (URL.hasOwnProperty('canParse')) {
|
|
29
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
30
|
+
return !URL.canParse(specifier)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// eslint-disable-next-line no-new
|
|
35
|
+
new URL(specifier)
|
|
36
|
+
return false
|
|
37
|
+
} catch {
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function resolve (specifier, context) {
|
|
43
|
+
// This comes from an import, that is why import makes preference
|
|
44
|
+
const conditions = ['import']
|
|
45
|
+
|
|
46
|
+
if (specifier.startsWith('file://')) {
|
|
47
|
+
specifier = fileURLToPath(specifier)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const resolved = require.resolve(specifier, { conditions, paths: [fileURLToPath(context.parentURL)] })
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
url: pathToFileURL(resolved),
|
|
54
|
+
format: isESMFile(resolved) ? 'module' : 'commonjs'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getSource (url, { format }) {
|
|
59
|
+
return {
|
|
60
|
+
source: fs.readFileSync(fileURLToPath(url), 'utf8'),
|
|
61
|
+
format
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generates the pieces of code for the proxy module before the path
|
|
67
|
+
*
|
|
68
|
+
* @param {Object} moduleData { path, internal, context, excludeDefault }
|
|
69
|
+
* @returns {Promise<Map>}
|
|
70
|
+
*/
|
|
71
|
+
async function processModule ({ path, internal, context, excludeDefault }) {
|
|
72
|
+
let exportNames, srcUrl
|
|
73
|
+
if (internal) {
|
|
74
|
+
// we can not read and parse of internal modules
|
|
75
|
+
exportNames = await getExportsImporting(path)
|
|
76
|
+
} else {
|
|
77
|
+
srcUrl = pathToFileURL(path)
|
|
78
|
+
exportNames = await getExports(srcUrl, context, getSource)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const starExports = new Set()
|
|
82
|
+
const setters = new Map()
|
|
83
|
+
|
|
84
|
+
const addSetter = (name, setter, isStarExport = false) => {
|
|
85
|
+
if (setters.has(name)) {
|
|
86
|
+
if (isStarExport) {
|
|
87
|
+
// If there's already a matching star export, delete it
|
|
88
|
+
if (starExports.has(name)) {
|
|
89
|
+
setters.delete(name)
|
|
90
|
+
}
|
|
91
|
+
// and return so this is excluded
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// if we already have this export but it is from a * export, overwrite it
|
|
96
|
+
if (starExports.has(name)) {
|
|
97
|
+
starExports.delete(name)
|
|
98
|
+
setters.set(name, setter)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// Store export * exports so we know they can be overridden by explicit
|
|
102
|
+
// named exports
|
|
103
|
+
if (isStarExport) {
|
|
104
|
+
starExports.add(name)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
setters.set(name, setter)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const n of exportNames) {
|
|
112
|
+
if (n === 'default' && excludeDefault) continue
|
|
113
|
+
|
|
114
|
+
if (isStarExportLine(n) === true) {
|
|
115
|
+
// export * from 'wherever'
|
|
116
|
+
const [, modFile] = n.split('* from ')
|
|
117
|
+
|
|
118
|
+
// Relative paths need to be resolved relative to the parent module
|
|
119
|
+
const newSpecifier = isBareSpecifier(modFile) ? modFile : new URL(modFile, srcUrl).href
|
|
120
|
+
// We need to call `parentResolve` to resolve bare specifiers to a full
|
|
121
|
+
// URL. We also need to call `parentResolve` for all sub-modules to get
|
|
122
|
+
// the `format`. We can't rely on the parents `format` to know if this
|
|
123
|
+
// sub-module is ESM or CJS!
|
|
124
|
+
|
|
125
|
+
const result = resolve(newSpecifier, { parentURL: srcUrl })
|
|
126
|
+
|
|
127
|
+
// eslint-disable-next-line no-await-in-loop
|
|
128
|
+
const subSetters = await processModule({
|
|
129
|
+
path: fileURLToPath(result.url),
|
|
130
|
+
context: { ...context, format: result.format },
|
|
131
|
+
excludeDefault: true
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
for (const [name, setter] of subSetters.entries()) {
|
|
135
|
+
addSetter(name, setter, true)
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
const variableName = `$${n.replaceAll(/[^a-zA-Z0-9_$]/g, '_')}`
|
|
139
|
+
const objectKey = JSON.stringify(n)
|
|
140
|
+
const reExportedName = n === 'default' ? n : objectKey
|
|
141
|
+
|
|
142
|
+
addSetter(n, `
|
|
143
|
+
let ${variableName}
|
|
144
|
+
try {
|
|
145
|
+
${variableName} = _[${objectKey}] = namespace[${objectKey}]
|
|
146
|
+
} catch (err) {
|
|
147
|
+
if (!(err instanceof ReferenceError)) throw err
|
|
148
|
+
}
|
|
149
|
+
export { ${variableName} as ${reExportedName} }
|
|
150
|
+
set[${objectKey}] = (v) => {
|
|
151
|
+
${variableName} = v
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
get[${objectKey}] = () => ${variableName}
|
|
155
|
+
`)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return setters
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Determines if a file is a ESM module or CommonJS
|
|
164
|
+
*
|
|
165
|
+
* @param {string} fullPathToModule File to analize
|
|
166
|
+
* @param {string} [modulePackageJsonPath] Path of the package.json
|
|
167
|
+
* @param {Object} [packageJson] The content of the module package.json
|
|
168
|
+
* @returns {boolean}
|
|
169
|
+
*/
|
|
170
|
+
function isESMFile (fullPathToModule, modulePackageJsonPath, packageJson = {}) {
|
|
171
|
+
if (fullPathToModule.endsWith('.mjs')) return true
|
|
172
|
+
if (fullPathToModule.endsWith('.cjs')) return false
|
|
173
|
+
|
|
174
|
+
const pathParts = fullPathToModule.split(path.sep)
|
|
175
|
+
do {
|
|
176
|
+
pathParts.pop()
|
|
177
|
+
|
|
178
|
+
const packageJsonPath = [...pathParts, 'package.json'].join(path.sep)
|
|
179
|
+
if (packageJsonPath === modulePackageJsonPath) {
|
|
180
|
+
return packageJson.type === 'module'
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath).toString()
|
|
185
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
186
|
+
return packageJson.type === 'module'
|
|
187
|
+
} catch {
|
|
188
|
+
// file does not exit, continue
|
|
189
|
+
}
|
|
190
|
+
} while (pathParts.length > 0)
|
|
191
|
+
|
|
192
|
+
return packageJson.type === 'module'
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
module.exports = {
|
|
196
|
+
processModule,
|
|
197
|
+
isESMFile
|
|
198
|
+
}
|