@depup/dd-trace 6.15.0-depup.1 → 6.16.0-depup.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.
Files changed (82) hide show
  1. package/README.md +3 -9
  2. package/changes.json +3 -8
  3. package/ci/test-optimization-validation/framework-adapters/cucumber.js +4 -2
  4. package/ci/test-optimization-validation/package-check.js +4 -1
  5. package/ci/test-optimization-validation/scenarios/ci-wiring.js +1 -1
  6. package/index.d.ts +4 -0
  7. package/next.d.ts +27 -0
  8. package/next.js +3 -0
  9. package/package.json +19 -20
  10. package/packages/datadog-esbuild/index.js +14 -1
  11. package/packages/datadog-esbuild/src/resolver.js +284 -0
  12. package/packages/datadog-esbuild/src/utils.js +163 -119
  13. package/packages/datadog-instrumentations/src/ai.js +39 -97
  14. package/packages/datadog-instrumentations/src/anthropic.js +76 -134
  15. package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +1 -1
  16. package/packages/datadog-instrumentations/src/azure-cosmos.js +1 -1
  17. package/packages/datadog-instrumentations/src/azure-durable-functions.js +23 -9
  18. package/packages/datadog-instrumentations/src/azure-functions.js +48 -0
  19. package/packages/datadog-instrumentations/src/bullmq.js +1 -1
  20. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
  21. package/packages/datadog-instrumentations/src/dd-trace-api.js +2 -2
  22. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  23. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +39 -14
  24. package/packages/datadog-instrumentations/src/helpers/instrument.js +25 -8
  25. package/packages/datadog-instrumentations/src/helpers/instrumentation-utils.js +72 -0
  26. package/packages/datadog-instrumentations/src/helpers/register.js +9 -64
  27. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +46 -14
  28. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-durable-functions.js +17 -0
  29. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  30. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +6 -7
  31. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  32. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +99 -70
  33. package/packages/datadog-instrumentations/src/langchain.js +1 -1
  34. package/packages/datadog-instrumentations/src/langgraph.js +1 -1
  35. package/packages/datadog-instrumentations/src/mercurius.js +1 -1
  36. package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +1 -1
  37. package/packages/datadog-instrumentations/src/openai-agents.js +1 -1
  38. package/packages/datadog-instrumentations/src/openai.js +54 -76
  39. package/packages/datadog-instrumentations/src/vitest-worker.js +7 -10
  40. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +7 -1
  41. package/packages/datadog-plugin-azure-cosmos/src/index.js +1 -1
  42. package/packages/datadog-plugin-azure-durable-functions/src/index.js +96 -1
  43. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -24
  44. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -36
  45. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-request-context.js +31 -0
  46. package/packages/datadog-plugin-graphql/src/resolve-error.js +33 -11
  47. package/packages/datadog-turbopack/index.js +212 -0
  48. package/packages/datadog-turbopack/src/constants.js +5 -0
  49. package/packages/datadog-turbopack/src/loader.js +500 -0
  50. package/packages/dd-trace/src/aiguard/index.js +2 -1
  51. package/packages/dd-trace/src/aiguard/integrations/anthropic.js +53 -25
  52. package/packages/dd-trace/src/aiguard/integrations/evaluate.js +49 -25
  53. package/packages/dd-trace/src/aiguard/integrations/index.js +3 -2
  54. package/packages/dd-trace/src/aiguard/integrations/openai.js +59 -30
  55. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +116 -42
  56. package/packages/dd-trace/src/aiguard/messages/utils.js +29 -1
  57. package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +25 -0
  58. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +2 -2
  59. package/packages/dd-trace/src/appsec/telemetry/api_security.js +1 -3
  60. package/packages/dd-trace/src/appsec/telemetry/common.js +4 -0
  61. package/packages/dd-trace/src/appsec/telemetry/index.js +23 -5
  62. package/packages/dd-trace/src/appsec/telemetry/rasp.js +1 -20
  63. package/packages/dd-trace/src/appsec/telemetry/user.js +1 -3
  64. package/packages/dd-trace/src/appsec/telemetry/waf.js +1 -20
  65. package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -0
  66. package/packages/dd-trace/src/config/helper.js +10 -2
  67. package/packages/dd-trace/src/config/index.js +20 -5
  68. package/packages/dd-trace/src/config/supported-configurations.json +8 -0
  69. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +14 -7
  70. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +14 -1
  71. package/packages/dd-trace/src/evp_proxy/discovery.js +3 -4
  72. package/packages/dd-trace/src/evp_proxy/path.js +12 -3
  73. package/packages/dd-trace/src/exporters/common/docker.js +4 -1
  74. package/packages/dd-trace/src/exporters/common/proxy.js +3 -0
  75. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  76. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +5 -4
  77. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +106 -25
  78. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +7 -1
  79. package/packages/dd-trace/src/plugin_manager.js +9 -3
  80. package/packages/dd-trace/src/plugins/index.js +1 -0
  81. package/packages/dd-trace/src/plugins/util/test.js +4 -1
  82. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/utils.js +0 -10
