@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64

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 (261) hide show
  1. package/AUTHORING.md +367 -9
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/bin/apifuse-check.ts +84 -2
  6. package/bin/apifuse-dev.ts +11 -31
  7. package/bin/apifuse-migrate-deployment.ts +200 -0
  8. package/bin/apifuse-pack-check.ts +11 -4
  9. package/bin/apifuse-pack-types.ts +187 -4
  10. package/bin/apifuse-record.ts +44 -32
  11. package/bin/apifuse-submit-check.ts +9 -5
  12. package/bin/apifuse-test.ts +3 -1
  13. package/dist/cli/commands.d.ts +1 -1
  14. package/dist/cli/commands.js +11 -0
  15. package/dist/cli/deployment-intent.d.ts +178 -0
  16. package/dist/cli/deployment-intent.js +277 -0
  17. package/dist/cli/migrate-deployment-intent.d.ts +132 -0
  18. package/dist/cli/migrate-deployment-intent.js +1552 -0
  19. package/dist/cli/migrate-provider-shape.d.ts +5 -1
  20. package/dist/cli/migrate-provider-shape.js +4 -2
  21. package/dist/cli/resolver-runtime.d.ts +21 -0
  22. package/dist/cli/resolver-runtime.js +31 -0
  23. package/dist/define.d.ts +3 -0
  24. package/dist/define.js +5 -0
  25. package/dist/dev.d.ts +3 -1
  26. package/dist/dev.js +6 -1
  27. package/dist/engine.d.ts +35 -1
  28. package/dist/engine.js +21 -2
  29. package/dist/error-resolution.d.ts +1 -0
  30. package/dist/error-resolution.js +54 -0
  31. package/dist/errors.d.ts +39 -1
  32. package/dist/errors.js +50 -0
  33. package/dist/handle-meta.d.ts +36 -1
  34. package/dist/handle-meta.js +16 -0
  35. package/dist/handle.d.ts +23 -5
  36. package/dist/handle.js +54 -8
  37. package/dist/health-scenario.d.ts +38 -0
  38. package/dist/i18n/error-messages.d.ts +86 -0
  39. package/dist/i18n/error-messages.js +192 -0
  40. package/dist/i18n/index.d.ts +1 -0
  41. package/dist/i18n/index.js +1 -0
  42. package/dist/i18n/keys.d.ts +12 -0
  43. package/dist/i18n/keys.js +76 -5
  44. package/dist/index.d.ts +11 -3
  45. package/dist/index.js +9 -1
  46. package/dist/lint.d.ts +15 -0
  47. package/dist/lint.js +469 -82
  48. package/dist/provider.d.ts +6 -6
  49. package/dist/provider.js +3 -3
  50. package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
  51. package/dist/runtime/browser-telemetry-binding.js +83 -0
  52. package/dist/runtime/browser-telemetry.d.ts +76 -0
  53. package/dist/runtime/browser-telemetry.js +165 -0
  54. package/dist/runtime/browser.d.ts +3 -0
  55. package/dist/runtime/browser.js +208 -47
  56. package/dist/runtime/cache-telemetry.d.ts +71 -0
  57. package/dist/runtime/cache-telemetry.js +177 -0
  58. package/dist/runtime/cache.js +67 -7
  59. package/dist/runtime/capability-response.d.ts +3 -0
  60. package/dist/runtime/capability-response.js +56 -0
  61. package/dist/runtime/capability-telemetry.d.ts +46 -0
  62. package/dist/runtime/capability-telemetry.js +68 -0
  63. package/dist/runtime/diagnostic-env.d.ts +3 -0
  64. package/dist/runtime/diagnostic-env.js +10 -1
  65. package/dist/runtime/engine-mode.d.ts +74 -0
  66. package/dist/runtime/engine-mode.js +152 -0
  67. package/dist/runtime/handle.js +9 -1
  68. package/dist/runtime/http-telemetry-guard.d.ts +10 -0
  69. package/dist/runtime/http-telemetry-guard.js +62 -10
  70. package/dist/runtime/http.js +141 -35
  71. package/dist/runtime/instrumentation.js +92 -13
  72. package/dist/runtime/ocr-telemetry.d.ts +82 -0
  73. package/dist/runtime/ocr-telemetry.js +192 -0
  74. package/dist/runtime/ocr.js +35 -8
  75. package/dist/runtime/request-telemetry.d.ts +2 -0
  76. package/dist/runtime/request-telemetry.js +2 -1
  77. package/dist/runtime/resolver-runtime-options.d.ts +14 -0
  78. package/dist/runtime/resolver-runtime-options.js +33 -0
  79. package/dist/runtime/resolver-shared.d.ts +3 -2
  80. package/dist/runtime/resolver-shared.js +4 -4
  81. package/dist/runtime/resolver-telemetry.d.ts +1 -0
  82. package/dist/runtime/resolver-telemetry.js +1 -1
  83. package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
  84. package/dist/runtime/resolver-vendors/browser.js +46 -0
  85. package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
  86. package/dist/runtime/resolver-vendors/hosts.js +35 -0
  87. package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
  88. package/dist/runtime/resolver-vendors/types.d.ts +5 -4
  89. package/dist/runtime/resolver.d.ts +4 -1
  90. package/dist/runtime/resolver.js +46 -13
  91. package/dist/runtime/state-telemetry.d.ts +79 -0
  92. package/dist/runtime/state-telemetry.js +194 -0
  93. package/dist/runtime/state.d.ts +3 -0
  94. package/dist/runtime/state.js +26 -7
  95. package/dist/runtime/stealth-cookies.d.ts +5 -1
  96. package/dist/runtime/stealth-cookies.js +21 -1
  97. package/dist/runtime/stealth-owned-headers.d.ts +26 -0
  98. package/dist/runtime/stealth-owned-headers.js +37 -0
  99. package/dist/runtime/stealth-telemetry.d.ts +92 -0
  100. package/dist/runtime/stealth-telemetry.js +179 -0
  101. package/dist/runtime/stealth.d.ts +4 -1
  102. package/dist/runtime/stealth.js +228 -85
  103. package/dist/runtime/stt-telemetry.d.ts +77 -0
  104. package/dist/runtime/stt-telemetry.js +176 -0
  105. package/dist/runtime/stt.js +15 -6
  106. package/dist/runtime-boundary-lint.d.ts +132 -0
  107. package/dist/runtime-boundary-lint.js +586 -0
  108. package/dist/server/error-stack-frames.d.ts +35 -0
  109. package/dist/server/error-stack-frames.js +219 -0
  110. package/dist/server/index.d.ts +7 -0
  111. package/dist/server/index.js +4 -0
  112. package/dist/server/sdk-version.d.ts +3 -0
  113. package/dist/server/sdk-version.js +19 -0
  114. package/dist/server/self-test.js +1 -18
  115. package/dist/server/sensitive-values.d.ts +1 -1
  116. package/dist/server/sensitive-values.js +9 -0
  117. package/dist/server/serve-implementation.d.ts +51 -2
  118. package/dist/server/serve-implementation.js +337 -90
  119. package/dist/server/types.d.ts +1 -0
  120. package/dist/server/types.js +7 -0
  121. package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
  122. package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
  123. package/dist/stateful/stateful-provider-runtime-context.js +1 -0
  124. package/dist/types.d.ts +123 -1
  125. package/dist/typescript-module.d.ts +39 -0
  126. package/dist/typescript-module.js +72 -0
  127. package/package.json +6 -1
  128. package/src/cli/commands.ts +14 -0
  129. package/src/cli/deployment-intent.ts +364 -0
  130. package/src/cli/migrate-deployment-intent.ts +1908 -0
  131. package/src/cli/migrate-provider-shape.ts +10 -4
  132. package/src/cli/resolver-runtime.ts +72 -0
  133. package/src/define.ts +13 -0
  134. package/src/dev.ts +9 -2
  135. package/src/engine.ts +38 -2
  136. package/src/error-resolution.ts +58 -0
  137. package/src/errors.ts +77 -1
  138. package/src/handle-meta.ts +51 -1
  139. package/src/handle.ts +92 -10
  140. package/src/health-scenario.ts +38 -0
  141. package/src/i18n/error-messages.ts +255 -0
  142. package/src/i18n/index.ts +1 -0
  143. package/src/i18n/keys.ts +80 -6
  144. package/src/index.ts +86 -0
  145. package/src/lint.ts +604 -91
  146. package/src/provider.ts +12 -0
  147. package/src/runtime/browser-telemetry-binding.ts +92 -0
  148. package/src/runtime/browser-telemetry.ts +289 -0
  149. package/src/runtime/browser.ts +249 -65
  150. package/src/runtime/cache-telemetry.ts +247 -0
  151. package/src/runtime/cache.ts +68 -17
  152. package/src/runtime/capability-response.ts +53 -0
  153. package/src/runtime/capability-telemetry.ts +101 -0
  154. package/src/runtime/diagnostic-env.ts +11 -1
  155. package/src/runtime/engine-mode.ts +233 -0
  156. package/src/runtime/handle.ts +9 -1
  157. package/src/runtime/http-telemetry-guard.ts +66 -13
  158. package/src/runtime/http.ts +168 -37
  159. package/src/runtime/instrumentation.ts +105 -16
  160. package/src/runtime/ocr-telemetry.ts +308 -0
  161. package/src/runtime/ocr.ts +114 -74
  162. package/src/runtime/request-telemetry.ts +2 -1
  163. package/src/runtime/resolver-runtime-options.ts +50 -0
  164. package/src/runtime/resolver-shared.ts +9 -4
  165. package/src/runtime/resolver-telemetry.ts +1 -1
  166. package/src/runtime/resolver-vendors/browser.ts +65 -7
  167. package/src/runtime/resolver-vendors/hosts.ts +43 -0
  168. package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
  169. package/src/runtime/resolver-vendors/types.ts +5 -4
  170. package/src/runtime/resolver.ts +64 -21
  171. package/src/runtime/state-telemetry.ts +298 -0
  172. package/src/runtime/state.ts +46 -45
  173. package/src/runtime/stealth-cookies.ts +24 -1
  174. package/src/runtime/stealth-owned-headers.ts +41 -0
  175. package/src/runtime/stealth-telemetry.ts +304 -0
  176. package/src/runtime/stealth.ts +355 -150
  177. package/src/runtime/stt-telemetry.ts +282 -0
  178. package/src/runtime/stt.ts +93 -71
  179. package/src/runtime-boundary-lint.ts +703 -0
  180. package/src/server/error-stack-frames.ts +214 -0
  181. package/src/server/index.ts +53 -0
  182. package/src/server/sdk-version.ts +22 -0
  183. package/src/server/self-test.ts +1 -21
  184. package/src/server/sensitive-values.ts +14 -0
  185. package/src/server/serve-implementation.ts +569 -108
  186. package/src/server/types.ts +7 -0
  187. package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
  188. package/src/stateful/stateful-provider-runtime-context.ts +4 -0
  189. package/src/types.ts +128 -1
  190. package/src/typescript-module.ts +100 -0
  191. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
  192. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
  193. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
  194. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
  195. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
  196. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
  197. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
  198. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
  199. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
  200. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
  201. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
  202. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
  203. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
  204. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
  205. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
  206. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
  207. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
  208. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
  209. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
  210. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
  211. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
  212. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
  213. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
  214. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
  215. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
  216. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
  217. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
  218. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
  219. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
  220. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
  221. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
  222. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
  246. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
  247. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
  248. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
  249. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
  250. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
  251. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
  252. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
  253. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
  254. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
  255. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
  256. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
  257. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
  258. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
  259. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
  260. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
  261. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
