@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.
- package/README.md +1 -1
- package/dist/__test-utils__/test-runtime.d.ts.map +1 -1
- package/dist/__test-utils__/test-runtime.js +9 -2
- package/dist/__test-utils__/test-runtime.js.map +1 -1
- package/dist/__tests__/core/sanitize.test.d.ts +2 -0
- package/dist/__tests__/core/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/hardening.test.d.ts +2 -0
- package/dist/__tests__/hardening.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/host-mfe.test.d.ts +2 -0
- package/dist/__tests__/integrations/host-mfe.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/use-journey-step.test.d.ts +2 -0
- package/dist/__tests__/integrations/use-journey-step.test.d.ts.map +1 -0
- package/dist/config.d.ts +57 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +87 -24
- package/dist/config.js.map +1 -1
- package/dist/core/abort-error.d.ts +4 -0
- package/dist/core/abort-error.d.ts.map +1 -0
- package/dist/core/abort-error.js +22 -0
- package/dist/core/abort-error.js.map +1 -0
- package/dist/core/api.d.ts +22 -9
- package/dist/core/api.d.ts.map +1 -1
- package/dist/core/api.js +77 -30
- package/dist/core/api.js.map +1 -1
- package/dist/core/endpoint-policy.d.ts +14 -4
- package/dist/core/endpoint-policy.d.ts.map +1 -1
- package/dist/core/endpoint-policy.js +32 -1
- package/dist/core/endpoint-policy.js.map +1 -1
- package/dist/core/index.d.ts +4 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/limits.d.ts +29 -0
- package/dist/core/limits.d.ts.map +1 -0
- package/dist/core/limits.js +63 -0
- package/dist/core/limits.js.map +1 -0
- package/dist/core/request-policy.d.ts +39 -0
- package/dist/core/request-policy.d.ts.map +1 -0
- package/dist/core/request-policy.js +18 -0
- package/dist/core/request-policy.js.map +1 -0
- package/dist/core/runtime.d.ts +65 -15
- package/dist/core/runtime.d.ts.map +1 -1
- package/dist/core/runtime.js +403 -126
- package/dist/core/runtime.js.map +1 -1
- package/dist/core/sanitize.d.ts +23 -0
- package/dist/core/sanitize.d.ts.map +1 -0
- package/dist/core/sanitize.js +143 -0
- package/dist/core/sanitize.js.map +1 -0
- package/dist/core/step-tag.d.ts +25 -6
- package/dist/core/step-tag.d.ts.map +1 -1
- package/dist/core/step-tag.js +56 -10
- package/dist/core/step-tag.js.map +1 -1
- package/dist/core/types.d.ts +73 -25
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +4 -1
- package/dist/core/types.js.map +1 -1
- package/dist/global.d.ts +91 -13
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +235 -25
- package/dist/global.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -6
- package/dist/index.js.map +1 -1
- package/dist/integrations/axios.d.ts +5 -1
- package/dist/integrations/axios.d.ts.map +1 -1
- package/dist/integrations/axios.js +146 -34
- package/dist/integrations/axios.js.map +1 -1
- package/dist/integrations/fetch.d.ts +3 -2
- package/dist/integrations/fetch.d.ts.map +1 -1
- package/dist/integrations/fetch.js +105 -26
- package/dist/integrations/fetch.js.map +1 -1
- package/dist/integrations/http-report.d.ts +27 -0
- package/dist/integrations/http-report.d.ts.map +1 -0
- package/dist/integrations/http-report.js +123 -0
- package/dist/integrations/http-report.js.map +1 -0
- package/dist/integrations/jquery/index.d.ts +8 -4
- package/dist/integrations/jquery/index.d.ts.map +1 -1
- package/dist/integrations/jquery/index.js +26 -8
- package/dist/integrations/jquery/index.js.map +1 -1
- package/dist/integrations/jquery/instrument.d.ts +14 -5
- package/dist/integrations/jquery/instrument.d.ts.map +1 -1
- package/dist/integrations/jquery/instrument.js +111 -29
- package/dist/integrations/jquery/instrument.js.map +1 -1
- package/dist/integrations/react/context.d.ts +4 -1
- package/dist/integrations/react/context.d.ts.map +1 -1
- package/dist/integrations/react/context.js +4 -1
- package/dist/integrations/react/context.js.map +1 -1
- package/dist/integrations/react/scope.d.ts +14 -3
- package/dist/integrations/react/scope.d.ts.map +1 -1
- package/dist/integrations/react/scope.js +46 -8
- package/dist/integrations/react/scope.js.map +1 -1
- package/dist/integrations/react/stable-config-keys.d.ts +6 -0
- package/dist/integrations/react/stable-config-keys.d.ts.map +1 -0
- package/dist/integrations/react/stable-config-keys.js +21 -0
- package/dist/integrations/react/stable-config-keys.js.map +1 -0
- package/dist/integrations/react/use-journey-step.d.ts +11 -0
- package/dist/integrations/react/use-journey-step.d.ts.map +1 -0
- package/dist/integrations/react/use-journey-step.js +19 -0
- package/dist/integrations/react/use-journey-step.js.map +1 -0
- package/dist/integrations/request-key.d.ts +8 -3
- package/dist/integrations/request-key.d.ts.map +1 -1
- package/dist/integrations/request-key.js +10 -9
- package/dist/integrations/request-key.js.map +1 -1
- package/dist/integrations/soft-skip.d.ts +7 -0
- package/dist/integrations/soft-skip.d.ts.map +1 -0
- package/dist/integrations/soft-skip.js +30 -0
- package/dist/integrations/soft-skip.js.map +1 -0
- package/dist/sinks/console.d.ts.map +1 -1
- package/dist/sinks/console.js +2 -1
- package/dist/sinks/console.js.map +1 -1
- package/dist/sinks/datadog.d.ts +1 -1
- package/dist/sinks/datadog.d.ts.map +1 -1
- package/dist/sinks/datadog.js +16 -20
- package/dist/sinks/datadog.js.map +1 -1
- package/package.json +2 -2
- package/src/__test-utils__/test-runtime.ts +9 -2
- package/src/__tests__/config.test.ts +150 -31
- package/src/__tests__/core/ambient.test.ts +16 -10
- package/src/__tests__/core/api.test.ts +7 -7
- package/src/__tests__/core/define-journey.test.ts +28 -11
- package/src/__tests__/core/requests.test.ts +49 -31
- package/src/__tests__/core/runtime.test.ts +67 -20
- package/src/__tests__/core/sanitize.test.ts +69 -0
- package/src/__tests__/core/step.test.ts +132 -36
- package/src/__tests__/core/timeouts.test.ts +69 -4
- package/src/__tests__/global.test.ts +44 -3
- package/src/__tests__/hardening.test.ts +613 -0
- package/src/__tests__/integrations/axios.test.ts +247 -27
- package/src/__tests__/integrations/expose-app-journey.test.ts +9 -3
- package/src/__tests__/integrations/fetch.test.ts +153 -19
- package/src/__tests__/integrations/host-mfe.test.ts +548 -0
- package/src/__tests__/integrations/jquery.test.ts +209 -34
- package/src/__tests__/integrations/scope.test.tsx +160 -2
- package/src/__tests__/integrations/use-journey-step.test.tsx +43 -0
- package/src/__tests__/sinks/console.test.ts +9 -4
- package/src/__tests__/sinks/datadog.test.ts +47 -0
- package/src/config.ts +162 -38
- package/src/core/abort-error.ts +24 -0
- package/src/core/api.ts +83 -33
- package/src/core/endpoint-policy.ts +46 -4
- package/src/core/index.ts +12 -4
- package/src/core/limits.ts +73 -0
- package/src/core/request-policy.ts +66 -0
- package/src/core/runtime.ts +507 -133
- package/src/core/sanitize.ts +177 -0
- package/src/core/step-tag.ts +82 -12
- package/src/core/types.ts +79 -25
- package/src/global.ts +312 -42
- package/src/index.ts +17 -17
- package/src/integrations/axios.ts +183 -45
- package/src/integrations/fetch.ts +125 -39
- package/src/integrations/http-report.ts +184 -0
- package/src/integrations/jquery/index.ts +34 -10
- package/src/integrations/jquery/instrument.ts +126 -42
- package/src/integrations/react/context.ts +4 -1
- package/src/integrations/react/scope.tsx +59 -9
- package/src/integrations/react/stable-config-keys.ts +28 -0
- package/src/integrations/react/use-journey-step.ts +31 -0
- package/src/integrations/request-key.ts +18 -10
- package/src/integrations/soft-skip.ts +35 -0
- package/src/sinks/console.ts +2 -1
- package/src/sinks/datadog.ts +23 -29
package/src/global.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { SlowRequestConfig } from './core/endpoint-policy';
|
|
2
|
+
import { type RequestPolicyConfig } from './core/request-policy';
|
|
1
3
|
import type { JourneyRuntime, JourneyRuntimeDebugSnapshot } from './core/runtime';
|
|
2
4
|
|
|
3
5
|
/** Force-enable journey host wiring outside go* hosts (`__stJourney.enable()`). */
|
|
@@ -9,21 +11,45 @@ export const JOURNEY_DEBUG_STORAGE_KEY = 'st:journey:debug';
|
|
|
9
11
|
/** @internal Shared cross-bundle bag on globalThis (`rum` fallback + DevTools helpers). */
|
|
10
12
|
export const ST_JOURNEY_GLOBAL_KEY = '__stJourney';
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
14
|
+
/** Bump when shared bag shape / policy semantics change incompatibly. */
|
|
15
|
+
export const ST_JOURNEY_SCHEMA_VERSION = 2;
|
|
15
16
|
|
|
16
17
|
export interface JourneyDebugState {
|
|
17
|
-
/**
|
|
18
|
+
/** Host default or force-enable (`isJourneyEnabled()`). */
|
|
18
19
|
enabled: boolean;
|
|
19
20
|
/** Console-logging flag (`st:journey:debug`). */
|
|
20
21
|
debug: boolean;
|
|
21
22
|
hasRum: boolean;
|
|
22
|
-
runtimes:
|
|
23
|
+
runtimes: JourneyRuntimeDebugSnapshot[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Shared host policies visible to every package copy on the page. */
|
|
27
|
+
export interface JourneySharedPolicies {
|
|
28
|
+
slowRequests?: SlowRequestConfig;
|
|
29
|
+
/** Whether shared slowRequests were explicitly set via configureJourney. */
|
|
30
|
+
slowRequestsConfigured: boolean;
|
|
31
|
+
httpAbortedRequests: RequestPolicyConfig;
|
|
32
|
+
httpClientErrorRequests: RequestPolicyConfig;
|
|
33
|
+
autoAttributeRequests: boolean;
|
|
34
|
+
/** True after the first configureJourney that set any shared policy knob. */
|
|
35
|
+
locked: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** DevTools registration — `{ id, getSnapshot }` so older package copies can still list runtimes. */
|
|
39
|
+
export interface RuntimeRegistration {
|
|
40
|
+
id: string;
|
|
41
|
+
getSnapshot: () => JourneyRuntimeDebugSnapshot;
|
|
42
|
+
teardown?: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @internal Restore/dispose record for HTTP instrumentation. */
|
|
46
|
+
export interface InstrumentRecord {
|
|
47
|
+
disposed: boolean;
|
|
48
|
+
restore?: () => void;
|
|
23
49
|
}
|
|
24
50
|
|
|
25
51
|
/**
|
|
26
|
-
*
|
|
52
|
+
* Cross-bundle surface on `globalThis.__stJourney`.
|
|
27
53
|
* Prefer importing `isJourneyEnabled` / `isJourneyDebugEnabled` from the package in app code.
|
|
28
54
|
*/
|
|
29
55
|
export interface StJourneyGlobal {
|
|
@@ -32,6 +58,24 @@ export interface StJourneyGlobal {
|
|
|
32
58
|
* Prefer `DD_RUM` (ST host: `datadogGuard`).
|
|
33
59
|
*/
|
|
34
60
|
rum?: unknown;
|
|
61
|
+
/** Shared bag schema; mismatched copies warn but continue. */
|
|
62
|
+
schemaVersion?: number;
|
|
63
|
+
/** Host default enable (e.g. RUM active). Set via `setJourneyDefaultEnabled`. */
|
|
64
|
+
defaultEnabled?: boolean;
|
|
65
|
+
/** Shared configureJourney policies. */
|
|
66
|
+
policies: JourneySharedPolicies;
|
|
67
|
+
/**
|
|
68
|
+
* Bundle runtimes registered for DevTools `getDebugState()`.
|
|
69
|
+
* `{ id, getSnapshot }` so mixed package copies can list each other.
|
|
70
|
+
*/
|
|
71
|
+
runtimeRegistrations: RuntimeRegistration[];
|
|
72
|
+
/** @internal Cross-bundle instrumented axios/fetch/jquery targets. */
|
|
73
|
+
instrumentedAxios: WeakSet<object>;
|
|
74
|
+
instrumentedFetch: WeakSet<object>;
|
|
75
|
+
instrumentedJquery: WeakSet<object>;
|
|
76
|
+
/** @internal Active instrument records for teardown. */
|
|
77
|
+
instrumentRecords: InstrumentRecord[];
|
|
78
|
+
fetchRestore?: () => void;
|
|
35
79
|
enable(): void;
|
|
36
80
|
disable(): void;
|
|
37
81
|
isEnabled(): boolean;
|
|
@@ -45,21 +89,17 @@ export interface StJourneyGlobal {
|
|
|
45
89
|
getDebugState(): JourneyDebugState;
|
|
46
90
|
}
|
|
47
91
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
92
|
+
let warnedMissingSlowRequests = false;
|
|
93
|
+
let debugEnabledCache: boolean | undefined;
|
|
94
|
+
const MAX_INSTRUMENT_RECORDS = 32;
|
|
52
95
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
runtimeRegistrations: RuntimeRegistration[];
|
|
96
|
+
function storageFor(key: string): Storage | undefined {
|
|
97
|
+
return key === JOURNEY_DEBUG_STORAGE_KEY ? globalThis.sessionStorage : globalThis.localStorage;
|
|
56
98
|
}
|
|
57
99
|
|
|
58
|
-
let runtimeSeq = 0;
|
|
59
|
-
|
|
60
100
|
function readFlag(key: string): boolean {
|
|
61
101
|
try {
|
|
62
|
-
return
|
|
102
|
+
return storageFor(key)?.getItem(key) === 'true';
|
|
63
103
|
} catch {
|
|
64
104
|
return false;
|
|
65
105
|
}
|
|
@@ -67,19 +107,31 @@ function readFlag(key: string): boolean {
|
|
|
67
107
|
|
|
68
108
|
function writeFlag(key: string, on: boolean): void {
|
|
69
109
|
try {
|
|
110
|
+
const storage = storageFor(key);
|
|
70
111
|
if (on) {
|
|
71
|
-
|
|
112
|
+
storage?.setItem(key, 'true');
|
|
72
113
|
} else {
|
|
73
|
-
|
|
114
|
+
storage?.removeItem(key);
|
|
74
115
|
}
|
|
75
116
|
} catch {
|
|
76
117
|
// ignore storage failures (privacy mode, non-browser)
|
|
77
118
|
}
|
|
78
119
|
}
|
|
79
120
|
|
|
80
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Host default for journey wiring (e.g. RUM initialized). Stored on `__stJourney` so
|
|
123
|
+
* MFEs see the same value without importing Datadog. Call once after RUM init.
|
|
124
|
+
*/
|
|
125
|
+
export function setJourneyDefaultEnabled(enabled: boolean): void {
|
|
126
|
+
ensureGlobal().defaultEnabled = enabled === true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* True when the host default is on or force-enable is set
|
|
131
|
+
* (`st:journey:enabled` / `__stJourney.enable()`).
|
|
132
|
+
*/
|
|
81
133
|
export function isJourneyEnabled(): boolean {
|
|
82
|
-
return readFlag(JOURNEY_ENABLED_STORAGE_KEY);
|
|
134
|
+
return ensureGlobal().defaultEnabled === true || readFlag(JOURNEY_ENABLED_STORAGE_KEY);
|
|
83
135
|
}
|
|
84
136
|
|
|
85
137
|
/** Set the force-enable flag. Reload after calling from DevTools. */
|
|
@@ -92,19 +144,25 @@ export function disableJourney(): void {
|
|
|
92
144
|
writeFlag(JOURNEY_ENABLED_STORAGE_KEY, false);
|
|
93
145
|
}
|
|
94
146
|
|
|
95
|
-
/** True when `
|
|
147
|
+
/** True when `sessionStorage['st:journey:debug'] === 'true'`. */
|
|
96
148
|
export function isJourneyDebugEnabled(): boolean {
|
|
97
|
-
|
|
149
|
+
const next = readFlag(JOURNEY_DEBUG_STORAGE_KEY);
|
|
150
|
+
if (debugEnabledCache !== next) {
|
|
151
|
+
debugEnabledCache = next;
|
|
152
|
+
}
|
|
153
|
+
return debugEnabledCache;
|
|
98
154
|
}
|
|
99
155
|
|
|
100
156
|
/** Set the console-debug flag. Reload after calling from DevTools. */
|
|
101
157
|
export function enableJourneyDebugging(): void {
|
|
102
158
|
writeFlag(JOURNEY_DEBUG_STORAGE_KEY, true);
|
|
159
|
+
debugEnabledCache = true;
|
|
103
160
|
}
|
|
104
161
|
|
|
105
162
|
/** Clear the console-debug flag. Reload after calling from DevTools. */
|
|
106
163
|
export function disableJourneyDebugging(): void {
|
|
107
164
|
writeFlag(JOURNEY_DEBUG_STORAGE_KEY, false);
|
|
165
|
+
debugEnabledCache = false;
|
|
108
166
|
}
|
|
109
167
|
|
|
110
168
|
function hasRum(): boolean {
|
|
@@ -113,7 +171,39 @@ function hasRum(): boolean {
|
|
|
113
171
|
);
|
|
114
172
|
}
|
|
115
173
|
|
|
116
|
-
function
|
|
174
|
+
function snapshotOf(entry: unknown): JourneyRuntimeDebugSnapshot | undefined {
|
|
175
|
+
if (entry == null || typeof entry !== 'object') {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
const rec = entry as {
|
|
179
|
+
id?: string;
|
|
180
|
+
getSnapshot?: () => JourneyRuntimeDebugSnapshot;
|
|
181
|
+
getDebugSnapshot?: () => JourneyRuntimeDebugSnapshot;
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
if (typeof rec.getSnapshot === 'function') {
|
|
185
|
+
const snap = rec.getSnapshot();
|
|
186
|
+
const withId = snap.id ? snap : { ...snap, id: rec.id ?? '' };
|
|
187
|
+
return {
|
|
188
|
+
...withId,
|
|
189
|
+
policyOverlay: withId.policyOverlay ?? {
|
|
190
|
+
slowRequests: false,
|
|
191
|
+
httpAbortedRequests: false,
|
|
192
|
+
httpClientErrorRequests: false,
|
|
193
|
+
autoAttributeRequests: false,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (typeof rec.getDebugSnapshot === 'function') {
|
|
198
|
+
return rec.getDebugSnapshot();
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function buildDebugState(runtimes: readonly unknown[]): JourneyDebugState {
|
|
117
207
|
if (!isJourneyDebugEnabled()) {
|
|
118
208
|
return {
|
|
119
209
|
enabled: isJourneyEnabled(),
|
|
@@ -127,26 +217,61 @@ function buildDebugState(runtimes: RuntimeRegistration[]): JourneyDebugState {
|
|
|
127
217
|
enabled: isJourneyEnabled(),
|
|
128
218
|
debug: true,
|
|
129
219
|
hasRum: hasRum(),
|
|
130
|
-
runtimes: runtimes
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
220
|
+
runtimes: runtimes
|
|
221
|
+
.map(snapshotOf)
|
|
222
|
+
.filter((snap): snap is JourneyRuntimeDebugSnapshot => snap != null),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createEmptyPolicies(): JourneySharedPolicies {
|
|
227
|
+
return {
|
|
228
|
+
slowRequestsConfigured: false,
|
|
229
|
+
httpAbortedRequests: 'continue',
|
|
230
|
+
httpClientErrorRequests: 'continue',
|
|
231
|
+
autoAttributeRequests: true,
|
|
232
|
+
locked: false,
|
|
134
233
|
};
|
|
135
234
|
}
|
|
136
235
|
|
|
137
|
-
function ensureGlobal():
|
|
236
|
+
function ensureGlobal(): StJourneyGlobal {
|
|
138
237
|
const g = globalThis as Record<string, unknown>;
|
|
139
|
-
const existing = g[ST_JOURNEY_GLOBAL_KEY] as
|
|
238
|
+
const existing = g[ST_JOURNEY_GLOBAL_KEY] as StJourneyGlobal | undefined;
|
|
140
239
|
// Reuse when a prior load already installed the full surface (incl. enable).
|
|
141
240
|
if (existing?.runtimeRegistrations && typeof existing.enable === 'function') {
|
|
241
|
+
if (
|
|
242
|
+
existing.schemaVersion != null &&
|
|
243
|
+
existing.schemaVersion !== ST_JOURNEY_SCHEMA_VERSION
|
|
244
|
+
) {
|
|
245
|
+
// eslint-disable-next-line no-console -- cross-bundle version skew
|
|
246
|
+
console.warn(
|
|
247
|
+
`[journey] __stJourney.schemaVersion mismatch: bag=${existing.schemaVersion}, package=${ST_JOURNEY_SCHEMA_VERSION}`
|
|
248
|
+
);
|
|
249
|
+
} else {
|
|
250
|
+
existing.schemaVersion ??= ST_JOURNEY_SCHEMA_VERSION;
|
|
251
|
+
}
|
|
252
|
+
existing.policies ??= createEmptyPolicies();
|
|
253
|
+
if (existing.policies.locked !== true && existing.policies.locked !== false) {
|
|
254
|
+
existing.policies.locked = false;
|
|
255
|
+
}
|
|
256
|
+
existing.instrumentedAxios ??= new WeakSet();
|
|
257
|
+
existing.instrumentedFetch ??= new WeakSet();
|
|
258
|
+
existing.instrumentedJquery ??= new WeakSet();
|
|
259
|
+
existing.instrumentRecords ??= [];
|
|
142
260
|
return existing;
|
|
143
261
|
}
|
|
144
262
|
|
|
145
263
|
const runtimes: RuntimeRegistration[] = existing?.runtimeRegistrations ?? [];
|
|
146
264
|
|
|
147
|
-
const api:
|
|
265
|
+
const api: StJourneyGlobal = {
|
|
148
266
|
rum: existing?.rum,
|
|
267
|
+
schemaVersion: ST_JOURNEY_SCHEMA_VERSION,
|
|
268
|
+
defaultEnabled: existing?.defaultEnabled === true,
|
|
149
269
|
runtimeRegistrations: runtimes,
|
|
270
|
+
policies: createEmptyPolicies(),
|
|
271
|
+
instrumentedAxios: new WeakSet(),
|
|
272
|
+
instrumentedFetch: new WeakSet(),
|
|
273
|
+
instrumentedJquery: new WeakSet(),
|
|
274
|
+
instrumentRecords: [],
|
|
150
275
|
enable: enableJourney,
|
|
151
276
|
disable: disableJourney,
|
|
152
277
|
isEnabled: isJourneyEnabled,
|
|
@@ -162,22 +287,129 @@ function ensureGlobal(): StJourneyGlobalInternal {
|
|
|
162
287
|
return api;
|
|
163
288
|
}
|
|
164
289
|
|
|
290
|
+
/** @internal Shared policies bag. */
|
|
291
|
+
export function getSharedPolicies(): JourneySharedPolicies {
|
|
292
|
+
return ensureGlobal().policies;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function areSharedPoliciesLocked(): boolean {
|
|
296
|
+
return ensureGlobal().policies.locked === true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function freezePolicies(policies: JourneySharedPolicies): JourneySharedPolicies {
|
|
300
|
+
const next: JourneySharedPolicies = { ...policies, locked: true };
|
|
301
|
+
if (next.slowRequests) {
|
|
302
|
+
const endpoints = next.slowRequests.endpoints
|
|
303
|
+
? Object.freeze([...next.slowRequests.endpoints])
|
|
304
|
+
: next.slowRequests.endpoints;
|
|
305
|
+
next.slowRequests = Object.freeze({ ...next.slowRequests, endpoints });
|
|
306
|
+
}
|
|
307
|
+
return Object.freeze(next);
|
|
308
|
+
}
|
|
309
|
+
|
|
165
310
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
311
|
+
* First writer: merge `patch` into the shared bag and freeze it.
|
|
312
|
+
* Returns false when already locked (caller should overlay locally instead).
|
|
168
313
|
*/
|
|
169
|
-
export function
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
314
|
+
export function seedSharedPolicies(patch: Partial<Omit<JourneySharedPolicies, 'locked'>>): boolean {
|
|
315
|
+
const api = ensureGlobal();
|
|
316
|
+
if (api.policies.locked) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
api.policies = freezePolicies({ ...api.policies, ...patch });
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export function getAutoAttributeRequests(): boolean {
|
|
324
|
+
return ensureGlobal().policies.autoAttributeRequests !== false;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function getHttpAbortedRequestsPolicy(): RequestPolicyConfig {
|
|
328
|
+
return ensureGlobal().policies.httpAbortedRequests;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function getHttpClientErrorRequestsPolicy(): RequestPolicyConfig {
|
|
332
|
+
return ensureGlobal().policies.httpClientErrorRequests;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function getSharedSlowRequests(): SlowRequestConfig | undefined {
|
|
336
|
+
return ensureGlobal().policies.slowRequests;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function areSharedSlowRequestsConfigured(): boolean {
|
|
340
|
+
return ensureGlobal().policies.slowRequestsConfigured === true;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** One-time warn when transports are wired without explicit slowRequests. */
|
|
344
|
+
export function warnIfSlowRequestsUnset(): void {
|
|
345
|
+
if (warnedMissingSlowRequests || areSharedSlowRequestsConfigured()) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
warnedMissingSlowRequests = true;
|
|
349
|
+
// eslint-disable-next-line no-console -- host config guidance
|
|
350
|
+
console.warn(
|
|
351
|
+
'[journey] using default slowRequests.defaultMs=4000 — set configureJourney({ slowRequests }) to tune'
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** @internal Reset shared policies (tests / teardown). */
|
|
356
|
+
export function resetSharedPolicies(): void {
|
|
357
|
+
const api = ensureGlobal();
|
|
358
|
+
api.policies = createEmptyPolicies();
|
|
359
|
+
warnedMissingSlowRequests = false;
|
|
360
|
+
debugEnabledCache = undefined;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function getInstrumentedAxiosSet(): WeakSet<object> {
|
|
364
|
+
return ensureGlobal().instrumentedAxios;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export function getInstrumentedFetchSet(): WeakSet<object> {
|
|
368
|
+
return ensureGlobal().instrumentedFetch;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export function getInstrumentedJquerySet(): WeakSet<object> {
|
|
372
|
+
return ensureGlobal().instrumentedJquery;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function registerInstrumentRecord(record: InstrumentRecord): void {
|
|
376
|
+
const api = ensureGlobal();
|
|
377
|
+
if (api.instrumentRecords.length >= MAX_INSTRUMENT_RECORDS) {
|
|
378
|
+
// eslint-disable-next-line no-console -- defensive cap for repeated instrumentation
|
|
379
|
+
console.warn('[journey] instrumentRecords cap reached — call teardownJourney()');
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
api.instrumentRecords.push(record);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export function setFetchRestore(restore: (() => void) | undefined): void {
|
|
386
|
+
ensureGlobal().fetchRestore = restore;
|
|
176
387
|
}
|
|
177
388
|
|
|
178
|
-
/**
|
|
179
|
-
|
|
180
|
-
|
|
389
|
+
/**
|
|
390
|
+
* @internal Register this bundle's engine on `__stJourney` so DevTools can list
|
|
391
|
+
* every host/MFE copy on the page. Auto-assigns `runtime-N` when `runtime.id` is empty.
|
|
392
|
+
* Replaces an existing registration with the same id (HMR / test re-register).
|
|
393
|
+
*/
|
|
394
|
+
export function registerJourneyRuntime(
|
|
395
|
+
runtime: JourneyRuntime,
|
|
396
|
+
options?: { teardown?: () => void }
|
|
397
|
+
): void {
|
|
398
|
+
const bag = ensureGlobal();
|
|
399
|
+
if (runtime.id === '') {
|
|
400
|
+
(runtime as { id: string }).id = `runtime-${bag.runtimeRegistrations.length + 1}`;
|
|
401
|
+
}
|
|
402
|
+
const entry: RuntimeRegistration = {
|
|
403
|
+
id: runtime.id,
|
|
404
|
+
getSnapshot: () => runtime.getDebugSnapshot(),
|
|
405
|
+
teardown: options?.teardown,
|
|
406
|
+
};
|
|
407
|
+
const existing = bag.runtimeRegistrations.findIndex(reg => reg.id === runtime.id);
|
|
408
|
+
if (existing >= 0) {
|
|
409
|
+
bag.runtimeRegistrations[existing] = entry;
|
|
410
|
+
} else {
|
|
411
|
+
bag.runtimeRegistrations.push(entry);
|
|
412
|
+
}
|
|
181
413
|
}
|
|
182
414
|
|
|
183
415
|
/**
|
|
@@ -194,3 +426,41 @@ export function getJourneyRumFallback(): unknown {
|
|
|
194
426
|
StJourneyGlobal | undefined;
|
|
195
427
|
return existing?.rum;
|
|
196
428
|
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Dispose HTTP instrumentation hooks and reset registered engines that supplied a
|
|
432
|
+
* teardown callback. Intended for tests (e.g. afterEach). Prefer `resetJourney`
|
|
433
|
+
* when you only need this bundle's engine state.
|
|
434
|
+
*/
|
|
435
|
+
export function teardownJourney(): void {
|
|
436
|
+
const api = ensureGlobal();
|
|
437
|
+
for (const record of api.instrumentRecords) {
|
|
438
|
+
record.disposed = true;
|
|
439
|
+
try {
|
|
440
|
+
record.restore?.();
|
|
441
|
+
} catch {
|
|
442
|
+
// ignore restore failures
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
api.instrumentRecords = [];
|
|
446
|
+
try {
|
|
447
|
+
api.fetchRestore?.();
|
|
448
|
+
} catch {
|
|
449
|
+
// ignore
|
|
450
|
+
}
|
|
451
|
+
api.fetchRestore = undefined;
|
|
452
|
+
|
|
453
|
+
const kept: RuntimeRegistration[] = [];
|
|
454
|
+
for (const entry of api.runtimeRegistrations) {
|
|
455
|
+
if (entry.teardown) {
|
|
456
|
+
try {
|
|
457
|
+
entry.teardown();
|
|
458
|
+
} catch {
|
|
459
|
+
// ignore
|
|
460
|
+
}
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
kept.push(entry);
|
|
464
|
+
}
|
|
465
|
+
api.runtimeRegistrations = kept;
|
|
466
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -15,38 +15,35 @@ export {
|
|
|
15
15
|
journeyStep,
|
|
16
16
|
setJourneyTags,
|
|
17
17
|
// Custom transport adapters / request attribution.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
JourneyStepTag,
|
|
18
|
+
singleInFlightJourneyStep,
|
|
19
|
+
resolveStamp,
|
|
20
|
+
JourneyStepStamp,
|
|
22
21
|
type JourneyDef,
|
|
23
22
|
type JourneyHandle,
|
|
24
23
|
type JourneyNameLike,
|
|
25
24
|
type JourneyStepOptions,
|
|
26
|
-
type JourneyStepRef,
|
|
27
25
|
type JourneyStepTarget,
|
|
28
26
|
type StepHandle,
|
|
29
27
|
} from './core';
|
|
30
28
|
|
|
31
|
-
export {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
export { configureJourney, type JourneyConfig } from './config';
|
|
30
|
+
export type { EndpointPolicy, SlowRequestConfig } from './core/endpoint-policy';
|
|
31
|
+
export type {
|
|
32
|
+
JourneyHttpPolicyContext,
|
|
33
|
+
JourneyHttpScore,
|
|
34
|
+
JourneyHttpScoreContext,
|
|
35
|
+
JourneyRequestPolicy,
|
|
36
|
+
JourneyStampOptions,
|
|
37
|
+
RequestPolicyConfig,
|
|
38
|
+
} from './core/request-policy';
|
|
37
39
|
|
|
38
40
|
export type { JourneySink } from './core';
|
|
39
41
|
|
|
40
|
-
/**
|
|
41
|
-
* @internal Accidentally exported — removing it is a breaking change, so it stays
|
|
42
|
-
* for compatibility. Not part of the supported public API. Test helper only.
|
|
43
|
-
*/
|
|
44
|
-
export { resetJourney } from './core';
|
|
45
|
-
|
|
46
42
|
export { instrumentAxios } from './integrations/axios';
|
|
47
43
|
export { instrumentFetch } from './integrations/fetch';
|
|
48
44
|
export { exposeAppJourney, instrumentJquery } from './integrations/jquery';
|
|
49
45
|
export { requestKey, type JourneyTimedMeta } from './integrations/request-key';
|
|
46
|
+
export { onHttpComplete, type HttpCompleteReport } from './integrations/http-report';
|
|
50
47
|
export {
|
|
51
48
|
disableJourney,
|
|
52
49
|
disableJourneyDebugging,
|
|
@@ -54,6 +51,8 @@ export {
|
|
|
54
51
|
enableJourneyDebugging,
|
|
55
52
|
isJourneyDebugEnabled,
|
|
56
53
|
isJourneyEnabled,
|
|
54
|
+
setJourneyDefaultEnabled,
|
|
55
|
+
teardownJourney,
|
|
57
56
|
} from './global';
|
|
58
57
|
export { sendToConsole } from './sinks/console';
|
|
59
58
|
export { normalizeTagValue, sendToDatadog, setJourneyRum } from './sinks/datadog';
|
|
@@ -62,3 +61,4 @@ export type { JourneyEvent, JourneyStepEvent, TagValue } from './core';
|
|
|
62
61
|
|
|
63
62
|
export { useJourneyName, useOptionalJourneyName } from './integrations/react/context';
|
|
64
63
|
export { JourneyScope } from './integrations/react/scope';
|
|
64
|
+
export { useJourneyStep } from './integrations/react/use-journey-step';
|