package/README.md CHANGED
@@ -13,16 +13,10 @@ npm install @depup/dd-trace
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [dd-trace](https://www.npmjs.com/package/dd-trace) @ 6.15.0 |
17
- | Processed | 2026-09-09 |
16
+ | Original | [dd-trace](https://www.npmjs.com/package/dd-trace) @ 6.16.0 |
17
+ | Processed | 2026-09-12 |
18
18
  | Smoke test | passed |
19
- | Deps updated | 1 |
20
-
21
- ## Dependency Changes
22
-
23
- | Dependency | From | To |
24
- |------------|------|-----|
25
- | import-in-the-middle | ^3.3.2 | ^3.5.0 |
19
+ | Deps updated | 0 |
26
20
 
27
21
  ---
28
22
 
package/changes.json CHANGED
@@ -1,10 +1,5 @@
1
1
  {
2
- "bumped": {
3
- "import-in-the-middle": {
4
- "from": "^3.3.2",
5
- "to": "^3.5.0"
6
- }
7
- },
8
- "timestamp": "2026-09-09T00:33:34.894Z",
9
- "totalUpdated": 1
2
+ "bumped": {},
3
+ "timestamp": "2026-09-12T00:31:24.778Z",
4
+ "totalUpdated": 0
10
5
  }
@@ -282,7 +282,9 @@ function readProfileDefinitions (filename) {
282
282
 
283
283
  function getJavascriptProfileDefinitions (source) {
284
284
  const syntax = maskJavascriptCommentsAndStrings(source)
285
- const exports = [...syntax.matchAll(/^\s*(?:module\s*\.\s*exports\s*=|export\s+default)\s*\{/gm)]
285
+ const exports = [...syntax.matchAll(
286
+ /(?:^|\S[\t\v\f\p{Zs}\uFEFF]*[\n\r\u2028\u2029])\s*(?:module\s*\.\s*exports\s*=|export\s+default)\s*\{/gu
287
+ )]
286
288
  if (exports.length === 0) return new Map()
287
289
  if (exports.length !== 1) throw new Error('configuration must export one literal profile object')
288
290
 
@@ -492,7 +494,7 @@ function getYamlStringProfileDefinition (source) {
492
494
  const value = source.trimStart()
493
495
  const quote = value[0]
494
496
  if (quote !== '"' && quote !== "'") {
495
- const comment = /\s+#/.exec(value)
497
+ const comment = /[ \t]#/.exec(value)
496
498
  const definition = value.slice(0, comment?.index ?? value.length).trimEnd()
497
499
  return definition || undefined
498
500
  }
@@ -88,7 +88,10 @@ function getFailureDetail (result) {
88
88
  }
89
89
 
90
90
  function sanitizeLine (value) {
91
- return sanitizeString(String(value)).replaceAll(/\p{Cc}+/gu, ' ').trim().slice(0, 1000).replace(/\.+$/, '')
91
+ const line = sanitizeString(String(value)).replaceAll(/\p{Cc}+/gu, ' ').trim().slice(0, 1000)
92
+ let end = line.length
93
+ while (end > 0 && line[end - 1] === '.') end--
94
+ return line.slice(0, end)
92
95
  }
93
96
 
94
97
  module.exports = { checkInstalledPackage, getInstalledPackageFailure }
@@ -442,7 +442,7 @@ function hasUnavailableRemoteCiCommand (ci) {
442
442
  })) return true
443
443
 
444
444
  return evidence.some(item => {
445
- const reference = /^\s*uses:\s*["']?([^"'\s]+)["']?\s*$/im.exec(item)?.[1]
445
+ const reference = /^[ \t]*uses:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/im.exec(item)?.[1]
446
446
  return reference && !reference.startsWith('./')
447
447
  })
448
448
  }
package/index.d.ts CHANGED
@@ -3287,6 +3287,10 @@ declare namespace tracer {
3287
3287
  }
3288
3288
 
3289
3289
  export namespace opentelemetry {
3290
+ export interface MeterProvider {
3291
+ shutdown(callback?: (error: Error | null) => void): void;
3292
+ }
3293
+
3290
3294
  /**
3291
3295
  * A registry for creating named {@link Tracer}s.
3292
3296
  */
package/next.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { NextConfig } from 'next'
2
+
3
+ type NextConfigValue = NextConfig | undefined
4
+
5
+ export function withDatadogTurbopack<TArguments extends unknown[]> (
6
+ nextConfig: (...args: TArguments) => Promise<NextConfigValue>
7
+ ): (...args: TArguments) => Promise<NextConfig>
8
+
9
+ export function withDatadogTurbopack<TArguments extends unknown[]> (
10
+ nextConfig: (...args: TArguments) => NextConfigValue
11
+ ): (...args: TArguments) => NextConfig
12
+
13
+ export function withDatadogTurbopack<TArguments extends unknown[]> (
14
+ nextConfig: (...args: TArguments) => NextConfigValue | Promise<NextConfigValue>
15
+ ): (...args: TArguments) => NextConfig | Promise<NextConfig>
16
+
17
+ export function withDatadogTurbopack (
18
+ nextConfig: Promise<NextConfigValue>
19
+ ): (phase?: string) => Promise<NextConfig>
20
+
21
+ export function withDatadogTurbopack (
22
+ nextConfig?: NextConfigValue
23
+ ): (phase?: string) => NextConfig
24
+
25
+ export function withDatadogTurbopack (
26
+ nextConfig: NextConfigValue | Promise<NextConfigValue>
27
+ ): (phase?: string) => NextConfig | Promise<NextConfig>
package/next.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict'
2
+
3
+ module.exports = require('./packages/datadog-turbopack')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depup/dd-trace",
3
- "version": "6.15.0-depup.1",
3
+ "version": "6.16.0-depup.0",
4
4
  "description": "Datadog APM tracing client for JavaScript (with updated dependencies)",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -20,12 +20,11 @@
20
20
  "type:check": "tsc --noEmit -p tsconfig.dev.json",
21
21
  "type:doc:build": "cd docs && yarn && yarn build",
22
22
  "type:doc:test": "cd docs && yarn && yarn test",
23
- "lint": "node scripts/check_licenses.js && node scripts/check-agents-md-size.js && node scripts/check-no-coverage-artifacts.js && node scripts/check-no-mcr-images.js && node scripts/check-docker-image-shas.js && eslint . --concurrency=auto --max-warnings 0 && npm run verify:carrier-fields && npm run lint:codeowners:ci && npm run verify-exercised-tests",
23
+ "lint": "bash ./scripts/lint.sh",
24
24
  "lint:fix": "node scripts/check_licenses.js && node scripts/check-agents-md-size.js && node scripts/check-no-coverage-artifacts.js && node scripts/check-no-mcr-images.js && node scripts/check-docker-image-shas.js && eslint . --concurrency=auto --max-warnings 0 --fix",
25
25
  "verify:carrier-fields": "node scripts/verify-carrier-fields.mjs",
26
26
  "lint:inspect": "npx @eslint/config-inspector@latest",
27
27
  "lint:codeowners": "codeowners-audit",
28
- "lint:codeowners:ci": "codeowners-audit --glob='**/*.spec.js' --glob='benchmark/sirun/**' --glob='.agents/**' --glob='.claude/**' --glob='integration-tests/**' --glob='packages/dd-trace/src/guardrails/**'",
29
28
  "lint:editorconfig": "docker build -q -t ec .github/editorconfig-checker && docker run --rm --volume=$PWD:/check ec",
30
29
  "release:proposal": "node scripts/release/proposal",
31
30
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
@@ -45,6 +44,8 @@
45
44
  "test:trace:guardrails:ci": "node scripts/c8-ci.js test:trace:guardrails",
46
45
  "test:esbuild": "mocha \"packages/datadog-esbuild/test/**/*.spec.js\"",
47
46
  "test:esbuild:ci": "node scripts/c8-ci.js test:esbuild",
47
+ "test:turbopack": "mocha \"packages/datadog-turbopack/test/**/*.spec.js\"",
48
+ "test:turbopack:ci": "node scripts/c8-ci.js test:turbopack",
48
49
  "test:webpack": "mocha \"packages/datadog-webpack/test/**/*.spec.js\"",
49
50
  "test:webpack:ci": "node scripts/c8-ci.js test:webpack",
50
51
  "test:instrumentations": "mocha --fail-zero \"packages/datadog-instrumentations/test/@(${PLUGINS}).spec.js\"",
@@ -89,6 +90,7 @@
89
90
  "test:integration:electron": "mocha \"integration-tests/electron/*.spec.js\"",
90
91
  "test:integration:esbuild": "mocha --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
91
92
  "test:integration:esbuild:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
93
+ "test:integration:turbopack": "mocha --timeout 60000 \"integration-tests/turbopack/*.spec.js\"",
92
94
  "test:integration:webpack": "mocha --timeout 60000 \"integration-tests/webpack/*.spec.js\"",
93
95
  "test:integration:openfeature": "mocha --timeout 60000 \"integration-tests/openfeature/*.spec.js\"",
94
96
  "test:integration:openfeature:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/openfeature/*.spec.js\"",
@@ -154,6 +156,8 @@
154
156
  "ci/**/*",
155
157
  "cypress/**/*",
156
158
  "esbuild.js",
159
+ "next.js",
160
+ "next.d.ts",
157
161
  "webpack.js",
158
162
  "ext/**/*",
159
163
  "index.d.ts",
@@ -184,7 +188,7 @@
184
188
  ],
185
189
  "dependencies": {
186
190
  "dc-polyfill": "^0.1.11",
187
- "import-in-the-middle": "^3.5.0",
191
+ "import-in-the-middle": "3.5.1",
188
192
  "opentracing": ">=0.14.7"
189
193
  },
190
194
  "optionalDependencies": {
@@ -203,9 +207,9 @@
203
207
  "@actions/core": "^3.0.1",
204
208
  "@actions/github": "^9.1.1",
205
209
  "@babel/helpers": "^8.0.0",
206
- "@eslint/eslintrc": "^3.3.6",
210
+ "@eslint/eslintrc": "^3.3.7",
207
211
  "@eslint/js": "^10.0.1",
208
- "@eslint/plugin-kit": "^0.7.2",
212
+ "@eslint/plugin-kit": "^0.7.3",
209
213
  "@datadog/openfeature-node-server": "2.2.0",
210
214
  "@msgpack/msgpack": "^3.1.3",
211
215
  "@openfeature/core": "^1.12.0",
@@ -225,16 +229,16 @@
225
229
  "eslint": "^10.9.1",
226
230
  "eslint-plugin-cypress": "^7.0.1",
227
231
  "eslint-plugin-import-x": "^4.16.2",
228
- "eslint-plugin-jsdoc": "^64.2.1",
232
+ "eslint-plugin-jsdoc": "^64.3.5",
229
233
  "eslint-plugin-mocha": "^12.0.2",
230
234
  "eslint-plugin-n": "^18.3.0",
231
235
  "eslint-plugin-promise": "^7.3.0",
232
- "eslint-plugin-regexp": "^3.1.0",
236
+ "eslint-plugin-regexp": "^3.2.0",
233
237
  "eslint-plugin-sonarjs": "^4.2.0",
234
238
  "eslint-plugin-unicorn": "^74.0.0",
235
239
  "express": "^5.1.0",
236
240
  "glob": "^10.4.5",
237
- "globals": "^17.11.0",
241
+ "globals": "^17.12.0",
238
242
  "graphql": "*",
239
243
  "husky": "^9.1.7",
240
244
  "istanbul-lib-coverage": "^3.2.2",
@@ -246,12 +250,12 @@
246
250
  "mocha": "^11.8.0",
247
251
  "mocha-junit-reporter": "^2.2.1",
248
252
  "mocha-multi-reporters": "^1.5.1",
249
- "multer": "^2.2.0",
253
+ "multer": "^2.3.0",
250
254
  "nock": "^14.0.17",
251
255
  "node-preload": "^0.2.1",
252
256
  "nyc": "^18.0.0",
253
257
  "octokit": "^5.0.3",
254
- "p-limit": "^7.3.1",
258
+ "p-limit": "^7.3.2",
255
259
  "proxyquire": "^2.1.3",
256
260
  "retry": "^0.13.1",
257
261
  "semifies": "^1.0.0",
@@ -267,16 +271,11 @@
267
271
  "yarn-deduplicate": "^6.0.2"
268
272
  },
269
273
  "depup": {
270
- "changes": {
271
- "import-in-the-middle": {
272
- "from": "^3.3.2",
273
- "to": "^3.5.0"
274
- }
275
- },
276
- "depsUpdated": 1,
274
+ "changes": {},
275
+ "depsUpdated": 0,
277
276
  "originalPackage": "dd-trace",
278
- "originalVersion": "6.15.0",
279
- "processedAt": "2026-09-09T00:33:53.111Z",
277
+ "originalVersion": "6.16.0",
278
+ "processedAt": "2026-09-12T00:31:43.733Z",
280
279
  "smokeTest": "passed"
281
280
  }
282
281
  }
@@ -8,8 +8,9 @@ const { pathToFileURL, fileURLToPath } = require('node:url')
8
8
  const instrumentations = require('../datadog-instrumentations/src/helpers/instrumentations')
9
9
  const extractPackageAndModulePath = require('../datadog-instrumentations/src/helpers/extract-package-and-module-path')
10
10
  const hooks = require('../datadog-instrumentations/src/helpers/hooks')
11
- const { processModule, isESMFile } = require('./src/utils')
12
11
  const log = require('./src/log')
12
+ const { createEsmResolver } = require('./src/resolver')
13
+ const { isESMFile, processModule } = require('./src/utils')
13
14
 
14
15
  const ESM_INTERCEPTED_SUFFIX = '._dd_esbuild_intercepted'
15
16
  const INTERNAL_ESM_INTERCEPTED_PREFIX = '/_dd_esm_internal_/'
@@ -166,6 +167,13 @@ ${build.initialOptions.banner.js}`
166
167
 
167
168
  // first time is intercepted, proxy should be created, next time the original should be loaded
168
169
  const interceptedESMModules = new Set()
170
+ let resolver
171
+
172
+ build.onEnd(async () => {
173
+ const activeResolver = resolver
174
+ resolver = undefined
175
+ await activeResolver?.close()
176
+ })
169
177
 
170
178
  build.onResolve({ filter: /.*/ }, args => {
171
179
  if (externalModules.has(args.path)) {
@@ -316,10 +324,15 @@ ${build.initialOptions.banner.js}`
316
324
 
317
325
  interceptedESMModules.add(args.path)
318
326
 
327
+ resolver ??= createEsmResolver()
319
328
  const setters = await processModule({
320
329
  path: args.path,
321
330
  internal: data.internal,
322
331
  context: { format: 'module' },
332
+ excludeDefault: false,
333
+ moduleSources: new Map(),
334
+ resolver,
335
+ transform: build.esbuild.transformSync,
323
336
  })
324
337
 
325
338
  const iitmPath = require.resolve('import-in-the-middle/lib/register.js')
@@ -0,0 +1,284 @@
1
+ 'use strict'
2
+
3
+ const childProcess = require('node:child_process')
4
+ const readline = require('node:readline')
5
+
6
+ const { getEnvironmentVariables } = require('../../dd-trace/src/config/helper')
7
+
8
+ const MAX_PENDING_REQUESTS = 1024
9
+ const MAX_STDERR_LENGTH = 16 * 1024
10
+ const LOAD_OPERATION = 0
11
+ const RESOLVE_OPERATION = 1
12
+ const RESOLVER_SOURCE = String.raw`
13
+ import { createReadStream, createWriteStream } from 'node:fs'
14
+ import readline from 'node:readline'
15
+
16
+ const requests = createReadStream(null, { fd: 3, autoClose: false })
17
+ const responses = createWriteStream(null, { fd: 4, autoClose: false })
18
+ const lines = readline.createInterface({ input: requests })
19
+
20
+ for await (const line of lines) {
21
+ let request
22
+ try {
23
+ request = JSON.parse(line)
24
+ const url = await import.meta.resolve(request.specifier, request.parentURL)
25
+ responses.write(JSON.stringify({ id: request.id, url }) + '\n')
26
+ } catch (error) {
27
+ responses.write(JSON.stringify({
28
+ error: {
29
+ code: error?.code,
30
+ message: String(error?.message ?? error),
31
+ },
32
+ id: request?.id,
33
+ }) + '\n')
34
+ }
35
+ }
36
+ responses.end()
37
+ `
38
+
39
+ /** @typedef {{ specifier: string, parentURL: string }} StarReexport */
40
+
41
+ /**
42
+ * @typedef {{ exportNames: Iterable<string>, starReexports?: StarReexport[] }} ModuleExports
43
+ */
44
+
45
+ /**
46
+ * @typedef {Set<string>|ModuleExports} GetExportsValue
47
+ */
48
+
49
+ /**
50
+ * @typedef {[typeof LOAD_OPERATION, URL, object] | [typeof RESOLVE_OPERATION, string, object]} GetExportsOperation
51
+ */
52
+
53
+ /**
54
+ * @typedef {{ done: false, value: GetExportsOperation } | { done: true, value: GetExportsValue }} GetExportsResult
55
+ */
56
+
57
+ /**
58
+ * @typedef {{
59
+ * next: (value?: unknown) => GetExportsResult,
60
+ * throw: (error?: unknown) => GetExportsResult,
61
+ * }} GetExportsGenerator
62
+ */
63
+
64
+ class EsmResolver {
65
+ #child
66
+ #closed = false
67
+ #closedPromise
68
+ #failure
69
+ #nextId = 0
70
+ #pending = new Map()
71
+ #readline
72
+ #rejectClosed
73
+ #request
74
+ #resolveClosed
75
+ #stderr = ''
76
+
77
+ constructor () {
78
+ this.#closedPromise = new Promise((resolve, reject) => {
79
+ this.#resolveClosed = resolve
80
+ this.#rejectClosed = reject
81
+ })
82
+ // Mark lifecycle failures handled immediately. close() still returns the original promise.
83
+ this.#closedPromise.catch(() => {})
84
+ }
85
+
86
+ /**
87
+ * @param {string} specifier
88
+ * @param {URL|string} parentURL
89
+ * @returns {Promise<string>}
90
+ */
91
+ resolve (specifier, parentURL) {
92
+ if (this.#closed) return Promise.reject(this.#failure ?? new Error('The ESM resolver is closed'))
93
+ if (this.#pending.size >= MAX_PENDING_REQUESTS) {
94
+ return Promise.reject(new Error(`The ESM resolver has more than ${MAX_PENDING_REQUESTS} pending requests`))
95
+ }
96
+
97
+ try {
98
+ this.#start()
99
+ } catch (error) {
100
+ this.#failure = error
101
+ this.#closed = true
102
+ this.#resolveClosed()
103
+ return Promise.reject(error)
104
+ }
105
+ const id = this.#nextId++
106
+ return new Promise((resolve, reject) => {
107
+ this.#pending.set(id, { reject, resolve })
108
+ this.#request.write(`${JSON.stringify({ id, parentURL: String(parentURL), specifier })}\n`, error => {
109
+ if (error) this.#rejectRequest(id, error)
110
+ })
111
+ })
112
+ }
113
+
114
+ /** @returns {Promise<void>} */
115
+ close () {
116
+ if (!this.#closed) {
117
+ this.#closed = true
118
+ if (this.#child) this.#request.end()
119
+ else this.#resolveClosed()
120
+ }
121
+ return this.#closedPromise
122
+ }
123
+
124
+ #start () {
125
+ if (this.#child) return
126
+ const env = getEnvironmentVariables()
127
+ env.DD_CIVISIBILITY_ENABLED = 'false'
128
+ env.DD_INSTRUMENTATION_TELEMETRY_ENABLED = 'false'
129
+ env.DD_TRACE_ENABLED = 'false'
130
+ this.#child = childProcess.spawn(process.execPath, [
131
+ '--no-warnings',
132
+ '--experimental-import-meta-resolve',
133
+ '--input-type=module',
134
+ '--eval',
135
+ RESOLVER_SOURCE,
136
+ ], {
137
+ env,
138
+ stdio: ['ignore', 'ignore', 'pipe', 'pipe', 'pipe'],
139
+ })
140
+ this.#request = this.#child.stdio[3]
141
+ this.#readline = readline.createInterface({ input: this.#child.stdio[4] })
142
+ this.#readline.on('line', this.#handleLine)
143
+ this.#request.once('error', this.#handleError)
144
+ this.#child.stdio[4].once('error', this.#handleError)
145
+ this.#child.stderr.on('data', this.#handleStderr)
146
+ this.#child.once('error', this.#handleError)
147
+ this.#child.once('close', this.#handleClose)
148
+ }
149
+
150
+ /** @param {string} line */
151
+ #handleLine = (line) => {
152
+ let response
153
+ try {
154
+ response = JSON.parse(line)
155
+ } catch (error) {
156
+ this.#fail(new Error(`The ESM resolver returned malformed JSON: ${error.message}`))
157
+ return
158
+ }
159
+
160
+ const id = response?.id
161
+ if (!Number.isSafeInteger(id) || !this.#pending.has(id)) {
162
+ this.#fail(new Error('The ESM resolver returned an unknown request identifier'))
163
+ return
164
+ }
165
+ if (typeof response.url === 'string' && response.error === undefined) {
166
+ const request = this.#pending.get(id)
167
+ this.#pending.delete(id)
168
+ request.resolve(response.url)
169
+ return
170
+ }
171
+ if (typeof response.error?.message !== 'string' || response.url !== undefined) {
172
+ this.#rejectRequest(id, new Error('The ESM resolver returned a malformed response'))
173
+ return
174
+ }
175
+
176
+ const error = /** @type {Error & { code?: string }} */ (new Error(response.error.message))
177
+ if (typeof response.error.code === 'string') error.code = response.error.code
178
+ this.#rejectRequest(id, error)
179
+ }
180
+
181
+ /** @param {Buffer|string} chunk */
182
+ #handleStderr = (chunk) => {
183
+ if (this.#stderr.length >= MAX_STDERR_LENGTH) return
184
+ this.#stderr += String(chunk).slice(0, MAX_STDERR_LENGTH - this.#stderr.length)
185
+ }
186
+
187
+ /** @param {Error} error */
188
+ #handleError = (error) => {
189
+ this.#fail(error)
190
+ }
191
+
192
+ /**
193
+ * @param {number|null} code
194
+ * @param {string|null} signal
195
+ */
196
+ #handleClose = (code, signal) => {
197
+ this.#readline?.close()
198
+ this.#closed = true
199
+ let error = this.#failure
200
+ if (!error && (code !== 0 || this.#pending.size > 0)) {
201
+ const reason = signal ? `signal ${signal}` : `status ${code}`
202
+ const stderr = this.#stderr.trim()
203
+ error = new Error(`The ESM resolver exited with ${reason}${stderr ? `: ${stderr}` : ''}`)
204
+ this.#failure = error
205
+ }
206
+ if (error) {
207
+ this.#rejectAll(error)
208
+ this.#rejectClosed(error)
209
+ } else {
210
+ this.#resolveClosed()
211
+ }
212
+ }
213
+
214
+ /**
215
+ * @param {number} id
216
+ * @param {Error} error
217
+ */
218
+ #rejectRequest (id, error) {
219
+ const request = this.#pending.get(id)
220
+ if (!request) return
221
+ this.#pending.delete(id)
222
+ request.reject(error)
223
+ }
224
+
225
+ /** @param {Error} error */
226
+ #fail (error) {
227
+ if (this.#failure) return
228
+ this.#failure = error
229
+ this.#closed = true
230
+ this.#rejectAll(error)
231
+ this.#request?.destroy()
232
+ this.#child?.kill()
233
+ }
234
+
235
+ /** @param {Error} error */
236
+ #rejectAll (error) {
237
+ for (const request of this.#pending.values()) request.reject(error)
238
+ this.#pending.clear()
239
+ }
240
+ }
241
+
242
+ /** @returns {EsmResolver} */
243
+ function createEsmResolver () {
244
+ return new EsmResolver()
245
+ }
246
+
247
+ /**
248
+ * Drives the generator returned by import-in-the-middle >=3.1.0 export discovery.
249
+ *
250
+ * @param {GetExportsGenerator} exportsGenerator
251
+ * @param {(url: URL, context: object) => { source: string, format: string }} getSource
252
+ * @param {(specifier: string, context: object) => Promise<{ format: string, url: URL }>} resolve
253
+ * @returns {Promise<ModuleExports>}
254
+ */
255
+ async function driveGetExportsGenerator (exportsGenerator, getSource, resolve) {
256
+ let next = exportsGenerator.next()
257
+ while (next.done === false) {
258
+ let result
259
+ let failure
260
+ let threw = false
261
+
262
+ try {
263
+ const operation = next.value
264
+ const operationType = operation[0]
265
+
266
+ if (operationType === LOAD_OPERATION) {
267
+ result = getSource(operation[1], operation[2])
268
+ } else if (operationType === RESOLVE_OPERATION) {
269
+ // eslint-disable-next-line no-await-in-loop
270
+ result = await resolve(operation[1], operation[2])
271
+ } else {
272
+ throw new Error(`Unsupported import-in-the-middle getExports operation: ${operationType}`)
273
+ }
274
+ } catch (error) {
275
+ threw = true
276
+ failure = error
277
+ }
278
+
279
+ next = threw ? exportsGenerator.throw(failure) : exportsGenerator.next(result)
280
+ }
281
+ return next.value instanceof Set ? { exportNames: next.value } : next.value
282
+ }
283
+
284
+ module.exports = { createEsmResolver, driveGetExportsGenerator }