@@ -0,0 +1,304 @@
1
+ import { Buffer } from "node:buffer";
2
+
3
+ import type {
4
+ StealthBrowser,
5
+ StealthChallengeClassification,
6
+ StealthOS,
7
+ StealthProfileDescriptor,
8
+ } from "../types.js";
9
+ import { type ClosedEnum, closedEnum, type TelemetryContributor } from "./request-telemetry.js";
10
+
11
+ export type StealthTelemetryErrorCode =
12
+ | "transport_network_error"
13
+ | "transport_timeout"
14
+ | "transport_cancelled"
15
+ | "upstream_http_error"
16
+ | "response_too_large"
17
+ | "proxy_connect_failed"
18
+ | "PROXY_POOL_STALE"
19
+ | "PROXY_EDGE_AUTH_REJECTED"
20
+ | "PROXY_AUTH_IP_DENIED"
21
+ | "PROXY_EDGE_TLS_REJECTED"
22
+ | "PROXY_REQUIRED"
23
+ | "other";
24
+
25
+ export type StealthTelemetryRequestClass = "navigation" | "script_navigation" | "xhr" | "post";
26
+
27
+ export type StealthTelemetryAttemptKind = "request" | "resolver" | "proxy_diagnostic";
28
+
29
+ export type StealthTelemetrySbsdOutcome =
30
+ | StealthChallengeClassification["outcome"]
31
+ | "detected"
32
+ | "refetch_clear";
33
+
34
+ export type StealthTelemetryDiagnostics = {
35
+ readonly name?: string;
36
+ readonly message?: string;
37
+ readonly code?: string;
38
+ };
39
+
40
+ export type StealthTelemetryAttemptEvent = {
41
+ readonly ms: number;
42
+ readonly status?: number;
43
+ readonly errorCode?: StealthTelemetryErrorCode;
44
+ readonly diagnostics?: StealthTelemetryDiagnostics;
45
+ readonly profileId: StealthProfileDescriptor;
46
+ readonly proxyUsed: boolean;
47
+ readonly requestClass: StealthTelemetryRequestClass;
48
+ readonly kind?: StealthTelemetryAttemptKind;
49
+ };
50
+
51
+ export type StealthTelemetrySbsdEvent = {
52
+ readonly detected: boolean;
53
+ readonly outcome?: StealthTelemetrySbsdOutcome;
54
+ };
55
+
56
+ export interface StealthTelemetrySink {
57
+ recordAttempt(event: StealthTelemetryAttemptEvent): void;
58
+ recordPoolRefresh(): void;
59
+ recordRedirectHop(): void;
60
+ recordSbsd(event?: StealthTelemetrySbsdEvent | StealthTelemetrySbsdOutcome): void;
61
+ recordSafeRefetch(): void;
62
+ }
63
+
64
+ export type StealthTelemetryAttemptSample = {
65
+ n: number;
66
+ ms: number;
67
+ status?: number;
68
+ e?: StealthTelemetryErrorCode;
69
+ kind?: StealthTelemetryAttemptKind;
70
+ diagnostics?: StealthTelemetryDiagnostics;
71
+ };
72
+
73
+ export type StealthTelemetryLogPayload = {
74
+ attempts: number;
75
+ poolRefreshes: number;
76
+ redirectHops: number;
77
+ profileId?: StealthProfileDescriptor;
78
+ proxyUsed: boolean;
79
+ requestClass?: StealthTelemetryRequestClass;
80
+ sbsdDetected?: boolean;
81
+ sbsdOutcome?: StealthTelemetrySbsdOutcome;
82
+ safeRefetch: number;
83
+ lastStatus?: number;
84
+ ms: number;
85
+ attemptSamples?: StealthTelemetryAttemptSample[];
86
+ attemptSamplesDropped?: number;
87
+ };
88
+
89
+ export type StealthTelemetryHeaderPayload = {
90
+ attempts: number;
91
+ poolRefreshes: number;
92
+ redirectHops: number;
93
+ profileId?: {
94
+ browser: ClosedEnum<StealthBrowser>;
95
+ os: ClosedEnum<StealthOS>;
96
+ };
97
+ proxyUsed: boolean;
98
+ requestClass?: ClosedEnum<StealthTelemetryRequestClass>;
99
+ sbsdDetected?: boolean;
100
+ sbsdOutcome?: ClosedEnum<StealthTelemetrySbsdOutcome>;
101
+ safeRefetch: number;
102
+ lastStatus?: number;
103
+ ms: number;
104
+ attemptSamples?: {
105
+ n: number;
106
+ ms: number;
107
+ status?: number;
108
+ e?: ClosedEnum<StealthTelemetryErrorCode>;
109
+ kind?: ClosedEnum<StealthTelemetryAttemptKind>;
110
+ }[];
111
+ };
112
+
113
+ const MAX_ATTEMPT_SAMPLES = 24;
114
+ const MAX_DIAGNOSTIC_TEXT = 300;
115
+
116
+ function boundedInteger(value: number): number {
117
+ if (!Number.isFinite(value)) return Number.MAX_SAFE_INTEGER;
118
+ return Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(value)));
119
+ }
120
+
121
+ function saturatingAdd(a: number, b: number): number {
122
+ if (!Number.isFinite(a) || !Number.isFinite(b)) return Number.MAX_SAFE_INTEGER;
123
+ return Math.min(Number.MAX_SAFE_INTEGER, boundedInteger(a) + boundedInteger(b));
124
+ }
125
+
126
+ function boundedText(value: string, redact?: (text: string) => string): string {
127
+ let result = value;
128
+ try {
129
+ result = redact?.(value) ?? value;
130
+ } catch {
131
+ result = "[REDACTION_FAILED]";
132
+ }
133
+ const length = Math.min(result.length, MAX_DIAGNOSTIC_TEXT);
134
+ const units = Buffer.alloc(length * 2);
135
+ for (let index = 0; index < length; index += 1) {
136
+ units.writeUInt16LE(result.charCodeAt(index), index * 2);
137
+ }
138
+ return units.toString("utf16le");
139
+ }
140
+
141
+ function cloneDiagnostics(
142
+ diagnostics: StealthTelemetryDiagnostics | undefined,
143
+ redact: ((text: string) => string) | undefined,
144
+ ): StealthTelemetryDiagnostics | undefined {
145
+ if (!diagnostics) return undefined;
146
+ const result: StealthTelemetryDiagnostics = {
147
+ ...(diagnostics.name === undefined ? {} : { name: boundedText(diagnostics.name, redact) }),
148
+ ...(diagnostics.message === undefined
149
+ ? {}
150
+ : { message: boundedText(diagnostics.message, redact) }),
151
+ ...(diagnostics.code === undefined ? {} : { code: boundedText(diagnostics.code, redact) }),
152
+ };
153
+ return Object.keys(result).length > 0 ? result : undefined;
154
+ }
155
+
156
+ function cloneProfile(profile: StealthProfileDescriptor): StealthProfileDescriptor {
157
+ return { browser: profile.browser, os: profile.os } as StealthProfileDescriptor;
158
+ }
159
+
160
+ export class StealthTelemetryCollector
161
+ implements
162
+ StealthTelemetrySink,
163
+ TelemetryContributor<StealthTelemetryLogPayload, StealthTelemetryHeaderPayload>
164
+ {
165
+ readonly key = "stealth" as const;
166
+ readonly #redact: ((text: string) => string) | undefined;
167
+ #attempts = 0;
168
+ #poolRefreshes = 0;
169
+ #redirectHops = 0;
170
+ #profileId: StealthProfileDescriptor | undefined;
171
+ #proxyUsed = false;
172
+ #requestClass: StealthTelemetryRequestClass | undefined;
173
+ #sbsdDetected: boolean | undefined;
174
+ #sbsdOutcome: StealthTelemetrySbsdOutcome | undefined;
175
+ #safeRefetch = 0;
176
+ #lastStatus: number | undefined;
177
+ #ms = 0;
178
+ #attemptSamples: StealthTelemetryAttemptSample[] = [];
179
+ #attemptSamplesDropped = 0;
180
+
181
+ constructor(options: { redact?: (text: string) => string } = {}) {
182
+ this.#redact = options.redact;
183
+ }
184
+
185
+ recordAttempt(event: StealthTelemetryAttemptEvent): void {
186
+ const ms = boundedInteger(event.ms);
187
+ this.#attempts = saturatingAdd(this.#attempts, 1);
188
+ this.#ms = saturatingAdd(this.#ms, ms);
189
+ this.#profileId = cloneProfile(event.profileId);
190
+ this.#proxyUsed ||= event.proxyUsed;
191
+ this.#requestClass = event.requestClass;
192
+ if (event.status !== undefined) this.#lastStatus = boundedInteger(event.status);
193
+ if (this.#attemptSamples.length >= MAX_ATTEMPT_SAMPLES) {
194
+ this.#attemptSamplesDropped = saturatingAdd(this.#attemptSamplesDropped, 1);
195
+ return;
196
+ }
197
+ const sample: StealthTelemetryAttemptSample = {
198
+ n: this.#attempts,
199
+ ms,
200
+ ...(event.status === undefined ? {} : { status: boundedInteger(event.status) }),
201
+ ...(event.errorCode === undefined ? {} : { e: event.errorCode }),
202
+ ...(event.kind === undefined ? {} : { kind: event.kind }),
203
+ ...(event.diagnostics
204
+ ? { diagnostics: cloneDiagnostics(event.diagnostics, this.#redact) }
205
+ : {}),
206
+ };
207
+ if (sample.diagnostics === undefined) delete sample.diagnostics;
208
+ this.#attemptSamples.push(sample);
209
+ }
210
+
211
+ recordPoolRefresh(): void {
212
+ this.#poolRefreshes = saturatingAdd(this.#poolRefreshes, 1);
213
+ }
214
+
215
+ recordRedirectHop(): void {
216
+ this.#redirectHops = saturatingAdd(this.#redirectHops, 1);
217
+ }
218
+
219
+ recordSbsd(event?: StealthTelemetrySbsdEvent | StealthTelemetrySbsdOutcome): void {
220
+ if (typeof event === "string") {
221
+ this.#sbsdDetected = true;
222
+ this.#sbsdOutcome = event;
223
+ return;
224
+ }
225
+ if (!event) return;
226
+ this.#sbsdDetected = (this.#sbsdDetected ?? false) || event.detected;
227
+ if (event.outcome !== undefined) this.#sbsdOutcome = event.outcome;
228
+ }
229
+
230
+ recordSafeRefetch(): void {
231
+ this.#safeRefetch = saturatingAdd(this.#safeRefetch, 1);
232
+ }
233
+
234
+ toLogPayload(): StealthTelemetryLogPayload | undefined {
235
+ if (
236
+ this.#attempts === 0 &&
237
+ this.#poolRefreshes === 0 &&
238
+ this.#redirectHops === 0 &&
239
+ this.#safeRefetch === 0 &&
240
+ this.#sbsdDetected === undefined
241
+ ) {
242
+ return undefined;
243
+ }
244
+ return {
245
+ attempts: this.#attempts,
246
+ poolRefreshes: this.#poolRefreshes,
247
+ redirectHops: this.#redirectHops,
248
+ ...(this.#profileId ? { profileId: cloneProfile(this.#profileId) } : {}),
249
+ proxyUsed: this.#proxyUsed,
250
+ ...(this.#requestClass ? { requestClass: this.#requestClass } : {}),
251
+ ...(this.#sbsdDetected === undefined ? {} : { sbsdDetected: this.#sbsdDetected }),
252
+ ...(this.#sbsdOutcome ? { sbsdOutcome: this.#sbsdOutcome } : {}),
253
+ safeRefetch: this.#safeRefetch,
254
+ ...(this.#lastStatus === undefined ? {} : { lastStatus: this.#lastStatus }),
255
+ ms: this.#ms,
256
+ ...(this.#attemptSamples.length > 0
257
+ ? {
258
+ attemptSamples: this.#attemptSamples.map((sample) => ({
259
+ ...sample,
260
+ ...(sample.diagnostics
261
+ ? {
262
+ diagnostics: { ...sample.diagnostics },
263
+ }
264
+ : {}),
265
+ })),
266
+ }
267
+ : {}),
268
+ ...(this.#attemptSamplesDropped > 0
269
+ ? { attemptSamplesDropped: this.#attemptSamplesDropped }
270
+ : {}),
271
+ };
272
+ }
273
+
274
+ toHeaderPayload(log: StealthTelemetryLogPayload): StealthTelemetryHeaderPayload {
275
+ const attemptSamples = log.attemptSamples?.map((sample) => ({
276
+ n: sample.n,
277
+ ms: sample.ms,
278
+ ...(sample.status === undefined ? {} : { status: sample.status }),
279
+ ...(sample.e ? { e: closedEnum(sample.e) } : {}),
280
+ ...(sample.kind ? { kind: closedEnum(sample.kind) } : {}),
281
+ }));
282
+ return {
283
+ attempts: log.attempts,
284
+ poolRefreshes: log.poolRefreshes,
285
+ redirectHops: log.redirectHops,
286
+ ...(log.profileId
287
+ ? {
288
+ profileId: {
289
+ browser: closedEnum(log.profileId.browser),
290
+ os: closedEnum(log.profileId.os),
291
+ },
292
+ }
293
+ : {}),
294
+ proxyUsed: log.proxyUsed,
295
+ ...(log.requestClass ? { requestClass: closedEnum(log.requestClass) } : {}),
296
+ ...(log.sbsdDetected === undefined ? {} : { sbsdDetected: log.sbsdDetected }),
297
+ ...(log.sbsdOutcome ? { sbsdOutcome: closedEnum(log.sbsdOutcome) } : {}),
298
+ safeRefetch: log.safeRefetch,
299
+ ...(log.lastStatus === undefined ? {} : { lastStatus: log.lastStatus }),
300
+ ms: log.ms,
301
+ ...(attemptSamples && attemptSamples.length > 0 ? { attemptSamples } : {}),
302
+ };
303
+ }
304
+ }