@servicetitan/journey 3.0.0 → 4.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/dist/__tests__/core/persist.test.d.ts +2 -0
- package/dist/__tests__/core/persist.test.d.ts.map +1 -0
- package/dist/core/api.d.ts +13 -1
- package/dist/core/api.d.ts.map +1 -1
- package/dist/core/api.js +14 -0
- package/dist/core/api.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/persist.d.ts +19 -0
- package/dist/core/persist.d.ts.map +1 -0
- package/dist/core/persist.js +111 -0
- package/dist/core/persist.js.map +1 -0
- package/dist/core/runtime.d.ts +16 -1
- package/dist/core/runtime.d.ts.map +1 -1
- package/dist/core/runtime.js +56 -21
- package/dist/core/runtime.js.map +1 -1
- package/dist/core/types.d.ts +25 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.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 +4 -10
- package/dist/sinks/datadog.js.map +1 -1
- package/package.json +2 -4
- package/src/__tests__/core/persist.test.ts +496 -0
- package/src/__tests__/sinks/datadog.test.ts +2 -16
- package/src/core/api.ts +19 -0
- package/src/core/index.ts +3 -0
- package/src/core/persist.ts +131 -0
- package/src/core/runtime.ts +62 -2
- package/src/core/types.ts +26 -0
- package/src/index.ts +3 -0
- package/src/sinks/datadog.ts +14 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persist.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/core/persist.test.ts"],"names":[],"mappings":""}
|
package/dist/core/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JourneyStepStamp } from './step-tag';
|
|
2
|
-
import type { JourneyDef, JourneyHandle, JourneyStepOptions, JourneyStepTarget, StepHandle, StepRecord, TagValue } from './types';
|
|
2
|
+
import type { JourneyDef, JourneyHandle, JourneyStepOptions, JourneyStepTarget, SerializedJourneyState, StepHandle, StepRecord, TagValue } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Unique in-flight step as a stamp-ready {@link JourneyStepStamp}, or null when
|
|
5
5
|
* auto-attribute is disabled, or when 0 or 2+ steps are in flight app-wide.
|
|
@@ -40,4 +40,16 @@ export declare function completeJourney(name: string | null, tags?: Record<strin
|
|
|
40
40
|
export declare function excludeJourney(name: string): void;
|
|
41
41
|
/** Turn a journey config into a handle with bound lifecycle methods. Preferred public API. */
|
|
42
42
|
export declare function defineJourney(config: JourneyDef): JourneyHandle;
|
|
43
|
+
/**
|
|
44
|
+
* Snapshot an open journey for cross-page transfer (e.g. into a cookie). Does
|
|
45
|
+
* NOT close the journey. Returns `null` when no journey is open under `name`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function serializeJourneyState(name: string): SerializedJourneyState | null;
|
|
48
|
+
/**
|
|
49
|
+
* Rehydrate a serialized journey onto this runtime. Returns `true` when the
|
|
50
|
+
* journey is now open; `false` when it exhausted its budget in transit (a
|
|
51
|
+
* `bad` `journey-timeout` event is emitted) or when a journey under the
|
|
52
|
+
* same name is already open.
|
|
53
|
+
*/
|
|
54
|
+
export declare function restoreJourney(serialized: SerializedJourneyState, config: JourneyDef): boolean;
|
|
43
55
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/core/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/core/api.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EACR,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,QAAQ,EACX,MAAM,SAAS,CAAC;AAKjB;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,IAAI,gBAAgB,GAAG,IAAI,CAiBnE;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAK9D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAM7E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACnB,IAAI,CAKN;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAC/B,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,CAEZ;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAExF;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAK9D;AAED,yHAAyH;AACzH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAE1F;AAED,qHAAqH;AACrH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKjD;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAoC/D"}
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/core/api.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EACR,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,UAAU,EACV,QAAQ,EACX,MAAM,SAAS,CAAC;AAKjB;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,IAAI,gBAAgB,GAAG,IAAI,CAiBnE;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAK9D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAM7E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACnB,IAAI,CAKN;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAC/B,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,CAEZ;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAExF;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAK9D;AAED,yHAAyH;AACzH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAE1F;AAED,qHAAqH;AACrH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKjD;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAoC/D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,sBAAsB,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAE9F"}
|
package/dist/core/api.js
CHANGED
|
@@ -118,5 +118,19 @@ let ambientStep = null;
|
|
|
118
118
|
}
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Snapshot an open journey for cross-page transfer (e.g. into a cookie). Does
|
|
123
|
+
* NOT close the journey. Returns `null` when no journey is open under `name`.
|
|
124
|
+
*/ export function serializeJourneyState(name) {
|
|
125
|
+
return moduleRuntime.serializeJourneyState(name);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Rehydrate a serialized journey onto this runtime. Returns `true` when the
|
|
129
|
+
* journey is now open; `false` when it exhausted its budget in transit (a
|
|
130
|
+
* `bad` `journey-timeout` event is emitted) or when a journey under the
|
|
131
|
+
* same name is already open.
|
|
132
|
+
*/ export function restoreJourney(serialized, config) {
|
|
133
|
+
return moduleRuntime.restoreJourney(serialized, config) !== null;
|
|
134
|
+
}
|
|
121
135
|
|
|
122
136
|
//# sourceMappingURL=api.js.map
|
package/dist/core/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/api.ts"],"sourcesContent":["import { moduleRuntime, resolveJourneyEngine } from './runtime';\nimport { adoptJourneyStepStamp, JourneyStepStamp } from './step-tag';\nimport type {\n JourneyDef,\n JourneyHandle,\n JourneyStepOptions,\n JourneyStepTarget,\n StepHandle,\n StepRecord,\n TagValue,\n} from './types';\n\nlet ambientStamp: JourneyStepStamp | null = null;\nlet ambientStep: StepRecord | null = null;\n\n/**\n * Unique in-flight step as a stamp-ready {@link JourneyStepStamp}, or null when\n * auto-attribute is disabled, or when 0 or 2+ steps are in flight app-wide.\n * Ambient stamps never carry `score` or `ignore`. Untagged traffic is attributed\n * to that lone step even if unrelated — prefer `step.stamp()` when the page has\n * background instrumented requests. Disable via\n * `configureJourney({ autoAttributeRequests: false })`.\n */\nexport function singleInFlightJourneyStep(): JourneyStepStamp | null {\n if (ambientStep?.journey.closed) {\n ambientStep = null;\n ambientStamp = null;\n }\n const activeStep = moduleRuntime.activeJourneyStep();\n if (!activeStep) {\n ambientStamp = null;\n ambientStep = null;\n return null;\n }\n if (ambientStep === activeStep && ambientStamp) {\n return ambientStamp;\n }\n ambientStep = activeStep;\n ambientStamp = new JourneyStepStamp(activeStep);\n return ambientStamp;\n}\n\n/** @internal Clear cached ambient stamp when runtime state changes. */\nexport function invalidateAmbientStamp(step?: StepRecord): void {\n if (!step || step === ambientStep) {\n ambientStamp = null;\n ambientStep = null;\n }\n}\n\n/**\n * Prefer an explicit `step.stamp()` value; else the ambient in-flight stamp.\n * Same-realm stamps are returned as-is (identity + score + ignore). Branded\n * foreign copies are adopted into a local stamp. Raw StepRecords are not stamps.\n */\nexport function resolveStamp(explicit?: unknown): JourneyStepStamp | undefined {\n const fromExplicit = adoptJourneyStepStamp(explicit);\n if (fromExplicit) {\n return fromExplicit;\n }\n return singleInFlightJourneyStep() ?? undefined;\n}\n\n/**\n * Record a finished backend request against a captured step.\n * 5xx / network / slow (over threshold) mark Bad; 4xx is not counted. Fail-fast on breach.\n * @internal Prefer {@link onHttpComplete} from adapters.\n */\nexport function reportBackendRequest(\n step: StepRecord | undefined,\n status: number | undefined,\n durationMs: number,\n requestKey: string\n): void {\n if (!step?.journey) {\n return;\n }\n resolveJourneyEngine(step.journey).reportBackendRequest(step, status, durationMs, requestKey);\n}\n\n/**\n * Run one step of a named journey. Runs untraced (noop handle) when no matching journey is open.\n * `journey` may be a name, null, an ordered candidate list, a def, or a handle.\n * A def or handle auto-starts when that journey is not already open; a bare name does not.\n * Prefer `defineJourney(...).step` when you own the journey config.\n */\nexport async function journeyStep<T>(\n journey: JourneyStepTarget,\n stepName: string,\n fn: (step: StepHandle) => T | Promise<T>,\n opts?: JourneyStepOptions\n): Promise<T> {\n return moduleRuntime.journeyStep(journey, stepName, fn, opts);\n}\n\n/** Merge custom tags onto an open journey. No-op if not open. Prefer `handle.setTags`. */\nexport function setJourneyTags(name: string | null, tags: Record<string, TagValue>): void {\n moduleRuntime.setJourneyTags(name, tags);\n}\n\n/** Mark a named journey Bad for a custom reason (fail-fast). Prefer `handle.fail`. */\nexport function failJourney(name: string, reason: string): void {\n const journey = moduleRuntime.getOpenJourney(name);\n if (journey) {\n moduleRuntime.failJourney(journey, reason);\n }\n}\n\n/** Successful end. Outcome stays Bad if a breach already occurred. No-op when name is null. Prefer `handle.complete`. */\nexport function completeJourney(name: string | null, tags?: Record<string, TagValue>): void {\n moduleRuntime.completeJourney(name, tags);\n}\n\n/** User left before finishing. Stays Bad if a breach already occurred (breach-anchored). Prefer `handle.exclude`. */\nexport function excludeJourney(name: string): void {\n const journey = moduleRuntime.getOpenJourney(name);\n if (journey) {\n moduleRuntime.excludeJourney(journey);\n }\n}\n\n/** Turn a journey config into a handle with bound lifecycle methods. Preferred public API. */\nexport function defineJourney(config: JourneyDef): JourneyHandle {\n return {\n config,\n start(tags) {\n moduleRuntime.startJourney(config);\n if (tags) {\n moduleRuntime.setJourneyTags(config.name, tags);\n }\n },\n step(stepName, fn, opts) {\n if (!moduleRuntime.getOpenJourney(config.name)) {\n moduleRuntime.startJourney(config);\n }\n return journeyStep(config.name, stepName, fn, opts);\n },\n async mountStep(stepName, fn, opts) {\n // Defer so a parent <JourneyScope> opens first (child effects run before parent).\n await Promise.resolve();\n if (!moduleRuntime.getOpenJourney(config.name)) {\n moduleRuntime.startJourney(config);\n }\n return journeyStep(config.name, stepName, fn, opts);\n },\n complete(tags) {\n completeJourney(config.name, tags);\n },\n fail(reason) {\n failJourney(config.name, reason);\n },\n exclude() {\n excludeJourney(config.name);\n },\n setTags(tags) {\n setJourneyTags(config.name, tags);\n },\n };\n}\n"],"names":["moduleRuntime","resolveJourneyEngine","adoptJourneyStepStamp","JourneyStepStamp","ambientStamp","ambientStep","singleInFlightJourneyStep","journey","closed","activeStep","activeJourneyStep","invalidateAmbientStamp","step","resolveStamp","explicit","fromExplicit","undefined","reportBackendRequest","status","durationMs","requestKey","journeyStep","stepName","fn","opts","setJourneyTags","name","tags","failJourney","reason","getOpenJourney","completeJourney","excludeJourney","defineJourney","config","start","startJourney","mountStep","Promise","resolve","complete","fail","exclude","setTags"],"mappings":"AAAA,SAASA,aAAa,EAAEC,oBAAoB,QAAQ,YAAY;AAChE,SAASC,qBAAqB,EAAEC,gBAAgB,QAAQ,aAAa;
|
|
1
|
+
{"version":3,"sources":["../../src/core/api.ts"],"sourcesContent":["import { moduleRuntime, resolveJourneyEngine } from './runtime';\nimport { adoptJourneyStepStamp, JourneyStepStamp } from './step-tag';\nimport type {\n JourneyDef,\n JourneyHandle,\n JourneyStepOptions,\n JourneyStepTarget,\n SerializedJourneyState,\n StepHandle,\n StepRecord,\n TagValue,\n} from './types';\n\nlet ambientStamp: JourneyStepStamp | null = null;\nlet ambientStep: StepRecord | null = null;\n\n/**\n * Unique in-flight step as a stamp-ready {@link JourneyStepStamp}, or null when\n * auto-attribute is disabled, or when 0 or 2+ steps are in flight app-wide.\n * Ambient stamps never carry `score` or `ignore`. Untagged traffic is attributed\n * to that lone step even if unrelated — prefer `step.stamp()` when the page has\n * background instrumented requests. Disable via\n * `configureJourney({ autoAttributeRequests: false })`.\n */\nexport function singleInFlightJourneyStep(): JourneyStepStamp | null {\n if (ambientStep?.journey.closed) {\n ambientStep = null;\n ambientStamp = null;\n }\n const activeStep = moduleRuntime.activeJourneyStep();\n if (!activeStep) {\n ambientStamp = null;\n ambientStep = null;\n return null;\n }\n if (ambientStep === activeStep && ambientStamp) {\n return ambientStamp;\n }\n ambientStep = activeStep;\n ambientStamp = new JourneyStepStamp(activeStep);\n return ambientStamp;\n}\n\n/** @internal Clear cached ambient stamp when runtime state changes. */\nexport function invalidateAmbientStamp(step?: StepRecord): void {\n if (!step || step === ambientStep) {\n ambientStamp = null;\n ambientStep = null;\n }\n}\n\n/**\n * Prefer an explicit `step.stamp()` value; else the ambient in-flight stamp.\n * Same-realm stamps are returned as-is (identity + score + ignore). Branded\n * foreign copies are adopted into a local stamp. Raw StepRecords are not stamps.\n */\nexport function resolveStamp(explicit?: unknown): JourneyStepStamp | undefined {\n const fromExplicit = adoptJourneyStepStamp(explicit);\n if (fromExplicit) {\n return fromExplicit;\n }\n return singleInFlightJourneyStep() ?? undefined;\n}\n\n/**\n * Record a finished backend request against a captured step.\n * 5xx / network / slow (over threshold) mark Bad; 4xx is not counted. Fail-fast on breach.\n * @internal Prefer {@link onHttpComplete} from adapters.\n */\nexport function reportBackendRequest(\n step: StepRecord | undefined,\n status: number | undefined,\n durationMs: number,\n requestKey: string\n): void {\n if (!step?.journey) {\n return;\n }\n resolveJourneyEngine(step.journey).reportBackendRequest(step, status, durationMs, requestKey);\n}\n\n/**\n * Run one step of a named journey. Runs untraced (noop handle) when no matching journey is open.\n * `journey` may be a name, null, an ordered candidate list, a def, or a handle.\n * A def or handle auto-starts when that journey is not already open; a bare name does not.\n * Prefer `defineJourney(...).step` when you own the journey config.\n */\nexport async function journeyStep<T>(\n journey: JourneyStepTarget,\n stepName: string,\n fn: (step: StepHandle) => T | Promise<T>,\n opts?: JourneyStepOptions\n): Promise<T> {\n return moduleRuntime.journeyStep(journey, stepName, fn, opts);\n}\n\n/** Merge custom tags onto an open journey. No-op if not open. Prefer `handle.setTags`. */\nexport function setJourneyTags(name: string | null, tags: Record<string, TagValue>): void {\n moduleRuntime.setJourneyTags(name, tags);\n}\n\n/** Mark a named journey Bad for a custom reason (fail-fast). Prefer `handle.fail`. */\nexport function failJourney(name: string, reason: string): void {\n const journey = moduleRuntime.getOpenJourney(name);\n if (journey) {\n moduleRuntime.failJourney(journey, reason);\n }\n}\n\n/** Successful end. Outcome stays Bad if a breach already occurred. No-op when name is null. Prefer `handle.complete`. */\nexport function completeJourney(name: string | null, tags?: Record<string, TagValue>): void {\n moduleRuntime.completeJourney(name, tags);\n}\n\n/** User left before finishing. Stays Bad if a breach already occurred (breach-anchored). Prefer `handle.exclude`. */\nexport function excludeJourney(name: string): void {\n const journey = moduleRuntime.getOpenJourney(name);\n if (journey) {\n moduleRuntime.excludeJourney(journey);\n }\n}\n\n/** Turn a journey config into a handle with bound lifecycle methods. Preferred public API. */\nexport function defineJourney(config: JourneyDef): JourneyHandle {\n return {\n config,\n start(tags) {\n moduleRuntime.startJourney(config);\n if (tags) {\n moduleRuntime.setJourneyTags(config.name, tags);\n }\n },\n step(stepName, fn, opts) {\n if (!moduleRuntime.getOpenJourney(config.name)) {\n moduleRuntime.startJourney(config);\n }\n return journeyStep(config.name, stepName, fn, opts);\n },\n async mountStep(stepName, fn, opts) {\n // Defer so a parent <JourneyScope> opens first (child effects run before parent).\n await Promise.resolve();\n if (!moduleRuntime.getOpenJourney(config.name)) {\n moduleRuntime.startJourney(config);\n }\n return journeyStep(config.name, stepName, fn, opts);\n },\n complete(tags) {\n completeJourney(config.name, tags);\n },\n fail(reason) {\n failJourney(config.name, reason);\n },\n exclude() {\n excludeJourney(config.name);\n },\n setTags(tags) {\n setJourneyTags(config.name, tags);\n },\n };\n}\n\n/**\n * Snapshot an open journey for cross-page transfer (e.g. into a cookie). Does\n * NOT close the journey. Returns `null` when no journey is open under `name`.\n */\nexport function serializeJourneyState(name: string): SerializedJourneyState | null {\n return moduleRuntime.serializeJourneyState(name);\n}\n\n/**\n * Rehydrate a serialized journey onto this runtime. Returns `true` when the\n * journey is now open; `false` when it exhausted its budget in transit (a\n * `bad` `journey-timeout` event is emitted) or when a journey under the\n * same name is already open.\n */\nexport function restoreJourney(serialized: SerializedJourneyState, config: JourneyDef): boolean {\n return moduleRuntime.restoreJourney(serialized, config) !== null;\n}\n"],"names":["moduleRuntime","resolveJourneyEngine","adoptJourneyStepStamp","JourneyStepStamp","ambientStamp","ambientStep","singleInFlightJourneyStep","journey","closed","activeStep","activeJourneyStep","invalidateAmbientStamp","step","resolveStamp","explicit","fromExplicit","undefined","reportBackendRequest","status","durationMs","requestKey","journeyStep","stepName","fn","opts","setJourneyTags","name","tags","failJourney","reason","getOpenJourney","completeJourney","excludeJourney","defineJourney","config","start","startJourney","mountStep","Promise","resolve","complete","fail","exclude","setTags","serializeJourneyState","restoreJourney","serialized"],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Core barrel — public free helpers, handles, and types. Engine lives in `./runtime`. */
|
|
2
|
-
export { completeJourney, defineJourney, excludeJourney, failJourney, journeyStep, reportBackendRequest, resolveStamp, setJourneyTags, singleInFlightJourneyStep, } from './api';
|
|
2
|
+
export { completeJourney, defineJourney, excludeJourney, failJourney, journeyStep, reportBackendRequest, resolveStamp, restoreJourney, serializeJourneyState, setJourneyTags, singleInFlightJourneyStep, } from './api';
|
|
3
3
|
export { resetJourney, } from './runtime';
|
|
4
|
-
export type { JourneyDef, JourneyEvent, JourneyHandle, JourneyNameLike, JourneySink, JourneyStepEvent, JourneyStepOptions, JourneyStepTarget, StepHandle, TagValue, } from './types';
|
|
4
|
+
export type { JourneyDef, JourneyEvent, JourneyHandle, JourneyNameLike, JourneySink, JourneyStepEvent, JourneyStepOptions, JourneyStepTarget, SerializedJourneyState, StepHandle, TagValue, } from './types';
|
|
5
5
|
export { JourneyStepStamp } from './step-tag';
|
|
6
6
|
export type { JourneyHttpPolicyContext, JourneyHttpScore, JourneyHttpScoreContext, JourneyRequestPolicy, JourneyStampOptions, RequestPolicyConfig, } from './request-policy';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,OAAO,EACH,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,yBAAyB,GAC5B,MAAM,OAAO,CAAC;AACf,OAAO,EAEH,YAAY,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACR,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,QAAQ,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACR,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,OAAO,EACH,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,yBAAyB,GAC5B,MAAM,OAAO,CAAC;AACf,OAAO,EAEH,YAAY,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACR,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,QAAQ,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACR,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,kBAAkB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Core barrel — public free helpers, handles, and types. Engine lives in `./runtime`. */ export { completeJourney, defineJourney, excludeJourney, failJourney, journeyStep, reportBackendRequest, resolveStamp, setJourneyTags, singleInFlightJourneyStep } from './api';
|
|
1
|
+
/** Core barrel — public free helpers, handles, and types. Engine lives in `./runtime`. */ export { completeJourney, defineJourney, excludeJourney, failJourney, journeyStep, reportBackendRequest, resolveStamp, restoreJourney, serializeJourneyState, setJourneyTags, singleInFlightJourneyStep } from './api';
|
|
2
2
|
export { // @internal Test helper — not a supported consumer API.
|
|
3
3
|
resetJourney } from './runtime';
|
|
4
4
|
export { JourneyStepStamp } from './step-tag';
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["/** Core barrel — public free helpers, handles, and types. Engine lives in `./runtime`. */\n\nexport {\n completeJourney,\n defineJourney,\n excludeJourney,\n failJourney,\n journeyStep,\n reportBackendRequest,\n resolveStamp,\n setJourneyTags,\n singleInFlightJourneyStep,\n} from './api';\nexport {\n // @internal Test helper — not a supported consumer API.\n resetJourney,\n} from './runtime';\nexport type {\n JourneyDef,\n JourneyEvent,\n JourneyHandle,\n JourneyNameLike,\n JourneySink,\n JourneyStepEvent,\n JourneyStepOptions,\n JourneyStepTarget,\n StepHandle,\n TagValue,\n} from './types';\nexport { JourneyStepStamp } from './step-tag';\nexport type {\n JourneyHttpPolicyContext,\n JourneyHttpScore,\n JourneyHttpScoreContext,\n JourneyRequestPolicy,\n JourneyStampOptions,\n RequestPolicyConfig,\n} from './request-policy';\n"],"names":["completeJourney","defineJourney","excludeJourney","failJourney","journeyStep","reportBackendRequest","resolveStamp","setJourneyTags","singleInFlightJourneyStep","resetJourney","JourneyStepStamp"],"mappings":"AAAA,wFAAwF,GAExF,SACIA,eAAe,EACfC,aAAa,EACbC,cAAc,EACdC,WAAW,EACXC,WAAW,EACXC,oBAAoB,EACpBC,YAAY,EACZC,cAAc,EACdC,yBAAyB,QACtB,QAAQ;AACf,SACI,wDAAwD;AACxDC,YAAY,QACT,YAAY;
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["/** Core barrel — public free helpers, handles, and types. Engine lives in `./runtime`. */\n\nexport {\n completeJourney,\n defineJourney,\n excludeJourney,\n failJourney,\n journeyStep,\n reportBackendRequest,\n resolveStamp,\n restoreJourney,\n serializeJourneyState,\n setJourneyTags,\n singleInFlightJourneyStep,\n} from './api';\nexport {\n // @internal Test helper — not a supported consumer API.\n resetJourney,\n} from './runtime';\nexport type {\n JourneyDef,\n JourneyEvent,\n JourneyHandle,\n JourneyNameLike,\n JourneySink,\n JourneyStepEvent,\n JourneyStepOptions,\n JourneyStepTarget,\n SerializedJourneyState,\n StepHandle,\n TagValue,\n} from './types';\nexport { JourneyStepStamp } from './step-tag';\nexport type {\n JourneyHttpPolicyContext,\n JourneyHttpScore,\n JourneyHttpScoreContext,\n JourneyRequestPolicy,\n JourneyStampOptions,\n RequestPolicyConfig,\n} from './request-policy';\n"],"names":["completeJourney","defineJourney","excludeJourney","failJourney","journeyStep","reportBackendRequest","resolveStamp","restoreJourney","serializeJourneyState","setJourneyTags","singleInFlightJourneyStep","resetJourney","JourneyStepStamp"],"mappings":"AAAA,wFAAwF,GAExF,SACIA,eAAe,EACfC,aAAa,EACbC,cAAc,EACdC,WAAW,EACXC,WAAW,EACXC,oBAAoB,EACpBC,YAAY,EACZC,cAAc,EACdC,qBAAqB,EACrBC,cAAc,EACdC,yBAAyB,QACtB,QAAQ;AACf,SACI,wDAAwD;AACxDC,YAAY,QACT,YAAY;AAcnB,SAASC,gBAAgB,QAAQ,aAAa"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type JourneyRuntime } from './runtime';
|
|
2
|
+
import { type JourneyDef, type JourneyState, type SerializedJourneyState } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* @internal Project an open {@link JourneyState} into a plain, JSON-safe
|
|
5
|
+
* {@link SerializedJourneyState} that can ride a cookie across page navigations.
|
|
6
|
+
* The step projection mirrors `finish()`; `startedAt` (a `performance.now()`
|
|
7
|
+
* monotonic stamp) is bridged to a wall-clock epoch so it survives the page
|
|
8
|
+
* load where `performance.now()` resets.
|
|
9
|
+
*/
|
|
10
|
+
export declare function projectJourneyState(journey: JourneyState): SerializedJourneyState;
|
|
11
|
+
/**
|
|
12
|
+
* @internal Rehydrate a {@link SerializedJourneyState} into a live
|
|
13
|
+
* {@link JourneyState} bound to the supplied runtime. `startedAt` is rebased
|
|
14
|
+
* from the wall-clock epoch back to a `performance.now()` monotonic stamp,
|
|
15
|
+
* `StepRecord[]` is rebuilt with re-linked circular references, and the
|
|
16
|
+
* `JOURNEY_ENGINE` hook is re-bound so HTTP attribution works on the new page.
|
|
17
|
+
*/
|
|
18
|
+
export declare function deserializeJourneyState(serialized: SerializedJourneyState, config: JourneyDef, api: JourneyRuntime, defaultJourneyIdleMs: number): JourneyState;
|
|
19
|
+
//# sourceMappingURL=persist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/core/persist.ts"],"names":[],"mappings":"AASA,OAAO,EAAuC,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACrF,OAAO,EAEH,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAE9B,MAAM,SAAS,CAAC;AAEjB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,sBAAsB,CA0BjF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACnC,UAAU,EAAE,sBAAsB,EAClC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,cAAc,EACnB,oBAAoB,EAAE,MAAM,GAC7B,YAAY,CAiEd"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { clampMaxSteps, finiteSlowRequestMs, finiteTimeoutMs, MAX_ATTRIBUTE_KEYS, MAX_TAG_KEYS, resolveJourneyTimeoutMs } from './limits';
|
|
2
|
+
import { assignRecord, emptyRecord } from './sanitize';
|
|
3
|
+
import { bindJourneyEngine, freezeJourneyDef } from './runtime';
|
|
4
|
+
import { JOURNEY_ENGINE } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* @internal Project an open {@link JourneyState} into a plain, JSON-safe
|
|
7
|
+
* {@link SerializedJourneyState} that can ride a cookie across page navigations.
|
|
8
|
+
* The step projection mirrors `finish()`; `startedAt` (a `performance.now()`
|
|
9
|
+
* monotonic stamp) is bridged to a wall-clock epoch so it survives the page
|
|
10
|
+
* load where `performance.now()` resets.
|
|
11
|
+
*/ export function projectJourneyState(journey) {
|
|
12
|
+
const steps = journey.steps.map((s)=>({
|
|
13
|
+
name: s.name,
|
|
14
|
+
startMs: Math.round(s.startedAt - journey.startedAt),
|
|
15
|
+
durationMs: s.durationMs || Math.round(globalThis.performance.now() - s.startedAt),
|
|
16
|
+
outcome: s.outcome,
|
|
17
|
+
...s.reason ? {
|
|
18
|
+
reason: s.reason
|
|
19
|
+
} : {},
|
|
20
|
+
...s.httpStatus !== undefined ? {
|
|
21
|
+
httpStatus: s.httpStatus
|
|
22
|
+
} : {},
|
|
23
|
+
// Attributes are raw here — final emission sanitization happens in finish().
|
|
24
|
+
...Object.keys(s.attributes).length ? {
|
|
25
|
+
attributes: {
|
|
26
|
+
...s.attributes
|
|
27
|
+
}
|
|
28
|
+
} : {}
|
|
29
|
+
}));
|
|
30
|
+
const startedAtEpoch = Date.now() - (globalThis.performance.now() - journey.startedAt);
|
|
31
|
+
// Coerce any non-null st_journey_id tag to a string so a numeric/boolean id survives the round-trip.
|
|
32
|
+
const stJourneyId = journey.tags.st_journey_id != null ? String(journey.tags.st_journey_id) : '';
|
|
33
|
+
return {
|
|
34
|
+
stJourneyId,
|
|
35
|
+
startedAtEpoch,
|
|
36
|
+
// Open journeys are never 'excluded' — that verdict is only set inside finish().
|
|
37
|
+
verdict: journey.verdict === 'bad' ? 'bad' : 'good',
|
|
38
|
+
reason: journey.reason,
|
|
39
|
+
steps,
|
|
40
|
+
tags: {
|
|
41
|
+
...journey.tags
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @internal Rehydrate a {@link SerializedJourneyState} into a live
|
|
47
|
+
* {@link JourneyState} bound to the supplied runtime. `startedAt` is rebased
|
|
48
|
+
* from the wall-clock epoch back to a `performance.now()` monotonic stamp,
|
|
49
|
+
* `StepRecord[]` is rebuilt with re-linked circular references, and the
|
|
50
|
+
* `JOURNEY_ENGINE` hook is re-bound so HTTP attribution works on the new page.
|
|
51
|
+
*/ export function deserializeJourneyState(serialized, config, api, defaultJourneyIdleMs) {
|
|
52
|
+
const tags = emptyRecord();
|
|
53
|
+
// Caller config tags win; serialized tags fill the rest (incl. st_journey_id).
|
|
54
|
+
assignRecord(tags, serialized.tags, MAX_TAG_KEYS);
|
|
55
|
+
assignRecord(tags, config.tags, MAX_TAG_KEYS);
|
|
56
|
+
if (serialized.stJourneyId && tags.st_journey_id === undefined) {
|
|
57
|
+
tags.st_journey_id = serialized.stJourneyId;
|
|
58
|
+
}
|
|
59
|
+
const snapshot = freezeJourneyDef(config, tags);
|
|
60
|
+
const timeout = resolveJourneyTimeoutMs(snapshot.timeoutMs, defaultJourneyIdleMs);
|
|
61
|
+
const startedAt = globalThis.performance.now() - (Date.now() - serialized.startedAtEpoch);
|
|
62
|
+
const journey = {
|
|
63
|
+
config: snapshot,
|
|
64
|
+
name: snapshot.name,
|
|
65
|
+
team: snapshot.team,
|
|
66
|
+
group: snapshot.group,
|
|
67
|
+
service: snapshot.service,
|
|
68
|
+
verdict: serialized.verdict === 'bad' ? 'bad' : 'good',
|
|
69
|
+
startedAt,
|
|
70
|
+
timeoutMs: timeout.ms,
|
|
71
|
+
timeoutExplicit: timeout.explicit,
|
|
72
|
+
stepTimeoutMs: snapshot.stepTimeoutMs !== undefined ? finiteTimeoutMs(snapshot.stepTimeoutMs) : undefined,
|
|
73
|
+
reason: serialized.reason,
|
|
74
|
+
steps: [],
|
|
75
|
+
expected: snapshot.expected ? [
|
|
76
|
+
...snapshot.expected
|
|
77
|
+
] : null,
|
|
78
|
+
tags,
|
|
79
|
+
slowRequestMs: finiteSlowRequestMs(snapshot.slowRequestMs),
|
|
80
|
+
endpoints: snapshot.endpoints,
|
|
81
|
+
timer: null,
|
|
82
|
+
closed: false,
|
|
83
|
+
maxSteps: snapshot.maxSteps !== undefined ? clampMaxSteps(snapshot.maxSteps) : undefined
|
|
84
|
+
};
|
|
85
|
+
// Rebuild StepRecord[] — re-link the circular `step.journey` reference and rebase `startedAt` from the offset.
|
|
86
|
+
for (const s of serialized.steps){
|
|
87
|
+
const step = {
|
|
88
|
+
name: s.name,
|
|
89
|
+
startedAt: journey.startedAt + s.startMs,
|
|
90
|
+
durationMs: s.durationMs,
|
|
91
|
+
outcome: s.outcome,
|
|
92
|
+
attributes: emptyRecord(),
|
|
93
|
+
journey
|
|
94
|
+
};
|
|
95
|
+
if (s.reason !== undefined) {
|
|
96
|
+
step.reason = s.reason;
|
|
97
|
+
}
|
|
98
|
+
if (s.httpStatus !== undefined) {
|
|
99
|
+
step.httpStatus = s.httpStatus;
|
|
100
|
+
}
|
|
101
|
+
if (s.attributes) {
|
|
102
|
+
assignRecord(step.attributes, s.attributes, MAX_ATTRIBUTE_KEYS);
|
|
103
|
+
}
|
|
104
|
+
journey.steps.push(step);
|
|
105
|
+
}
|
|
106
|
+
// Re-bind the engine so HTTP attribution / fail-fast works on this page.
|
|
107
|
+
journey[JOURNEY_ENGINE] = bindJourneyEngine(api, journey, api.shouldIgnoreRequest);
|
|
108
|
+
return journey;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=persist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/persist.ts"],"sourcesContent":["import {\n clampMaxSteps,\n finiteSlowRequestMs,\n finiteTimeoutMs,\n MAX_ATTRIBUTE_KEYS,\n MAX_TAG_KEYS,\n resolveJourneyTimeoutMs,\n} from './limits';\nimport { assignRecord, emptyRecord } from './sanitize';\nimport { bindJourneyEngine, freezeJourneyDef, type JourneyRuntime } from './runtime';\nimport {\n JOURNEY_ENGINE,\n type JourneyDef,\n type JourneyState,\n type SerializedJourneyState,\n type StepRecord,\n} from './types';\n\n/**\n * @internal Project an open {@link JourneyState} into a plain, JSON-safe\n * {@link SerializedJourneyState} that can ride a cookie across page navigations.\n * The step projection mirrors `finish()`; `startedAt` (a `performance.now()`\n * monotonic stamp) is bridged to a wall-clock epoch so it survives the page\n * load where `performance.now()` resets.\n */\nexport function projectJourneyState(journey: JourneyState): SerializedJourneyState {\n const steps = journey.steps.map(s => ({\n name: s.name,\n startMs: Math.round(s.startedAt - journey.startedAt),\n durationMs: s.durationMs || Math.round(globalThis.performance.now() - s.startedAt),\n outcome: s.outcome,\n ...(s.reason ? { reason: s.reason } : {}),\n ...(s.httpStatus !== undefined ? { httpStatus: s.httpStatus } : {}),\n // Attributes are raw here — final emission sanitization happens in finish().\n ...(Object.keys(s.attributes).length ? { attributes: { ...s.attributes } } : {}),\n }));\n\n const startedAtEpoch = Date.now() - (globalThis.performance.now() - journey.startedAt);\n // Coerce any non-null st_journey_id tag to a string so a numeric/boolean id survives the round-trip.\n const stJourneyId =\n journey.tags.st_journey_id != null ? String(journey.tags.st_journey_id) : '';\n\n return {\n stJourneyId,\n startedAtEpoch,\n // Open journeys are never 'excluded' — that verdict is only set inside finish().\n verdict: journey.verdict === 'bad' ? 'bad' : 'good',\n reason: journey.reason,\n steps,\n tags: { ...journey.tags },\n };\n}\n\n/**\n * @internal Rehydrate a {@link SerializedJourneyState} into a live\n * {@link JourneyState} bound to the supplied runtime. `startedAt` is rebased\n * from the wall-clock epoch back to a `performance.now()` monotonic stamp,\n * `StepRecord[]` is rebuilt with re-linked circular references, and the\n * `JOURNEY_ENGINE` hook is re-bound so HTTP attribution works on the new page.\n */\nexport function deserializeJourneyState(\n serialized: SerializedJourneyState,\n config: JourneyDef,\n api: JourneyRuntime,\n defaultJourneyIdleMs: number\n): JourneyState {\n const tags = emptyRecord();\n // Caller config tags win; serialized tags fill the rest (incl. st_journey_id).\n assignRecord(tags, serialized.tags, MAX_TAG_KEYS);\n assignRecord(tags, config.tags, MAX_TAG_KEYS);\n if (serialized.stJourneyId && tags.st_journey_id === undefined) {\n tags.st_journey_id = serialized.stJourneyId;\n }\n\n const snapshot = freezeJourneyDef(config, tags);\n const timeout = resolveJourneyTimeoutMs(snapshot.timeoutMs, defaultJourneyIdleMs);\n\n const startedAt = globalThis.performance.now() - (Date.now() - serialized.startedAtEpoch);\n\n const journey: JourneyState = {\n config: snapshot,\n name: snapshot.name,\n team: snapshot.team,\n group: snapshot.group,\n service: snapshot.service,\n verdict: serialized.verdict === 'bad' ? 'bad' : 'good',\n startedAt,\n timeoutMs: timeout.ms,\n timeoutExplicit: timeout.explicit,\n stepTimeoutMs:\n snapshot.stepTimeoutMs !== undefined\n ? finiteTimeoutMs(snapshot.stepTimeoutMs)\n : undefined,\n reason: serialized.reason,\n steps: [],\n expected: snapshot.expected ? [...snapshot.expected] : null,\n tags,\n slowRequestMs: finiteSlowRequestMs(snapshot.slowRequestMs),\n endpoints: snapshot.endpoints,\n timer: null,\n closed: false,\n maxSteps: snapshot.maxSteps !== undefined ? clampMaxSteps(snapshot.maxSteps) : undefined,\n };\n\n // Rebuild StepRecord[] — re-link the circular `step.journey` reference and rebase `startedAt` from the offset.\n for (const s of serialized.steps) {\n const step: StepRecord = {\n name: s.name,\n startedAt: journey.startedAt + s.startMs,\n durationMs: s.durationMs,\n outcome: s.outcome,\n attributes: emptyRecord(),\n journey,\n };\n if (s.reason !== undefined) {\n step.reason = s.reason;\n }\n if (s.httpStatus !== undefined) {\n step.httpStatus = s.httpStatus;\n }\n if (s.attributes) {\n assignRecord(step.attributes, s.attributes, MAX_ATTRIBUTE_KEYS);\n }\n journey.steps.push(step);\n }\n\n // Re-bind the engine so HTTP attribution / fail-fast works on this page.\n journey[JOURNEY_ENGINE] = bindJourneyEngine(api, journey, api.shouldIgnoreRequest);\n\n return journey;\n}\n"],"names":["clampMaxSteps","finiteSlowRequestMs","finiteTimeoutMs","MAX_ATTRIBUTE_KEYS","MAX_TAG_KEYS","resolveJourneyTimeoutMs","assignRecord","emptyRecord","bindJourneyEngine","freezeJourneyDef","JOURNEY_ENGINE","projectJourneyState","journey","steps","map","s","name","startMs","Math","round","startedAt","durationMs","globalThis","performance","now","outcome","reason","httpStatus","undefined","Object","keys","attributes","length","startedAtEpoch","Date","stJourneyId","tags","st_journey_id","String","verdict","deserializeJourneyState","serialized","config","api","defaultJourneyIdleMs","snapshot","timeout","timeoutMs","team","group","service","ms","timeoutExplicit","explicit","stepTimeoutMs","expected","slowRequestMs","endpoints","timer","closed","maxSteps","step","push","shouldIgnoreRequest"],"mappings":"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"}
|
package/dist/core/runtime.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type SlowRequestConfig } from './endpoint-policy';
|
|
2
2
|
import type { RequestPolicyConfig } from './request-policy';
|
|
3
|
-
import { type JourneyDef, type JourneyEngine, type JourneyEvent, type JourneySink, type JourneyState, type JourneyStepOptions, type JourneyStepTarget, type Outcome, type StepHandle, type StepRecord, type TagValue } from './types';
|
|
3
|
+
import { type JourneyDef, type JourneyEngine, type JourneyEvent, type JourneySink, type JourneyState, type JourneyStepOptions, type JourneyStepTarget, type Outcome, type SerializedJourneyState, type StepHandle, type StepRecord, type TagValue } from './types';
|
|
4
4
|
/** @internal Private — not part of the public package API. */
|
|
5
5
|
export interface JourneyRuntimeOptions {
|
|
6
6
|
/**
|
|
@@ -49,6 +49,8 @@ export interface JourneyRuntimeDebugSnapshot {
|
|
|
49
49
|
autoAttributeRequests: boolean;
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
/** @internal Freeze a caller-supplied journey def + tags snapshot. */
|
|
53
|
+
export declare function freezeJourneyDef(config: JourneyDef, tags: Record<string, TagValue>): JourneyDef;
|
|
52
54
|
/**
|
|
53
55
|
* @internal Private — not part of the public package API.
|
|
54
56
|
* Isolated journey engine (open journeys, ambient steps, sinks, request thresholds).
|
|
@@ -89,6 +91,17 @@ export interface JourneyRuntime {
|
|
|
89
91
|
completeJourneyState(journey: JourneyState, tags?: Record<string, TagValue>): void;
|
|
90
92
|
excludeJourney(journey: JourneyState): void;
|
|
91
93
|
updateOpenJourney(config: JourneyDef): void;
|
|
94
|
+
/**
|
|
95
|
+
* @internal Snapshot an open journey for cross-page transfer. Does NOT
|
|
96
|
+
* close the journey. Returns `null` when no journey is open under `name`.
|
|
97
|
+
*/
|
|
98
|
+
serializeJourneyState(name: string): SerializedJourneyState | null;
|
|
99
|
+
/**
|
|
100
|
+
* @internal Rehydrate a serialized journey onto this runtime. Returns
|
|
101
|
+
* `null` (after emitting a `bad` `journey-timeout` event) when the journey
|
|
102
|
+
* already exhausted its budget in transit.
|
|
103
|
+
*/
|
|
104
|
+
restoreJourney(serialized: SerializedJourneyState, config: JourneyDef): JourneyState | null;
|
|
92
105
|
activeJourneyStep(): StepRecord | null;
|
|
93
106
|
journeyStep<T>(journey: JourneyStepTarget, stepName: string, fn: (step: StepHandle) => T | Promise<T>, opts?: JourneyStepOptions): Promise<T>;
|
|
94
107
|
journeyMountStep<T>(journey: JourneyStepTarget, stepName: string, fn: (step: StepHandle) => T | Promise<T>, opts?: JourneyStepOptions): Promise<T>;
|
|
@@ -98,6 +111,8 @@ export interface JourneyRuntime {
|
|
|
98
111
|
/** Close open journeys, clear ambient steps, restore default timeouts/sinks. */
|
|
99
112
|
reset(options?: JourneyRuntimeOptions): void;
|
|
100
113
|
}
|
|
114
|
+
/** @internal Bind the fail/exclude/report hooks for a journey's creating engine. */
|
|
115
|
+
export declare function bindJourneyEngine(api: JourneyRuntime, journey: JourneyState, shouldIgnoreRequest: (target: JourneyState, key: string) => boolean): JourneyEngine;
|
|
101
116
|
/**
|
|
102
117
|
* @internal Private — not part of the public package API.
|
|
103
118
|
* Build an isolated engine. Rarely needed — apps use the default via free helpers.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/core/runtime.ts"],"names":[],"mappings":"AAQA,OAAO,EAGH,KAAK,iBAAiB,EACzB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/core/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/core/runtime.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getAutoAttributeRequests as getSharedAutoAttributeRequests, getHttpAbortedRequestsPolicy as getSharedHttpAbortedRequestsPolicy, getHttpClientErrorRequestsPolicy as getSharedHttpClientErrorRequestsPolicy, getSharedSlowRequests, isJourneyDebugEnabled } from '../global';
|
|
2
2
|
import { isCanceledError } from './abort-error';
|
|
3
3
|
import { resolveEndpointPolicy, sortEndpointsByLongestMatch } from './endpoint-policy';
|
|
4
|
+
import { deserializeJourneyState, projectJourneyState } from './persist';
|
|
4
5
|
import { clampMaxSteps, DEFAULT_MAX_STEPS, DEFAULT_JOURNEY_IDLE_MS, finiteSlowRequestMs, finiteTimeoutMs, MAX_ATTRIBUTED_REQUEST_KEYS, MAX_TAG_KEYS, resolveJourneyTimeoutMs } from './limits';
|
|
5
6
|
import { assignRecord, emptyRecord, sanitizeJourneyEvent, setSafeAttribute } from './sanitize';
|
|
6
7
|
import { JourneyStepStamp, resolveStampOpts } from './step-tag';
|
|
@@ -23,7 +24,7 @@ function toName(target) {
|
|
|
23
24
|
}
|
|
24
25
|
return 'config' in target ? target.config.name : target.name;
|
|
25
26
|
}
|
|
26
|
-
function freezeJourneyDef(config, tags) {
|
|
27
|
+
/** @internal Freeze a caller-supplied journey def + tags snapshot. */ export function freezeJourneyDef(config, tags) {
|
|
27
28
|
const endpoints = sortEndpointsByLongestMatch(config.endpoints);
|
|
28
29
|
return Object.freeze({
|
|
29
30
|
...config,
|
|
@@ -42,7 +43,7 @@ function freezeJourneyDef(config, tags) {
|
|
|
42
43
|
})
|
|
43
44
|
});
|
|
44
45
|
}
|
|
45
|
-
function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
46
|
+
/** @internal Bind the fail/exclude/report hooks for a journey's creating engine. */ export function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
46
47
|
return {
|
|
47
48
|
failJourney (reason) {
|
|
48
49
|
api.failJourney(journey, reason);
|
|
@@ -281,35 +282,35 @@ function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
|
281
282
|
getSlowRequests () {
|
|
282
283
|
return effectiveSlowRequests();
|
|
283
284
|
},
|
|
284
|
-
setSlowRequests (
|
|
285
|
+
setSlowRequests (next) {
|
|
285
286
|
slowRequests = {
|
|
286
|
-
...
|
|
287
|
-
endpoints: sortEndpointsByLongestMatch(
|
|
287
|
+
...next,
|
|
288
|
+
endpoints: sortEndpointsByLongestMatch(next.endpoints)
|
|
288
289
|
};
|
|
289
290
|
},
|
|
290
291
|
getMaxSteps () {
|
|
291
292
|
return maxSteps;
|
|
292
293
|
},
|
|
293
|
-
setMaxSteps (
|
|
294
|
-
maxSteps = clampMaxSteps(
|
|
294
|
+
setMaxSteps (next) {
|
|
295
|
+
maxSteps = clampMaxSteps(next);
|
|
295
296
|
},
|
|
296
297
|
getDefaultJourneyIdleMs () {
|
|
297
298
|
return defaultJourneyIdleMs;
|
|
298
299
|
},
|
|
299
|
-
setDefaultJourneyIdleMs (
|
|
300
|
-
defaultJourneyIdleMs = finiteTimeoutMs(
|
|
300
|
+
setDefaultJourneyIdleMs (next) {
|
|
301
|
+
defaultJourneyIdleMs = finiteTimeoutMs(next);
|
|
301
302
|
},
|
|
302
|
-
setSinks (
|
|
303
|
+
setSinks (next) {
|
|
303
304
|
sinks = [
|
|
304
|
-
...
|
|
305
|
+
...next
|
|
305
306
|
];
|
|
306
307
|
},
|
|
307
|
-
trySetConfiguredSinks (
|
|
308
|
+
trySetConfiguredSinks (next) {
|
|
308
309
|
if (sinksConfigured) {
|
|
309
310
|
return false;
|
|
310
311
|
}
|
|
311
312
|
sinks = [
|
|
312
|
-
...
|
|
313
|
+
...next
|
|
313
314
|
];
|
|
314
315
|
sinksConfigured = true;
|
|
315
316
|
return true;
|
|
@@ -318,10 +319,10 @@ function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
|
318
319
|
sinks.push(sink);
|
|
319
320
|
},
|
|
320
321
|
emit,
|
|
321
|
-
setPolicyOverlay (
|
|
322
|
+
setPolicyOverlay (next) {
|
|
322
323
|
overlay = {
|
|
323
324
|
...overlay,
|
|
324
|
-
...
|
|
325
|
+
...next
|
|
325
326
|
};
|
|
326
327
|
},
|
|
327
328
|
getAutoAttributeRequests () {
|
|
@@ -507,6 +508,40 @@ function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
|
507
508
|
}
|
|
508
509
|
armCountdown(journey, remainingMs);
|
|
509
510
|
},
|
|
511
|
+
serializeJourneyState (name) {
|
|
512
|
+
const journey = journeys.get(name);
|
|
513
|
+
if (!journey || journey.closed) {
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
return projectJourneyState(journey);
|
|
517
|
+
},
|
|
518
|
+
restoreJourney (serialized, config) {
|
|
519
|
+
// Refuse double-registration: leave an existing journey under this name in place.
|
|
520
|
+
if (journeys.has(config.name)) {
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
const journey = deserializeJourneyState(serialized, config, api, defaultJourneyIdleMs);
|
|
524
|
+
if (journey.timeoutMs > 0) {
|
|
525
|
+
const elapsedMs = globalThis.performance.now() - journey.startedAt;
|
|
526
|
+
if (elapsedMs >= journey.timeoutMs) {
|
|
527
|
+
// journey not yet in journeys Map — finish() handles unregistered journeys gracefully.
|
|
528
|
+
if (journey.timeoutExplicit) {
|
|
529
|
+
finish(journey, 'bad', 'journey-timeout');
|
|
530
|
+
} else {
|
|
531
|
+
finish(journey, journey.verdict === 'bad' ? 'bad' : 'excluded', 'journey-idle-timeout');
|
|
532
|
+
}
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
journeys.set(config.name, journey);
|
|
536
|
+
const remainingMs = journey.timeoutMs - elapsedMs;
|
|
537
|
+
if (remainingMs > 0) {
|
|
538
|
+
armCountdown(journey, remainingMs);
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
journeys.set(config.name, journey);
|
|
542
|
+
}
|
|
543
|
+
return journey;
|
|
544
|
+
},
|
|
510
545
|
activeJourneyStep () {
|
|
511
546
|
var _inFlight_values_next_value;
|
|
512
547
|
if (!api.getAutoAttributeRequests()) {
|
|
@@ -617,7 +652,7 @@ function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
|
617
652
|
}
|
|
618
653
|
api.failJourney(journey, category);
|
|
619
654
|
},
|
|
620
|
-
reset (
|
|
655
|
+
reset (next = {}) {
|
|
621
656
|
var _next_sinks, _ref, _ref1, _next_defaultJourneyIdleMs;
|
|
622
657
|
var _next_slowRequests, _next_slowRequests1;
|
|
623
658
|
for (const journey of [
|
|
@@ -631,14 +666,14 @@ function bindJourneyEngine(api, journey, shouldIgnoreRequest) {
|
|
|
631
666
|
overlay = {};
|
|
632
667
|
sinksConfigured = false;
|
|
633
668
|
sinks = [
|
|
634
|
-
...(_next_sinks =
|
|
669
|
+
...(_next_sinks = next.sinks) !== null && _next_sinks !== void 0 ? _next_sinks : []
|
|
635
670
|
];
|
|
636
671
|
slowRequests = {
|
|
637
|
-
defaultMs: (_ref = (_next_slowRequests =
|
|
638
|
-
endpoints: sortEndpointsByLongestMatch((_ref1 = (_next_slowRequests1 =
|
|
672
|
+
defaultMs: (_ref = (_next_slowRequests = next.slowRequests) === null || _next_slowRequests === void 0 ? void 0 : _next_slowRequests.defaultMs) !== null && _ref !== void 0 ? _ref : DEFAULT_SLOW_REQUESTS.defaultMs,
|
|
673
|
+
endpoints: sortEndpointsByLongestMatch((_ref1 = (_next_slowRequests1 = next.slowRequests) === null || _next_slowRequests1 === void 0 ? void 0 : _next_slowRequests1.endpoints) !== null && _ref1 !== void 0 ? _ref1 : DEFAULT_SLOW_REQUESTS.endpoints)
|
|
639
674
|
};
|
|
640
|
-
maxSteps =
|
|
641
|
-
defaultJourneyIdleMs = finiteTimeoutMs((_next_defaultJourneyIdleMs =
|
|
675
|
+
maxSteps = next.maxSteps !== undefined ? clampMaxSteps(next.maxSteps) : DEFAULT_MAX_STEPS;
|
|
676
|
+
defaultJourneyIdleMs = finiteTimeoutMs((_next_defaultJourneyIdleMs = next.defaultJourneyIdleMs) !== null && _next_defaultJourneyIdleMs !== void 0 ? _next_defaultJourneyIdleMs : DEFAULT_JOURNEY_IDLE_MS);
|
|
642
677
|
}
|
|
643
678
|
};
|
|
644
679
|
return api;
|