@glubean/sdk 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/contract-http/adapter.d.ts.map +1 -1
  2. package/dist/contract-http/adapter.js +9 -0
  3. package/dist/contract-http/adapter.js.map +1 -1
  4. package/dist/data-path.d.ts.map +1 -1
  5. package/dist/data-path.js +10 -2
  6. package/dist/data-path.js.map +1 -1
  7. package/dist/load/artifact.d.ts +376 -0
  8. package/dist/load/artifact.d.ts.map +1 -0
  9. package/dist/load/artifact.js +14 -0
  10. package/dist/load/artifact.js.map +1 -0
  11. package/dist/load/builder.d.ts +80 -0
  12. package/dist/load/builder.d.ts.map +1 -0
  13. package/dist/load/builder.js +262 -0
  14. package/dist/load/builder.js.map +1 -0
  15. package/dist/load/context.d.ts +81 -0
  16. package/dist/load/context.d.ts.map +1 -0
  17. package/dist/load/context.js +2 -0
  18. package/dist/load/context.js.map +1 -0
  19. package/dist/load/duration.d.ts +9 -0
  20. package/dist/load/duration.d.ts.map +1 -0
  21. package/dist/load/duration.js +22 -0
  22. package/dist/load/duration.js.map +1 -0
  23. package/dist/load/events.d.ts +132 -0
  24. package/dist/load/events.d.ts.map +1 -0
  25. package/dist/load/events.js +2 -0
  26. package/dist/load/events.js.map +1 -0
  27. package/dist/load/feeder.d.ts +118 -0
  28. package/dist/load/feeder.d.ts.map +1 -0
  29. package/dist/load/feeder.js +170 -0
  30. package/dist/load/feeder.js.map +1 -0
  31. package/dist/load/index.d.ts +32 -0
  32. package/dist/load/index.d.ts.map +1 -0
  33. package/dist/load/index.js +7 -0
  34. package/dist/load/index.js.map +1 -0
  35. package/dist/load/progress.d.ts +56 -0
  36. package/dist/load/progress.d.ts.map +1 -0
  37. package/dist/load/progress.js +2 -0
  38. package/dist/load/progress.js.map +1 -0
  39. package/dist/load/projection.d.ts +36 -0
  40. package/dist/load/projection.d.ts.map +1 -0
  41. package/dist/load/projection.js +47 -0
  42. package/dist/load/projection.js.map +1 -0
  43. package/dist/load/runner.d.ts +201 -0
  44. package/dist/load/runner.d.ts.map +1 -0
  45. package/dist/load/runner.js +78 -0
  46. package/dist/load/runner.js.map +1 -0
  47. package/dist/load/scenario.d.ts +130 -0
  48. package/dist/load/scenario.d.ts.map +1 -0
  49. package/dist/load/scenario.js +9 -0
  50. package/dist/load/scenario.js.map +1 -0
  51. package/dist/load/step.d.ts +42 -0
  52. package/dist/load/step.d.ts.map +1 -0
  53. package/dist/load/step.js +2 -0
  54. package/dist/load/step.js.map +1 -0
  55. package/dist/types.d.ts +16 -0
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/types.js.map +1 -1
  58. package/package.json +5 -1
  59. package/dist/workflow/execute.d.ts +0 -277
  60. package/dist/workflow/execute.d.ts.map +0 -1
  61. package/dist/workflow/execute.js +0 -1489
  62. package/dist/workflow/execute.js.map +0 -1
