@synode/core 1.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/LICENSE +35 -0
- package/dist/engine-CgLY6SKJ.cjs +593 -0
- package/dist/engine-CgLY6SKJ.cjs.map +1 -0
- package/dist/engine-SRByMZvP.mjs +515 -0
- package/dist/engine-SRByMZvP.mjs.map +1 -0
- package/dist/execution/worker.cjs +125 -0
- package/dist/execution/worker.cjs.map +1 -0
- package/dist/execution/worker.d.cts +1 -0
- package/dist/execution/worker.d.mts +1 -0
- package/dist/execution/worker.mjs +125 -0
- package/dist/execution/worker.mjs.map +1 -0
- package/dist/index.cjs +1163 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1142 -0
- package/dist/index.d.mts +1142 -0
- package/dist/index.mjs +1093 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +60 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1142 @@
|
|
|
1
|
+
import { Faker } from "@faker-js/faker";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a generated event.
|
|
8
|
+
* @see {@link Action} for how events are generated
|
|
9
|
+
*/
|
|
10
|
+
interface Event {
|
|
11
|
+
id: string;
|
|
12
|
+
userId: string;
|
|
13
|
+
sessionId: string;
|
|
14
|
+
name: string;
|
|
15
|
+
timestamp: Date;
|
|
16
|
+
payload: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Lifecycle scope for context fields.
|
|
20
|
+
* Fields with a scope will be automatically cleared when that scope ends.
|
|
21
|
+
*/
|
|
22
|
+
type ContextScope = 'action' | 'adventure' | 'journey';
|
|
23
|
+
/**
|
|
24
|
+
* Options for setting a context field with TTL/scope.
|
|
25
|
+
*/
|
|
26
|
+
interface ContextSetOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Lifecycle scope for this field. When the scope ends, the field is automatically cleared.
|
|
29
|
+
* - 'action': Field lives only for the duration of the current action
|
|
30
|
+
* - 'adventure': Field lives for the duration of the current adventure
|
|
31
|
+
* - 'journey': Field lives for the duration of the current journey
|
|
32
|
+
*/
|
|
33
|
+
scope?: ContextScope;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Represents the execution context for a user's journey.
|
|
37
|
+
* @see {@link SynodeContext} for the implementation
|
|
38
|
+
*/
|
|
39
|
+
interface Context {
|
|
40
|
+
readonly userId: string;
|
|
41
|
+
readonly sessionId: string;
|
|
42
|
+
readonly locale: string;
|
|
43
|
+
readonly faker: Faker;
|
|
44
|
+
get<T>(key: string): T | undefined;
|
|
45
|
+
set<T>(key: string, value: T, options?: ContextSetOptions): void;
|
|
46
|
+
now(): Date;
|
|
47
|
+
generateId(prefix?: string): string;
|
|
48
|
+
hasCompletedJourney(journeyId: string): boolean;
|
|
49
|
+
markJourneyComplete(journeyId: string): void;
|
|
50
|
+
dataset(id: string): DatasetHandle;
|
|
51
|
+
/**
|
|
52
|
+
* Get a typed dataset handle. Use this with InferDatasetRow for type safety.
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const productsDef = defineDataset({ ... });
|
|
56
|
+
* type Product = InferDatasetRow<typeof productsDef>;
|
|
57
|
+
* const products = ctx.typedDataset<Product>('products');
|
|
58
|
+
* const product = products.randomRow(); // typed as Product
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
typedDataset<TRow extends DatasetRow>(id: string): DatasetHandle<TRow>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Handle for querying a dataset from context.
|
|
65
|
+
*/
|
|
66
|
+
interface DatasetHandle<TRow = DatasetRow> {
|
|
67
|
+
randomRow(): TRow;
|
|
68
|
+
getRowById(id: string | number): TRow | undefined;
|
|
69
|
+
getRowByIndex(index: number): TRow | undefined;
|
|
70
|
+
getAllRows(): TRow[];
|
|
71
|
+
size(): number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Represents a single row in a dataset.
|
|
75
|
+
*/
|
|
76
|
+
type DatasetRow = Record<string, unknown>;
|
|
77
|
+
/**
|
|
78
|
+
* Represents a generated dataset with metadata and rows.
|
|
79
|
+
*/
|
|
80
|
+
interface Dataset<TRow = DatasetRow> {
|
|
81
|
+
id: string;
|
|
82
|
+
name: string;
|
|
83
|
+
rows: TRow[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Field generator with access to row metadata.
|
|
87
|
+
*/
|
|
88
|
+
type DatasetFieldGenerator<T = unknown> = T | ((context: Context, row: {
|
|
89
|
+
index: number;
|
|
90
|
+
data: DatasetRow;
|
|
91
|
+
}) => T | Promise<T>);
|
|
92
|
+
/**
|
|
93
|
+
* Configuration for defining a dataset.
|
|
94
|
+
* @see {@link InferDatasetRow} for type inference
|
|
95
|
+
* @see {@link defineDataset} for the builder function
|
|
96
|
+
*/
|
|
97
|
+
interface DatasetDefinition<TFields$1 extends Record<string, unknown> = Record<string, unknown>> {
|
|
98
|
+
id: string;
|
|
99
|
+
name: string;
|
|
100
|
+
count: number;
|
|
101
|
+
fields: { [K in keyof TFields$1]: TFields$1[K] | ((context: Context, row: {
|
|
102
|
+
index: number;
|
|
103
|
+
data: DatasetRow;
|
|
104
|
+
}) => TFields$1[K] | Promise<TFields$1[K]>) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Infer the row type from a dataset definition.
|
|
108
|
+
* This provides type safety similar to Zod's z.infer.
|
|
109
|
+
* @see {@link DatasetDefinition} for defining datasets
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const productsDef = defineDataset({
|
|
114
|
+
* id: 'products',
|
|
115
|
+
* name: 'Products',
|
|
116
|
+
* count: 100,
|
|
117
|
+
* fields: {
|
|
118
|
+
* id: (ctx, row) => `prod-${row.index}`,
|
|
119
|
+
* name: (ctx) => ctx.faker.commerce.productName(),
|
|
120
|
+
* price: (ctx) => ctx.faker.number.float({ min: 10, max: 500 }),
|
|
121
|
+
* category: oneOf(['electronics', 'clothing', 'home']),
|
|
122
|
+
* },
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* // Infer the type
|
|
126
|
+
* type Product = InferDatasetRow<typeof productsDef>;
|
|
127
|
+
* // Result: { id: string; name: string; price: number; category: string; }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
/**
|
|
131
|
+
* Infers the row type from a dataset definition, unwrapping generator functions and promises.
|
|
132
|
+
* For each field, if it is a function, uses its return type (unwrapping Promise if needed); otherwise, uses the type as-is.
|
|
133
|
+
*/
|
|
134
|
+
type InferDatasetRow<T> = T extends DatasetDefinition<infer TFields> ? { [K in keyof TFields]: TFields[K] extends ((...args: any[]) => infer R) ? R extends Promise<infer U> ? U : R : TFields[K] } : never;
|
|
135
|
+
/**
|
|
136
|
+
* Time span configuration for delays.
|
|
137
|
+
*/
|
|
138
|
+
interface TimeSpan {
|
|
139
|
+
min: number;
|
|
140
|
+
max: number;
|
|
141
|
+
distribution?: 'uniform' | 'gaussian' | 'exponential';
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Suppression period after journey completion or bounce.
|
|
145
|
+
*/
|
|
146
|
+
interface SuppressionPeriod {
|
|
147
|
+
min: number;
|
|
148
|
+
max: number;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Represents the configuration for a synthetic data generation journey.
|
|
152
|
+
* @see {@link Adventure} for session sequences
|
|
153
|
+
* @see {@link defineJourney} for the builder function
|
|
154
|
+
*/
|
|
155
|
+
interface Journey {
|
|
156
|
+
id: string;
|
|
157
|
+
name: string;
|
|
158
|
+
/**
|
|
159
|
+
* Journey IDs that must be completed before this journey can start.
|
|
160
|
+
*/
|
|
161
|
+
requires?: string[];
|
|
162
|
+
adventures: Adventure[];
|
|
163
|
+
/**
|
|
164
|
+
* Chance (0-1) that the journey is never started or completed.
|
|
165
|
+
*/
|
|
166
|
+
bounceChance?: number;
|
|
167
|
+
/**
|
|
168
|
+
* Suppression period after journey completes or bounces.
|
|
169
|
+
*/
|
|
170
|
+
suppressionPeriod?: SuppressionPeriod;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Represents a sequence of actions within a journey.
|
|
174
|
+
* @see {@link Action} for individual behaviors
|
|
175
|
+
* @see {@link defineAdventure} for the builder function
|
|
176
|
+
*/
|
|
177
|
+
interface Adventure {
|
|
178
|
+
id: string;
|
|
179
|
+
name: string;
|
|
180
|
+
actions: Action[];
|
|
181
|
+
/**
|
|
182
|
+
* Time span between actions in this adventure.
|
|
183
|
+
*/
|
|
184
|
+
timeSpan?: TimeSpan;
|
|
185
|
+
/**
|
|
186
|
+
* Chance (0-1) to abandon this adventure.
|
|
187
|
+
*/
|
|
188
|
+
bounceChance?: number;
|
|
189
|
+
/**
|
|
190
|
+
* What to do on bounce: 'stop' ends the journey, 'skip' continues to next adventure.
|
|
191
|
+
*/
|
|
192
|
+
onBounce?: 'stop' | 'skip';
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Represents a single step or event generator in an adventure.
|
|
196
|
+
* @see {@link defineAction} for the builder function
|
|
197
|
+
*/
|
|
198
|
+
interface Action {
|
|
199
|
+
id: string;
|
|
200
|
+
name: string;
|
|
201
|
+
/**
|
|
202
|
+
* Handler must return an array of Events.
|
|
203
|
+
*/
|
|
204
|
+
handler: (context: Context) => Event[] | Promise<Event[]>;
|
|
205
|
+
/**
|
|
206
|
+
* Time span between individual events generated by this action.
|
|
207
|
+
*/
|
|
208
|
+
timeSpan?: TimeSpan;
|
|
209
|
+
/**
|
|
210
|
+
* Chance (0-1) to abandon during this action.
|
|
211
|
+
*/
|
|
212
|
+
bounceChance?: number;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Type definition for a field generator.
|
|
216
|
+
* Can be a static value or a function that returns a value.
|
|
217
|
+
*/
|
|
218
|
+
type FieldGenerator<T = unknown> = T | ((context: Context, payload: Record<string, unknown>) => T | Promise<T>);
|
|
219
|
+
/**
|
|
220
|
+
* Configuration object for defining an action.
|
|
221
|
+
* @see {@link Action} for the resolved type
|
|
222
|
+
*/
|
|
223
|
+
interface ActionDefinition {
|
|
224
|
+
id: string;
|
|
225
|
+
name: string;
|
|
226
|
+
/**
|
|
227
|
+
* Map of field names to their generators.
|
|
228
|
+
*/
|
|
229
|
+
fields?: Record<string, FieldGenerator>;
|
|
230
|
+
/**
|
|
231
|
+
* Custom handler function. If provided, 'fields' is ignored.
|
|
232
|
+
* Must return an array of Events.
|
|
233
|
+
*/
|
|
234
|
+
handler?: (context: Context) => Event[] | Promise<Event[]>;
|
|
235
|
+
/**
|
|
236
|
+
* Time span between individual events generated by this action.
|
|
237
|
+
*/
|
|
238
|
+
timeSpan?: TimeSpan;
|
|
239
|
+
/**
|
|
240
|
+
* Chance (0-1) to abandon during this action.
|
|
241
|
+
*/
|
|
242
|
+
bounceChance?: number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Validation behavior when an event fails schema validation.
|
|
246
|
+
* - 'strict': throw on first invalid event
|
|
247
|
+
* - 'warn': keep the event but record the failure in the summary
|
|
248
|
+
* - 'skip': drop the event and record the failure in the summary
|
|
249
|
+
*/
|
|
250
|
+
type EventValidationMode = 'strict' | 'warn' | 'skip';
|
|
251
|
+
/**
|
|
252
|
+
* Configuration for event schema validation.
|
|
253
|
+
*
|
|
254
|
+
* @param schema - A single Zod schema applied to all events, or a record mapping
|
|
255
|
+
* event names to their individual Zod schemas
|
|
256
|
+
* @param mode - Validation behavior on failure (default: 'strict')
|
|
257
|
+
*/
|
|
258
|
+
interface EventSchemaConfig {
|
|
259
|
+
schema: z.ZodType | Record<string, z.ZodType>;
|
|
260
|
+
mode?: EventValidationMode;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Interface for output adapters that handle generated events.
|
|
264
|
+
*
|
|
265
|
+
* Adapters receive events one at a time during generation and are responsible
|
|
266
|
+
* for routing them to their final destination (console, file, HTTP, etc.).
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```ts
|
|
270
|
+
* const adapter: OutputAdapter = {
|
|
271
|
+
* write(event) { console.log(event.name); },
|
|
272
|
+
* close() { console.log('done'); },
|
|
273
|
+
* };
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
interface OutputAdapter {
|
|
277
|
+
/**
|
|
278
|
+
* Writes a single event to the output destination.
|
|
279
|
+
*
|
|
280
|
+
* @param event - The generated event to write
|
|
281
|
+
* @returns void or a Promise that resolves when the write completes
|
|
282
|
+
*/
|
|
283
|
+
write(event: Event): Promise<void> | void;
|
|
284
|
+
/**
|
|
285
|
+
* Optional cleanup hook called once after all events have been written.
|
|
286
|
+
* Use for flushing buffers, closing file handles, or finalizing connections.
|
|
287
|
+
*
|
|
288
|
+
* @returns void or a Promise that resolves when cleanup completes
|
|
289
|
+
*/
|
|
290
|
+
close?(): Promise<void> | void;
|
|
291
|
+
}
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/errors.d.ts
|
|
294
|
+
/**
|
|
295
|
+
* Error codes for all Synode validation and runtime errors.
|
|
296
|
+
*/
|
|
297
|
+
type ErrorCode = 'INVALID_BOUNCE_CHANCE' | 'INVALID_TIME_SPAN' | 'INVALID_SUPPRESSION_PERIOD' | 'UNKNOWN_JOURNEY_REF' | 'CIRCULAR_DEPENDENCY' | 'DUPLICATE_ID' | 'DATASET_NOT_FOUND' | 'DATASET_EMPTY' | 'HANDLER_ERROR' | 'ADAPTER_WRITE_ERROR' | 'INVALID_HANDLER_RETURN' | 'TYPO_DETECTED' | 'INVALID_DATASET_COUNT';
|
|
298
|
+
/**
|
|
299
|
+
* Options for constructing a SynodeError.
|
|
300
|
+
*
|
|
301
|
+
* @param code - The structured error code identifying the error type
|
|
302
|
+
* @param message - The human-readable error message
|
|
303
|
+
* @param path - Hierarchical path segments (journey, adventure, action, step)
|
|
304
|
+
* @param suggestion - Optional suggestion for fixing the error
|
|
305
|
+
* @param expected - Optional description of the expected value
|
|
306
|
+
* @param received - Optional description of the actual value received
|
|
307
|
+
* @param cause - Optional underlying error that caused this one
|
|
308
|
+
*/
|
|
309
|
+
interface SynodeErrorOptions {
|
|
310
|
+
code: ErrorCode;
|
|
311
|
+
message: string;
|
|
312
|
+
path: string[];
|
|
313
|
+
suggestion?: string;
|
|
314
|
+
expected?: string;
|
|
315
|
+
received?: string;
|
|
316
|
+
cause?: unknown;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Formats an error message with a hierarchical path prefix and optional suggestion.
|
|
320
|
+
*
|
|
321
|
+
* @param message - The base error message
|
|
322
|
+
* @param path - Hierarchical path segments labeled Journey/Adventure/Action/Step
|
|
323
|
+
* @param suggestion - Optional suggestion appended on a new line
|
|
324
|
+
* @returns The formatted message string
|
|
325
|
+
*/
|
|
326
|
+
declare function formatErrorMessage(message: string, path: string[], suggestion?: string): string;
|
|
327
|
+
/**
|
|
328
|
+
* Structured error class for all Synode validation and runtime errors.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* throw new SynodeError({
|
|
333
|
+
* code: 'INVALID_BOUNCE_CHANCE',
|
|
334
|
+
* message: 'Bounce chance must be between 0 and 1',
|
|
335
|
+
* path: ['Purchase Flow', 'Checkout', 'Submit Order'],
|
|
336
|
+
* expected: 'number between 0 and 1',
|
|
337
|
+
* received: '1.5',
|
|
338
|
+
* });
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
declare class SynodeError extends Error {
|
|
342
|
+
/** Structured error code identifying the error type. */
|
|
343
|
+
readonly code: ErrorCode;
|
|
344
|
+
/** Hierarchical path where the error occurred. */
|
|
345
|
+
readonly path: string[];
|
|
346
|
+
/** Optional suggestion for fixing the error. */
|
|
347
|
+
readonly suggestion: string | undefined;
|
|
348
|
+
/** The original unformatted error message. */
|
|
349
|
+
readonly rawMessage: string;
|
|
350
|
+
/** Optional description of the expected value. */
|
|
351
|
+
readonly expected: string | undefined;
|
|
352
|
+
/** Optional description of the actual value received. */
|
|
353
|
+
readonly received: string | undefined;
|
|
354
|
+
constructor(options: SynodeErrorOptions);
|
|
355
|
+
/**
|
|
356
|
+
* Produces a structured multi-line representation of the error for human-readable output.
|
|
357
|
+
*
|
|
358
|
+
* Format:
|
|
359
|
+
* ```
|
|
360
|
+
* [ERROR_CODE] rawMessage
|
|
361
|
+
* Path: Journey 'x' > Adventure 'y' > Action 'z'
|
|
362
|
+
* Expected: what was expected
|
|
363
|
+
* Received: what was provided
|
|
364
|
+
* Fix: suggestion
|
|
365
|
+
* ```
|
|
366
|
+
*
|
|
367
|
+
* Path is omitted when path is empty. Expected/Received are omitted when not provided.
|
|
368
|
+
* Fix is omitted when there is no suggestion.
|
|
369
|
+
*
|
|
370
|
+
* @returns A formatted string representation of the error.
|
|
371
|
+
*/
|
|
372
|
+
format(): string;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Computes the Levenshtein edit distance between two strings using a space-efficient
|
|
376
|
+
* two-row approach.
|
|
377
|
+
*
|
|
378
|
+
* @param a - First string
|
|
379
|
+
* @param b - Second string
|
|
380
|
+
* @returns The minimum number of single-character edits (insertions, deletions, substitutions)
|
|
381
|
+
*/
|
|
382
|
+
declare function levenshtein(a: string, b: string): number;
|
|
383
|
+
/**
|
|
384
|
+
* Finds the closest matching string from a list of candidates using Levenshtein distance.
|
|
385
|
+
* Returns undefined if no candidate is within the dynamic threshold.
|
|
386
|
+
*
|
|
387
|
+
* The threshold is `max(3, floor(maxLen * 0.4))` where maxLen is the longer of the
|
|
388
|
+
* input and candidate strings.
|
|
389
|
+
*
|
|
390
|
+
* @param input - The string to match against candidates
|
|
391
|
+
* @param candidates - List of valid strings to compare against
|
|
392
|
+
* @returns The closest matching candidate, or undefined if none is close enough
|
|
393
|
+
*/
|
|
394
|
+
declare function suggestClosest(input: string, candidates: string[]): string | undefined;
|
|
395
|
+
/**
|
|
396
|
+
* Builds a human-readable suggestion string for a not-found error, including
|
|
397
|
+
* the closest match (if any) and the full list of available options.
|
|
398
|
+
*
|
|
399
|
+
* @param kind - The kind of entity (e.g., "dataset", "journey")
|
|
400
|
+
* @param requested - The name that was requested but not found
|
|
401
|
+
* @param available - List of valid names
|
|
402
|
+
* @returns A suggestion string with "Did you mean..." and/or available options
|
|
403
|
+
*/
|
|
404
|
+
declare function buildNotFoundSuggestion(kind: string, requested: string, available: string[]): string;
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/state/ids.d.ts
|
|
407
|
+
/**
|
|
408
|
+
* Interface for ID generation strategies.
|
|
409
|
+
*/
|
|
410
|
+
interface IdGenerator {
|
|
411
|
+
generate(prefix?: string): string;
|
|
412
|
+
}
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/state/context.d.ts
|
|
415
|
+
declare class SynodeContext implements Context {
|
|
416
|
+
private idGenerator;
|
|
417
|
+
readonly locale: string;
|
|
418
|
+
private state;
|
|
419
|
+
private fieldMetadata;
|
|
420
|
+
private currentTime;
|
|
421
|
+
private _userId;
|
|
422
|
+
private _sessionId;
|
|
423
|
+
private _faker;
|
|
424
|
+
private completedJourneys;
|
|
425
|
+
private datasets;
|
|
426
|
+
constructor(startTime?: Date, idGenerator?: IdGenerator, locale?: string);
|
|
427
|
+
get faker(): Faker;
|
|
428
|
+
get userId(): string;
|
|
429
|
+
get sessionId(): string;
|
|
430
|
+
get<T>(key: string): T | undefined;
|
|
431
|
+
/**
|
|
432
|
+
* Set a context field value with optional scope for automatic cleanup.
|
|
433
|
+
*
|
|
434
|
+
* @param key - The field name
|
|
435
|
+
* @param value - The field value
|
|
436
|
+
* @param options - Optional settings including lifecycle scope
|
|
437
|
+
*
|
|
438
|
+
* @remarks
|
|
439
|
+
* When calling `set()` multiple times on the same field with different scopes,
|
|
440
|
+
* the most recent scope setting will be used. For example, if a field is first
|
|
441
|
+
* set with `scope: 'adventure'` and later set again with `scope: 'action'`,
|
|
442
|
+
* it will be cleared at the end of the action rather than the adventure.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* ctx.set('cartItems', [], { scope: 'adventure' });
|
|
447
|
+
* // Later in the same adventure...
|
|
448
|
+
* ctx.set('cartItems', ['item1'], { scope: 'action' }); // Now scoped to action
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
set<T>(key: string, value: T, options?: ContextSetOptions): void;
|
|
452
|
+
now(): Date;
|
|
453
|
+
generateId(prefix?: string): string;
|
|
454
|
+
hasCompletedJourney(journeyId: string): boolean;
|
|
455
|
+
markJourneyComplete(journeyId: string): void;
|
|
456
|
+
dataset(id: string): DatasetHandle;
|
|
457
|
+
typedDataset<TRow extends DatasetRow>(id: string): DatasetHandle<TRow>;
|
|
458
|
+
/**
|
|
459
|
+
* Internal: Register a dataset for use in this context.
|
|
460
|
+
*/
|
|
461
|
+
registerDataset(dataset: Dataset): void;
|
|
462
|
+
/**
|
|
463
|
+
* Internal: Advance the simulation time.
|
|
464
|
+
*/
|
|
465
|
+
advanceTime(ms: number): void;
|
|
466
|
+
/**
|
|
467
|
+
* Internal: Rotate the session ID.
|
|
468
|
+
*/
|
|
469
|
+
rotateSession(): void;
|
|
470
|
+
/**
|
|
471
|
+
* Internal: Clear all fields with the specified scope.
|
|
472
|
+
* Called by the engine when a scope ends.
|
|
473
|
+
*/
|
|
474
|
+
clearScope(scope: ContextScope): void;
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
477
|
+
//#region src/generators/builder.d.ts
|
|
478
|
+
/**
|
|
479
|
+
* Defines a new journey.
|
|
480
|
+
* @param config The journey configuration.
|
|
481
|
+
* @returns The configured journey object.
|
|
482
|
+
* @see {@link Journey}
|
|
483
|
+
*/
|
|
484
|
+
declare function defineJourney(config: Journey): Journey;
|
|
485
|
+
/**
|
|
486
|
+
* Defines a new adventure.
|
|
487
|
+
* @param config The adventure configuration.
|
|
488
|
+
* @returns The configured adventure object.
|
|
489
|
+
* @see {@link Adventure}
|
|
490
|
+
*/
|
|
491
|
+
declare function defineAdventure(config: Adventure): Adventure;
|
|
492
|
+
/**
|
|
493
|
+
* Defines a new action.
|
|
494
|
+
* @param config The action configuration.
|
|
495
|
+
* @returns The configured action object.
|
|
496
|
+
* @see {@link Action}
|
|
497
|
+
* @see {@link ActionDefinition}
|
|
498
|
+
*/
|
|
499
|
+
declare function defineAction(config: ActionDefinition): Action;
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/generators/fields.d.ts
|
|
502
|
+
/**
|
|
503
|
+
* Returns a value generated by Faker.js using the context's locale.
|
|
504
|
+
* @param generator Function that takes a Faker instance and returns a value.
|
|
505
|
+
*/
|
|
506
|
+
declare function fake<T>(generator: (faker: Faker) => T): FieldGenerator<T>;
|
|
507
|
+
/**
|
|
508
|
+
* Returns one of the provided options randomly.
|
|
509
|
+
*/
|
|
510
|
+
declare function oneOf<T>(options: T[]): FieldGenerator<T>;
|
|
511
|
+
/**
|
|
512
|
+
* Returns true with the given probability (0-1).
|
|
513
|
+
*/
|
|
514
|
+
declare function chance(probability: number): FieldGenerator<boolean>;
|
|
515
|
+
/**
|
|
516
|
+
* Returns a value based on weighted probabilities.
|
|
517
|
+
* @param options Map of value to weight (weights should sum to 1, but will be normalized if not)
|
|
518
|
+
*/
|
|
519
|
+
declare function weighted<T extends string>(options: Record<T, number>): FieldGenerator<T>;
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region src/generators/persona.d.ts
|
|
522
|
+
/**
|
|
523
|
+
* Configuration for a user persona.
|
|
524
|
+
*/
|
|
525
|
+
interface PersonaDefinition {
|
|
526
|
+
id: string;
|
|
527
|
+
name: string;
|
|
528
|
+
/**
|
|
529
|
+
* Attributes to initialize in the user's context.
|
|
530
|
+
* Can include 'locale' to set the faker locale.
|
|
531
|
+
*/
|
|
532
|
+
attributes: Record<string, FieldGenerator>;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Represents an instantiated persona.
|
|
536
|
+
*/
|
|
537
|
+
interface Persona {
|
|
538
|
+
id: string;
|
|
539
|
+
name: string;
|
|
540
|
+
attributes: Record<string, unknown>;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Defines a new persona.
|
|
544
|
+
*/
|
|
545
|
+
declare function definePersona(config: PersonaDefinition): PersonaDefinition;
|
|
546
|
+
/**
|
|
547
|
+
* Generates a concrete persona instance from a definition.
|
|
548
|
+
* This resolves all dynamic fields and weighted distributions.
|
|
549
|
+
*/
|
|
550
|
+
declare function generatePersona(definition: PersonaDefinition, baseContext: Context): Promise<Persona>;
|
|
551
|
+
//#endregion
|
|
552
|
+
//#region src/generators/dataset.d.ts
|
|
553
|
+
/**
|
|
554
|
+
* Defines a new dataset with type inference support.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```typescript
|
|
558
|
+
* const products = defineDataset({
|
|
559
|
+
* id: 'products',
|
|
560
|
+
* name: 'Products',
|
|
561
|
+
* count: 100,
|
|
562
|
+
* fields: {
|
|
563
|
+
* id: (ctx, row) => `prod-${row.index}`,
|
|
564
|
+
* name: (ctx) => ctx.faker.commerce.productName(),
|
|
565
|
+
* price: (ctx) => ctx.faker.number.float({ min: 10, max: 500 }),
|
|
566
|
+
* },
|
|
567
|
+
* });
|
|
568
|
+
*
|
|
569
|
+
* // Type inference works automatically
|
|
570
|
+
* type Product = InferDatasetRow<typeof products>;
|
|
571
|
+
* ```
|
|
572
|
+
*/
|
|
573
|
+
declare function defineDataset<TFields$1 extends Record<string, unknown>>(config: DatasetDefinition<TFields$1>): DatasetDefinition<TFields$1>;
|
|
574
|
+
/**
|
|
575
|
+
* Generates a concrete dataset from a definition.
|
|
576
|
+
* @param definition The dataset definition.
|
|
577
|
+
* @param context Context providing access to faker, other datasets, and user data.
|
|
578
|
+
*/
|
|
579
|
+
declare function generateDataset<TFields$1 extends Record<string, unknown>>(definition: DatasetDefinition<TFields$1>, context: Context): Promise<Dataset>;
|
|
580
|
+
//#endregion
|
|
581
|
+
//#region src/execution/engine.d.ts
|
|
582
|
+
declare class Engine {
|
|
583
|
+
private journey;
|
|
584
|
+
constructor(journey: Journey);
|
|
585
|
+
/**
|
|
586
|
+
* Executes the journey and yields events.
|
|
587
|
+
* @param context Optional context to use. If not provided, a new one is created.
|
|
588
|
+
*/
|
|
589
|
+
run(context?: SynodeContext): AsyncGenerator<Event>;
|
|
590
|
+
}
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/execution/runner.d.ts
|
|
593
|
+
interface RunOptions {
|
|
594
|
+
/**
|
|
595
|
+
* Total number of users to simulate.
|
|
596
|
+
*/
|
|
597
|
+
users: number;
|
|
598
|
+
/**
|
|
599
|
+
* Persona definition to use for generating users.
|
|
600
|
+
* If provided, context will be initialized with persona attributes.
|
|
601
|
+
*/
|
|
602
|
+
persona?: PersonaDefinition;
|
|
603
|
+
/**
|
|
604
|
+
* Optional dataset definitions to pre-generate before journey execution.
|
|
605
|
+
* Datasets can be referenced within journey actions using ctx.dataset('id').
|
|
606
|
+
*/
|
|
607
|
+
datasets?: DatasetDefinition[];
|
|
608
|
+
/**
|
|
609
|
+
* Number of parallel lanes to use for generation.
|
|
610
|
+
* Lanes process users concurrently using async execution.
|
|
611
|
+
* @default 1
|
|
612
|
+
*/
|
|
613
|
+
lanes?: number;
|
|
614
|
+
/**
|
|
615
|
+
* Output adapter to write events to.
|
|
616
|
+
* @default ConsoleAdapter
|
|
617
|
+
*/
|
|
618
|
+
adapter?: OutputAdapter;
|
|
619
|
+
/**
|
|
620
|
+
* Enable debug mode with telemetry collection.
|
|
621
|
+
* When enabled, collects detailed metrics about the generation run.
|
|
622
|
+
* @default false
|
|
623
|
+
*/
|
|
624
|
+
debug?: boolean;
|
|
625
|
+
/**
|
|
626
|
+
* File path to save telemetry data when debug mode is enabled.
|
|
627
|
+
* @default './telemetry-report.json'
|
|
628
|
+
*/
|
|
629
|
+
telemetryPath?: string;
|
|
630
|
+
/**
|
|
631
|
+
* Pre-loaded datasets to register with each user's context.
|
|
632
|
+
* Unlike `datasets` (which generates from definitions), these are already populated.
|
|
633
|
+
* Useful for datasets imported from external sources like BigQuery.
|
|
634
|
+
*/
|
|
635
|
+
preloadedDatasets?: Dataset[];
|
|
636
|
+
/**
|
|
637
|
+
* Start of the date range for user start times.
|
|
638
|
+
* Must be provided together with endDate.
|
|
639
|
+
*/
|
|
640
|
+
startDate?: Date;
|
|
641
|
+
/**
|
|
642
|
+
* End of the date range for user start times.
|
|
643
|
+
* Must be provided together with startDate.
|
|
644
|
+
*/
|
|
645
|
+
endDate?: Date;
|
|
646
|
+
/**
|
|
647
|
+
* Event schema validation configuration.
|
|
648
|
+
* When provided, each event is validated against the schema before adapter.write().
|
|
649
|
+
*/
|
|
650
|
+
eventSchema?: EventSchemaConfig;
|
|
651
|
+
/**
|
|
652
|
+
* Path to a module that exports journey definitions for worker thread parallelism.
|
|
653
|
+
* When provided, generation runs in worker threads instead of Promise.all lanes.
|
|
654
|
+
* The module must export: { journeys: Journey[], persona?, datasets?, preloadedDatasets? }
|
|
655
|
+
*/
|
|
656
|
+
workerModule?: string;
|
|
657
|
+
/**
|
|
658
|
+
* Number of worker threads to spawn. Default: number of CPU cores.
|
|
659
|
+
* Only used when workerModule is set.
|
|
660
|
+
*/
|
|
661
|
+
workers?: number;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Generates synthetic data based on the provided journey configuration.
|
|
665
|
+
*/
|
|
666
|
+
declare function generate(journey: Journey | Journey[], options: RunOptions): Promise<void>;
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region src/execution/worker-types.d.ts
|
|
669
|
+
/**
|
|
670
|
+
* Initialization payload sent to each worker thread via `workerData`.
|
|
671
|
+
* Contains the module path, user range assignment, and any pre-serialized datasets.
|
|
672
|
+
*/
|
|
673
|
+
interface WorkerInit {
|
|
674
|
+
/** Absolute path to the user's journey module (TS or JS). */
|
|
675
|
+
workerModule: string;
|
|
676
|
+
/** First user index (inclusive) this worker should process. */
|
|
677
|
+
userStart: number;
|
|
678
|
+
/** Last user index (exclusive) this worker should process. */
|
|
679
|
+
userEnd: number;
|
|
680
|
+
/** ISO 8601 start date for randomizing user start times. */
|
|
681
|
+
startDate?: string;
|
|
682
|
+
/** ISO 8601 end date for randomizing user start times. */
|
|
683
|
+
endDate?: string;
|
|
684
|
+
/** Pre-generated datasets serialized for structured clone transfer. */
|
|
685
|
+
serializedDatasets?: SerializedDataset[];
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* A dataset serialized for transfer across the structured clone boundary.
|
|
689
|
+
* Mirrors {@link Dataset} but uses plain objects instead of class instances.
|
|
690
|
+
*/
|
|
691
|
+
interface SerializedDataset {
|
|
692
|
+
/** Unique dataset identifier. */
|
|
693
|
+
id: string;
|
|
694
|
+
/** Human-readable dataset name. */
|
|
695
|
+
name: string;
|
|
696
|
+
/** The dataset rows as plain objects. */
|
|
697
|
+
rows: Record<string, unknown>[];
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Message sent from a worker when it has generated a batch of events for one user.
|
|
701
|
+
*/
|
|
702
|
+
interface WorkerEventBatch {
|
|
703
|
+
type: 'events';
|
|
704
|
+
events: Event[];
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Message sent from a worker when it begins processing a new user.
|
|
708
|
+
*/
|
|
709
|
+
interface WorkerUserStarted {
|
|
710
|
+
type: 'user-started';
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Message sent from a worker when it finishes processing a user.
|
|
714
|
+
*/
|
|
715
|
+
interface WorkerUserCompleted {
|
|
716
|
+
type: 'user-completed';
|
|
717
|
+
/** Number of events generated for this user. */
|
|
718
|
+
eventCount: number;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Message sent from a worker when an unrecoverable error occurs.
|
|
722
|
+
*/
|
|
723
|
+
interface WorkerErrorMessage {
|
|
724
|
+
type: 'error';
|
|
725
|
+
/** Human-readable error message. */
|
|
726
|
+
message: string;
|
|
727
|
+
/** Optional stack trace from the original error. */
|
|
728
|
+
stack?: string;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Final message sent from a worker when all assigned users have been processed.
|
|
732
|
+
*/
|
|
733
|
+
interface WorkerDone {
|
|
734
|
+
type: 'done';
|
|
735
|
+
/** Total events generated across all users in this worker. */
|
|
736
|
+
totalEvents: number;
|
|
737
|
+
/** Total users processed by this worker. */
|
|
738
|
+
totalUsers: number;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Discriminated union of all messages a worker thread can send to the parent.
|
|
742
|
+
* Use the `type` field to narrow the message in a switch/if block.
|
|
743
|
+
*/
|
|
744
|
+
type WorkerMessage = WorkerEventBatch | WorkerUserStarted | WorkerUserCompleted | WorkerErrorMessage | WorkerDone;
|
|
745
|
+
//#endregion
|
|
746
|
+
//#region src/monitoring/validation.d.ts
|
|
747
|
+
declare const ActionSchema: z.ZodObject<{
|
|
748
|
+
id: z.ZodString;
|
|
749
|
+
name: z.ZodString;
|
|
750
|
+
handler: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
751
|
+
}, z.core.$strip>;
|
|
752
|
+
declare const AdventureSchema: z.ZodObject<{
|
|
753
|
+
id: z.ZodString;
|
|
754
|
+
name: z.ZodString;
|
|
755
|
+
actions: z.ZodArray<z.ZodObject<{
|
|
756
|
+
id: z.ZodString;
|
|
757
|
+
name: z.ZodString;
|
|
758
|
+
handler: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
759
|
+
}, z.core.$strip>>;
|
|
760
|
+
}, z.core.$strip>;
|
|
761
|
+
declare const JourneySchema: z.ZodObject<{
|
|
762
|
+
id: z.ZodString;
|
|
763
|
+
name: z.ZodString;
|
|
764
|
+
adventures: z.ZodArray<z.ZodObject<{
|
|
765
|
+
id: z.ZodString;
|
|
766
|
+
name: z.ZodString;
|
|
767
|
+
actions: z.ZodArray<z.ZodObject<{
|
|
768
|
+
id: z.ZodString;
|
|
769
|
+
name: z.ZodString;
|
|
770
|
+
handler: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
771
|
+
}, z.core.$strip>>;
|
|
772
|
+
}, z.core.$strip>>;
|
|
773
|
+
}, z.core.$strip>;
|
|
774
|
+
/**
|
|
775
|
+
* Validates that a bounce chance value is between 0 and 1 (inclusive).
|
|
776
|
+
*
|
|
777
|
+
* @param value - The bounce chance value to validate
|
|
778
|
+
* @param path - Hierarchical path for error reporting
|
|
779
|
+
* @throws SynodeError with INVALID_BOUNCE_CHANCE code if out of range
|
|
780
|
+
*/
|
|
781
|
+
declare function validateBounceChance(value: number | undefined, path: string[]): void;
|
|
782
|
+
/**
|
|
783
|
+
* Validates that a time span has min <= max.
|
|
784
|
+
*
|
|
785
|
+
* @param timeSpan - The time span to validate
|
|
786
|
+
* @param path - Hierarchical path for error reporting
|
|
787
|
+
* @throws SynodeError with INVALID_TIME_SPAN code if min > max
|
|
788
|
+
*/
|
|
789
|
+
declare function validateTimeSpan(timeSpan: TimeSpan | undefined, path: string[]): void;
|
|
790
|
+
/**
|
|
791
|
+
* Validates the journey configuration including structural checks for bounce chances,
|
|
792
|
+
* time spans, suppression periods, duplicate IDs, unknown references, and circular dependencies.
|
|
793
|
+
*
|
|
794
|
+
* @param config - The journey configuration to validate
|
|
795
|
+
* @param allJourneys - Optional list of all journeys for cross-journey validation
|
|
796
|
+
* @throws ZodError if basic schema validation fails
|
|
797
|
+
* @throws SynodeError for structural validation failures
|
|
798
|
+
*/
|
|
799
|
+
declare function validateConfig(config: Journey, allJourneys?: Journey[]): void;
|
|
800
|
+
/**
|
|
801
|
+
* Performs a dry run of the journey for a specified number of users.
|
|
802
|
+
* Returns all generated events in memory.
|
|
803
|
+
*/
|
|
804
|
+
declare function dryRun(journey: Journey, userCount?: number): Promise<Event[]>;
|
|
805
|
+
//#endregion
|
|
806
|
+
//#region src/monitoring/event-validation.d.ts
|
|
807
|
+
/**
|
|
808
|
+
* A single validation issue from a failed schema check.
|
|
809
|
+
*/
|
|
810
|
+
interface ValidationIssue {
|
|
811
|
+
path: (string | number)[];
|
|
812
|
+
message: string;
|
|
813
|
+
code: string;
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Options for constructing a SynodeValidationError.
|
|
817
|
+
*/
|
|
818
|
+
interface SynodeValidationErrorOptions {
|
|
819
|
+
message: string;
|
|
820
|
+
event: Event;
|
|
821
|
+
issues: ValidationIssue[];
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Error thrown when an event fails schema validation in strict mode.
|
|
825
|
+
*/
|
|
826
|
+
declare class SynodeValidationError extends Error {
|
|
827
|
+
readonly event: Event;
|
|
828
|
+
readonly issues: ValidationIssue[];
|
|
829
|
+
constructor(options: SynodeValidationErrorOptions);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Aggregate summary of event validation results.
|
|
833
|
+
*/
|
|
834
|
+
interface ValidationSummary {
|
|
835
|
+
eventsValidated: number;
|
|
836
|
+
eventsValid: number;
|
|
837
|
+
eventsInvalid: number;
|
|
838
|
+
validationErrors: {
|
|
839
|
+
eventName: string;
|
|
840
|
+
path: string;
|
|
841
|
+
message: string;
|
|
842
|
+
}[];
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Wraps `z.object()` for defining event payload schemas.
|
|
846
|
+
*
|
|
847
|
+
* @param shape - Zod raw shape describing the expected payload fields
|
|
848
|
+
* @returns A ZodObject schema
|
|
849
|
+
*
|
|
850
|
+
* @example
|
|
851
|
+
* ```typescript
|
|
852
|
+
* const pageViewSchema = defineEventSchema({
|
|
853
|
+
* url: z.string().url(),
|
|
854
|
+
* referrer: z.string().optional(),
|
|
855
|
+
* });
|
|
856
|
+
* ```
|
|
857
|
+
*/
|
|
858
|
+
declare function defineEventSchema<T extends z.ZodRawShape>(shape: T): z.ZodObject<T>;
|
|
859
|
+
/**
|
|
860
|
+
* Creates a fresh zeroed validation summary.
|
|
861
|
+
*
|
|
862
|
+
* @returns An empty ValidationSummary ready for accumulation
|
|
863
|
+
*/
|
|
864
|
+
declare function createValidationSummary(): ValidationSummary;
|
|
865
|
+
/**
|
|
866
|
+
* Validates an event against its configured schema.
|
|
867
|
+
*
|
|
868
|
+
* Behavior depends on the configured mode:
|
|
869
|
+
* - `strict` (default): throws {@link SynodeValidationError} on first failure
|
|
870
|
+
* - `warn`: returns the event but records failure in the summary
|
|
871
|
+
* - `skip`: returns `undefined` (event is dropped) and records failure in the summary
|
|
872
|
+
*
|
|
873
|
+
* Events with no matching schema in a per-name map are passed through without validation.
|
|
874
|
+
*
|
|
875
|
+
* @param event - The event to validate
|
|
876
|
+
* @param config - Schema and mode configuration
|
|
877
|
+
* @param summary - Mutable summary accumulating validation statistics
|
|
878
|
+
* @returns The event if it passes or is kept (warn mode), or undefined if skipped
|
|
879
|
+
* @throws SynodeValidationError in strict mode when validation fails
|
|
880
|
+
*/
|
|
881
|
+
declare function validateEvent(event: Event, config: EventSchemaConfig, summary: ValidationSummary): Event | undefined;
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/monitoring/telemetry.d.ts
|
|
884
|
+
/**
|
|
885
|
+
* Telemetry data point captured every second during generation.
|
|
886
|
+
*/
|
|
887
|
+
interface TelemetrySnapshot {
|
|
888
|
+
/**
|
|
889
|
+
* Timestamp of this snapshot in ISO format.
|
|
890
|
+
*/
|
|
891
|
+
timestamp: string;
|
|
892
|
+
/**
|
|
893
|
+
* Elapsed time since generation started in milliseconds.
|
|
894
|
+
*/
|
|
895
|
+
elapsedMs: number;
|
|
896
|
+
/**
|
|
897
|
+
* Number of events generated in this second.
|
|
898
|
+
*/
|
|
899
|
+
eventsPerSecond: number;
|
|
900
|
+
/**
|
|
901
|
+
* Total events generated so far.
|
|
902
|
+
*/
|
|
903
|
+
totalEvents: number;
|
|
904
|
+
/**
|
|
905
|
+
* Number of users currently being processed across all lanes.
|
|
906
|
+
*/
|
|
907
|
+
activeUsers: number;
|
|
908
|
+
/**
|
|
909
|
+
* Number of users completed so far.
|
|
910
|
+
*/
|
|
911
|
+
completedUsers: number;
|
|
912
|
+
/**
|
|
913
|
+
* Number of parallel lanes in use.
|
|
914
|
+
*/
|
|
915
|
+
lanes: number;
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* A single validation error captured during event generation.
|
|
919
|
+
*/
|
|
920
|
+
interface TelemetryValidationError {
|
|
921
|
+
eventName: string;
|
|
922
|
+
path: string;
|
|
923
|
+
message: string;
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Complete telemetry report for a generation run.
|
|
927
|
+
*/
|
|
928
|
+
interface TelemetryReport {
|
|
929
|
+
/**
|
|
930
|
+
* When the generation started.
|
|
931
|
+
*/
|
|
932
|
+
startTime: string;
|
|
933
|
+
/**
|
|
934
|
+
* When the generation ended.
|
|
935
|
+
*/
|
|
936
|
+
endTime: string;
|
|
937
|
+
/**
|
|
938
|
+
* Total duration in milliseconds.
|
|
939
|
+
*/
|
|
940
|
+
durationMs: number;
|
|
941
|
+
/**
|
|
942
|
+
* Total number of users processed.
|
|
943
|
+
*/
|
|
944
|
+
totalUsers: number;
|
|
945
|
+
/**
|
|
946
|
+
* Total number of events generated.
|
|
947
|
+
*/
|
|
948
|
+
totalEvents: number;
|
|
949
|
+
/**
|
|
950
|
+
* Number of parallel lanes used.
|
|
951
|
+
*/
|
|
952
|
+
lanes: number;
|
|
953
|
+
/**
|
|
954
|
+
* Average events per second across the entire run.
|
|
955
|
+
*/
|
|
956
|
+
averageEventsPerSecond: number;
|
|
957
|
+
/**
|
|
958
|
+
* Number of users currently active (at report time).
|
|
959
|
+
*/
|
|
960
|
+
activeUsers: number;
|
|
961
|
+
/**
|
|
962
|
+
* Number of users completed (at report time).
|
|
963
|
+
*/
|
|
964
|
+
completedUsers: number;
|
|
965
|
+
/**
|
|
966
|
+
* Total number of events that were validated.
|
|
967
|
+
*/
|
|
968
|
+
eventsValidated: number;
|
|
969
|
+
/**
|
|
970
|
+
* Total number of events that passed validation.
|
|
971
|
+
*/
|
|
972
|
+
eventsValid: number;
|
|
973
|
+
/**
|
|
974
|
+
* Total number of events that failed validation.
|
|
975
|
+
*/
|
|
976
|
+
eventsInvalid: number;
|
|
977
|
+
/**
|
|
978
|
+
* Validation errors collected during the run (capped at 50).
|
|
979
|
+
*/
|
|
980
|
+
validationErrors: TelemetryValidationError[];
|
|
981
|
+
/**
|
|
982
|
+
* Per-second telemetry snapshots.
|
|
983
|
+
*/
|
|
984
|
+
snapshots: TelemetrySnapshot[];
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Collects telemetry data during generation runs.
|
|
988
|
+
*/
|
|
989
|
+
declare class TelemetryCollector {
|
|
990
|
+
private startTime;
|
|
991
|
+
private snapshots;
|
|
992
|
+
private intervalHandle;
|
|
993
|
+
private currentSecondEvents;
|
|
994
|
+
private totalEvents;
|
|
995
|
+
private activeUsers;
|
|
996
|
+
private completedUsers;
|
|
997
|
+
private lanes;
|
|
998
|
+
private eventsValidated;
|
|
999
|
+
private eventsValid;
|
|
1000
|
+
private eventsInvalid;
|
|
1001
|
+
private validationErrors;
|
|
1002
|
+
constructor(lanes: number);
|
|
1003
|
+
/**
|
|
1004
|
+
* Start collecting telemetry data every second.
|
|
1005
|
+
*/
|
|
1006
|
+
start(): void;
|
|
1007
|
+
/**
|
|
1008
|
+
* Stop collecting telemetry data.
|
|
1009
|
+
*/
|
|
1010
|
+
stop(): void;
|
|
1011
|
+
/**
|
|
1012
|
+
* Record that an event was generated.
|
|
1013
|
+
*/
|
|
1014
|
+
recordEvent(): void;
|
|
1015
|
+
/**
|
|
1016
|
+
* Record that a user started processing.
|
|
1017
|
+
*/
|
|
1018
|
+
recordUserStarted(): void;
|
|
1019
|
+
/**
|
|
1020
|
+
* Record that a user completed processing.
|
|
1021
|
+
*/
|
|
1022
|
+
recordUserCompleted(): void;
|
|
1023
|
+
/**
|
|
1024
|
+
* Merge a validation summary from a lane or journey into the collector totals.
|
|
1025
|
+
*
|
|
1026
|
+
* @param summary - Aggregated validation counts and errors to record.
|
|
1027
|
+
*/
|
|
1028
|
+
recordValidationSummary(summary: {
|
|
1029
|
+
eventsValidated: number;
|
|
1030
|
+
eventsValid: number;
|
|
1031
|
+
eventsInvalid: number;
|
|
1032
|
+
validationErrors: {
|
|
1033
|
+
eventName: string;
|
|
1034
|
+
path: string;
|
|
1035
|
+
message: string;
|
|
1036
|
+
}[];
|
|
1037
|
+
}): void;
|
|
1038
|
+
/**
|
|
1039
|
+
* Generate the final telemetry report.
|
|
1040
|
+
*/
|
|
1041
|
+
getReport(): TelemetryReport;
|
|
1042
|
+
/**
|
|
1043
|
+
* Save the telemetry report to a JSON file.
|
|
1044
|
+
*/
|
|
1045
|
+
saveReport(filePath: string): Promise<void>;
|
|
1046
|
+
private captureSnapshot;
|
|
1047
|
+
}
|
|
1048
|
+
//#endregion
|
|
1049
|
+
//#region src/monitoring/timing.d.ts
|
|
1050
|
+
/**
|
|
1051
|
+
* Generates a delay in milliseconds based on a time span configuration.
|
|
1052
|
+
*/
|
|
1053
|
+
declare function generateDelay(timeSpan: TimeSpan): number;
|
|
1054
|
+
/**
|
|
1055
|
+
* Checks if a bounce should occur based on probability.
|
|
1056
|
+
*/
|
|
1057
|
+
declare function shouldBounce(bounceChance?: number): boolean;
|
|
1058
|
+
//#endregion
|
|
1059
|
+
//#region src/adapters/console.d.ts
|
|
1060
|
+
/**
|
|
1061
|
+
* Adapter that writes events to the console as pretty-printed JSON.
|
|
1062
|
+
*
|
|
1063
|
+
* @example
|
|
1064
|
+
* ```ts
|
|
1065
|
+
* await generate(journey, { users: 10, adapter: new ConsoleAdapter() });
|
|
1066
|
+
* ```
|
|
1067
|
+
*/
|
|
1068
|
+
declare class ConsoleAdapter implements OutputAdapter {
|
|
1069
|
+
/** @inheritdoc */
|
|
1070
|
+
write(event: Event): void;
|
|
1071
|
+
}
|
|
1072
|
+
//#endregion
|
|
1073
|
+
//#region src/adapters/memory.d.ts
|
|
1074
|
+
/**
|
|
1075
|
+
* Adapter that stores events in memory.
|
|
1076
|
+
* Useful for testing and dry runs.
|
|
1077
|
+
*
|
|
1078
|
+
* @example
|
|
1079
|
+
* ```ts
|
|
1080
|
+
* const adapter = new InMemoryAdapter();
|
|
1081
|
+
* await generate(journey, { users: 10, adapter });
|
|
1082
|
+
* console.log(adapter.events.length);
|
|
1083
|
+
* ```
|
|
1084
|
+
*/
|
|
1085
|
+
declare class InMemoryAdapter implements OutputAdapter {
|
|
1086
|
+
readonly events: Event[];
|
|
1087
|
+
/** @inheritdoc */
|
|
1088
|
+
write(event: Event): void;
|
|
1089
|
+
/**
|
|
1090
|
+
* Clears all stored events.
|
|
1091
|
+
*/
|
|
1092
|
+
clear(): void;
|
|
1093
|
+
}
|
|
1094
|
+
//#endregion
|
|
1095
|
+
//#region src/adapters/callback.d.ts
|
|
1096
|
+
/**
|
|
1097
|
+
* Adapter that forwards events to a user-supplied callback function.
|
|
1098
|
+
* Supports both synchronous and asynchronous callbacks.
|
|
1099
|
+
*
|
|
1100
|
+
* @example
|
|
1101
|
+
* ```ts
|
|
1102
|
+
* const events: Event[] = [];
|
|
1103
|
+
* const adapter = new CallbackAdapter((event) => events.push(event));
|
|
1104
|
+
* await generate(journey, { users: 10, adapter });
|
|
1105
|
+
* ```
|
|
1106
|
+
*/
|
|
1107
|
+
declare class CallbackAdapter implements OutputAdapter {
|
|
1108
|
+
private callback;
|
|
1109
|
+
constructor(callback: (event: Event) => void | Promise<void>);
|
|
1110
|
+
/** @inheritdoc */
|
|
1111
|
+
write(event: Event): Promise<void>;
|
|
1112
|
+
}
|
|
1113
|
+
//#endregion
|
|
1114
|
+
//#region src/dataset-io.d.ts
|
|
1115
|
+
/**
|
|
1116
|
+
* Export format options.
|
|
1117
|
+
*/
|
|
1118
|
+
type ExportFormat = 'csv' | 'json' | 'jsonl';
|
|
1119
|
+
/**
|
|
1120
|
+
* Exports a dataset to a string in the specified format.
|
|
1121
|
+
*/
|
|
1122
|
+
declare function exportDatasetToString(dataset: Dataset, format: ExportFormat): string;
|
|
1123
|
+
/**
|
|
1124
|
+
* Imports a dataset from a string in the specified format.
|
|
1125
|
+
*/
|
|
1126
|
+
declare function importDatasetFromString(content: string, format: ExportFormat, id?: string, name?: string): Dataset;
|
|
1127
|
+
/**
|
|
1128
|
+
* Validates that a file path does not escape the given base directory.
|
|
1129
|
+
* @throws Error if path traversal is detected.
|
|
1130
|
+
*/
|
|
1131
|
+
declare function validateFilePath(filePath: string, basePath?: string): string;
|
|
1132
|
+
/**
|
|
1133
|
+
* Exports a dataset to a file in the specified format.
|
|
1134
|
+
*/
|
|
1135
|
+
declare function exportDataset(dataset: Dataset, filePath: string, format: ExportFormat): Promise<void>;
|
|
1136
|
+
/**
|
|
1137
|
+
* Imports a dataset from a file in the specified format.
|
|
1138
|
+
*/
|
|
1139
|
+
declare function importDataset(id: string, name: string, filePath: string, format: ExportFormat): Promise<Dataset>;
|
|
1140
|
+
//#endregion
|
|
1141
|
+
export { Action, ActionDefinition, ActionSchema, Adventure, AdventureSchema, CallbackAdapter, ConsoleAdapter, Context, ContextScope, ContextSetOptions, Dataset, DatasetDefinition, DatasetFieldGenerator, DatasetHandle, DatasetRow, Engine, ErrorCode, Event, EventSchemaConfig, EventValidationMode, ExportFormat, FieldGenerator, InMemoryAdapter, InferDatasetRow, Journey, JourneySchema, OutputAdapter, Persona, PersonaDefinition, RunOptions, SerializedDataset, SuppressionPeriod, SynodeContext, SynodeError, SynodeErrorOptions, SynodeValidationError, SynodeValidationErrorOptions, TelemetryCollector, TelemetryReport, TelemetrySnapshot, TelemetryValidationError, TimeSpan, ValidationIssue, ValidationSummary, WorkerDone, WorkerErrorMessage, WorkerEventBatch, WorkerInit, WorkerMessage, WorkerUserCompleted, WorkerUserStarted, buildNotFoundSuggestion, chance, createValidationSummary, defineAction, defineAdventure, defineDataset, defineEventSchema, defineJourney, definePersona, dryRun, exportDataset, exportDatasetToString, fake, formatErrorMessage, generate, generateDataset, generateDelay, generatePersona, importDataset, importDatasetFromString, levenshtein, oneOf, shouldBounce, suggestClosest, validateBounceChance, validateConfig, validateEvent, validateFilePath, validateTimeSpan, weighted };
|
|
1142
|
+
//# sourceMappingURL=index.d.cts.map
|