@servicetitan/journey 2.1.0 → 3.0.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 (163) hide show
  1. package/README.md +1 -1
  2. package/dist/__test-utils__/test-runtime.d.ts.map +1 -1
  3. package/dist/__test-utils__/test-runtime.js +9 -2
  4. package/dist/__test-utils__/test-runtime.js.map +1 -1
  5. package/dist/__tests__/core/sanitize.test.d.ts +2 -0
  6. package/dist/__tests__/core/sanitize.test.d.ts.map +1 -0
  7. package/dist/__tests__/hardening.test.d.ts +2 -0
  8. package/dist/__tests__/hardening.test.d.ts.map +1 -0
  9. package/dist/__tests__/integrations/host-mfe.test.d.ts +2 -0
  10. package/dist/__tests__/integrations/host-mfe.test.d.ts.map +1 -0
  11. package/dist/__tests__/integrations/use-journey-step.test.d.ts +2 -0
  12. package/dist/__tests__/integrations/use-journey-step.test.d.ts.map +1 -0
  13. package/dist/config.d.ts +57 -13
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +87 -24
  16. package/dist/config.js.map +1 -1
  17. package/dist/core/abort-error.d.ts +4 -0
  18. package/dist/core/abort-error.d.ts.map +1 -0
  19. package/dist/core/abort-error.js +22 -0
  20. package/dist/core/abort-error.js.map +1 -0
  21. package/dist/core/api.d.ts +22 -9
  22. package/dist/core/api.d.ts.map +1 -1
  23. package/dist/core/api.js +77 -30
  24. package/dist/core/api.js.map +1 -1
  25. package/dist/core/endpoint-policy.d.ts +14 -4
  26. package/dist/core/endpoint-policy.d.ts.map +1 -1
  27. package/dist/core/endpoint-policy.js +32 -1
  28. package/dist/core/endpoint-policy.js.map +1 -1
  29. package/dist/core/index.d.ts +4 -3
  30. package/dist/core/index.d.ts.map +1 -1
  31. package/dist/core/index.js +3 -3
  32. package/dist/core/index.js.map +1 -1
  33. package/dist/core/limits.d.ts +29 -0
  34. package/dist/core/limits.d.ts.map +1 -0
  35. package/dist/core/limits.js +63 -0
  36. package/dist/core/limits.js.map +1 -0
  37. package/dist/core/request-policy.d.ts +39 -0
  38. package/dist/core/request-policy.d.ts.map +1 -0
  39. package/dist/core/request-policy.js +18 -0
  40. package/dist/core/request-policy.js.map +1 -0
  41. package/dist/core/runtime.d.ts +65 -15
  42. package/dist/core/runtime.d.ts.map +1 -1
  43. package/dist/core/runtime.js +403 -126
  44. package/dist/core/runtime.js.map +1 -1
  45. package/dist/core/sanitize.d.ts +23 -0
  46. package/dist/core/sanitize.d.ts.map +1 -0
  47. package/dist/core/sanitize.js +143 -0
  48. package/dist/core/sanitize.js.map +1 -0
  49. package/dist/core/step-tag.d.ts +25 -6
  50. package/dist/core/step-tag.d.ts.map +1 -1
  51. package/dist/core/step-tag.js +56 -10
  52. package/dist/core/step-tag.js.map +1 -1
  53. package/dist/core/types.d.ts +73 -25
  54. package/dist/core/types.d.ts.map +1 -1
  55. package/dist/core/types.js +4 -1
  56. package/dist/core/types.js.map +1 -1
  57. package/dist/global.d.ts +91 -13
  58. package/dist/global.d.ts.map +1 -1
  59. package/dist/global.js +235 -25
  60. package/dist/global.js.map +1 -1
  61. package/dist/index.d.ts +7 -8
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +4 -6
  64. package/dist/index.js.map +1 -1
  65. package/dist/integrations/axios.d.ts +5 -1
  66. package/dist/integrations/axios.d.ts.map +1 -1
  67. package/dist/integrations/axios.js +146 -34
  68. package/dist/integrations/axios.js.map +1 -1
  69. package/dist/integrations/fetch.d.ts +3 -2
  70. package/dist/integrations/fetch.d.ts.map +1 -1
  71. package/dist/integrations/fetch.js +105 -26
  72. package/dist/integrations/fetch.js.map +1 -1
  73. package/dist/integrations/http-report.d.ts +27 -0
  74. package/dist/integrations/http-report.d.ts.map +1 -0
  75. package/dist/integrations/http-report.js +123 -0
  76. package/dist/integrations/http-report.js.map +1 -0
  77. package/dist/integrations/jquery/index.d.ts +8 -4
  78. package/dist/integrations/jquery/index.d.ts.map +1 -1
  79. package/dist/integrations/jquery/index.js +26 -8
  80. package/dist/integrations/jquery/index.js.map +1 -1
  81. package/dist/integrations/jquery/instrument.d.ts +14 -5
  82. package/dist/integrations/jquery/instrument.d.ts.map +1 -1
  83. package/dist/integrations/jquery/instrument.js +111 -29
  84. package/dist/integrations/jquery/instrument.js.map +1 -1
  85. package/dist/integrations/react/context.d.ts +4 -1
  86. package/dist/integrations/react/context.d.ts.map +1 -1
  87. package/dist/integrations/react/context.js +4 -1
  88. package/dist/integrations/react/context.js.map +1 -1
  89. package/dist/integrations/react/scope.d.ts +14 -3
  90. package/dist/integrations/react/scope.d.ts.map +1 -1
  91. package/dist/integrations/react/scope.js +46 -8
  92. package/dist/integrations/react/scope.js.map +1 -1
  93. package/dist/integrations/react/stable-config-keys.d.ts +6 -0
  94. package/dist/integrations/react/stable-config-keys.d.ts.map +1 -0
  95. package/dist/integrations/react/stable-config-keys.js +21 -0
  96. package/dist/integrations/react/stable-config-keys.js.map +1 -0
  97. package/dist/integrations/react/use-journey-step.d.ts +11 -0
  98. package/dist/integrations/react/use-journey-step.d.ts.map +1 -0
  99. package/dist/integrations/react/use-journey-step.js +19 -0
  100. package/dist/integrations/react/use-journey-step.js.map +1 -0
  101. package/dist/integrations/request-key.d.ts +8 -3
  102. package/dist/integrations/request-key.d.ts.map +1 -1
  103. package/dist/integrations/request-key.js +10 -9
  104. package/dist/integrations/request-key.js.map +1 -1
  105. package/dist/integrations/soft-skip.d.ts +7 -0
  106. package/dist/integrations/soft-skip.d.ts.map +1 -0
  107. package/dist/integrations/soft-skip.js +30 -0
  108. package/dist/integrations/soft-skip.js.map +1 -0
  109. package/dist/sinks/console.d.ts.map +1 -1
  110. package/dist/sinks/console.js +2 -1
  111. package/dist/sinks/console.js.map +1 -1
  112. package/dist/sinks/datadog.d.ts +1 -1
  113. package/dist/sinks/datadog.d.ts.map +1 -1
  114. package/dist/sinks/datadog.js +16 -20
  115. package/dist/sinks/datadog.js.map +1 -1
  116. package/package.json +2 -2
  117. package/src/__test-utils__/test-runtime.ts +9 -2
  118. package/src/__tests__/config.test.ts +150 -31
  119. package/src/__tests__/core/ambient.test.ts +16 -10
  120. package/src/__tests__/core/api.test.ts +7 -7
  121. package/src/__tests__/core/define-journey.test.ts +28 -11
  122. package/src/__tests__/core/requests.test.ts +49 -31
  123. package/src/__tests__/core/runtime.test.ts +67 -20
  124. package/src/__tests__/core/sanitize.test.ts +69 -0
  125. package/src/__tests__/core/step.test.ts +132 -36
  126. package/src/__tests__/core/timeouts.test.ts +69 -4
  127. package/src/__tests__/global.test.ts +44 -3
  128. package/src/__tests__/hardening.test.ts +613 -0
  129. package/src/__tests__/integrations/axios.test.ts +247 -27
  130. package/src/__tests__/integrations/expose-app-journey.test.ts +9 -3
  131. package/src/__tests__/integrations/fetch.test.ts +153 -19
  132. package/src/__tests__/integrations/host-mfe.test.ts +548 -0
  133. package/src/__tests__/integrations/jquery.test.ts +209 -34
  134. package/src/__tests__/integrations/scope.test.tsx +160 -2
  135. package/src/__tests__/integrations/use-journey-step.test.tsx +43 -0
  136. package/src/__tests__/sinks/console.test.ts +9 -4
  137. package/src/__tests__/sinks/datadog.test.ts +47 -0
  138. package/src/config.ts +162 -38
  139. package/src/core/abort-error.ts +24 -0
  140. package/src/core/api.ts +83 -33
  141. package/src/core/endpoint-policy.ts +46 -4
  142. package/src/core/index.ts +12 -4
  143. package/src/core/limits.ts +73 -0
  144. package/src/core/request-policy.ts +66 -0
  145. package/src/core/runtime.ts +507 -133
  146. package/src/core/sanitize.ts +177 -0
  147. package/src/core/step-tag.ts +82 -12
  148. package/src/core/types.ts +79 -25
  149. package/src/global.ts +312 -42
  150. package/src/index.ts +17 -17
  151. package/src/integrations/axios.ts +183 -45
  152. package/src/integrations/fetch.ts +125 -39
  153. package/src/integrations/http-report.ts +184 -0
  154. package/src/integrations/jquery/index.ts +34 -10
  155. package/src/integrations/jquery/instrument.ts +126 -42
  156. package/src/integrations/react/context.ts +4 -1
  157. package/src/integrations/react/scope.tsx +59 -9
  158. package/src/integrations/react/stable-config-keys.ts +28 -0
  159. package/src/integrations/react/use-journey-step.ts +31 -0
  160. package/src/integrations/request-key.ts +18 -10
  161. package/src/integrations/soft-skip.ts +35 -0
  162. package/src/sinks/console.ts +2 -1
  163. package/src/sinks/datadog.ts +23 -29
