@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/integrations/http-report.ts"],"sourcesContent":["import { MAX_ATTRIBUTED_REQUEST_KEYS } from '../core/limits';\nimport {\n isJourneyRequestPolicy,\n resolveRequestPolicy,\n type JourneyHttpPolicyContext,\n type JourneyRequestPolicy,\n} from '../core/request-policy';\nimport { reportBackendRequest } from '../core/api';\nimport { canRouteHttpToJourney, resolveJourneyEngine } from '../core/runtime';\nimport type { JourneyStepStamp } from '../core/step-tag';\nimport type { StepRecord } from '../core/types';\nimport type { JourneyTimedMeta } from './request-key';\n\nexport interface HttpCompleteReport {\n stamp: JourneyStepStamp | undefined;\n status?: number;\n durationMs: number;\n requestKey: string;\n aborted?: boolean;\n url?: string;\n method?: string;\n /** Per-request literal overrides from JourneyTimedMeta. */\n meta?: JourneyTimedMeta;\n /** Transport request (axios config, fetch input/init, jQuery settings). */\n request?: unknown;\n /** Transport response (axios response, fetch Response, jqXHR). */\n response?: unknown;\n /** Rejection reason when the transport failed. */\n error?: unknown;\n}\n\nfunction applyPolicy(\n policy: JourneyRequestPolicy,\n step: StepRecord,\n reason: string,\n status?: number\n): void {\n if (policy === 'continue') {\n return;\n }\n const journey = step.journey;\n if (!journey || journey.closed) {\n return;\n }\n const engine = resolveJourneyEngine(journey);\n if (policy === 'exclude') {\n engine.exclude();\n return;\n }\n // 'bad'\n step.outcome = 'bad';\n step.reason ??= reason;\n if (status !== undefined) {\n step.httpStatus = status;\n }\n engine.failJourney(reason);\n}\n\nfunction httpScoreReason(report: HttpCompleteReport): string {\n if (report.aborted) {\n return 'request-aborted';\n }\n const status = report.status;\n if (status !== undefined && status >= 400 && status < 500) {\n return 'request-client-error';\n }\n return 'request-error';\n}\n\n/**\n * Attribute a finished HTTP call: abort / 4xx policies, else 5xx+latency via reportBackendRequest.\n * Ignored endpoint prefixes never change the journey verdict.\n * 4xx with policy `'continue'` (default) still scores latency.\n */\nexport function onHttpComplete(report: HttpCompleteReport): void {\n const {\n stamp,\n status,\n durationMs,\n requestKey,\n aborted,\n url,\n method,\n meta,\n request,\n response,\n error,\n } = report;\n if (!stamp) {\n return;\n }\n const step = stamp.step;\n if (!step?.journey) {\n return;\n }\n /*\n * Unstamped foreign journeys (older package copies) cannot be closed from\n * this bundle — do not write onHttpAborted / step.outcome on them.\n */\n if (!canRouteHttpToJourney(step.journey)) {\n return;\n }\n const engine = resolveJourneyEngine(step.journey);\n\n if (meta?.ignore === true || stamp.ignore === true) {\n return;\n }\n\n if (aborted) {\n step.onHttpAborted = true;\n }\n\n if (requestKey) {\n step.attributedRequestKeys ??= [];\n if (\n step.attributedRequestKeys.length < MAX_ATTRIBUTED_REQUEST_KEYS &&\n !step.attributedRequestKeys.includes(requestKey)\n ) {\n step.attributedRequestKeys.push(requestKey);\n }\n }\n\n if (requestKey && engine.shouldIgnoreRequest(requestKey)) {\n return;\n }\n\n const ctx: JourneyHttpPolicyContext = {\n requestKey,\n status,\n aborted: aborted === true,\n url,\n method,\n journeyName: step.journey.name,\n stepName: step.name,\n };\n\n const score = stamp.score;\n if (score) {\n let policy: JourneyRequestPolicy | undefined;\n try {\n const scored = score({\n ...ctx,\n durationMs,\n request,\n response,\n error,\n });\n if (isJourneyRequestPolicy(scored)) {\n policy = scored;\n }\n } catch {\n policy = undefined;\n }\n if (policy !== undefined) {\n applyPolicy(policy, step, httpScoreReason(report), status);\n return;\n }\n }\n\n if (aborted) {\n const override = meta?.httpAbortedRequests;\n const policy = isJourneyRequestPolicy(override)\n ? override\n : resolveRequestPolicy(engine.getHttpAbortedRequestsPolicy(), 'continue', ctx);\n applyPolicy(policy, step, 'request-aborted');\n return;\n }\n\n if (status !== undefined && status >= 400 && status < 500) {\n const override = meta?.httpClientErrorRequests;\n const policy = isJourneyRequestPolicy(override)\n ? override\n : resolveRequestPolicy(engine.getHttpClientErrorRequestsPolicy(), 'continue', ctx);\n if (policy !== 'continue') {\n applyPolicy(policy, step, 'request-client-error', status);\n return;\n }\n // 'continue' does not count 4xx as an error; still score latency below.\n }\n\n reportBackendRequest(step, status, durationMs, requestKey);\n}\n\nexport { isAbortError, isCanceledError } from '../core/abort-error';\n"],"names":["MAX_ATTRIBUTED_REQUEST_KEYS","isJourneyRequestPolicy","resolveRequestPolicy","reportBackendRequest","canRouteHttpToJourney","resolveJourneyEngine","applyPolicy","policy","step","reason","status","journey","closed","engine","exclude","outcome","undefined","httpStatus","failJourney","httpScoreReason","report","aborted","onHttpComplete","stamp","durationMs","requestKey","url","method","meta","request","response","error","ignore","onHttpAborted","attributedRequestKeys","length","includes","push","shouldIgnoreRequest","ctx","journeyName","name","stepName","score","scored","override","httpAbortedRequests","getHttpAbortedRequestsPolicy","httpClientErrorRequests","getHttpClientErrorRequestsPolicy","isAbortError","isCanceledError"],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { type JourneyDef, type JourneyHandle, type JourneyStepOptions, type JourneyStepTarget, type StepHandle } from '../../core';
|
|
2
2
|
/**
|
|
3
3
|
* Knockout / desktop-legacy bridge on `window.App.Journey`.
|
|
4
|
-
* Prefer `defineJourney` handles; `journeyStep` / `
|
|
4
|
+
* Prefer `defineJourney` handles; `journeyStep` / `firstOpenJourneyName` cover multi-journey steps.
|
|
5
|
+
* Use `getJourneyHandle(name)` when you need the handle from another module.
|
|
5
6
|
*/
|
|
6
7
|
interface AppJourneyApi {
|
|
7
|
-
defineJourney(
|
|
8
|
+
defineJourney(config: JourneyDef): JourneyHandle;
|
|
8
9
|
journeyStep<T>(journey: JourneyStepTarget, stepName: string, fn: (step: StepHandle) => T | Promise<T>, opts?: JourneyStepOptions): Promise<T>;
|
|
9
|
-
|
|
10
|
+
/** First open journey **name** among candidates, or null. */
|
|
11
|
+
firstOpenJourneyName(names: readonly string[]): string | null;
|
|
12
|
+
/** `defineJourney` handle for an open name, or null. */
|
|
13
|
+
getJourneyHandle(name: string): JourneyHandle | null;
|
|
10
14
|
}
|
|
11
15
|
export type WindowWithAppJourney = Window & {
|
|
12
16
|
App?: {
|
|
@@ -15,7 +19,7 @@ export type WindowWithAppJourney = Window & {
|
|
|
15
19
|
};
|
|
16
20
|
/**
|
|
17
21
|
* Publish the Knockout bridge on window.App.Journey. Idempotent for the real window.
|
|
18
|
-
* Optional `target` is for tests.
|
|
22
|
+
* Optional `target` is for tests. Never throws — logs and returns a usable API if publish fails.
|
|
19
23
|
*/
|
|
20
24
|
export declare function exposeAppJourney(target?: WindowWithAppJourney): AppJourneyApi;
|
|
21
25
|
export { instrumentJquery, type JqueryStatic } from './instrument';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/jquery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AAGpB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/jquery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,UAAU,aAAa;IACnB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC;IACjD,WAAW,CAAC,CAAC,EACT,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxC,IAAI,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,6DAA6D;IAC7D,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9D,wDAAwD;IACxD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG;IACxC,GAAG,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,aAAa,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/D,CAAC;AAaF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,oBAA6B,GAAG,aAAa,CA6BrF;AAED,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -2,24 +2,42 @@ import { defineJourney, journeyStep } from '../../core';
|
|
|
2
2
|
import { moduleRuntime } from '../../core/runtime';
|
|
3
3
|
let journeyExposed = false;
|
|
4
4
|
let windowJourneyApi;
|
|
5
|
+
function handleForOpenJourney(name) {
|
|
6
|
+
const open = moduleRuntime.getOpenJourney(name);
|
|
7
|
+
if (!open) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return defineJourney(open.config);
|
|
11
|
+
}
|
|
5
12
|
/**
|
|
6
13
|
* Publish the Knockout bridge on window.App.Journey. Idempotent for the real window.
|
|
7
|
-
* Optional `target` is for tests.
|
|
14
|
+
* Optional `target` is for tests. Never throws — logs and returns a usable API if publish fails.
|
|
8
15
|
*/ export function exposeAppJourney(target = window) {
|
|
9
|
-
var _target_App;
|
|
10
16
|
if (journeyExposed && target === window && windowJourneyApi) {
|
|
11
17
|
return windowJourneyApi;
|
|
12
18
|
}
|
|
13
19
|
const api = {
|
|
14
20
|
defineJourney,
|
|
15
21
|
journeyStep,
|
|
16
|
-
|
|
22
|
+
firstOpenJourneyName: (names)=>moduleRuntime.firstOpenJourneyName(names),
|
|
23
|
+
getJourneyHandle: handleForOpenJourney
|
|
17
24
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
try {
|
|
26
|
+
var _target_App;
|
|
27
|
+
if (target == null || typeof target !== 'object' && typeof target !== 'function') {
|
|
28
|
+
// eslint-disable-next-line no-console -- soft-skip missing host window
|
|
29
|
+
console.warn('[journey] exposeAppJourney: skipped — missing');
|
|
30
|
+
return api;
|
|
31
|
+
}
|
|
32
|
+
target.App = (_target_App = target.App) !== null && _target_App !== void 0 ? _target_App : {};
|
|
33
|
+
target.App.Journey = Object.freeze(api);
|
|
34
|
+
if (target === window) {
|
|
35
|
+
journeyExposed = true;
|
|
36
|
+
windowJourneyApi = api;
|
|
37
|
+
}
|
|
38
|
+
} catch (err) {
|
|
39
|
+
// eslint-disable-next-line no-console -- soft-fail host wiring
|
|
40
|
+
console.error('[journey] exposeAppJourney failed', err);
|
|
23
41
|
}
|
|
24
42
|
return api;
|
|
25
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/jquery/index.ts"],"sourcesContent":["import {\n defineJourney,\n journeyStep,\n type JourneyDef,\n type JourneyHandle,\n type JourneyStepOptions,\n type JourneyStepTarget,\n type StepHandle,\n} from '../../core';\nimport { moduleRuntime } from '../../core/runtime';\n\n/**\n * Knockout / desktop-legacy bridge on `window.App.Journey`.\n * Prefer `defineJourney` handles; `journeyStep` / `
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/jquery/index.ts"],"sourcesContent":["import {\n defineJourney,\n journeyStep,\n type JourneyDef,\n type JourneyHandle,\n type JourneyStepOptions,\n type JourneyStepTarget,\n type StepHandle,\n} from '../../core';\nimport { moduleRuntime } from '../../core/runtime';\n\n/**\n * Knockout / desktop-legacy bridge on `window.App.Journey`.\n * Prefer `defineJourney` handles; `journeyStep` / `firstOpenJourneyName` cover multi-journey steps.\n * Use `getJourneyHandle(name)` when you need the handle from another module.\n */\ninterface AppJourneyApi {\n defineJourney(config: JourneyDef): JourneyHandle;\n journeyStep<T>(\n journey: JourneyStepTarget,\n stepName: string,\n fn: (step: StepHandle) => T | Promise<T>,\n opts?: JourneyStepOptions\n ): Promise<T>;\n /** First open journey **name** among candidates, or null. */\n firstOpenJourneyName(names: readonly string[]): string | null;\n /** `defineJourney` handle for an open name, or null. */\n getJourneyHandle(name: string): JourneyHandle | null;\n}\n\nexport type WindowWithAppJourney = Window & {\n App?: { Journey?: AppJourneyApi } & Record<string, unknown>;\n};\n\nlet journeyExposed = false;\nlet windowJourneyApi: AppJourneyApi | undefined;\n\nfunction handleForOpenJourney(name: string): JourneyHandle | null {\n const open = moduleRuntime.getOpenJourney(name);\n if (!open) {\n return null;\n }\n return defineJourney(open.config);\n}\n\n/**\n * Publish the Knockout bridge on window.App.Journey. Idempotent for the real window.\n * Optional `target` is for tests. Never throws — logs and returns a usable API if publish fails.\n */\nexport function exposeAppJourney(target: WindowWithAppJourney = window): AppJourneyApi {\n if (journeyExposed && target === window && windowJourneyApi) {\n return windowJourneyApi;\n }\n\n const api: AppJourneyApi = {\n defineJourney,\n journeyStep,\n firstOpenJourneyName: names => moduleRuntime.firstOpenJourneyName(names),\n getJourneyHandle: handleForOpenJourney,\n };\n\n try {\n if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {\n // eslint-disable-next-line no-console -- soft-skip missing host window\n console.warn('[journey] exposeAppJourney: skipped — missing');\n return api;\n }\n target.App = target.App ?? {};\n target.App.Journey = Object.freeze(api);\n if (target === window) {\n journeyExposed = true;\n windowJourneyApi = api;\n }\n } catch (err) {\n // eslint-disable-next-line no-console -- soft-fail host wiring\n console.error('[journey] exposeAppJourney failed', err);\n }\n return api;\n}\n\nexport { instrumentJquery, type JqueryStatic } from './instrument';\n"],"names":["defineJourney","journeyStep","moduleRuntime","journeyExposed","windowJourneyApi","handleForOpenJourney","name","open","getOpenJourney","config","exposeAppJourney","target","window","api","firstOpenJourneyName","names","getJourneyHandle","console","warn","App","Journey","Object","freeze","err","error","instrumentJquery"],"mappings":"AAAA,SACIA,aAAa,EACbC,WAAW,QAMR,aAAa;AACpB,SAASC,aAAa,QAAQ,qBAAqB;AAyBnD,IAAIC,iBAAiB;AACrB,IAAIC;AAEJ,SAASC,qBAAqBC,IAAY;IACtC,MAAMC,OAAOL,cAAcM,cAAc,CAACF;IAC1C,IAAI,CAACC,MAAM;QACP,OAAO;IACX;IACA,OAAOP,cAAcO,KAAKE,MAAM;AACpC;AAEA;;;CAGC,GACD,OAAO,SAASC,iBAAiBC,SAA+BC,MAAM;IAClE,IAAIT,kBAAkBQ,WAAWC,UAAUR,kBAAkB;QACzD,OAAOA;IACX;IAEA,MAAMS,MAAqB;QACvBb;QACAC;QACAa,sBAAsBC,CAAAA,QAASb,cAAcY,oBAAoB,CAACC;QAClEC,kBAAkBX;IACtB;IAEA,IAAI;YAMaM;QALb,IAAIA,UAAU,QAAS,OAAOA,WAAW,YAAY,OAAOA,WAAW,YAAa;YAChF,uEAAuE;YACvEM,QAAQC,IAAI,CAAC;YACb,OAAOL;QACX;QACAF,OAAOQ,GAAG,IAAGR,cAAAA,OAAOQ,GAAG,cAAVR,yBAAAA,cAAc,CAAC;QAC5BA,OAAOQ,GAAG,CAACC,OAAO,GAAGC,OAAOC,MAAM,CAACT;QACnC,IAAIF,WAAWC,QAAQ;YACnBT,iBAAiB;YACjBC,mBAAmBS;QACvB;IACJ,EAAE,OAAOU,KAAK;QACV,+DAA+D;QAC/DN,QAAQO,KAAK,CAAC,qCAAqCD;IACvD;IACA,OAAOV;AACX;AAEA,SAASY,gBAAgB,QAA2B,eAAe"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { type JourneyTimedMeta } from '../request-key';
|
|
1
2
|
export interface JqueryXHR {
|
|
2
3
|
status: number;
|
|
3
|
-
|
|
4
|
+
statusText?: string;
|
|
5
|
+
stamp?: unknown;
|
|
4
6
|
journeyStart?: number;
|
|
5
7
|
}
|
|
6
|
-
export interface JqueryAjaxSettings {
|
|
8
|
+
export interface JqueryAjaxSettings extends JourneyTimedMeta {
|
|
7
9
|
url?: string;
|
|
8
|
-
|
|
10
|
+
type?: string;
|
|
11
|
+
method?: string;
|
|
9
12
|
}
|
|
10
13
|
export interface JqueryStatic {
|
|
11
14
|
ajaxPrefilter(handler: (options: JqueryAjaxSettings, originalOptions: JqueryAjaxSettings, jqXHR: JqueryXHR) => void): void;
|
|
@@ -13,6 +16,12 @@ export interface JqueryStatic {
|
|
|
13
16
|
ajaxComplete(handler: (event: unknown, jqXHR: JqueryXHR, settings: JqueryAjaxSettings) => void): void;
|
|
14
17
|
};
|
|
15
18
|
}
|
|
16
|
-
/**
|
|
17
|
-
export declare function
|
|
19
|
+
/** Resolve `globalThis.$`, then `globalThis.jQuery`. */
|
|
20
|
+
export declare function resolveGlobalJquery(): JqueryStatic | null | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Wire a jQuery static into the journey engine. Call once per $ (idempotent). Observation-only.
|
|
23
|
+
* Soft-skips when `$` is missing or not a real jQuery (no `ajaxPrefilter`) so hosts can pass `$` as-is.
|
|
24
|
+
* Returns a restore that disposes handlers (they no-op after restore).
|
|
25
|
+
*/
|
|
26
|
+
export declare function instrumentJquery($: JqueryStatic | null | undefined): () => void;
|
|
18
27
|
//# sourceMappingURL=instrument.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../../../src/integrations/jquery/instrument.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../../../src/integrations/jquery/instrument.ts"],"names":[],"mappings":"AAQA,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGnE,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,YAAY;IACzB,aAAa,CACT,OAAO,EAAE,CACL,OAAO,EAAE,kBAAkB,EAC3B,eAAe,EAAE,kBAAkB,EACnC,KAAK,EAAE,SAAS,KACf,IAAI,GACV,IAAI,CAAC;IACR,CAAC,QAAQ,EAAE,QAAQ,GAAG;QAClB,YAAY,CACR,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,GAClF,IAAI,CAAC;KACX,CAAC;CACL;AA+BD,wDAAwD;AACxD,wBAAgB,mBAAmB,IAAI,YAAY,GAAG,IAAI,GAAG,SAAS,CAGrE;AAuBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,IAAI,CAiE/E"}
|
|
@@ -1,44 +1,126 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveStamp } from '../../core';
|
|
2
|
+
import { adoptJourneyStepStamp } from '../../core/step-tag';
|
|
3
|
+
import { getInstrumentedJquerySet, registerInstrumentRecord } from '../../global';
|
|
4
|
+
import { onHttpComplete } from '../http-report';
|
|
2
5
|
import { requestKey } from '../request-key';
|
|
3
|
-
|
|
6
|
+
import { acceptInstrumentTarget } from '../soft-skip';
|
|
7
|
+
const jqueryStamps = new WeakMap();
|
|
4
8
|
function reportTiming(jqXHR, settings) {
|
|
5
|
-
var _jqXHR_journeyStart;
|
|
6
|
-
const
|
|
7
|
-
if (!
|
|
9
|
+
var _jqueryStamps_get, _jqXHR_journeyStart, _settings_type;
|
|
10
|
+
const stamp = (_jqueryStamps_get = jqueryStamps.get(jqXHR)) !== null && _jqueryStamps_get !== void 0 ? _jqueryStamps_get : adoptJourneyStepStamp(jqXHR.stamp);
|
|
11
|
+
if (!stamp || stamp.ignore || settings.ignore === true) {
|
|
8
12
|
return;
|
|
9
13
|
}
|
|
10
14
|
const start = (_jqXHR_journeyStart = jqXHR.journeyStart) !== null && _jqXHR_journeyStart !== void 0 ? _jqXHR_journeyStart : globalThis.performance.now();
|
|
15
|
+
const aborted = jqXHR.statusText === 'abort';
|
|
11
16
|
// jQuery uses status 0 for network / abort failures — treat like a missing status.
|
|
12
|
-
const status = jqXHR.status === 0 ? undefined : jqXHR.status;
|
|
13
|
-
|
|
17
|
+
const status = aborted || jqXHR.status === 0 ? undefined : jqXHR.status;
|
|
18
|
+
onHttpComplete({
|
|
19
|
+
stamp,
|
|
20
|
+
status,
|
|
21
|
+
durationMs: globalThis.performance.now() - start,
|
|
22
|
+
requestKey: requestKey(settings.url, undefined, undefined),
|
|
23
|
+
aborted,
|
|
24
|
+
url: settings.url,
|
|
25
|
+
method: (_settings_type = settings.type) !== null && _settings_type !== void 0 ? _settings_type : settings.method,
|
|
26
|
+
meta: settings,
|
|
27
|
+
request: settings,
|
|
28
|
+
response: jqXHR
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function isJqueryStatic(value) {
|
|
32
|
+
return typeof value === 'function' && typeof value.ajaxPrefilter === 'function';
|
|
14
33
|
}
|
|
15
|
-
/**
|
|
16
|
-
|
|
34
|
+
/** Resolve `globalThis.$`, then `globalThis.jQuery`. */ export function resolveGlobalJquery() {
|
|
35
|
+
var _g_$;
|
|
36
|
+
const g = globalThis;
|
|
37
|
+
return (_g_$ = g.$) !== null && _g_$ !== void 0 ? _g_$ : g.jQuery;
|
|
38
|
+
}
|
|
39
|
+
/** Live record per $ — handlers look this up so restore+rewire does not stack prefilters. */ const jqueryLiveRecords = new WeakMap();
|
|
40
|
+
/** jQuery cannot unregister these; track each so a partial-wire retry does not stack. */ const jqueryPrefiltersInstalled = new WeakSet();
|
|
41
|
+
const jqueryCompletesInstalled = new WeakSet();
|
|
42
|
+
function stampAjax(jqXHR, options) {
|
|
43
|
+
var _jqXHR_stamp;
|
|
44
|
+
if (options.ignore === true) {
|
|
17
45
|
return;
|
|
18
46
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
const stamp = resolveStamp((_jqXHR_stamp = jqXHR.stamp) !== null && _jqXHR_stamp !== void 0 ? _jqXHR_stamp : options.stamp);
|
|
48
|
+
if (stamp) {
|
|
49
|
+
jqueryStamps.set(jqXHR, stamp);
|
|
50
|
+
delete jqXHR.stamp;
|
|
51
|
+
delete options.stamp;
|
|
52
|
+
}
|
|
53
|
+
if (stamp && !stamp.ignore) {
|
|
54
|
+
jqXHR.journeyStart = globalThis.performance.now();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Wire a jQuery static into the journey engine. Call once per $ (idempotent). Observation-only.
|
|
59
|
+
* Soft-skips when `$` is missing or not a real jQuery (no `ajaxPrefilter`) so hosts can pass `$` as-is.
|
|
60
|
+
* Returns a restore that disposes handlers (they no-op after restore).
|
|
61
|
+
*/ export function instrumentJquery($) {
|
|
62
|
+
const jquery = acceptInstrumentTarget('Jquery', $, isJqueryStatic);
|
|
63
|
+
const instrumented = getInstrumentedJquerySet();
|
|
64
|
+
if (!jquery || instrumented.has(jquery)) {
|
|
65
|
+
return ()=>{};
|
|
66
|
+
}
|
|
67
|
+
const key = jquery;
|
|
68
|
+
const record = {
|
|
69
|
+
disposed: false
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
if (!jqueryPrefiltersInstalled.has(key)) {
|
|
73
|
+
jquery.ajaxPrefilter((options, _originalOptions, jqXHR)=>{
|
|
74
|
+
const current = jqueryLiveRecords.get(key);
|
|
75
|
+
if (!current || current.disposed) {
|
|
76
|
+
return;
|
|
32
77
|
}
|
|
33
|
-
|
|
78
|
+
stampAjax(jqXHR, options);
|
|
79
|
+
});
|
|
80
|
+
jqueryPrefiltersInstalled.add(key);
|
|
34
81
|
}
|
|
35
|
-
if (
|
|
36
|
-
|
|
82
|
+
if (!jqueryCompletesInstalled.has(key)) {
|
|
83
|
+
jquery(document).ajaxComplete((_event, jqXHR, settings)=>{
|
|
84
|
+
const current = jqueryLiveRecords.get(key);
|
|
85
|
+
if (!current || current.disposed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
reportTiming(jqXHR, settings);
|
|
89
|
+
});
|
|
90
|
+
jqueryCompletesInstalled.add(key);
|
|
37
91
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
92
|
+
jqueryLiveRecords.set(key, record);
|
|
93
|
+
instrumented.add(key);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
/*
|
|
96
|
+
* Keep per-handler installed flags so a retry cannot double-register
|
|
97
|
+
* prefilters. Restore deletes the shared instrumented slot so teardown /
|
|
98
|
+
* retry can finish whichever handler never succeeded.
|
|
99
|
+
*/ record.disposed = true;
|
|
100
|
+
instrumented.add(key);
|
|
101
|
+
const restore = ()=>{
|
|
102
|
+
record.disposed = true;
|
|
103
|
+
if (jqueryLiveRecords.get(key) === record) {
|
|
104
|
+
jqueryLiveRecords.delete(key);
|
|
105
|
+
}
|
|
106
|
+
instrumented.delete(key);
|
|
107
|
+
};
|
|
108
|
+
record.restore = restore;
|
|
109
|
+
registerInstrumentRecord(record);
|
|
110
|
+
// eslint-disable-next-line no-console -- soft-fail host wiring
|
|
111
|
+
console.error('[journey] instrumentJquery failed', err);
|
|
112
|
+
return restore;
|
|
113
|
+
}
|
|
114
|
+
const restore = ()=>{
|
|
115
|
+
record.disposed = true;
|
|
116
|
+
if (jqueryLiveRecords.get(key) === record) {
|
|
117
|
+
jqueryLiveRecords.delete(key);
|
|
118
|
+
}
|
|
119
|
+
instrumented.delete(key);
|
|
120
|
+
};
|
|
121
|
+
record.restore = restore;
|
|
122
|
+
registerInstrumentRecord(record);
|
|
123
|
+
return restore;
|
|
42
124
|
}
|
|
43
125
|
|
|
44
126
|
//# sourceMappingURL=instrument.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/jquery/instrument.ts"],"sourcesContent":["import {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/jquery/instrument.ts"],"sourcesContent":["import { resolveStamp } from '../../core';\nimport { adoptJourneyStepStamp, type JourneyStepStamp } from '../../core/step-tag';\nimport {\n getInstrumentedJquerySet,\n registerInstrumentRecord,\n type InstrumentRecord,\n} from '../../global';\nimport { onHttpComplete } from '../http-report';\nimport { requestKey, type JourneyTimedMeta } from '../request-key';\nimport { acceptInstrumentTarget } from '../soft-skip';\n\nexport interface JqueryXHR {\n status: number;\n statusText?: string;\n stamp?: unknown;\n journeyStart?: number;\n}\n\nexport interface JqueryAjaxSettings extends JourneyTimedMeta {\n url?: string;\n type?: string;\n method?: string;\n}\n\nconst jqueryStamps = new WeakMap<object, JourneyStepStamp>();\n\nexport interface JqueryStatic {\n ajaxPrefilter(\n handler: (\n options: JqueryAjaxSettings,\n originalOptions: JqueryAjaxSettings,\n jqXHR: JqueryXHR\n ) => void\n ): void;\n (selector: Document): {\n ajaxComplete(\n handler: (event: unknown, jqXHR: JqueryXHR, settings: JqueryAjaxSettings) => void\n ): void;\n };\n}\n\nfunction reportTiming(jqXHR: JqueryXHR, settings: JqueryAjaxSettings): void {\n const stamp = jqueryStamps.get(jqXHR) ?? adoptJourneyStepStamp(jqXHR.stamp);\n if (!stamp || stamp.ignore || settings.ignore === true) {\n return;\n }\n const start = jqXHR.journeyStart ?? globalThis.performance.now();\n const aborted = jqXHR.statusText === 'abort';\n // jQuery uses status 0 for network / abort failures — treat like a missing status.\n const status = aborted || jqXHR.status === 0 ? undefined : jqXHR.status;\n onHttpComplete({\n stamp,\n status,\n durationMs: globalThis.performance.now() - start,\n requestKey: requestKey(settings.url, undefined, undefined),\n aborted,\n url: settings.url,\n method: settings.type ?? settings.method,\n meta: settings,\n request: settings,\n response: jqXHR,\n });\n}\n\nfunction isJqueryStatic(value: unknown): value is JqueryStatic {\n return (\n typeof value === 'function' && typeof (value as JqueryStatic).ajaxPrefilter === 'function'\n );\n}\n\n/** Resolve `globalThis.$`, then `globalThis.jQuery`. */\nexport function resolveGlobalJquery(): JqueryStatic | null | undefined {\n const g = globalThis as typeof globalThis & { $?: unknown; jQuery?: unknown };\n return (g.$ ?? g.jQuery) as JqueryStatic | null | undefined;\n}\n\n/** Live record per $ — handlers look this up so restore+rewire does not stack prefilters. */\nconst jqueryLiveRecords = new WeakMap<object, InstrumentRecord>();\n/** jQuery cannot unregister these; track each so a partial-wire retry does not stack. */\nconst jqueryPrefiltersInstalled = new WeakSet<object>();\nconst jqueryCompletesInstalled = new WeakSet<object>();\n\nfunction stampAjax(jqXHR: JqueryXHR, options: JqueryAjaxSettings): void {\n if (options.ignore === true) {\n return;\n }\n const stamp = resolveStamp(jqXHR.stamp ?? options.stamp);\n if (stamp) {\n jqueryStamps.set(jqXHR, stamp);\n delete jqXHR.stamp;\n delete options.stamp;\n }\n if (stamp && !stamp.ignore) {\n jqXHR.journeyStart = globalThis.performance.now();\n }\n}\n\n/**\n * Wire a jQuery static into the journey engine. Call once per $ (idempotent). Observation-only.\n * Soft-skips when `$` is missing or not a real jQuery (no `ajaxPrefilter`) so hosts can pass `$` as-is.\n * Returns a restore that disposes handlers (they no-op after restore).\n */\nexport function instrumentJquery($: JqueryStatic | null | undefined): () => void {\n const jquery = acceptInstrumentTarget('Jquery', $, isJqueryStatic);\n const instrumented = getInstrumentedJquerySet();\n if (!jquery || instrumented.has(jquery as object)) {\n return () => {};\n }\n\n const key = jquery as object;\n const record: InstrumentRecord = { disposed: false };\n\n try {\n if (!jqueryPrefiltersInstalled.has(key)) {\n jquery.ajaxPrefilter((options, _originalOptions, jqXHR) => {\n const current = jqueryLiveRecords.get(key);\n if (!current || current.disposed) {\n return;\n }\n stampAjax(jqXHR, options);\n });\n jqueryPrefiltersInstalled.add(key);\n }\n if (!jqueryCompletesInstalled.has(key)) {\n jquery(document).ajaxComplete((_event, jqXHR, settings) => {\n const current = jqueryLiveRecords.get(key);\n if (!current || current.disposed) {\n return;\n }\n reportTiming(jqXHR, settings);\n });\n jqueryCompletesInstalled.add(key);\n }\n jqueryLiveRecords.set(key, record);\n instrumented.add(key);\n } catch (err) {\n /*\n * Keep per-handler installed flags so a retry cannot double-register\n * prefilters. Restore deletes the shared instrumented slot so teardown /\n * retry can finish whichever handler never succeeded.\n */\n record.disposed = true;\n instrumented.add(key);\n const restore = () => {\n record.disposed = true;\n if (jqueryLiveRecords.get(key) === record) {\n jqueryLiveRecords.delete(key);\n }\n instrumented.delete(key);\n };\n record.restore = restore;\n registerInstrumentRecord(record);\n // eslint-disable-next-line no-console -- soft-fail host wiring\n console.error('[journey] instrumentJquery failed', err);\n return restore;\n }\n\n const restore = () => {\n record.disposed = true;\n if (jqueryLiveRecords.get(key) === record) {\n jqueryLiveRecords.delete(key);\n }\n instrumented.delete(key);\n };\n record.restore = restore;\n registerInstrumentRecord(record);\n return restore;\n}\n"],"names":["resolveStamp","adoptJourneyStepStamp","getInstrumentedJquerySet","registerInstrumentRecord","onHttpComplete","requestKey","acceptInstrumentTarget","jqueryStamps","WeakMap","reportTiming","jqXHR","settings","stamp","get","ignore","start","journeyStart","globalThis","performance","now","aborted","statusText","status","undefined","durationMs","url","method","type","meta","request","response","isJqueryStatic","value","ajaxPrefilter","resolveGlobalJquery","g","$","jQuery","jqueryLiveRecords","jqueryPrefiltersInstalled","WeakSet","jqueryCompletesInstalled","stampAjax","options","set","instrumentJquery","jquery","instrumented","has","key","record","disposed","_originalOptions","current","add","document","ajaxComplete","_event","err","restore","delete","console","error"],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export declare const JourneyNameContext: import("react").Context<string | null>;
|
|
2
2
|
/** Active journey name, or null outside a `<JourneyScope>` (steps run untraced). */
|
|
3
3
|
export declare function useOptionalJourneyName(): string | null;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Active journey name; throws outside a `<JourneyScope>`.
|
|
6
|
+
* Prefer {@link useOptionalJourneyName} when the shell may omit a scope.
|
|
7
|
+
*/
|
|
5
8
|
export declare function useJourneyName(): string;
|
|
6
9
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/context.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,wCAAqC,CAAC;AAErE,oFAAoF;AACpF,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,IAAI,CAEtD;AAED
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/context.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,wCAAqC,CAAC;AAErE,oFAAoF;AACpF,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,IAAI,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAMvC"}
|
|
@@ -3,7 +3,10 @@ export const JourneyNameContext = createContext(null);
|
|
|
3
3
|
/** Active journey name, or null outside a `<JourneyScope>` (steps run untraced). */ export function useOptionalJourneyName() {
|
|
4
4
|
return useContext(JourneyNameContext);
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Active journey name; throws outside a `<JourneyScope>`.
|
|
8
|
+
* Prefer {@link useOptionalJourneyName} when the shell may omit a scope.
|
|
9
|
+
*/ export function useJourneyName() {
|
|
7
10
|
const name = useContext(JourneyNameContext);
|
|
8
11
|
if (!name) {
|
|
9
12
|
throw new Error('useJourneyName must be used within a <JourneyScope>');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/react/context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport const JourneyNameContext = createContext<string | null>(null);\n\n/** Active journey name, or null outside a `<JourneyScope>` (steps run untraced). */\nexport function useOptionalJourneyName(): string | null {\n return useContext(JourneyNameContext);\n}\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/react/context.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport const JourneyNameContext = createContext<string | null>(null);\n\n/** Active journey name, or null outside a `<JourneyScope>` (steps run untraced). */\nexport function useOptionalJourneyName(): string | null {\n return useContext(JourneyNameContext);\n}\n\n/**\n * Active journey name; throws outside a `<JourneyScope>`.\n * Prefer {@link useOptionalJourneyName} when the shell may omit a scope.\n */\nexport function useJourneyName(): string {\n const name = useContext(JourneyNameContext);\n if (!name) {\n throw new Error('useJourneyName must be used within a <JourneyScope>');\n }\n return name;\n}\n"],"names":["createContext","useContext","JourneyNameContext","useOptionalJourneyName","useJourneyName","name","Error"],"mappings":"AAAA,SAASA,aAAa,EAAEC,UAAU,QAAQ,QAAQ;AAElD,OAAO,MAAMC,qBAAqBF,cAA6B,MAAM;AAErE,kFAAkF,GAClF,OAAO,SAASG;IACZ,OAAOF,WAAWC;AACtB;AAEA;;;CAGC,GACD,OAAO,SAASE;IACZ,MAAMC,OAAOJ,WAAWC;IACxB,IAAI,CAACG,MAAM;QACP,MAAM,IAAIC,MAAM;IACpB;IACA,OAAOD;AACX"}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type JourneyDef } from '../../core';
|
|
3
3
|
import type { TagValue } from '../../core/types';
|
|
4
|
+
type JourneyScopeDef = JourneyDef | {
|
|
5
|
+
config: JourneyDef;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* Opens a journey while the subtree is mounted; Excludes on unmount.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
9
|
+
* `name` is the lifecycle key — changing it excludes the previous instance
|
|
10
|
+
* and opens a new one. Other config fields and `tags` update the open instance
|
|
11
|
+
* in place (timeouts re-arm; they do not restart).
|
|
12
|
+
*
|
|
13
|
+
* Pass a {@link JourneyDef} (`<JourneyScope {...def}>`) or spread a handle
|
|
14
|
+
* (`<JourneyScope {...makeASaleJourney}>` reads `handle.config`).
|
|
15
|
+
*
|
|
16
|
+
* React 18 Strict Mode (development) remounts once: expect an `excluded` emission
|
|
17
|
+
* then a fresh open. Production single-mount does not.
|
|
8
18
|
*/
|
|
9
|
-
export declare function JourneyScope({ tags, children, ...
|
|
19
|
+
export declare function JourneyScope({ tags, children, ...rest }: JourneyScopeDef & {
|
|
10
20
|
tags?: Record<string, TagValue>;
|
|
11
21
|
children: ReactNode;
|
|
12
22
|
}): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
13
24
|
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/scope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/scope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,KAAK,eAAe,GAAG,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,GAAG,IAAI,EACV,EAAE,eAAe,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,QAAQ,EAAE,SAAS,CAAC;CACvB,2CAqDA"}
|
|
@@ -1,23 +1,61 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { setJourneyTags } from '../../core';
|
|
4
4
|
import { moduleRuntime } from '../../core/runtime';
|
|
5
5
|
import { JourneyNameContext } from './context';
|
|
6
|
+
import { stableEndpointKey, stableExpectedKey, stableTagsKey } from './stable-config-keys';
|
|
6
7
|
/**
|
|
7
8
|
* Opens a journey while the subtree is mounted; Excludes on unmount.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
* `name` is the lifecycle key — changing it excludes the previous instance
|
|
10
|
+
* and opens a new one. Other config fields and `tags` update the open instance
|
|
11
|
+
* in place (timeouts re-arm; they do not restart).
|
|
12
|
+
*
|
|
13
|
+
* Pass a {@link JourneyDef} (`<JourneyScope {...def}>`) or spread a handle
|
|
14
|
+
* (`<JourneyScope {...makeASaleJourney}>` reads `handle.config`).
|
|
15
|
+
*
|
|
16
|
+
* React 18 Strict Mode (development) remounts once: expect an `excluded` emission
|
|
17
|
+
* then a fresh open. Production single-mount does not.
|
|
18
|
+
*/ export function JourneyScope({ tags, children, ...rest }) {
|
|
19
|
+
const def = 'config' in rest ? rest.config : rest;
|
|
20
|
+
const { name, timeoutMs, stepTimeoutMs, slowRequestMs, endpoints, expected, service, team, group, maxSteps } = def;
|
|
21
|
+
const endpointKey = stableEndpointKey(endpoints);
|
|
22
|
+
const expectedKey = stableExpectedKey(expected);
|
|
23
|
+
const configTagsKey = stableTagsKey(def.tags);
|
|
12
24
|
useEffect(()=>{
|
|
13
25
|
moduleRuntime.startJourney(def);
|
|
26
|
+
const opened = moduleRuntime.getOpenJourney(name);
|
|
27
|
+
return ()=>{
|
|
28
|
+
if (opened) {
|
|
29
|
+
moduleRuntime.excludeJourney(opened);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- name is the lifecycle key
|
|
33
|
+
}, [
|
|
34
|
+
name
|
|
35
|
+
]);
|
|
36
|
+
useEffect(()=>{
|
|
14
37
|
if (tags) {
|
|
15
38
|
setJourneyTags(name, tags);
|
|
16
39
|
}
|
|
17
|
-
return ()=>excludeJourney(name);
|
|
18
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- freeze-on-mount; name is the lifecycle key
|
|
19
40
|
}, [
|
|
20
|
-
name
|
|
41
|
+
name,
|
|
42
|
+
tags
|
|
43
|
+
]);
|
|
44
|
+
useEffect(()=>{
|
|
45
|
+
moduleRuntime.updateOpenJourney(def);
|
|
46
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- field-level live updates; name-change is the other effect
|
|
47
|
+
}, [
|
|
48
|
+
name,
|
|
49
|
+
timeoutMs,
|
|
50
|
+
stepTimeoutMs,
|
|
51
|
+
slowRequestMs,
|
|
52
|
+
endpointKey,
|
|
53
|
+
expectedKey,
|
|
54
|
+
service,
|
|
55
|
+
team,
|
|
56
|
+
group,
|
|
57
|
+
maxSteps,
|
|
58
|
+
configTagsKey
|
|
21
59
|
]);
|
|
22
60
|
return /*#__PURE__*/ _jsx(JourneyNameContext.Provider, {
|
|
23
61
|
value: name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/react/scope.tsx"],"sourcesContent":["import { useEffect, type ReactNode } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/react/scope.tsx"],"sourcesContent":["import { useEffect, type ReactNode } from 'react';\n\nimport { setJourneyTags, type JourneyDef } from '../../core';\nimport { moduleRuntime } from '../../core/runtime';\nimport type { TagValue } from '../../core/types';\nimport { JourneyNameContext } from './context';\nimport { stableEndpointKey, stableExpectedKey, stableTagsKey } from './stable-config-keys';\n\ntype JourneyScopeDef = JourneyDef | { config: JourneyDef };\n\n/**\n * Opens a journey while the subtree is mounted; Excludes on unmount.\n * `name` is the lifecycle key — changing it excludes the previous instance\n * and opens a new one. Other config fields and `tags` update the open instance\n * in place (timeouts re-arm; they do not restart).\n *\n * Pass a {@link JourneyDef} (`<JourneyScope {...def}>`) or spread a handle\n * (`<JourneyScope {...makeASaleJourney}>` reads `handle.config`).\n *\n * React 18 Strict Mode (development) remounts once: expect an `excluded` emission\n * then a fresh open. Production single-mount does not.\n */\nexport function JourneyScope({\n tags,\n children,\n ...rest\n}: JourneyScopeDef & {\n tags?: Record<string, TagValue>;\n children: ReactNode;\n}) {\n const def: JourneyDef = 'config' in rest ? rest.config : rest;\n const {\n name,\n timeoutMs,\n stepTimeoutMs,\n slowRequestMs,\n endpoints,\n expected,\n service,\n team,\n group,\n maxSteps,\n } = def;\n const endpointKey = stableEndpointKey(endpoints);\n const expectedKey = stableExpectedKey(expected);\n const configTagsKey = stableTagsKey(def.tags);\n\n useEffect(() => {\n moduleRuntime.startJourney(def);\n const opened = moduleRuntime.getOpenJourney(name);\n return () => {\n if (opened) {\n moduleRuntime.excludeJourney(opened);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- name is the lifecycle key\n }, [name]);\n\n useEffect(() => {\n if (tags) {\n setJourneyTags(name, tags);\n }\n }, [name, tags]);\n\n useEffect(() => {\n moduleRuntime.updateOpenJourney(def);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- field-level live updates; name-change is the other effect\n }, [\n name,\n timeoutMs,\n stepTimeoutMs,\n slowRequestMs,\n endpointKey,\n expectedKey,\n service,\n team,\n group,\n maxSteps,\n configTagsKey,\n ]);\n\n return <JourneyNameContext.Provider value={name}>{children}</JourneyNameContext.Provider>;\n}\n"],"names":["useEffect","setJourneyTags","moduleRuntime","JourneyNameContext","stableEndpointKey","stableExpectedKey","stableTagsKey","JourneyScope","tags","children","rest","def","config","name","timeoutMs","stepTimeoutMs","slowRequestMs","endpoints","expected","service","team","group","maxSteps","endpointKey","expectedKey","configTagsKey","startJourney","opened","getOpenJourney","excludeJourney","updateOpenJourney","Provider","value"],"mappings":";AAAA,SAASA,SAAS,QAAwB,QAAQ;AAElD,SAASC,cAAc,QAAyB,aAAa;AAC7D,SAASC,aAAa,QAAQ,qBAAqB;AAEnD,SAASC,kBAAkB,QAAQ,YAAY;AAC/C,SAASC,iBAAiB,EAAEC,iBAAiB,EAAEC,aAAa,QAAQ,uBAAuB;AAI3F;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,aAAa,EACzBC,IAAI,EACJC,QAAQ,EACR,GAAGC,MAIN;IACG,MAAMC,MAAkB,YAAYD,OAAOA,KAAKE,MAAM,GAAGF;IACzD,MAAM,EACFG,IAAI,EACJC,SAAS,EACTC,aAAa,EACbC,aAAa,EACbC,SAAS,EACTC,QAAQ,EACRC,OAAO,EACPC,IAAI,EACJC,KAAK,EACLC,QAAQ,EACX,GAAGX;IACJ,MAAMY,cAAcnB,kBAAkBa;IACtC,MAAMO,cAAcnB,kBAAkBa;IACtC,MAAMO,gBAAgBnB,cAAcK,IAAIH,IAAI;IAE5CR,UAAU;QACNE,cAAcwB,YAAY,CAACf;QAC3B,MAAMgB,SAASzB,cAAc0B,cAAc,CAACf;QAC5C,OAAO;YACH,IAAIc,QAAQ;gBACRzB,cAAc2B,cAAc,CAACF;YACjC;QACJ;IACA,oFAAoF;IACxF,GAAG;QAACd;KAAK;IAETb,UAAU;QACN,IAAIQ,MAAM;YACNP,eAAeY,MAAML;QACzB;IACJ,GAAG;QAACK;QAAML;KAAK;IAEfR,UAAU;QACNE,cAAc4B,iBAAiB,CAACnB;IAChC,oHAAoH;IACxH,GAAG;QACCE;QACAC;QACAC;QACAC;QACAO;QACAC;QACAL;QACAC;QACAC;QACAC;QACAG;KACH;IAED,qBAAO,KAACtB,mBAAmB4B,QAAQ;QAACC,OAAOnB;kBAAOJ;;AACtD"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EndpointPolicy } from '../../core/endpoint-policy';
|
|
2
|
+
import type { TagValue } from '../../core/types';
|
|
3
|
+
export declare function stableEndpointKey(endpoints?: readonly EndpointPolicy[]): string;
|
|
4
|
+
export declare function stableExpectedKey(expected?: readonly string[]): string;
|
|
5
|
+
export declare function stableTagsKey(tags?: Record<string, TagValue>): string;
|
|
6
|
+
//# sourceMappingURL=stable-config-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-config-keys.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/stable-config-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAU/E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtE;AAED,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,CAQrE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function stableEndpointKey(endpoints) {
|
|
2
|
+
if (!(endpoints === null || endpoints === void 0 ? void 0 : endpoints.length)) {
|
|
3
|
+
return '';
|
|
4
|
+
}
|
|
5
|
+
return endpoints.map((endpoint)=>{
|
|
6
|
+
var _endpoint_slowRequestMs;
|
|
7
|
+
return `${endpoint.match}\0${(_endpoint_slowRequestMs = endpoint.slowRequestMs) !== null && _endpoint_slowRequestMs !== void 0 ? _endpoint_slowRequestMs : ''}\0${endpoint.ignore === true}`;
|
|
8
|
+
}).join('\n');
|
|
9
|
+
}
|
|
10
|
+
export function stableExpectedKey(expected) {
|
|
11
|
+
var _ref;
|
|
12
|
+
return (_ref = expected === null || expected === void 0 ? void 0 : expected.join('\0')) !== null && _ref !== void 0 ? _ref : '';
|
|
13
|
+
}
|
|
14
|
+
export function stableTagsKey(tags) {
|
|
15
|
+
if (!tags) {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
return Object.keys(tags).sort().map((key)=>`${key}\0${String(tags[key])}`).join('\n');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=stable-config-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/react/stable-config-keys.ts"],"sourcesContent":["import type { EndpointPolicy } from '../../core/endpoint-policy';\nimport type { TagValue } from '../../core/types';\n\nexport function stableEndpointKey(endpoints?: readonly EndpointPolicy[]): string {\n if (!endpoints?.length) {\n return '';\n }\n return endpoints\n .map(\n endpoint =>\n `${endpoint.match}\\0${endpoint.slowRequestMs ?? ''}\\0${endpoint.ignore === true}`\n )\n .join('\\n');\n}\n\nexport function stableExpectedKey(expected?: readonly string[]): string {\n return expected?.join('\\0') ?? '';\n}\n\nexport function stableTagsKey(tags?: Record<string, TagValue>): string {\n if (!tags) {\n return '';\n }\n return Object.keys(tags)\n .sort()\n .map(key => `${key}\\0${String(tags[key])}`)\n .join('\\n');\n}\n"],"names":["stableEndpointKey","endpoints","length","map","endpoint","match","slowRequestMs","ignore","join","stableExpectedKey","expected","stableTagsKey","tags","Object","keys","sort","key","String"],"mappings":"AAGA,OAAO,SAASA,kBAAkBC,SAAqC;IACnE,IAAI,EAACA,sBAAAA,gCAAAA,UAAWC,MAAM,GAAE;QACpB,OAAO;IACX;IACA,OAAOD,UACFE,GAAG,CACAC,CAAAA;YAC0BA;eAAtB,GAAGA,SAASC,KAAK,CAAC,EAAE,GAAED,0BAAAA,SAASE,aAAa,cAAtBF,qCAAAA,0BAA0B,GAAG,EAAE,EAAEA,SAASG,MAAM,KAAK,MAAM;OAExFC,IAAI,CAAC;AACd;AAEA,OAAO,SAASC,kBAAkBC,QAA4B;;IAC1D,eAAOA,qBAAAA,+BAAAA,SAAUF,IAAI,CAAC,4CAAS;AACnC;AAEA,OAAO,SAASG,cAAcC,IAA+B;IACzD,IAAI,CAACA,MAAM;QACP,OAAO;IACX;IACA,OAAOC,OAAOC,IAAI,CAACF,MACdG,IAAI,GACJZ,GAAG,CAACa,CAAAA,MAAO,GAAGA,IAAI,EAAE,EAAEC,OAAOL,IAAI,CAACI,IAAI,GAAG,EACzCR,IAAI,CAAC;AACd"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type JourneyHandle, type JourneyStepOptions, type StepHandle } from '../../core';
|
|
2
|
+
/**
|
|
3
|
+
* Run a step on the active `<JourneyScope>` journey, an explicit name, or a handle.
|
|
4
|
+
* A handle auto-starts when the journey is not open; a bare name does not.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const runStep = useJourneyStep();
|
|
8
|
+
* await runStep('load', async step => { await api.get('/x', { stamp: step.stamp() }); });
|
|
9
|
+
*/
|
|
10
|
+
export declare function useJourneyStep(journey?: string | JourneyHandle | null): <T>(stepName: string, fn: (step: StepHandle) => T | Promise<T>, opts?: JourneyStepOptions) => Promise<T>;
|
|
11
|
+
//# sourceMappingURL=use-journey-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-journey-step.d.ts","sourceRoot":"","sources":["../../../src/integrations/react/use-journey-step.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AAGpB;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,IAK7D,CAAC,YACY,MAAM,MACZ,CAAC,IAAI,EAAE,UAAU,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,SACjC,kBAAkB,KAC1B,OAAO,CAAC,CAAC,CAAC,CAGpB"}
|