@glubean/sdk 0.5.1 → 0.8.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.
Files changed (151) hide show
  1. package/dist/contract-artifacts.d.ts +39 -21
  2. package/dist/contract-artifacts.d.ts.map +1 -1
  3. package/dist/contract-artifacts.js +80 -24
  4. package/dist/contract-artifacts.js.map +1 -1
  5. package/dist/contract-core.d.ts +10 -21
  6. package/dist/contract-core.d.ts.map +1 -1
  7. package/dist/contract-core.js +26 -812
  8. package/dist/contract-core.js.map +1 -1
  9. package/dist/contract-http/adapter.d.ts +13 -0
  10. package/dist/contract-http/adapter.d.ts.map +1 -1
  11. package/dist/contract-http/adapter.js +191 -23
  12. package/dist/contract-http/adapter.js.map +1 -1
  13. package/dist/contract-http/factory.d.ts +2 -2
  14. package/dist/contract-http/factory.d.ts.map +1 -1
  15. package/dist/contract-http/factory.js +5 -0
  16. package/dist/contract-http/factory.js.map +1 -1
  17. package/dist/contract-http/inbound-match.d.ts +47 -0
  18. package/dist/contract-http/inbound-match.d.ts.map +1 -0
  19. package/dist/contract-http/inbound-match.js +136 -0
  20. package/dist/contract-http/inbound-match.js.map +1 -0
  21. package/dist/contract-http/inbound-verify.d.ts +46 -0
  22. package/dist/contract-http/inbound-verify.d.ts.map +1 -0
  23. package/dist/contract-http/inbound-verify.js +101 -0
  24. package/dist/contract-http/inbound-verify.js.map +1 -0
  25. package/dist/contract-http/inbound.d.ts +45 -0
  26. package/dist/contract-http/inbound.d.ts.map +1 -0
  27. package/dist/contract-http/inbound.js +89 -0
  28. package/dist/contract-http/inbound.js.map +1 -0
  29. package/dist/contract-http/index.d.ts +5 -0
  30. package/dist/contract-http/index.d.ts.map +1 -1
  31. package/dist/contract-http/index.js +3 -0
  32. package/dist/contract-http/index.js.map +1 -1
  33. package/dist/contract-http/openapi.d.ts +0 -7
  34. package/dist/contract-http/openapi.d.ts.map +1 -1
  35. package/dist/contract-http/openapi.js +20 -14
  36. package/dist/contract-http/openapi.js.map +1 -1
  37. package/dist/contract-http/types.d.ts +106 -2
  38. package/dist/contract-http/types.d.ts.map +1 -1
  39. package/dist/contract-http/types.js +33 -0
  40. package/dist/contract-http/types.js.map +1 -1
  41. package/dist/contract-types.d.ts +148 -446
  42. package/dist/contract-types.d.ts.map +1 -1
  43. package/dist/data-path.d.ts.map +1 -1
  44. package/dist/data-path.js +10 -2
  45. package/dist/data-path.js.map +1 -1
  46. package/dist/index.d.ts +10 -6
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +10 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/internal.d.ts +7 -0
  51. package/dist/internal.d.ts.map +1 -1
  52. package/dist/internal.js +14 -0
  53. package/dist/internal.js.map +1 -1
  54. package/dist/load/artifact.d.ts +376 -0
  55. package/dist/load/artifact.d.ts.map +1 -0
  56. package/dist/load/artifact.js +14 -0
  57. package/dist/load/artifact.js.map +1 -0
  58. package/dist/load/builder.d.ts +80 -0
  59. package/dist/load/builder.d.ts.map +1 -0
  60. package/dist/load/builder.js +262 -0
  61. package/dist/load/builder.js.map +1 -0
  62. package/dist/load/context.d.ts +81 -0
  63. package/dist/load/context.d.ts.map +1 -0
  64. package/dist/load/context.js +2 -0
  65. package/dist/load/context.js.map +1 -0
  66. package/dist/load/duration.d.ts +9 -0
  67. package/dist/load/duration.d.ts.map +1 -0
  68. package/dist/load/duration.js +22 -0
  69. package/dist/load/duration.js.map +1 -0
  70. package/dist/load/events.d.ts +132 -0
  71. package/dist/load/events.d.ts.map +1 -0
  72. package/dist/load/events.js +2 -0
  73. package/dist/load/events.js.map +1 -0
  74. package/dist/load/feeder.d.ts +118 -0
  75. package/dist/load/feeder.d.ts.map +1 -0
  76. package/dist/load/feeder.js +170 -0
  77. package/dist/load/feeder.js.map +1 -0
  78. package/dist/load/index.d.ts +32 -0
  79. package/dist/load/index.d.ts.map +1 -0
  80. package/dist/load/index.js +7 -0
  81. package/dist/load/index.js.map +1 -0
  82. package/dist/load/progress.d.ts +56 -0
  83. package/dist/load/progress.d.ts.map +1 -0
  84. package/dist/load/progress.js +2 -0
  85. package/dist/load/progress.js.map +1 -0
  86. package/dist/load/projection.d.ts +36 -0
  87. package/dist/load/projection.d.ts.map +1 -0
  88. package/dist/load/projection.js +47 -0
  89. package/dist/load/projection.js.map +1 -0
  90. package/dist/load/runner.d.ts +201 -0
  91. package/dist/load/runner.d.ts.map +1 -0
  92. package/dist/load/runner.js +78 -0
  93. package/dist/load/runner.js.map +1 -0
  94. package/dist/load/scenario.d.ts +130 -0
  95. package/dist/load/scenario.d.ts.map +1 -0
  96. package/dist/load/scenario.js +9 -0
  97. package/dist/load/scenario.js.map +1 -0
  98. package/dist/load/step.d.ts +42 -0
  99. package/dist/load/step.d.ts.map +1 -0
  100. package/dist/load/step.js +2 -0
  101. package/dist/load/step.js.map +1 -0
  102. package/dist/{contract-flow-poll.d.ts → poll-primitives.d.ts} +8 -81
  103. package/dist/poll-primitives.d.ts.map +1 -0
  104. package/dist/{contract-flow-poll.js → poll-primitives.js} +10 -64
  105. package/dist/poll-primitives.js.map +1 -0
  106. package/dist/{contract-flow-condition.d.ts → predicates.d.ts} +34 -71
  107. package/dist/predicates.d.ts.map +1 -0
  108. package/dist/{contract-flow-condition.js → predicates.js} +86 -80
  109. package/dist/predicates.js.map +1 -0
  110. package/dist/test/builder.js +2 -2
  111. package/dist/test/builder.js.map +1 -1
  112. package/dist/test/utils.d.ts +7 -0
  113. package/dist/test/utils.d.ts.map +1 -1
  114. package/dist/test/utils.js +22 -17
  115. package/dist/test/utils.js.map +1 -1
  116. package/dist/types.d.ts +42 -14
  117. package/dist/types.d.ts.map +1 -1
  118. package/dist/types.js.map +1 -1
  119. package/dist/workflow/builder.d.ts +386 -0
  120. package/dist/workflow/builder.d.ts.map +1 -0
  121. package/dist/workflow/builder.js +1150 -0
  122. package/dist/workflow/builder.js.map +1 -0
  123. package/dist/workflow/execute.d.ts +277 -0
  124. package/dist/workflow/execute.d.ts.map +1 -0
  125. package/dist/workflow/execute.js +1489 -0
  126. package/dist/workflow/execute.js.map +1 -0
  127. package/dist/workflow/index.d.ts +11 -0
  128. package/dist/workflow/index.d.ts.map +1 -0
  129. package/dist/workflow/index.js +15 -0
  130. package/dist/workflow/index.js.map +1 -0
  131. package/dist/workflow/project.d.ts +18 -0
  132. package/dist/workflow/project.d.ts.map +1 -0
  133. package/dist/workflow/project.js +321 -0
  134. package/dist/workflow/project.js.map +1 -0
  135. package/dist/workflow/retry.d.ts +13 -0
  136. package/dist/workflow/retry.d.ts.map +1 -0
  137. package/dist/workflow/retry.js +15 -0
  138. package/dist/workflow/retry.js.map +1 -0
  139. package/dist/workflow/types.d.ts +512 -0
  140. package/dist/workflow/types.d.ts.map +1 -0
  141. package/dist/workflow/types.js +2 -0
  142. package/dist/workflow/types.js.map +1 -0
  143. package/package.json +9 -2
  144. package/dist/contract-flow-condition.d.ts.map +0 -1
  145. package/dist/contract-flow-condition.js.map +0 -1
  146. package/dist/contract-flow-poll.d.ts.map +0 -1
  147. package/dist/contract-flow-poll.js.map +0 -1
  148. package/dist/contract-http/flow-helpers.d.ts +0 -12
  149. package/dist/contract-http/flow-helpers.d.ts.map +0 -1
  150. package/dist/contract-http/flow-helpers.js +0 -34
  151. package/dist/contract-http/flow-helpers.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":""}