@@ -0,0 +1,73 @@
1
+ /** Payload / timer bounds shared by the engine and default sinks. */
2
+
3
+ export const DEFAULT_MAX_STEPS = 50;
4
+ export const MAX_STEPS_CAP = 200;
5
+ export const MAX_TAG_KEYS = 32;
6
+ export const MAX_ATTRIBUTE_KEYS = 64;
7
+ export const MAX_ATTRIBUTED_REQUEST_KEYS = 50;
8
+ export const MAX_TAG_VALUE_LEN = 200;
9
+ export const DEFAULT_JOURNEY_IDLE_MS = 15 * 60 * 1_000;
10
+
11
+ const DENIED_KEYS = new Set([
12
+ '__proto__',
13
+ 'constructor',
14
+ 'prototype',
15
+ 'authorization',
16
+ 'cookie',
17
+ 'set-cookie',
18
+ 'password',
19
+ 'token',
20
+ 'secret',
21
+ 'ssn',
22
+ ]);
23
+
24
+ /** True for prototype-polluting keys and a small secret-name deny-list (case-insensitive). */
25
+ export function isUnsafeKey(key: string): boolean {
26
+ return DENIED_KEYS.has(key.toLowerCase());
27
+ }
28
+
29
+ /**
30
+ * Finite integer ≥ 1, else `fallback`. Used for maxSteps-like caps.
31
+ * Non-finite / ≤ 0 / non-numbers return `fallback`.
32
+ */
33
+ export function finitePositiveInt(n: unknown, fallback: number): number {
34
+ if (typeof n !== 'number' || !Number.isFinite(n) || n <= 0) {
35
+ return fallback;
36
+ }
37
+ return Math.floor(n);
38
+ }
39
+
40
+ /**
41
+ * Journey/step timeout: finite ≥ 0 keeps the value (floored); anything else is 0 (disabled).
42
+ */
43
+ export function finiteTimeoutMs(n: unknown): number {
44
+ if (typeof n !== 'number' || !Number.isFinite(n) || n < 0) {
45
+ return 0;
46
+ }
47
+ return Math.floor(n);
48
+ }
49
+
50
+ /** Clamp recorded-step cap to 1..MAX_STEPS_CAP; invalid → DEFAULT_MAX_STEPS. */
51
+ export function clampMaxSteps(n: unknown): number {
52
+ const value = finitePositiveInt(n, DEFAULT_MAX_STEPS);
53
+ return Math.min(value, MAX_STEPS_CAP);
54
+ }
55
+
56
+ /** Finite ≥ 0 slow-request threshold, or undefined to fall through. */
57
+ export function finiteSlowRequestMs(n: unknown): number | undefined {
58
+ if (typeof n !== 'number' || !Number.isFinite(n) || n < 0) {
59
+ return undefined;
60
+ }
61
+ return Math.floor(n);
62
+ }
63
+
64
+ /** Explicit 0 disables; omitted uses idle default; finite N keeps caller timeout. */
65
+ export function resolveJourneyTimeoutMs(
66
+ timeoutMs: number | undefined,
67
+ idleDefaultMs: number = DEFAULT_JOURNEY_IDLE_MS
68
+ ): { ms: number; explicit: boolean } {
69
+ if (timeoutMs === undefined) {
70
+ return { ms: finiteTimeoutMs(idleDefaultMs), explicit: false };
71
+ }
72
+ return { ms: finiteTimeoutMs(timeoutMs), explicit: true };
73
+ }
@@ -0,0 +1,66 @@
1
+ /** Verdict for attributed HTTP (abort / 4xx / similar). */
2
+ export type JourneyRequestPolicy = 'continue' | 'bad' | 'exclude';
3
+
4
+ /** Normalized facts adapters pass into policy resolvers (not axios/jqXHR). */
5
+ export interface JourneyHttpPolicyContext {
6
+ requestKey: string;
7
+ /** Present when an HTTP response exists; omitted on abort / hard network failure. */
8
+ status?: number;
9
+ aborted: boolean;
10
+ url?: string;
11
+ method?: string;
12
+ journeyName?: string;
13
+ stepName?: string;
14
+ }
15
+
16
+ /**
17
+ * Per-stamp HTTP scorer from {@link StepHandle.stamp}. Must be synchronous.
18
+ * Return a policy to set the journey verdict; omit / void to keep default scoring.
19
+ * Do not consume a fetch body (clone first if you need to read it).
20
+ */
21
+ export type JourneyHttpScore = (
22
+ ctx: JourneyHttpScoreContext
23
+ ) => JourneyRequestPolicy | void | undefined;
24
+
25
+ /** Context for {@link JourneyHttpScore} — policy facts plus the transport req/res. */
26
+ export interface JourneyHttpScoreContext extends JourneyHttpPolicyContext {
27
+ durationMs: number;
28
+ /** Transport request (axios config, fetch input/init, jQuery ajax settings). */
29
+ request?: unknown;
30
+ /** Transport response (axios response, fetch Response, jqXHR). */
31
+ response?: unknown;
32
+ /** Rejection reason when the transport failed. */
33
+ error?: unknown;
34
+ }
35
+
36
+ /** Options for {@link StepHandle.stamp}. */
37
+ export interface JourneyStampOptions {
38
+ score?: JourneyHttpScore;
39
+ /** Skip scoring for this stamped request. Ignore wins over `score`. */
40
+ ignore?: boolean;
41
+ }
42
+
43
+ export type RequestPolicyConfig =
44
+ JourneyRequestPolicy | ((ctx: JourneyHttpPolicyContext) => JourneyRequestPolicy);
45
+
46
+ export function resolveRequestPolicy(
47
+ config: RequestPolicyConfig | undefined,
48
+ fallback: JourneyRequestPolicy,
49
+ ctx: JourneyHttpPolicyContext
50
+ ): JourneyRequestPolicy {
51
+ if (config === undefined) {
52
+ return fallback;
53
+ }
54
+ if (typeof config === 'function') {
55
+ try {
56
+ return config(ctx);
57
+ } catch {
58
+ return fallback;
59
+ }
60
+ }
61
+ return config;
62
+ }
63
+
64
+ export function isJourneyRequestPolicy(value: unknown): value is JourneyRequestPolicy {
65
+ return value === 'continue' || value === 'bad' || value === 'exclude';
66
+ }