@@ -0,0 +1,201 @@
1
+ /**
2
+ * loadRunner(): the pressure model + report model over a loadScenario.
3
+ *
4
+ * `loadRunner()` is the runnable: it references one `loadScenario()` (or a
5
+ * traffic mix of several) and says how much pressure to apply. Discovery
6
+ * (M2) surfaces only `loadRunner()` exports as runnable; the referenced
7
+ * scenarios are workloads, not independently scheduled.
8
+ *
9
+ * M1 is the static authoring surface: `loadRunner()` returns a `LoadPlan`
10
+ * holding the resolved config. Actual execution lives in @glubean/runner.
11
+ */
12
+ import type { LoadBuilder } from "./builder.js";
13
+ import type { FeederBinding } from "./feeder.js";
14
+ import type { LoadProjection } from "./projection.js";
15
+ import type { LoadScenario } from "./scenario.js";
16
+ import type { LoadAssertionFailureMode } from "./step.js";
17
+ /** A duration as milliseconds (number) or a human string like `"60s"` / `"2m"`. */
18
+ export type LoadDuration = number | string;
19
+ export interface LoadProducerSlotInfo {
20
+ id: string;
21
+ index: number;
22
+ }
23
+ export interface LoadIterationInfo {
24
+ id: string;
25
+ index: number;
26
+ }
27
+ /**
28
+ * Arguments passed to a function-form `input`. `TRow` is the `loadRunner.each()`
29
+ * row type that produced this plan (typed and present for each variants);
30
+ * `undefined` for non-each plans.
31
+ */
32
+ export interface LoadInputArgs<TRow = undefined> {
33
+ row: TRow;
34
+ /** Feeder-allocated rows for this iteration, keyed by feeder name. */
35
+ feed: Record<string, any>;
36
+ producerSlot: LoadProducerSlotInfo;
37
+ iteration: LoadIterationInfo;
38
+ }
39
+ /**
40
+ * Per-iteration scenario input. Object form is a static input (same for every
41
+ * iteration); function form is the canonical form when feeders / producer-slot /
42
+ * iteration / `.each()` row participate. There is no hidden merge.
43
+ */
44
+ export type LoadInputOption<TInput, TRow = undefined> = TInput | ((args: LoadInputArgs<TRow>) => TInput);
45
+ /** Safety valve for `ctx.report.primaryComplete(... releaseProducerSlot: true)`. */
46
+ export interface LoadContinuationConfig {
47
+ maxOutstanding?: number;
48
+ maxConcurrent?: number;
49
+ minPollInterval?: LoadDuration;
50
+ drainTimeout?: LoadDuration;
51
+ onBacklogFull?: "block-producer" | "fail-iteration";
52
+ }
53
+ /** Optional pacing / think-time (MVP may leave unimplemented → back-to-back). */
54
+ export interface LoadPacingConfig {
55
+ thinkTime?: LoadDuration | {
56
+ min: LoadDuration;
57
+ max: LoadDuration;
58
+ };
59
+ }
60
+ /** Threshold expressions for one scope (e.g. `errorRate: "<1%"`, `p95: "<800ms"`). */
61
+ export interface LoadThresholdScope {
62
+ errorRate?: string;
63
+ p50?: string;
64
+ p90?: string;
65
+ p95?: string;
66
+ p99?: string;
67
+ throughputPerSec?: string;
68
+ backlog?: string;
69
+ backpressureMs?: string;
70
+ }
71
+ /** Structured thresholds. `endpoints` / `steps` are keyed by routeKey / stepId. */
72
+ export interface LoadThresholds {
73
+ transaction?: LoadThresholdScope;
74
+ primary?: LoadThresholdScope;
75
+ endToEnd?: LoadThresholdScope;
76
+ continuation?: LoadThresholdScope;
77
+ endpoints?: Record<string, LoadThresholdScope>;
78
+ steps?: Record<string, LoadThresholdScope>;
79
+ }
80
+ /** Bounded report sampling caps. */
81
+ export interface LoadReportConfig {
82
+ failureTraces?: number;
83
+ slowTransactionSummaries?: number;
84
+ }
85
+ /** A scenario reference: a built `LoadScenario` or an un-built `LoadBuilder`. */
86
+ export type LoadScenarioRef<Input = unknown> = LoadScenario<Input, any> | LoadBuilder<Input, any>;
87
+ type Feeders = Record<string, FeederBinding>;
88
+ interface LoadRunnerCommon {
89
+ concurrency: number;
90
+ duration?: LoadDuration;
91
+ iterations?: number;
92
+ rampUp?: LoadDuration;
93
+ pacing?: LoadPacingConfig;
94
+ continuation?: LoadContinuationConfig;
95
+ assertions?: {
96
+ onFailure?: LoadAssertionFailureMode;
97
+ };
98
+ thresholds?: LoadThresholds;
99
+ report?: LoadReportConfig;
100
+ /** How a run-level abort (stop / duration deadline / SIGINT) reaches in-flight
101
+ * requests.
102
+ * - `"precise"` (default): cancel in-flight HTTP at once. Uses a leak-free
103
+ * per-iteration abort bridge — no per-request listener accumulation.
104
+ * - `"coarse"`: don't wire the abort signal into each request; stop between steps
105
+ * instead. A few % more throughput for high-RPS runs where requests are short,
106
+ * at the cost of letting an already-sent request finish before the run stops. */
107
+ abort?: "precise" | "coarse";
108
+ }
109
+ /** Single-scenario load runner config. `TRow` is the `.each()` row, if any. */
110
+ export interface LoadRunnerConfig<Input = unknown, TRow = undefined> extends LoadRunnerCommon {
111
+ scenario: LoadScenarioRef<Input>;
112
+ feeders?: Feeders;
113
+ input?: LoadInputOption<Input, TRow>;
114
+ }
115
+ /** One entry in a traffic mix. */
116
+ export interface LoadMixEntry<Input = unknown, TRow = undefined> {
117
+ id: string;
118
+ scenario: LoadScenarioRef<Input>;
119
+ weight: number;
120
+ feeders?: Feeders;
121
+ input?: LoadInputOption<Input, TRow>;
122
+ }
123
+ /** Multi-scenario (traffic mix) config. Each entry may have its own input/feeders. */
124
+ export interface LoadMixConfig<TRow = undefined> extends LoadRunnerCommon {
125
+ scenarios: LoadMixEntry<any, TRow>[];
126
+ /** Shared feeders (no Input coupling). Per-entry feeders override these. */
127
+ feeders?: Feeders;
128
+ }
129
+ export type AnyLoadRunnerConfig = LoadRunnerConfig<any, any> | LoadMixConfig<any>;
130
+ /** A runnable load plan (output of `loadRunner()`). */
131
+ export interface LoadPlan {
132
+ readonly __glubean_type: "load-runner";
133
+ id: string;
134
+ config: AnyLoadRunnerConfig;
135
+ /**
136
+ * For `loadRunner.each()` variants: the table row that produced this plan.
137
+ * The load runtime surfaces it to function-form `input` as `args.row`.
138
+ * Absent for non-each plans.
139
+ */
140
+ row?: Record<string, unknown>;
141
+ /**
142
+ * Plain-data projection of this plan (runnerId / scenarios / steps /
143
+ * normalized durations / threshold scopes), exposed as a lazily-recomputed
144
+ * getter so it always reflects the current config / scenario builders — no
145
+ * stale snapshot if a scenario gains steps after `loadRunner()`. Discovery
146
+ * (scanner / CLI) reads it by duck-typing the exported value: no SDK import
147
+ * and no global registry needed.
148
+ */
149
+ readonly projection: LoadProjection;
150
+ }
151
+ interface LoadRunnerFn {
152
+ /** Single-scenario load plan. */
153
+ <Input, TRow = undefined>(id: string, config: LoadRunnerConfig<Input, TRow>): LoadPlan;
154
+ /** Traffic-mix load plan. */
155
+ (id: string, config: LoadMixConfig): LoadPlan;
156
+ /**
157
+ * Scenario-level inventory expansion: one load plan per row (e.g. by plan,
158
+ * region, tenant). Each variant has its own id / thresholds / report, and the
159
+ * factory may return a single scenario or a traffic mix. Function-form `input`
160
+ * receives the producing row as a typed `args.row`.
161
+ */
162
+ each<TRow extends object>(table: readonly TRow[]): <Input>(idTemplate: string, factory: (row: TRow, index: number) => LoadRunnerConfig<Input, TRow> | LoadMixConfig<TRow>) => LoadPlan[];
163
+ }
164
+ /**
165
+ * Define a pressure plan over one or more load scenarios.
166
+ *
167
+ * @example single scenario
168
+ * ```ts
169
+ * export const checkoutLoad = loadRunner("checkout-300", {
170
+ * scenario: checkoutScenario,
171
+ * concurrency: 300,
172
+ * duration: "60s",
173
+ * input: ({ feed, producerSlot, iteration }) => ({
174
+ * user: feed.user,
175
+ * clientRequestId: `${producerSlot.id}-${iteration.id}`,
176
+ * }),
177
+ * thresholds: { transaction: { errorRate: "<1%", p95: "<2000ms" } },
178
+ * });
179
+ * ```
180
+ */
181
+ export declare const loadRunner: LoadRunnerFn;
182
+ /**
183
+ * Type-safe constructor for a traffic-mix entry: it binds `input` to the
184
+ * scenario's `Input`, so a mismatched input shape is rejected at author time.
185
+ *
186
+ * Use it inside `scenarios: [...]`. A bare object literal in the array is only
187
+ * checked against `LoadMixEntry<any>` (TypeScript can't infer a distinct `Input`
188
+ * per array element), so wrap each entry with `loadMixEntry()` for per-entry
189
+ * type checking of heterogeneous typed scenarios.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * scenarios: [
194
+ * loadMixEntry({ id: "checkout", scenario: checkout, weight: 70, input: () => ({ sku: "s" }) }),
195
+ * loadMixEntry({ id: "refund", scenario: refund, weight: 30, input: () => ({ orderId: "o" }) }),
196
+ * ]
197
+ * ```
198
+ */
199
+ export declare function loadMixEntry<Input, TRow = undefined>(entry: LoadMixEntry<Input, TRow>): LoadMixEntry<any, TRow>;
200
+ export {};
201
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/load/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { projectLoadPlan } from "./projection.js";
2
+ /** Interpolate `$index` and `$field` placeholders in an `.each()` id template. */
3
+ function interpolateId(template, row, index) {
4
+ // Token-aware: match a whole `$identifier` placeholder, so a field name that
5
+ // prefixes another (possibly missing) longer placeholder can't corrupt it
6
+ // (e.g. `$plan` must not eat the `$plan` inside a missing `$planId`).
7
+ return template.replace(/\$(\w+)/g, (match, name) => {
8
+ if (name === "index")
9
+ return String(index);
10
+ if (Object.prototype.hasOwnProperty.call(row, name))
11
+ return String(row[name]);
12
+ return match; // unknown placeholder — leave intact rather than silently corrupt
13
+ });
14
+ }
15
+ /**
16
+ * Build a LoadPlan whose `projection` is a lazily-recomputed getter, so it
17
+ * always reflects the current config / scenario builders (no stale snapshot if
18
+ * a scenario gains steps after `loadRunner()` is called).
19
+ */
20
+ function makeLoadPlan(id, config, row) {
21
+ const plan = {
22
+ __glubean_type: "load-runner",
23
+ id,
24
+ config,
25
+ ...(row !== undefined ? { row } : {}),
26
+ };
27
+ Object.defineProperty(plan, "projection", {
28
+ get: () => projectLoadPlan(plan),
29
+ enumerable: true,
30
+ });
31
+ return plan;
32
+ }
33
+ const loadRunnerImpl = (id, config) => makeLoadPlan(id, config);
34
+ loadRunnerImpl.each = (table) => {
35
+ return (idTemplate, factory) => table.map((row, index) => {
36
+ const rowRecord = row;
37
+ return makeLoadPlan(interpolateId(idTemplate, rowRecord, index), factory(row, index), rowRecord);
38
+ });
39
+ };
40
+ /**
41
+ * Define a pressure plan over one or more load scenarios.
42
+ *
43
+ * @example single scenario
44
+ * ```ts
45
+ * export const checkoutLoad = loadRunner("checkout-300", {
46
+ * scenario: checkoutScenario,
47
+ * concurrency: 300,
48
+ * duration: "60s",
49
+ * input: ({ feed, producerSlot, iteration }) => ({
50
+ * user: feed.user,
51
+ * clientRequestId: `${producerSlot.id}-${iteration.id}`,
52
+ * }),
53
+ * thresholds: { transaction: { errorRate: "<1%", p95: "<2000ms" } },
54
+ * });
55
+ * ```
56
+ */
57
+ export const loadRunner = loadRunnerImpl;
58
+ /**
59
+ * Type-safe constructor for a traffic-mix entry: it binds `input` to the
60
+ * scenario's `Input`, so a mismatched input shape is rejected at author time.
61
+ *
62
+ * Use it inside `scenarios: [...]`. A bare object literal in the array is only
63
+ * checked against `LoadMixEntry<any>` (TypeScript can't infer a distinct `Input`
64
+ * per array element), so wrap each entry with `loadMixEntry()` for per-entry
65
+ * type checking of heterogeneous typed scenarios.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * scenarios: [
70
+ * loadMixEntry({ id: "checkout", scenario: checkout, weight: 70, input: () => ({ sku: "s" }) }),
71
+ * loadMixEntry({ id: "refund", scenario: refund, weight: 30, input: () => ({ orderId: "o" }) }),
72
+ * ]
73
+ * ```
74
+ */
75
+ export function loadMixEntry(entry) {
76
+ return entry;
77
+ }
78
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/load/runner.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAmKlD,kFAAkF;AAClF,SAAS,aAAa,CACpB,QAAgB,EAChB,GAA4B,EAC5B,KAAa;IAEb,6EAA6E;IAC7E,0EAA0E;IAC1E,sEAAsE;IACtE,OAAO,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC1D,IAAI,IAAI,KAAK,OAAO;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC,CAAC,kEAAkE;IAClF,CAAC,CAAC,CAAC;AACL,CAAC;AAwBD;;;;GAIG;AACH,SAAS,YAAY,CACnB,EAAU,EACV,MAA2B,EAC3B,GAA6B;IAE7B,MAAM,IAAI,GAAG;QACX,cAAc,EAAE,aAAsB;QACtC,EAAE;QACF,MAAM;QACN,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;IACF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE;QACxC,GAAG,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QAChC,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IACH,OAAO,IAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,EAAU,EAAE,MAA2B,EAAY,EAAE,CAC3E,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AAE3B,cAAc,CAAC,IAAI,GAAG,CAAsB,KAAsB,EAAE,EAAE;IACpE,OAAO,CACL,UAAkB,EAClB,OAGwD,EAC5C,EAAE,CACd,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACvB,MAAM,SAAS,GAAG,GAA8B,CAAC;QACjD,OAAO,YAAY,CACjB,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,EAC3C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAwB,EAC1C,SAAS,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,cAA8B,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAgC;IAEhC,OAAO,KAAgC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * loadScenario definition shape + branch/poll runtime data.
3
+ *
4
+ * These mirror the test() step / branch / poll runtime structures, but bind to
5
+ * `LoadContext` and carry a load-specific per-step assertion policy. The load
6
+ * orchestrator (later milestones) executes these. They are intentionally
7
+ * independent of `Test` / `TestEvent` structures so load's bounded-aggregation
8
+ * model never inherits ordinary test timeline semantics.
9
+ */
10
+ import type { StepJsonScalar, StepMeta, StepNoExtraKeys } from "../types.js";
11
+ import type { LoadContext } from "./context.js";
12
+ import type { LoadAssertionFailureMode, LoadStepOptions } from "./step.js";
13
+ /** Step metadata for a load scenario step: StepMeta plus a load assertion policy. */
14
+ export interface LoadStepMeta extends StepMeta {
15
+ assertions?: {
16
+ onFailure?: LoadAssertionFailureMode;
17
+ };
18
+ }
19
+ /**
20
+ * A scenario step's runtime structure. A normal step has a callable `fn`; a
21
+ * branch step (condition/switch) additionally carries `branch`, and a poll step
22
+ * carries `poll` — for both, `fn` is a throwing stub and the orchestrator
23
+ * dispatches on the extra field.
24
+ */
25
+ export interface LoadStepDefinition<Input = unknown, S = unknown> {
26
+ meta: LoadStepMeta;
27
+ fn: (ctx: LoadContext<Input>, state: S) => Promise<S | void>;
28
+ branch?: LoadBranchData<Input, S>;
29
+ poll?: LoadPollData<Input, S>;
30
+ }
31
+ /** Runtime branch data (condition / switchOn / switchCond) bound to LoadContext. */
32
+ export interface LoadBranchData<Input = unknown, S = unknown> {
33
+ mode: "predicate" | "value";
34
+ message?: string;
35
+ /** value-mode only: subject lens evaluated once against committed state. */
36
+ subject?: (ctx: LoadContext<Input>, state: S) => unknown;
37
+ cases: Array<{
38
+ predicate?: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
39
+ value?: StepJsonScalar;
40
+ message?: string;
41
+ steps: LoadStepDefinition<Input, S>[];
42
+ }>;
43
+ default: LoadStepDefinition<Input, S>[];
44
+ }
45
+ /** Runtime poll data (bounded poll-until) bound to LoadContext. */
46
+ export interface LoadPollData<Input = unknown, S = unknown> {
47
+ fn: (ctx: LoadContext<Input>, state: S) => Promise<unknown>;
48
+ until: (ctx: LoadContext<Input>, res: unknown, state: S) => boolean | Promise<boolean>;
49
+ out?: (state: S, res: unknown) => unknown;
50
+ every?: number;
51
+ backoff?: number;
52
+ timeout?: number;
53
+ perAttemptTimeout?: number;
54
+ maxAttempts?: number;
55
+ }
56
+ /** Narrow a LoadStepDefinition to a branch step. */
57
+ export declare function isLoadBranchStep<Input, S>(step: LoadStepDefinition<Input, S>): step is LoadStepDefinition<Input, S> & {
58
+ branch: LoadBranchData<Input, S>;
59
+ };
60
+ /** Narrow a LoadStepDefinition to a poll step. */
61
+ export declare function isLoadPollStep<Input, S>(step: LoadStepDefinition<Input, S>): step is LoadStepDefinition<Input, S> & {
62
+ poll: LoadPollData<Input, S>;
63
+ };
64
+ /** `loadScenario().condition` spec — arbitrary runtime predicate. */
65
+ export interface LoadConditionSpec<Input = unknown, S = unknown> {
66
+ predicate: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
67
+ message?: string;
68
+ }
69
+ /** `loadScenario().poll` options. `Res` is inferred from the attempt `fn`'s return. */
70
+ export interface LoadPollOpts<Input, S, Res, NewS> {
71
+ until: (ctx: LoadContext<Input>, res: Res, state: S) => boolean | Promise<boolean>;
72
+ every?: number;
73
+ backoff?: number;
74
+ timeout?: number;
75
+ perAttemptTimeout?: number;
76
+ maxAttempts?: number;
77
+ out?: (state: S, res: Res) => NewS;
78
+ }
79
+ /** Module-private phantom brand making LoadFragmentBuilder invariant in State. */
80
+ declare const LOAD_FRAGMENT_STATE: unique symbol;
81
+ /**
82
+ * Restricted builder for a `loadScenario()` branch body (condition then/else,
83
+ * switch case/default). Exposes step / use / condition / switchOn / switchCond /
84
+ * poll and accumulates them into the branch node; it deliberately does NOT
85
+ * expose setup / teardown / meta / build. Invariant in `State` via the phantom
86
+ * brand (same convergence guarantee as TestFragmentBuilder).
87
+ */
88
+ export interface LoadFragmentBuilder<Input = unknown, S = unknown> {
89
+ readonly [LOAD_FRAGMENT_STATE]: (s: S) => S;
90
+ step(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<void>): LoadFragmentBuilder<Input, S>;
91
+ step<NewS>(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<NewS>): LoadFragmentBuilder<Input, NewS>;
92
+ step(name: string, options: LoadStepOptions, fn: (ctx: LoadContext<Input>, state: S) => Promise<void>): LoadFragmentBuilder<Input, S>;
93
+ step<NewS>(name: string, options: LoadStepOptions, fn: (ctx: LoadContext<Input>, state: S) => Promise<NewS>): LoadFragmentBuilder<Input, NewS>;
94
+ use<NewS>(fn: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NewS>): LoadFragmentBuilder<Input, NewS>;
95
+ condition<R extends S = S>(spec: LoadConditionSpec<Input, S>, thenBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, R & StepNoExtraKeys<R, S>>): LoadFragmentBuilder<Input, S>;
96
+ condition<T>(spec: LoadConditionSpec<Input, S>, thenBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>, elseBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>): LoadFragmentBuilder<Input, T>;
97
+ switchOn<V>(lens: (ctx: LoadContext<Input>, state: S) => V): <T>(cases: ReadonlyArray<{
98
+ value: [Exclude<Awaited<V>, undefined>] extends [StepJsonScalar] ? Exclude<Awaited<V>, undefined> : never;
99
+ then: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>;
100
+ }>, deflt: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>) => LoadFragmentBuilder<Input, T>;
101
+ switchCond<T>(cases: ReadonlyArray<{
102
+ when: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
103
+ then: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>;
104
+ }>, deflt: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>): LoadFragmentBuilder<Input, T>;
105
+ poll<Res, NewS = S>(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<Res>, opts: LoadPollOpts<Input, S, Res, NewS>): LoadFragmentBuilder<Input, NewS>;
106
+ }
107
+ /** Scenario-level metadata. */
108
+ export interface LoadScenarioMeta {
109
+ id: string;
110
+ description?: string;
111
+ /** Scenario-level default for guard/assertion failures. */
112
+ assertions?: {
113
+ onFailure?: LoadAssertionFailureMode;
114
+ };
115
+ }
116
+ /**
117
+ * A complete loadScenario definition (output of `LoadBuilder.build()`).
118
+ *
119
+ * This is the performance-transaction workload that a `loadRunner()` executes.
120
+ * It is NOT independently runnable — only `loadRunner()` exports are scheduled.
121
+ */
122
+ export interface LoadScenario<Input = unknown, S = unknown> {
123
+ readonly __glubean_type: "load-scenario";
124
+ meta: LoadScenarioMeta;
125
+ setup?: (ctx: LoadContext<Input>) => Promise<unknown>;
126
+ steps: LoadStepDefinition<Input, unknown>[];
127
+ teardown?: (ctx: LoadContext<Input>, state: S) => Promise<void>;
128
+ }
129
+ export {};
130
+ //# sourceMappingURL=scenario.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../../src/load/scenario.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Narrow a LoadStepDefinition to a branch step. */
2
+ export function isLoadBranchStep(step) {
3
+ return step.branch !== undefined;
4
+ }
5
+ /** Narrow a LoadStepDefinition to a poll step. */
6
+ export function isLoadPollStep(step) {
7
+ return step.poll !== undefined;
8
+ }
9
+ //# sourceMappingURL=scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../src/load/scenario.ts"],"names":[],"mappings":"AA4DA,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAC9B,IAAkC;IAElC,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;AACnC,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAC5B,IAAkC;IAElC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Load scenario step authoring types.
3
+ *
4
+ * These mirror the `test().builder()` step model (return-state threading:
5
+ * a step returns the next state, or `void`/`undefined` to keep the current
6
+ * state) but bind to `LoadContext` and add a load-specific assertion policy.
7
+ */
8
+ import type { StepMeta } from "../types.js";
9
+ import type { LoadContext } from "./context.js";
10
+ /**
11
+ * What happens when a guard/assertion fails inside a load step.
12
+ *
13
+ * Resolution order (most specific wins):
14
+ * per-assertion `.orFail()` / thrown error
15
+ * > step-level `assertions.onFailure`
16
+ * > scenario-level `assertions.onFailure`
17
+ * > loadRunner `assertions.onFailure`
18
+ * > default `"continue"`
19
+ */
20
+ export type LoadAssertionFailureMode =
21
+ /** Default: record + count the failure, keep running the scenario. */
22
+ "continue"
23
+ /** Current step completes; remaining steps are skipped. */
24
+ | "skipRemainingSteps"
25
+ /** Fail-fast the current iteration. */
26
+ | "abortIteration";
27
+ /** Per-step options for `loadScenario` steps (`StepMeta` minus `name`, plus load policy). */
28
+ export type LoadStepOptions = Omit<StepMeta, "name"> & {
29
+ assertions?: {
30
+ onFailure?: LoadAssertionFailureMode;
31
+ };
32
+ };
33
+ /** A scenario `setup` producing the initial state from the context. */
34
+ export type LoadSetupFunction<Input, NewState> = (ctx: LoadContext<Input>) => Promise<NewState>;
35
+ /**
36
+ * A scenario step. Returns the next state, or `void`/`undefined` to keep the
37
+ * current state (matching `test().builder()` semantics).
38
+ */
39
+ export type LoadStepFunction<Input, State, NewState = State> = (ctx: LoadContext<Input>, state: State) => Promise<NewState | void>;
40
+ /** A scenario `teardown`, always run with the last committed state. */
41
+ export type LoadTeardownFunction<Input, State> = (ctx: LoadContext<Input>, state: State) => Promise<void>;
42
+ //# sourceMappingURL=step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/load/step.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB;AAClC,sEAAsE;AACpE,UAAU;AACZ,2DAA2D;GACzD,oBAAoB;AACtB,uCAAuC;GACrC,gBAAgB,CAAC;AAErB,6FAA6F;AAC7F,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG;IACrD,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,wBAAwB,CAAC;KACtC,CAAC;CACH,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,iBAAiB,CAAC,KAAK,EAAE,QAAQ,IAAI,CAC/C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,KACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAG,KAAK,IAAI,CAC7D,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EACvB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAE9B,uEAAuE;AACvE,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,KAAK,IAAI,CAC/C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EACvB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/load/step.ts"],"names":[],"mappings":""}
package/dist/types.d.ts CHANGED
@@ -1332,6 +1332,16 @@ export interface HttpRequestOptions {
1332
1332
  * ```
1333
1333
  */
1334
1334
  schema?: HttpSchemaOptions;
1335
+ /**
1336
+ * Per-request context — a non-wire object shared across this request's hooks (never
1337
+ * sent to the server). The runtime reads `context.glubeanRoute` (an exact route
1338
+ * template like `"GET /runs/:runId"`) to attribute the load runner's endpoint stats
1339
+ * exactly instead of heuristically normalizing the URL; a `contract.http()` client
1340
+ * sets it automatically. A custom `HttpClient` may ignore this option.
1341
+ */
1342
+ context?: {
1343
+ glubeanRoute?: string;
1344
+ } & Record<string, unknown>;
1335
1345
  }
1336
1346
  /**
1337
1347
  * Hooks for intercepting HTTP request/response lifecycle.
@@ -1713,6 +1723,12 @@ export interface Trace {
1713
1723
  name?: string;
1714
1724
  /** Optional detailed description */
1715
1725
  description?: string;
1726
+ /** Optional EXACT route template, e.g. "GET /runs/:runId". Carried via the request's
1727
+ * non-wire `context.glubeanRoute` option (set by a `contract.http()` client from its
1728
+ * `endpoint`, or by a caller) — NEVER a request header, so it can't leak to the server.
1729
+ * The load runner uses it for an exact endpoint routeKey instead of the heuristic
1730
+ * URL-normalization fallback. Absent → fall back. */
1731
+ routeKey?: string;
1716
1732
  /** @deprecated Use `target` and `metadata` instead. HTTP method. */
1717
1733
  method?: string;
1718
1734
  /** @deprecated Use `target` and `metadata` instead. Request URL. */