@servicetitan/journey 2.0.0 → 2.1.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/dist/__test-utils__/test-runtime.d.ts.map +1 -0
- package/dist/__test-utils__/test-runtime.js +47 -0
- package/dist/__test-utils__/test-runtime.js.map +1 -0
- package/dist/__tests__/core/ambient.test.d.ts.map +1 -0
- package/dist/__tests__/core/api.test.d.ts +2 -0
- package/dist/__tests__/core/api.test.d.ts.map +1 -0
- package/dist/__tests__/core/define-journey.test.d.ts.map +1 -0
- package/dist/__tests__/core/requests.test.d.ts.map +1 -0
- package/dist/__tests__/core/runtime.test.d.ts.map +1 -0
- package/dist/__tests__/core/step.test.d.ts.map +1 -0
- package/dist/__tests__/core/timeouts.test.d.ts.map +1 -0
- package/dist/__tests__/global.test.d.ts +3 -0
- package/dist/__tests__/global.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/axios.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/context.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/expose-app-journey.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/fetch.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/jquery.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/request-key.test.d.ts.map +1 -0
- package/dist/__tests__/integrations/scope.test.d.ts.map +1 -0
- package/dist/__tests__/sinks/console.test.d.ts +2 -0
- package/dist/__tests__/sinks/console.test.d.ts.map +1 -0
- package/dist/__tests__/sinks/datadog.test.d.ts.map +1 -0
- package/dist/__tests__/sinks/sinks.test.d.ts.map +1 -0
- package/dist/config.d.ts +8 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -13
- package/dist/config.js.map +1 -1
- package/dist/core/{registry.d.ts → api.d.ts} +2 -22
- package/dist/core/api.d.ts.map +1 -0
- package/dist/core/{registry.js → api.js} +13 -40
- package/dist/core/api.js.map +1 -0
- package/dist/core/endpoint-policy.d.ts.map +1 -0
- package/dist/core/endpoint-policy.js.map +1 -0
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/runtime.d.ts +35 -7
- package/dist/core/runtime.d.ts.map +1 -1
- package/dist/core/runtime.js +39 -5
- package/dist/core/runtime.js.map +1 -1
- package/dist/core/step-tag.d.ts +6 -0
- package/dist/core/step-tag.d.ts.map +1 -1
- package/dist/core/step-tag.js +7 -0
- package/dist/core/step-tag.js.map +1 -1
- package/dist/core/types.d.ts +3 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/global.d.ts +67 -0
- package/dist/global.d.ts.map +1 -0
- package/dist/global.js +116 -0
- package/dist/global.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.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.map +1 -1
- package/dist/integrations/jquery/index.d.ts +2 -2
- package/dist/integrations/jquery/index.d.ts.map +1 -1
- package/dist/integrations/jquery/index.js +3 -2
- package/dist/integrations/jquery/index.js.map +1 -1
- package/dist/integrations/react/scope.d.ts.map +1 -1
- package/dist/integrations/react/scope.js +3 -2
- package/dist/integrations/react/scope.js.map +1 -1
- package/dist/sinks/console.d.ts +11 -0
- package/dist/sinks/console.d.ts.map +1 -0
- package/dist/sinks/console.js +18 -0
- package/dist/sinks/console.js.map +1 -0
- package/dist/sinks/datadog.d.ts +12 -1
- package/dist/sinks/datadog.d.ts.map +1 -1
- package/dist/sinks/datadog.js +28 -7
- package/dist/sinks/datadog.js.map +1 -1
- package/package.json +2 -2
- package/src/{__mocks__ → __test-utils__}/test-runtime.ts +6 -2
- package/src/__tests__/config.test.ts +9 -12
- package/src/__tests__/{ambient.test.ts → core/ambient.test.ts} +8 -7
- package/src/__tests__/{registry.test.ts → core/api.test.ts} +30 -25
- package/src/__tests__/{define-journey.test.ts → core/define-journey.test.ts} +5 -4
- package/src/__tests__/{requests.test.ts → core/requests.test.ts} +12 -8
- package/src/__tests__/{runtime.test.ts → core/runtime.test.ts} +18 -18
- package/src/__tests__/{step.test.ts → core/step.test.ts} +16 -18
- package/src/__tests__/{timeouts.test.ts → core/timeouts.test.ts} +15 -10
- package/src/__tests__/global.test.ts +113 -0
- package/src/__tests__/{axios.test.ts → integrations/axios.test.ts} +46 -15
- package/src/__tests__/{context.test.tsx → integrations/context.test.tsx} +1 -1
- package/src/__tests__/{expose-app-journey.test.ts → integrations/expose-app-journey.test.ts} +2 -2
- package/src/__tests__/{fetch.test.ts → integrations/fetch.test.ts} +6 -6
- package/src/__tests__/{jquery.test.ts → integrations/jquery.test.ts} +49 -12
- package/src/__tests__/{request-key.test.ts → integrations/request-key.test.ts} +1 -1
- package/src/__tests__/{scope.test.tsx → integrations/scope.test.tsx} +4 -4
- package/src/__tests__/sinks/console.test.ts +98 -0
- package/src/__tests__/{datadog.test.ts → sinks/datadog.test.ts} +62 -5
- package/src/__tests__/{sinks.test.ts → sinks/sinks.test.ts} +13 -12
- package/src/config.ts +20 -12
- package/src/core/{registry.ts → api.ts} +12 -65
- package/src/core/index.ts +5 -14
- package/src/core/runtime.ts +56 -7
- package/src/core/step-tag.ts +9 -0
- package/src/core/types.ts +3 -1
- package/src/global.ts +196 -0
- package/src/index.ts +20 -7
- package/src/integrations/fetch.ts +2 -2
- package/src/integrations/jquery/index.ts +4 -9
- package/src/integrations/react/scope.tsx +3 -2
- package/src/sinks/console.ts +20 -0
- package/src/sinks/datadog.ts +31 -6
- package/dist/__mocks__/test-runtime.d.ts.map +0 -1
- package/dist/__tests__/ambient.test.d.ts.map +0 -1
- package/dist/__tests__/axios.test.d.ts.map +0 -1
- package/dist/__tests__/context.test.d.ts.map +0 -1
- package/dist/__tests__/datadog.test.d.ts.map +0 -1
- package/dist/__tests__/define-journey.test.d.ts.map +0 -1
- package/dist/__tests__/expose-app-journey.test.d.ts.map +0 -1
- package/dist/__tests__/fetch.test.d.ts.map +0 -1
- package/dist/__tests__/jquery.test.d.ts.map +0 -1
- package/dist/__tests__/registry.test.d.ts +0 -2
- package/dist/__tests__/registry.test.d.ts.map +0 -1
- package/dist/__tests__/request-key.test.d.ts.map +0 -1
- package/dist/__tests__/requests.test.d.ts.map +0 -1
- package/dist/__tests__/runtime.test.d.ts.map +0 -1
- package/dist/__tests__/scope.test.d.ts.map +0 -1
- package/dist/__tests__/sinks.test.d.ts.map +0 -1
- package/dist/__tests__/step.test.d.ts.map +0 -1
- package/dist/__tests__/timeouts.test.d.ts.map +0 -1
- package/dist/core/registry.d.ts.map +0 -1
- package/dist/core/registry.js.map +0 -1
- package/dist/endpoint-policy.d.ts.map +0 -1
- package/dist/endpoint-policy.js.map +0 -1
- /package/dist/{__mocks__ → __test-utils__}/test-runtime.d.ts +0 -0
- /package/dist/__tests__/{ambient.test.d.ts → core/ambient.test.d.ts} +0 -0
- /package/dist/__tests__/{define-journey.test.d.ts → core/define-journey.test.d.ts} +0 -0
- /package/dist/__tests__/{requests.test.d.ts → core/requests.test.d.ts} +0 -0
- /package/dist/__tests__/{runtime.test.d.ts → core/runtime.test.d.ts} +0 -0
- /package/dist/__tests__/{step.test.d.ts → core/step.test.d.ts} +0 -0
- /package/dist/__tests__/{timeouts.test.d.ts → core/timeouts.test.d.ts} +0 -0
- /package/dist/__tests__/{axios.test.d.ts → integrations/axios.test.d.ts} +0 -0
- /package/dist/__tests__/{context.test.d.ts → integrations/context.test.d.ts} +0 -0
- /package/dist/__tests__/{expose-app-journey.test.d.ts → integrations/expose-app-journey.test.d.ts} +0 -0
- /package/dist/__tests__/{fetch.test.d.ts → integrations/fetch.test.d.ts} +0 -0
- /package/dist/__tests__/{jquery.test.d.ts → integrations/jquery.test.d.ts} +0 -0
- /package/dist/__tests__/{request-key.test.d.ts → integrations/request-key.test.d.ts} +0 -0
- /package/dist/__tests__/{scope.test.d.ts → integrations/scope.test.d.ts} +0 -0
- /package/dist/__tests__/{datadog.test.d.ts → sinks/datadog.test.d.ts} +0 -0
- /package/dist/__tests__/{sinks.test.d.ts → sinks/sinks.test.d.ts} +0 -0
- /package/dist/{endpoint-policy.d.ts → core/endpoint-policy.d.ts} +0 -0
- /package/dist/{endpoint-policy.js → core/endpoint-policy.js} +0 -0
- /package/src/{endpoint-policy.ts → core/endpoint-policy.ts} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/*\n * Force-evaluate config so the default Datadog sink registers even when consumers only\n * import core APIs (defineJourney, etc.). Paired with package.json \"sideEffects\" for\n * config — otherwise bundlers with sideEffects:false would drop an unused re-export.\n */\nimport './config';\n\nexport {\n //
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/*\n * Force-evaluate config so the default Datadog sink registers even when consumers only\n * import core APIs (defineJourney, etc.). Paired with package.json \"sideEffects\" for\n * config — otherwise bundlers with sideEffects:false would drop an unused re-export.\n */\nimport './config';\n\nexport {\n // Preferred app API.\n defineJourney,\n // Name-string lifecycle (prefer handle methods when you own the journey).\n completeJourney,\n excludeJourney,\n failJourney,\n journeyStep,\n setJourneyTags,\n // Custom transport adapters / request attribution.\n activeJourneyStep,\n reportBackendRequest,\n resolveJourneyStep,\n JourneyStepTag,\n type JourneyDef,\n type JourneyHandle,\n type JourneyNameLike,\n type JourneyStepOptions,\n type JourneyStepRef,\n type JourneyStepTarget,\n type StepHandle,\n} from './core';\n\nexport {\n configureJourney,\n type AppRequestTimeouts,\n type EndpointPolicy,\n type JourneyConfig,\n} from './config';\n\nexport type { JourneySink } from './core';\n\n/**\n * @internal Accidentally exported — removing it is a breaking change, so it stays\n * for compatibility. Not part of the supported public API. Test helper only.\n */\nexport { resetJourney } from './core';\n\nexport { instrumentAxios } from './integrations/axios';\nexport { instrumentFetch } from './integrations/fetch';\nexport { exposeAppJourney, instrumentJquery } from './integrations/jquery';\nexport { requestKey, type JourneyTimedMeta } from './integrations/request-key';\nexport {\n disableJourney,\n disableJourneyDebugging,\n enableJourney,\n enableJourneyDebugging,\n isJourneyDebugEnabled,\n isJourneyEnabled,\n} from './global';\nexport { sendToConsole } from './sinks/console';\nexport { normalizeTagValue, sendToDatadog, setJourneyRum } from './sinks/datadog';\n\nexport type { JourneyEvent, JourneyStepEvent, TagValue } from './core';\n\nexport { useJourneyName, useOptionalJourneyName } from './integrations/react/context';\nexport { JourneyScope } from './integrations/react/scope';\n"],"names":["defineJourney","completeJourney","excludeJourney","failJourney","journeyStep","setJourneyTags","activeJourneyStep","reportBackendRequest","resolveJourneyStep","JourneyStepTag","configureJourney","resetJourney","instrumentAxios","instrumentFetch","exposeAppJourney","instrumentJquery","requestKey","disableJourney","disableJourneyDebugging","enableJourney","enableJourneyDebugging","isJourneyDebugEnabled","isJourneyEnabled","sendToConsole","normalizeTagValue","sendToDatadog","setJourneyRum","useJourneyName","useOptionalJourneyName","JourneyScope"],"mappings":"AAAA;;;;CAIC,GACD,OAAO,WAAW;AAElB,SACI,qBAAqB;AACrBA,aAAa,EACb,0EAA0E;AAC1EC,eAAe,EACfC,cAAc,EACdC,WAAW,EACXC,WAAW,EACXC,cAAc,EACd,mDAAmD;AACnDC,iBAAiB,EACjBC,oBAAoB,EACpBC,kBAAkB,EAClBC,cAAc,QAQX,SAAS;AAEhB,SACIC,gBAAgB,QAIb,WAAW;AAIlB;;;CAGC,GACD,SAASC,YAAY,QAAQ,SAAS;AAEtC,SAASC,eAAe,QAAQ,uBAAuB;AACvD,SAASC,eAAe,QAAQ,uBAAuB;AACvD,SAASC,gBAAgB,EAAEC,gBAAgB,QAAQ,wBAAwB;AAC3E,SAASC,UAAU,QAA+B,6BAA6B;AAC/E,SACIC,cAAc,EACdC,uBAAuB,EACvBC,aAAa,EACbC,sBAAsB,EACtBC,qBAAqB,EACrBC,gBAAgB,QACb,WAAW;AAClB,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,iBAAiB,EAAEC,aAAa,EAAEC,aAAa,QAAQ,kBAAkB;AAIlF,SAASC,cAAc,EAAEC,sBAAsB,QAAQ,+BAA+B;AACtF,SAASC,YAAY,QAAQ,6BAA6B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Minimal structural fetch shape. */
|
|
2
|
-
|
|
2
|
+
type FetchLike = (input: any, init?: any) => Promise<{
|
|
3
3
|
status: number;
|
|
4
4
|
}>;
|
|
5
5
|
/** Holder of a `fetch` property — globalThis by default, or a scoped object. */
|
|
6
|
-
|
|
6
|
+
interface FetchTarget {
|
|
7
7
|
fetch: FetchLike;
|
|
8
8
|
}
|
|
9
9
|
export interface InstrumentFetchOptions {
|
|
@@ -18,4 +18,5 @@ export interface InstrumentFetchOptions {
|
|
|
18
18
|
* function that puts the original fetch back. Observation-only.
|
|
19
19
|
*/
|
|
20
20
|
export declare function instrumentFetch(options?: InstrumentFetchOptions): () => void;
|
|
21
|
+
export {};
|
|
21
22
|
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/integrations/fetch.ts"],"names":[],"mappings":"AAGA,sCAAsC;AACtC,
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/integrations/fetch.ts"],"names":[],"mappings":"AAGA,sCAAsC;AACtC,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEzE,gFAAgF;AAChF,UAAU,WAAW;IACjB,KAAK,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACnC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,IAAI,CAyDhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/integrations/fetch.ts"],"sourcesContent":["import { activeJourneyStep, reportBackendRequest, resolveJourneyStep } from '../core';\nimport { requestKey, type JourneyTimedMeta } from './request-key';\n\n/** Minimal structural fetch shape. */\
|
|
1
|
+
{"version":3,"sources":["../../src/integrations/fetch.ts"],"sourcesContent":["import { activeJourneyStep, reportBackendRequest, resolveJourneyStep } from '../core';\nimport { requestKey, type JourneyTimedMeta } from './request-key';\n\n/** Minimal structural fetch shape. */\ntype FetchLike = (input: any, init?: any) => Promise<{ status: number }>;\n\n/** Holder of a `fetch` property — globalThis by default, or a scoped object. */\ninterface FetchTarget {\n fetch: FetchLike;\n}\n\nexport interface InstrumentFetchOptions {\n /** Object whose `fetch` is wrapped. Defaults to globalThis. */\n target?: FetchTarget;\n /** Home API base URL for request-key origin resolution. */\n baseURL?: string;\n}\n\nconst instrumented = new WeakSet<object>();\nconst originals = new WeakMap<object, FetchLike>();\n\nfunction resolveUrl(input: any): string | undefined {\n if (typeof input === 'string') {\n return input;\n }\n if (input && typeof input.url === 'string') {\n return input.url;\n }\n if (input && typeof input.href === 'string') {\n return input.href;\n }\n return undefined;\n}\n\n/**\n * Wrap a target's fetch so requests inside a journeyStep are attributed and timed.\n * Call once per target (idempotent — second call is a no-op). Returns a restore\n * function that puts the original fetch back. Observation-only.\n */\nexport function instrumentFetch(options: InstrumentFetchOptions = {}): () => void {\n const target = options.target ?? (globalThis as unknown as FetchTarget);\n const key = target as object;\n\n if (instrumented.has(key)) {\n return () => {};\n }\n\n const original = target.fetch;\n originals.set(key, original);\n instrumented.add(key);\n\n // Call through `target` — native fetch throws \"Illegal invocation\" with the wrong receiver.\n const wrapped: FetchLike = (input, init) => {\n // Prefer explicit step.tag(); else soft ambient.\n const explicit = resolveJourneyStep((init as JourneyTimedMeta | undefined)?.journeyStep);\n const step = explicit ?? activeJourneyStep();\n if (!step) {\n return original.call(target, input, init);\n }\n\n const start = globalThis.performance.now();\n const endpointKey = requestKey(resolveUrl(input), undefined, options.baseURL);\n const promise = original.call(target, input, init);\n return promise.then(\n response => {\n reportBackendRequest(\n step,\n response.status,\n globalThis.performance.now() - start,\n endpointKey\n );\n return response;\n },\n (error: unknown) => {\n reportBackendRequest(\n step,\n undefined,\n globalThis.performance.now() - start,\n endpointKey\n );\n // Passthrough original rejection reason; do not wrap (identity / AbortError).\n return Promise.reject(error as Error);\n }\n );\n };\n\n target.fetch = wrapped;\n\n return () => {\n if (!instrumented.has(key)) {\n return;\n }\n target.fetch = originals.get(key) ?? original;\n instrumented.delete(key);\n originals.delete(key);\n };\n}\n"],"names":["activeJourneyStep","reportBackendRequest","resolveJourneyStep","requestKey","instrumented","WeakSet","originals","WeakMap","resolveUrl","input","url","href","undefined","instrumentFetch","options","target","globalThis","key","has","original","fetch","set","add","wrapped","init","explicit","journeyStep","step","call","start","performance","now","endpointKey","baseURL","promise","then","response","status","error","Promise","reject","get","delete"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,oBAAoB,EAAEC,kBAAkB,QAAQ,UAAU;AACtF,SAASC,UAAU,QAA+B,gBAAgB;AAiBlE,MAAMC,eAAe,IAAIC;AACzB,MAAMC,YAAY,IAAIC;AAEtB,SAASC,WAAWC,KAAU;IAC1B,IAAI,OAAOA,UAAU,UAAU;QAC3B,OAAOA;IACX;IACA,IAAIA,SAAS,OAAOA,MAAMC,GAAG,KAAK,UAAU;QACxC,OAAOD,MAAMC,GAAG;IACpB;IACA,IAAID,SAAS,OAAOA,MAAME,IAAI,KAAK,UAAU;QACzC,OAAOF,MAAME,IAAI;IACrB;IACA,OAAOC;AACX;AAEA;;;;CAIC,GACD,OAAO,SAASC,gBAAgBC,UAAkC,CAAC,CAAC;QACjDA;IAAf,MAAMC,UAASD,kBAAAA,QAAQC,MAAM,cAAdD,6BAAAA,kBAAmBE;IAClC,MAAMC,MAAMF;IAEZ,IAAIX,aAAac,GAAG,CAACD,MAAM;QACvB,OAAO,KAAO;IAClB;IAEA,MAAME,WAAWJ,OAAOK,KAAK;IAC7Bd,UAAUe,GAAG,CAACJ,KAAKE;IACnBf,aAAakB,GAAG,CAACL;IAEjB,4FAA4F;IAC5F,MAAMM,UAAqB,CAACd,OAAOe;QAC/B,iDAAiD;QACjD,MAAMC,WAAWvB,mBAAoBsB,iBAAAA,2BAAD,AAACA,KAAuCE,WAAW;QACvF,MAAMC,OAAOF,qBAAAA,sBAAAA,WAAYzB;QACzB,IAAI,CAAC2B,MAAM;YACP,OAAOR,SAASS,IAAI,CAACb,QAAQN,OAAOe;QACxC;QAEA,MAAMK,QAAQb,WAAWc,WAAW,CAACC,GAAG;QACxC,MAAMC,cAAc7B,WAAWK,WAAWC,QAAQG,WAAWE,QAAQmB,OAAO;QAC5E,MAAMC,UAAUf,SAASS,IAAI,CAACb,QAAQN,OAAOe;QAC7C,OAAOU,QAAQC,IAAI,CACfC,CAAAA;YACInC,qBACI0B,MACAS,SAASC,MAAM,EACfrB,WAAWc,WAAW,CAACC,GAAG,KAAKF,OAC/BG;YAEJ,OAAOI;QACX,GACA,CAACE;YACGrC,qBACI0B,MACAf,WACAI,WAAWc,WAAW,CAACC,GAAG,KAAKF,OAC/BG;YAEJ,8EAA8E;YAC9E,OAAOO,QAAQC,MAAM,CAACF;QAC1B;IAER;IAEAvB,OAAOK,KAAK,GAAGG;IAEf,OAAO;YAIYjB;QAHf,IAAI,CAACF,aAAac,GAAG,CAACD,MAAM;YACxB;QACJ;QACAF,OAAOK,KAAK,IAAGd,iBAAAA,UAAUmC,GAAG,CAACxB,kBAAdX,4BAAAA,iBAAsBa;QACrCf,aAAasC,MAAM,CAACzB;QACpBX,UAAUoC,MAAM,CAACzB;IACrB;AACJ"}
|
|
@@ -3,7 +3,7 @@ import { type JourneyDef, type JourneyHandle, type JourneyStepOptions, type Jour
|
|
|
3
3
|
* Knockout / desktop-legacy bridge on `window.App.Journey`.
|
|
4
4
|
* Prefer `defineJourney` handles; `journeyStep` / `firstOpenJourney` cover multi-journey steps.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
interface AppJourneyApi {
|
|
7
7
|
defineJourney(def: JourneyDef): JourneyHandle;
|
|
8
8
|
journeyStep<T>(journey: JourneyStepTarget, stepName: string, fn: (step: StepHandle) => T | Promise<T>, opts?: JourneyStepOptions): Promise<T>;
|
|
9
9
|
firstOpenJourney(names: readonly string[]): string | null;
|
|
@@ -18,5 +18,5 @@ export type WindowWithAppJourney = Window & {
|
|
|
18
18
|
* Optional `target` is for tests.
|
|
19
19
|
*/
|
|
20
20
|
export declare function exposeAppJourney(target?: WindowWithAppJourney): AppJourneyApi;
|
|
21
|
-
export { instrumentJquery, type
|
|
21
|
+
export { instrumentJquery, type JqueryStatic } from './instrument';
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/jquery/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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;;;GAGG;AACH,UAAU,aAAa;IACnB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,aAAa,CAAC;IAC9C,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,gBAAgB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC;CAC7D;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;AAKF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,oBAA6B,GAAG,aAAa,CAiBrF;AAED,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineJourney,
|
|
1
|
+
import { defineJourney, journeyStep } from '../../core';
|
|
2
|
+
import { moduleRuntime } from '../../core/runtime';
|
|
2
3
|
let journeyExposed = false;
|
|
3
4
|
let windowJourneyApi;
|
|
4
5
|
/**
|
|
@@ -12,7 +13,7 @@ let windowJourneyApi;
|
|
|
12
13
|
const api = {
|
|
13
14
|
defineJourney,
|
|
14
15
|
journeyStep,
|
|
15
|
-
firstOpenJourney
|
|
16
|
+
firstOpenJourney: (names)=>moduleRuntime.firstOpenJourney(names)
|
|
16
17
|
};
|
|
17
18
|
target.App = (_target_App = target.App) !== null && _target_App !== void 0 ? _target_App : {};
|
|
18
19
|
target.App.Journey = api;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/jquery/index.ts"],"sourcesContent":["import {\n defineJourney,\n
|
|
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` / `firstOpenJourney` cover multi-journey steps.\n */\ninterface AppJourneyApi {\n defineJourney(def: 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 firstOpenJourney(names: readonly string[]): string | null;\n}\n\nexport type WindowWithAppJourney = Window & {\n App?: { Journey?: AppJourneyApi } & Record<string, unknown>;\n};\n\nlet journeyExposed = false;\nlet windowJourneyApi: AppJourneyApi | undefined;\n\n/**\n * Publish the Knockout bridge on window.App.Journey. Idempotent for the real window.\n * Optional `target` is for tests.\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 firstOpenJourney: names => moduleRuntime.firstOpenJourney(names),\n };\n target.App = target.App ?? {};\n target.App.Journey = api;\n if (target === window) {\n journeyExposed = true;\n windowJourneyApi = api;\n }\n return api;\n}\n\nexport { instrumentJquery, type JqueryStatic } from './instrument';\n"],"names":["defineJourney","journeyStep","moduleRuntime","journeyExposed","windowJourneyApi","exposeAppJourney","target","window","api","firstOpenJourney","names","App","Journey","instrumentJquery"],"mappings":"AAAA,SACIA,aAAa,EACbC,WAAW,QAMR,aAAa;AACpB,SAASC,aAAa,QAAQ,qBAAqB;AAqBnD,IAAIC,iBAAiB;AACrB,IAAIC;AAEJ;;;CAGC,GACD,OAAO,SAASC,iBAAiBC,SAA+BC,MAAM;QAUrDD;IATb,IAAIH,kBAAkBG,WAAWC,UAAUH,kBAAkB;QACzD,OAAOA;IACX;IAEA,MAAMI,MAAqB;QACvBR;QACAC;QACAQ,kBAAkBC,CAAAA,QAASR,cAAcO,gBAAgB,CAACC;IAC9D;IACAJ,OAAOK,GAAG,IAAGL,cAAAA,OAAOK,GAAG,cAAVL,yBAAAA,cAAc,CAAC;IAC5BA,OAAOK,GAAG,CAACC,OAAO,GAAGJ;IACrB,IAAIF,WAAWC,QAAQ;QACnBJ,iBAAiB;QACjBC,mBAAmBI;IACvB;IACA,OAAOA;AACX;AAEA,SAASK,gBAAgB,QAA2B,eAAe"}
|
|
@@ -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,EAAkC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGjD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,GAAG,GAAG,EACT,EAAE,UAAU,GAAG;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,QAAQ,EAAE,SAAS,CAAC;CACvB,2CAaA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import { excludeJourney, setJourneyTags
|
|
3
|
+
import { excludeJourney, setJourneyTags } from '../../core';
|
|
4
|
+
import { moduleRuntime } from '../../core/runtime';
|
|
4
5
|
import { JourneyNameContext } from './context';
|
|
5
6
|
/**
|
|
6
7
|
* Opens a journey while the subtree is mounted; Excludes on unmount.
|
|
@@ -9,7 +10,7 @@ import { JourneyNameContext } from './context';
|
|
|
9
10
|
*/ export function JourneyScope({ tags, children, ...def }) {
|
|
10
11
|
const { name } = def;
|
|
11
12
|
useEffect(()=>{
|
|
12
|
-
startJourney(def);
|
|
13
|
+
moduleRuntime.startJourney(def);
|
|
13
14
|
if (tags) {
|
|
14
15
|
setJourneyTags(name, tags);
|
|
15
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/integrations/react/scope.tsx"],"sourcesContent":["import { useEffect, type ReactNode } from 'react';\n\nimport { excludeJourney, setJourneyTags,
|
|
1
|
+
{"version":3,"sources":["../../../src/integrations/react/scope.tsx"],"sourcesContent":["import { useEffect, type ReactNode } from 'react';\n\nimport { excludeJourney, setJourneyTags, type JourneyDef } from '../../core';\nimport { moduleRuntime } from '../../core/runtime';\nimport type { TagValue } from '../../core/types';\nimport { JourneyNameContext } from './context';\n\n/**\n * Opens a journey while the subtree is mounted; Excludes on unmount.\n * Config (timeouts, endpoints, tags, …) is captured when the journey opens;\n * only a `name` change re-opens.\n */\nexport function JourneyScope({\n tags,\n children,\n ...def\n}: JourneyDef & {\n tags?: Record<string, TagValue>;\n children: ReactNode;\n}) {\n const { name } = def;\n\n useEffect(() => {\n moduleRuntime.startJourney(def);\n if (tags) {\n setJourneyTags(name, tags);\n }\n return () => excludeJourney(name);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- freeze-on-mount; name is the lifecycle key\n }, [name]);\n\n return <JourneyNameContext.Provider value={name}>{children}</JourneyNameContext.Provider>;\n}\n"],"names":["useEffect","excludeJourney","setJourneyTags","moduleRuntime","JourneyNameContext","JourneyScope","tags","children","def","name","startJourney","Provider","value"],"mappings":";AAAA,SAASA,SAAS,QAAwB,QAAQ;AAElD,SAASC,cAAc,EAAEC,cAAc,QAAyB,aAAa;AAC7E,SAASC,aAAa,QAAQ,qBAAqB;AAEnD,SAASC,kBAAkB,QAAQ,YAAY;AAE/C;;;;CAIC,GACD,OAAO,SAASC,aAAa,EACzBC,IAAI,EACJC,QAAQ,EACR,GAAGC,KAIN;IACG,MAAM,EAAEC,IAAI,EAAE,GAAGD;IAEjBR,UAAU;QACNG,cAAcO,YAAY,CAACF;QAC3B,IAAIF,MAAM;YACNJ,eAAeO,MAAMH;QACzB;QACA,OAAO,IAAML,eAAeQ;IAC5B,qGAAqG;IACzG,GAAG;QAACA;KAAK;IAET,qBAAO,KAACL,mBAAmBO,QAAQ;QAACC,OAAOH;kBAAOF;;AACtD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JourneyEvent } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* Log a terminal journey to the browser console when debugging is enabled.
|
|
4
|
+
* No-op unless `__stJourney.enableDebugging()` / `enableJourneyDebugging()` was used
|
|
5
|
+
* (reload after enabling from DevTools).
|
|
6
|
+
*
|
|
7
|
+
* There is no reliable cross-browser API to detect an open DevTools console;
|
|
8
|
+
* use the explicit debug flag instead.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sendToConsole(event: JourneyEvent): void;
|
|
11
|
+
//# sourceMappingURL=console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/sinks/console.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAQvD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isJourneyDebugEnabled } from '../global';
|
|
2
|
+
/**
|
|
3
|
+
* Log a terminal journey to the browser console when debugging is enabled.
|
|
4
|
+
* No-op unless `__stJourney.enableDebugging()` / `enableJourneyDebugging()` was used
|
|
5
|
+
* (reload after enabling from DevTools).
|
|
6
|
+
*
|
|
7
|
+
* There is no reliable cross-browser API to detect an open DevTools console;
|
|
8
|
+
* use the explicit debug flag instead.
|
|
9
|
+
*/ export function sendToConsole(event) {
|
|
10
|
+
if (!isJourneyDebugEnabled()) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const j = event.journey;
|
|
14
|
+
// eslint-disable-next-line no-console -- intentional debug sink
|
|
15
|
+
console.debug(`[journey] ${j.name} → ${j.outcome}`, j);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/sinks/console.ts"],"sourcesContent":["import { isJourneyDebugEnabled } from '../global';\nimport type { JourneyEvent } from '../core/types';\n\n/**\n * Log a terminal journey to the browser console when debugging is enabled.\n * No-op unless `__stJourney.enableDebugging()` / `enableJourneyDebugging()` was used\n * (reload after enabling from DevTools).\n *\n * There is no reliable cross-browser API to detect an open DevTools console;\n * use the explicit debug flag instead.\n */\nexport function sendToConsole(event: JourneyEvent): void {\n if (!isJourneyDebugEnabled()) {\n return;\n }\n\n const j = event.journey;\n // eslint-disable-next-line no-console -- intentional debug sink\n console.debug(`[journey] ${j.name} → ${j.outcome}`, j);\n}\n"],"names":["isJourneyDebugEnabled","sendToConsole","event","j","journey","console","debug","name","outcome"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,YAAY;AAGlD;;;;;;;CAOC,GACD,OAAO,SAASC,cAAcC,KAAmB;IAC7C,IAAI,CAACF,yBAAyB;QAC1B;IACJ;IAEA,MAAMG,IAAID,MAAME,OAAO;IACvB,gEAAgE;IAChEC,QAAQC,KAAK,CAAC,CAAC,UAAU,EAAEH,EAAEI,IAAI,CAAC,GAAG,EAAEJ,EAAEK,OAAO,EAAE,EAAEL;AACxD"}
|
package/dist/sinks/datadog.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { JourneyEvent } from '../core/types';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Publish a RUM instance for MFE bundles to share — **only needed if
|
|
4
|
+
* `globalThis.DD_RUM` is not set**.
|
|
5
|
+
*
|
|
6
|
+
* Prefer exposing the initialized instance as `globalThis.DD_RUM` (ST host:
|
|
7
|
+
* `datadogGuard`). `sendToDatadog` resolves `DD_RUM` first, then `__stJourney.rum`
|
|
8
|
+
* (this fallback), then the bundle's imported `datadogRum`.
|
|
9
|
+
*
|
|
10
|
+
* Calling `setJourneyRum` while `globalThis.DD_RUM` is already set logs a warning —
|
|
11
|
+
* the call is redundant because `sendToDatadog` prefers `DD_RUM`.
|
|
12
|
+
*/
|
|
3
13
|
export declare function setJourneyRum(rum: unknown): void;
|
|
14
|
+
export declare function normalizeTagValue(value: string): string;
|
|
4
15
|
/** Ship one terminal journey as a RUM custom action (`user_journey`). */
|
|
5
16
|
export declare function sendToDatadog(payload: JourneyEvent): void;
|
|
6
17
|
//# sourceMappingURL=datadog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datadog.d.ts","sourceRoot":"","sources":["../../src/sinks/datadog.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"datadog.d.ts","sourceRoot":"","sources":["../../src/sinks/datadog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,eAAe,CAAC;AAU9E;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAQhD;AAaD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOvD;AAwBD,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAkBzD"}
|
package/dist/sinks/datadog.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
import { datadogRum } from '@datadog/browser-rum';
|
|
2
|
+
import { getJourneyRumFallback, setJourneyRumFallback } from '../global';
|
|
2
3
|
const JOURNEY_ACTION = 'user_journey';
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
globalThis[
|
|
4
|
+
const DD_RUM_KEY = 'DD_RUM';
|
|
5
|
+
function getDdRum() {
|
|
6
|
+
return globalThis[DD_RUM_KEY];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Publish a RUM instance for MFE bundles to share — **only needed if
|
|
10
|
+
* `globalThis.DD_RUM` is not set**.
|
|
11
|
+
*
|
|
12
|
+
* Prefer exposing the initialized instance as `globalThis.DD_RUM` (ST host:
|
|
13
|
+
* `datadogGuard`). `sendToDatadog` resolves `DD_RUM` first, then `__stJourney.rum`
|
|
14
|
+
* (this fallback), then the bundle's imported `datadogRum`.
|
|
15
|
+
*
|
|
16
|
+
* Calling `setJourneyRum` while `globalThis.DD_RUM` is already set logs a warning —
|
|
17
|
+
* the call is redundant because `sendToDatadog` prefers `DD_RUM`.
|
|
18
|
+
*/ export function setJourneyRum(rum) {
|
|
19
|
+
if (getDdRum()) {
|
|
20
|
+
// eslint-disable-next-line no-console -- soft-deprecate redundant bridge use
|
|
21
|
+
console.warn('[journey] setJourneyRum() is unnecessary when globalThis.DD_RUM is set — sendToDatadog already prefers DD_RUM');
|
|
22
|
+
}
|
|
23
|
+
setJourneyRumFallback(rum);
|
|
6
24
|
}
|
|
7
25
|
function resolveRum() {
|
|
8
|
-
const
|
|
26
|
+
const ddRum = getDdRum();
|
|
27
|
+
if (ddRum) {
|
|
28
|
+
return ddRum;
|
|
29
|
+
}
|
|
30
|
+
const shared = getJourneyRumFallback();
|
|
9
31
|
return shared !== null && shared !== void 0 ? shared : datadogRum;
|
|
10
32
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function normalizeTagValue(value) {
|
|
33
|
+
/** Match Datadog metric-tag value rules so RUM attributes / globals join derived SLO tags. */ const MAX_TAG_VALUE_LEN = 200;
|
|
34
|
+
export function normalizeTagValue(value) {
|
|
14
35
|
return value.toLowerCase().replace(/[^a-z0-9_\-:./]/g, '_').replace(/_+/g, '_').slice(0, MAX_TAG_VALUE_LEN).replace(/_+$/, '');
|
|
15
36
|
}
|
|
16
37
|
function normalizeTags(tags) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/sinks/datadog.ts"],"sourcesContent":["import { datadogRum } from '@datadog/browser-rum';\n\nimport type { JourneyEvent, JourneyStepEvent, TagValue } from '../core/types';\n\nconst JOURNEY_ACTION = 'user_journey';\n\nconst
|
|
1
|
+
{"version":3,"sources":["../../src/sinks/datadog.ts"],"sourcesContent":["import { datadogRum } from '@datadog/browser-rum';\n\nimport { getJourneyRumFallback, setJourneyRumFallback } from '../global';\nimport type { JourneyEvent, JourneyStepEvent, TagValue } from '../core/types';\n\nconst JOURNEY_ACTION = 'user_journey';\n\nconst DD_RUM_KEY = 'DD_RUM';\n\nfunction getDdRum(): typeof datadogRum | undefined {\n return (globalThis as Record<string, unknown>)[DD_RUM_KEY] as typeof datadogRum | undefined;\n}\n\n/**\n * Publish a RUM instance for MFE bundles to share — **only needed if\n * `globalThis.DD_RUM` is not set**.\n *\n * Prefer exposing the initialized instance as `globalThis.DD_RUM` (ST host:\n * `datadogGuard`). `sendToDatadog` resolves `DD_RUM` first, then `__stJourney.rum`\n * (this fallback), then the bundle's imported `datadogRum`.\n *\n * Calling `setJourneyRum` while `globalThis.DD_RUM` is already set logs a warning —\n * the call is redundant because `sendToDatadog` prefers `DD_RUM`.\n */\nexport function setJourneyRum(rum: unknown): void {\n if (getDdRum()) {\n // eslint-disable-next-line no-console -- soft-deprecate redundant bridge use\n console.warn(\n '[journey] setJourneyRum() is unnecessary when globalThis.DD_RUM is set — sendToDatadog already prefers DD_RUM'\n );\n }\n setJourneyRumFallback(rum);\n}\n\nfunction resolveRum(): typeof datadogRum {\n const ddRum = getDdRum();\n if (ddRum) {\n return ddRum;\n }\n const shared = getJourneyRumFallback();\n return (shared as typeof datadogRum | undefined) ?? datadogRum;\n}\n\n/** Match Datadog metric-tag value rules so RUM attributes / globals join derived SLO tags. */\nconst MAX_TAG_VALUE_LEN = 200;\nexport function normalizeTagValue(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9_\\-:./]/g, '_')\n .replace(/_+/g, '_')\n .slice(0, MAX_TAG_VALUE_LEN)\n .replace(/_+$/, '');\n}\n\nfunction normalizeTags(tags: Record<string, TagValue>): Record<string, TagValue> {\n const out: Record<string, TagValue> = {};\n for (const [key, value] of Object.entries(tags)) {\n out[key] = typeof value === 'string' ? normalizeTagValue(value) : value;\n }\n return out;\n}\n\nfunction toDatadogStep(step: JourneyStepEvent) {\n /* eslint-disable @typescript-eslint/naming-convention -- Datadog RUM wire format (snake_case) */\n return {\n name: step.name,\n start_ms: step.startMs,\n duration_ms: step.durationMs,\n outcome: step.outcome,\n ...(step.reason ? { reason: step.reason } : {}),\n ...(step.httpStatus !== undefined ? { http_status: step.httpStatus } : {}),\n ...(step.attributes ? { attributes: step.attributes } : {}),\n };\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\n/** Ship one terminal journey as a RUM custom action (`user_journey`). */\nexport function sendToDatadog(payload: JourneyEvent): void {\n const j = payload.journey;\n /* eslint-disable @typescript-eslint/naming-convention -- Datadog RUM wire format (snake_case) */\n resolveRum().addAction(JOURNEY_ACTION, {\n journey: {\n name: normalizeTagValue(j.name),\n team: normalizeTagValue(j.team),\n group: normalizeTagValue(j.group),\n service: normalizeTagValue(j.service),\n outcome: j.outcome,\n ...(j.reason ? { reason: normalizeTagValue(j.reason) } : {}),\n duration_ms: j.durationMs,\n steps: j.steps.map(toDatadogStep),\n ...(j.expected ? { expected: j.expected } : {}),\n ...(j.tags ? { tags: normalizeTags(j.tags) } : {}),\n },\n });\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n"],"names":["datadogRum","getJourneyRumFallback","setJourneyRumFallback","JOURNEY_ACTION","DD_RUM_KEY","getDdRum","globalThis","setJourneyRum","rum","console","warn","resolveRum","ddRum","shared","MAX_TAG_VALUE_LEN","normalizeTagValue","value","toLowerCase","replace","slice","normalizeTags","tags","out","key","Object","entries","toDatadogStep","step","name","start_ms","startMs","duration_ms","durationMs","outcome","reason","httpStatus","undefined","http_status","attributes","sendToDatadog","payload","j","journey","addAction","team","group","service","steps","map","expected"],"mappings":"AAAA,SAASA,UAAU,QAAQ,uBAAuB;AAElD,SAASC,qBAAqB,EAAEC,qBAAqB,QAAQ,YAAY;AAGzE,MAAMC,iBAAiB;AAEvB,MAAMC,aAAa;AAEnB,SAASC;IACL,OAAO,AAACC,UAAsC,CAACF,WAAW;AAC9D;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASG,cAAcC,GAAY;IACtC,IAAIH,YAAY;QACZ,6EAA6E;QAC7EI,QAAQC,IAAI,CACR;IAER;IACAR,sBAAsBM;AAC1B;AAEA,SAASG;IACL,MAAMC,QAAQP;IACd,IAAIO,OAAO;QACP,OAAOA;IACX;IACA,MAAMC,SAASZ;IACf,OAAQY,mBAAAA,oBAAAA,SAA4Cb;AACxD;AAEA,4FAA4F,GAC5F,MAAMc,oBAAoB;AAC1B,OAAO,SAASC,kBAAkBC,KAAa;IAC3C,OAAOA,MACFC,WAAW,GACXC,OAAO,CAAC,oBAAoB,KAC5BA,OAAO,CAAC,OAAO,KACfC,KAAK,CAAC,GAAGL,mBACTI,OAAO,CAAC,OAAO;AACxB;AAEA,SAASE,cAAcC,IAA8B;IACjD,MAAMC,MAAgC,CAAC;IACvC,KAAK,MAAM,CAACC,KAAKP,MAAM,IAAIQ,OAAOC,OAAO,CAACJ,MAAO;QAC7CC,GAAG,CAACC,IAAI,GAAG,OAAOP,UAAU,WAAWD,kBAAkBC,SAASA;IACtE;IACA,OAAOM;AACX;AAEA,SAASI,cAAcC,IAAsB;IACzC,+FAA+F,GAC/F,OAAO;QACHC,MAAMD,KAAKC,IAAI;QACfC,UAAUF,KAAKG,OAAO;QACtBC,aAAaJ,KAAKK,UAAU;QAC5BC,SAASN,KAAKM,OAAO;QACrB,GAAIN,KAAKO,MAAM,GAAG;YAAEA,QAAQP,KAAKO,MAAM;QAAC,IAAI,CAAC,CAAC;QAC9C,GAAIP,KAAKQ,UAAU,KAAKC,YAAY;YAAEC,aAAaV,KAAKQ,UAAU;QAAC,IAAI,CAAC,CAAC;QACzE,GAAIR,KAAKW,UAAU,GAAG;YAAEA,YAAYX,KAAKW,UAAU;QAAC,IAAI,CAAC,CAAC;IAC9D;AACA,sDAAsD,GAC1D;AAEA,uEAAuE,GACvE,OAAO,SAASC,cAAcC,OAAqB;IAC/C,MAAMC,IAAID,QAAQE,OAAO;IACzB,+FAA+F,GAC/F/B,aAAagC,SAAS,CAACxC,gBAAgB;QACnCuC,SAAS;YACLd,MAAMb,kBAAkB0B,EAAEb,IAAI;YAC9BgB,MAAM7B,kBAAkB0B,EAAEG,IAAI;YAC9BC,OAAO9B,kBAAkB0B,EAAEI,KAAK;YAChCC,SAAS/B,kBAAkB0B,EAAEK,OAAO;YACpCb,SAASQ,EAAER,OAAO;YAClB,GAAIQ,EAAEP,MAAM,GAAG;gBAAEA,QAAQnB,kBAAkB0B,EAAEP,MAAM;YAAE,IAAI,CAAC,CAAC;YAC3DH,aAAaU,EAAET,UAAU;YACzBe,OAAON,EAAEM,KAAK,CAACC,GAAG,CAACtB;YACnB,GAAIe,EAAEQ,QAAQ,GAAG;gBAAEA,UAAUR,EAAEQ,QAAQ;YAAC,IAAI,CAAC,CAAC;YAC9C,GAAIR,EAAEpB,IAAI,GAAG;gBAAEA,MAAMD,cAAcqB,EAAEpB,IAAI;YAAE,IAAI,CAAC,CAAC;QACrD;IACJ;AACA,sDAAsD,GAC1D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/journey",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Critical user journey monitoring — reports good/bad/excluded verdicts to Datadog RUM as a custom action",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/journey",
|
|
6
6
|
"repository": {
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"cli": {
|
|
42
42
|
"webpack": false
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "f4f3b8308ccf1237e7671e3669e71af47d6b48af"
|
|
45
45
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { resetJourney } from '../core';
|
|
1
|
+
import { resetJourney } from '../core/runtime';
|
|
2
|
+
import { sendToConsole } from '../sinks/console';
|
|
2
3
|
import { sendToDatadog } from '../sinks/datadog';
|
|
3
4
|
|
|
5
|
+
/** Package default sinks installed by `config.ts` bootstrap. */
|
|
6
|
+
const DEFAULT_SINKS = [sendToDatadog, sendToConsole] as const;
|
|
7
|
+
|
|
4
8
|
/** Standard journey def used across engine suites. */
|
|
5
9
|
export const baseJourneyDef = {
|
|
6
10
|
name: 'journey-under-test',
|
|
@@ -30,7 +34,7 @@ export function useJourneyTestRuntime(emitMock: jest.Mock) {
|
|
|
30
34
|
|
|
31
35
|
afterEach(() => {
|
|
32
36
|
resetJourney({
|
|
33
|
-
sinks: [
|
|
37
|
+
sinks: [...DEFAULT_SINKS],
|
|
34
38
|
requestTimeouts: { defaultMs: 4_000, endpoints: [] },
|
|
35
39
|
});
|
|
36
40
|
});
|
|
@@ -16,15 +16,11 @@ jest.mock('../integrations/jquery', () => ({
|
|
|
16
16
|
exposeAppJourney: jest.fn(),
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
configureJourney,
|
|
21
|
-
getRequestTimeouts,
|
|
22
|
-
longestEndpointMatch,
|
|
23
|
-
sortEndpointsByLongestMatch,
|
|
24
|
-
} from '../config';
|
|
19
|
+
import { configureJourney, getRequestTimeouts } from '../config';
|
|
25
20
|
import { resetJourney } from '../core';
|
|
26
|
-
import {
|
|
21
|
+
import { moduleRuntime } from '../core/runtime';
|
|
27
22
|
import type { JourneyEvent } from '../core/types';
|
|
23
|
+
import { longestEndpointMatch, sortEndpointsByLongestMatch } from '../core/endpoint-policy';
|
|
28
24
|
import { instrumentAxios } from '../integrations/axios';
|
|
29
25
|
import { instrumentFetch } from '../integrations/fetch';
|
|
30
26
|
import {
|
|
@@ -32,6 +28,7 @@ import {
|
|
|
32
28
|
instrumentJquery,
|
|
33
29
|
type WindowWithAppJourney,
|
|
34
30
|
} from '../integrations/jquery';
|
|
31
|
+
import { sendToConsole } from '../sinks/console';
|
|
35
32
|
import { sendToDatadog } from '../sinks/datadog';
|
|
36
33
|
|
|
37
34
|
const instrumentAxiosMock = jest.mocked(instrumentAxios);
|
|
@@ -42,7 +39,7 @@ const exposeAppJourneyMock = jest.mocked(exposeAppJourney);
|
|
|
42
39
|
describe('[journey] configureJourney / getRequestTimeouts', () => {
|
|
43
40
|
afterEach(() => {
|
|
44
41
|
resetJourney({
|
|
45
|
-
sinks: [sendToDatadog],
|
|
42
|
+
sinks: [sendToDatadog, sendToConsole],
|
|
46
43
|
requestTimeouts: { defaultMs: 4_000, endpoints: [] },
|
|
47
44
|
});
|
|
48
45
|
instrumentAxiosMock.mockClear();
|
|
@@ -97,7 +94,7 @@ describe('[journey] configureJourney / getRequestTimeouts', () => {
|
|
|
97
94
|
|
|
98
95
|
test('replaces the sink list', () => {
|
|
99
96
|
configureJourney({ sinks: [custom] });
|
|
100
|
-
|
|
97
|
+
moduleRuntime.emit(payload);
|
|
101
98
|
|
|
102
99
|
expect(custom).toHaveBeenCalledWith(payload);
|
|
103
100
|
expect(sendToDatadog).not.toHaveBeenCalled();
|
|
@@ -106,7 +103,7 @@ describe('[journey] configureJourney / getRequestTimeouts', () => {
|
|
|
106
103
|
test('leaves sinks unchanged when sinks is omitted', () => {
|
|
107
104
|
configureJourney({ sinks: [custom] });
|
|
108
105
|
configureJourney({ requestTimeouts: { defaultMs: 2_000, endpoints: [] } });
|
|
109
|
-
|
|
106
|
+
moduleRuntime.emit(payload);
|
|
110
107
|
|
|
111
108
|
expect(custom).toHaveBeenCalledWith(payload);
|
|
112
109
|
expect(sendToDatadog).not.toHaveBeenCalled();
|
|
@@ -114,7 +111,7 @@ describe('[journey] configureJourney / getRequestTimeouts', () => {
|
|
|
114
111
|
|
|
115
112
|
test('disables emission when sinks is empty', () => {
|
|
116
113
|
configureJourney({ sinks: [] });
|
|
117
|
-
|
|
114
|
+
moduleRuntime.emit(payload);
|
|
118
115
|
|
|
119
116
|
expect(sendToDatadog).not.toHaveBeenCalled();
|
|
120
117
|
expect(custom).not.toHaveBeenCalled();
|
|
@@ -219,7 +216,7 @@ describe('longestEndpointMatch', () => {
|
|
|
219
216
|
describe('configureJourney endpoint ordering', () => {
|
|
220
217
|
afterEach(() => {
|
|
221
218
|
resetJourney({
|
|
222
|
-
sinks: [sendToDatadog],
|
|
219
|
+
sinks: [sendToDatadog, sendToConsole],
|
|
223
220
|
requestTimeouts: { defaultMs: 4_000, endpoints: [] },
|
|
224
221
|
});
|
|
225
222
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @jest-environment jsdom */
|
|
2
|
-
import { baseJourneyDef, useJourneyTestRuntime } from '
|
|
3
|
-
import { activeJourneyStep, completeJourney, journeyStep
|
|
2
|
+
import { baseJourneyDef, useJourneyTestRuntime } from '../../__test-utils__/test-runtime';
|
|
3
|
+
import { activeJourneyStep, completeJourney, journeyStep } from '../../core';
|
|
4
|
+
import { moduleRuntime } from '../../core/runtime';
|
|
4
5
|
|
|
5
6
|
const emitMock = jest.fn();
|
|
6
7
|
const baseDef = { ...baseJourneyDef, name: 'ambient-a' };
|
|
@@ -11,7 +12,7 @@ describe('[journey] activeJourneyStep', () => {
|
|
|
11
12
|
|
|
12
13
|
describe('around a single step', () => {
|
|
13
14
|
beforeEach(() => {
|
|
14
|
-
startJourney(baseDef);
|
|
15
|
+
moduleRuntime.startJourney(baseDef);
|
|
15
16
|
});
|
|
16
17
|
|
|
17
18
|
test('is set only while the step is running', async () => {
|
|
@@ -31,8 +32,8 @@ describe('[journey] activeJourneyStep', () => {
|
|
|
31
32
|
let stepA: Promise<unknown>;
|
|
32
33
|
|
|
33
34
|
beforeEach(() => {
|
|
34
|
-
startJourney(baseDef);
|
|
35
|
-
startJourney(otherDef);
|
|
35
|
+
moduleRuntime.startJourney(baseDef);
|
|
36
|
+
moduleRuntime.startJourney(otherDef);
|
|
36
37
|
|
|
37
38
|
const gateA = new Promise<void>(r => {
|
|
38
39
|
releaseA = r;
|
|
@@ -62,8 +63,8 @@ describe('[journey] activeJourneyStep', () => {
|
|
|
62
63
|
let ambientWhileBAlone: ReturnType<typeof activeJourneyStep> | 'unset';
|
|
63
64
|
|
|
64
65
|
beforeEach(() => {
|
|
65
|
-
startJourney(baseDef);
|
|
66
|
-
startJourney(otherDef);
|
|
66
|
+
moduleRuntime.startJourney(baseDef);
|
|
67
|
+
moduleRuntime.startJourney(otherDef);
|
|
67
68
|
ambientWhileBAlone = 'unset';
|
|
68
69
|
|
|
69
70
|
const gateB = new Promise<void>(r => {
|