@@ -1,7 +1,12 @@
1
1
  /**
2
- * @module contract-flow-poll
2
+ * @module poll-primitives
3
3
  *
4
- * Bounded poll-until primitive for `contract.flow()` runtime + projection.
4
+ * Bounded poll-until primitives shared by the vNext `workflow().poll`
5
+ * executor, `test()` helpers, and (until D2 deletes it) the legacy
6
+ * `contract.flow()` loop. Renamed from `contract-flow-poll.ts` (Nv1-D1,
7
+ * 2026-06-13): the quarantine/budget/bounds machinery was never
8
+ * flow-specific. The legacy flow's poll step shapes that used to live here
9
+ * were deleted with the flow itself (Nv1-D2).
5
10
  *
6
11
  * A poll repeats ONE contract case until an exit predicate over the RESPONSE
7
12
  * holds, BOUNDED by a total wall-clock deadline and/or a finite per-attempt
@@ -15,50 +20,7 @@
15
20
  * validation, and the JSON-safe projection. The execution LOOP lives in
16
21
  * `contract-core.ts` (it needs the shared committed-state cell).
17
22
  */
18
- import type { ContractCaseRef, ProtocolContract, FieldMapping } from "./contract-types.js";
19
23
  import type { TestContext } from "./types.js";
20
- import { type BranchPredicate, type ExtractedPredicate } from "./contract-flow-condition.js";
21
- /**
22
- * Runtime representation of a `flow().poll()` step. Carries live callbacks +
23
- * the live contract ref. Never serialized — `extractPollStep` produces the
24
- * JSON-safe form.
25
- *
26
- * The exit predicate (`until`) is over the RESPONSE (not state): L2 declarative
27
- * (`BranchPredicate`, projectable) or opaque (L1 sync / L0 async, marked). The
28
- * opaque form additionally receives `state` so a poll can wait for the response
29
- * to reflect something already in state (e.g. `res.version >= state.lastSeen`).
30
- */
31
- export interface RuntimePollStep {
32
- kind: "poll";
33
- name?: string;
34
- ref: ContractCaseRef<any, any, any, any>;
35
- caseKey: string;
36
- /** Live contract instance (mirrors ref.contract). */
37
- contract: ProtocolContract<any, any, any>;
38
- bindings?: {
39
- in?: (state: any) => any;
40
- out?: (state: any, response: any) => any;
41
- accept?: readonly unknown[];
42
- };
43
- /** Exit predicate — L2 declarative (over the response) or opaque (gets ctx, res, state). */
44
- until: BranchPredicate<any> | {
45
- kind: "opaque";
46
- sync: boolean;
47
- fn: (ctx: TestContext, res: any, state: any) => boolean | Promise<boolean>;
48
- };
49
- /** Author-supplied label (opaque tiers require it; L2 can auto-generate). */
50
- message?: string;
51
- /** Interval between attempts (ms). */
52
- every: number;
53
- /** Multiplier applied to `every` after each retry (1 = fixed). Capped at BACKOFF_CAP_MS. */
54
- backoff: number;
55
- /** Total wall-clock bound (ms). */
56
- timeoutMs?: number;
57
- /** Per-attempt budget (ms) — required when `timeoutMs` is absent. */
58
- perAttemptTimeoutMs?: number;
59
- /** Max attempts (>= 1). */
60
- maxAttempts?: number;
61
- }
62
24
  /** Backoff cap — mirrors the test() step retry-backoff ceiling. */
63
25
  export declare const BACKOFF_CAP_MS = 30000;
64
26
  /** Default interval between attempts when `every` is omitted. */
@@ -104,13 +66,6 @@ export declare function quarantinedCtx(real: TestContext): QuarantinedContext;
104
66
  * happens defensively).
105
67
  */
106
68
  export declare function raceBudget<T>(promise: Promise<T>, budgetMs: number, onTimeout: () => Error): Promise<T>;
107
- /**
108
- * Evaluate a poll exit predicate. L2 declarative reads the RESPONSE (`evalPredicate`
109
- * with subject = response). Opaque tiers get `(ctx, res, state)`. Non-boolean
110
- * results fail fast (mirrors condition Phase 6); a thrown error / `ctx.skip()`
111
- * propagates to the caller.
112
- */
113
- export declare function evalPollExit(until: RuntimePollStep["until"], response: unknown, ctx: TestContext, state: unknown): Promise<boolean>;
114
69
  /**
115
70
  * Validate poll bounds at construction. Two rules (both required), plus
116
71
  * finiteness on every timing value (an `Infinity` bound would un-bound the loop):
@@ -126,32 +81,4 @@ export declare function validatePollBounds(bounds: {
126
81
  every?: number;
127
82
  backoff?: number;
128
83
  }, stepLabel: string): void;
129
- export interface ExtractedPollStep {
130
- kind: "poll";
131
- name?: string;
132
- contractId: string;
133
- caseKey: string;
134
- protocol: string;
135
- target: string;
136
- inputs?: FieldMapping[];
137
- outputs?: FieldMapping[];
138
- accept?: ReadonlyArray<string | number>;
139
- /** Exit predicate — L2 precise (compare/in/...) or `{kind:"opaque",...}`. */
140
- until: ExtractedPredicate;
141
- message?: string;
142
- every: number;
143
- backoff: number;
144
- timeoutMs?: number;
145
- perAttemptTimeoutMs?: number;
146
- maxAttempts?: number;
147
- }
148
- /**
149
- * Normalize a runtime poll step to JSON-safe form. `dryRun` produces the
150
- * input/output field mappings (the same Proxy dry-run normalizeFlow uses for a
151
- * contract-call step), so the poll node carries data-flow edges like a step.
152
- */
153
- export declare function extractPollStep(step: RuntimePollStep, dryRun: (step: RuntimePollStep) => {
154
- inputs?: FieldMapping[];
155
- outputs?: FieldMapping[];
156
- }): ExtractedPollStep;
157
- //# sourceMappingURL=contract-flow-poll.d.ts.map
84
+ //# sourceMappingURL=poll-primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll-primitives.d.ts","sourceRoot":"","sources":["../src/poll-primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AAG1D,mEAAmE;AACnE,eAAO,MAAM,cAAc,QAAS,CAAC;AACrC,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAMrC,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBACd,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQjE;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,oGAAoG;IACpG,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,6EAA6E;IAC7E,UAAU,IAAI,OAAO,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,kBAAkB,CA2FpE;AAMD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,KAAK,GACrB,OAAO,CAAC,CAAC,CAAC,CAeZ;AAID;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE;IACN,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,EACD,SAAS,EAAE,MAAM,GAChB,IAAI,CA2BN"}