@chaos-maker/core 0.3.0 → 0.5.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @chaos-maker/core
2
2
 
3
- Core chaos engine for web applications. Intercepts `fetch`, `XMLHttpRequest`, and DOM mutations to inject controlled failures, latency, aborts, corruption, and UI disruptions.
3
+ Core chaos engine for web applications. Intercepts `fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, DOM mutations, and Service Worker fetches to inject controlled failures, latency, aborts, corruption, drops, closes, and UI disruptions.
4
4
 
5
5
  Framework-agnostic. Works with Playwright, Cypress, Selenium, or any browser environment.
6
6
 
@@ -49,14 +49,82 @@ chaos.stop(); // restores original fetch/XHR
49
49
 
50
50
  ### Presets
51
51
 
52
+ Presets are reusable bundles of rules. Drop them into a config by name with the `presets` field, and the engine merges them at construction time.
53
+
52
54
  ```ts
53
- import { ChaosMaker, presets } from '@chaos-maker/core';
55
+ import { ChaosMaker } from '@chaos-maker/core';
54
56
 
55
- // Available: unstableApi, slowNetwork, offlineMode, flakyConnection, degradedUi
56
- const chaos = new ChaosMaker(presets.slowNetwork);
57
+ const chaos = new ChaosMaker({
58
+ presets: ['slow-api'],
59
+ network: {
60
+ failures: [{ urlPattern: '/api/checkout', statusCode: 500, probability: 1 }],
61
+ },
62
+ });
57
63
  chaos.start();
58
64
  ```
59
65
 
66
+ **Built-in catalog**
67
+
68
+ | camelCase name | Kebab alias | Behavior |
69
+ | ----------------------- | --------------- | ----------------------------------------------------------------- |
70
+ | `slowNetwork` | `slow-api` | 2000ms latency on every request |
71
+ | `flakyConnection` | `flaky-api` | 5% aborts plus 3000ms latency on 10% of requests |
72
+ | `offlineMode` | `offline-mode` | Force CORS failure on every request |
73
+ | `unstableApi` | `high-latency` | 10% failures + 20% 1000ms latency, scoped to `/api/` |
74
+ | `degradedUi` | | 20% disable buttons, 10% hide links |
75
+ | `unreliableWebSocket` | | 10% drops, 500ms inbound delay, 5% inbound truncation |
76
+ | `unreliableEventStream` | | 5% drops, 200ms delay, 2% close after 2000ms |
77
+
78
+ Kebab-case aliases (`slow-api`, `flaky-api`, `offline-mode`, `high-latency`) are registry-only. They resolve via `presets: ['slow-api']` and `new PresetRegistry().get('slow-api')`. They are NOT keys on the legacy `presets` record export — `presets['slow-api']` is `undefined` by design. Use the camelCase key (`presets.slowNetwork`) when reading from the record.
79
+
80
+ **Custom presets**
81
+
82
+ Register your own bundle inline via `customPresets`. Names collide fail-fast against built-ins and against each other.
83
+
84
+ ```ts
85
+ new ChaosMaker({
86
+ customPresets: {
87
+ 'team-flow': {
88
+ network: {
89
+ failures: [{ urlPattern: '/checkout', statusCode: 503, probability: 1 }],
90
+ },
91
+ },
92
+ },
93
+ presets: ['team-flow'],
94
+ });
95
+ ```
96
+
97
+ Custom preset values may carry only rule arrays plus the optional `groups` field — `presets`, `customPresets`, `seed`, and `debug` are rejected at validation. Dependency chains are out of scope.
98
+
99
+ **Builder helper**
100
+
101
+ ```ts
102
+ import { ChaosConfigBuilder } from '@chaos-maker/core';
103
+
104
+ const config = new ChaosConfigBuilder()
105
+ .usePreset('slow-api')
106
+ .failRequests('/api/checkout', 500, 1)
107
+ .build();
108
+ ```
109
+
110
+ **Validation**
111
+
112
+ Unknown preset names, chain attempts, forbidden subfields, duplicate registrations, and group-name collisions across preset+user all surface as `ChaosConfigError` at construction time, never at runtime.
113
+
114
+ **Mutability**
115
+
116
+ Built-in preset configs are deep-frozen — `presets.slowNetwork.network!.latencies![0].delayMs = 1` throws. Your own custom presets passed via `customPresets` are NOT frozen — keep treating them as your data. The engine takes a deep clone at expansion, so any tweaks you make after construction are not observed.
117
+
118
+ **Legacy spread**
119
+
120
+ ```ts
121
+ import { presets } from '@chaos-maker/core';
122
+
123
+ new ChaosMaker({ ...presets.slowNetwork, network: { failures: [{ urlPattern: '/api', statusCode: 500, probability: 1 }] } });
124
+ ```
125
+
126
+ Still supported for migration. Prefer the declarative `presets:` field for new code.
127
+
60
128
  ### Config Builder
61
129
 
62
130
  ```ts
@@ -82,6 +150,9 @@ const config = new ChaosConfigBuilder()
82
150
  | Corruption | `network.corruptions` | Corrupt response bodies |
83
151
  | CORS | `network.cors` | Simulate CORS errors |
84
152
  | UI Assault | `ui.assaults` | Disable, hide, or remove DOM elements |
153
+ | WebSocket | `websocket.*` | Drop, delay, corrupt, or close socket messages |
154
+ | SSE | `sse.*` | Drop, delay, corrupt, or close EventSource events |
155
+ | GraphQL | `graphqlOperation` | Target one operation on a shared endpoint |
85
156
 
86
157
  ## Configuration Reference
87
158
 
@@ -93,6 +164,7 @@ const config = new ChaosConfigBuilder()
93
164
  | `statusCode` | `number` | Yes | HTTP status code (100-599) |
94
165
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
95
166
  | `methods` | `string[]` | No | HTTP methods to match (default: all) |
167
+ | `graphqlOperation` | `string \| RegExp` | No | Operation name matcher for GraphQL requests |
96
168
  | `body` | `string` | No | Custom response body |
97
169
  | `statusText` | `string` | No | Custom status text |
98
170
  | `headers` | `Record<string, string>` | No | Custom response headers |
@@ -105,6 +177,7 @@ const config = new ChaosConfigBuilder()
105
177
  | `delayMs` | `number` | Yes | Delay in milliseconds |
106
178
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
107
179
  | `methods` | `string[]` | No | HTTP methods to match |
180
+ | `graphqlOperation` | `string \| RegExp` | No | Operation name matcher for GraphQL requests |
108
181
 
109
182
  ### NetworkAbortConfig
110
183
 
@@ -114,6 +187,7 @@ const config = new ChaosConfigBuilder()
114
187
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
115
188
  | `timeout` | `number` | No | ms before abort (0 or omitted = immediate) |
116
189
  | `methods` | `string[]` | No | HTTP methods to match |
190
+ | `graphqlOperation` | `string \| RegExp` | No | Operation name matcher for GraphQL requests |
117
191
 
118
192
  ### NetworkCorruptionConfig
119
193
 
@@ -123,6 +197,7 @@ const config = new ChaosConfigBuilder()
123
197
  | `strategy` | `CorruptionStrategy` | Yes | `'truncate'` \| `'malformed-json'` \| `'empty'` \| `'wrong-type'` |
124
198
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
125
199
  | `methods` | `string[]` | No | HTTP methods to match |
200
+ | `graphqlOperation` | `string \| RegExp` | No | Operation name matcher for GraphQL requests |
126
201
 
127
202
  ### NetworkCorsConfig
128
203
 
@@ -131,6 +206,7 @@ const config = new ChaosConfigBuilder()
131
206
  | `urlPattern` | `string` | Yes | Substring match against request URL |
132
207
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
133
208
  | `methods` | `string[]` | No | HTTP methods to match |
209
+ | `graphqlOperation` | `string \| RegExp` | No | Operation name matcher for GraphQL requests |
134
210
 
135
211
  ### UiAssaultConfig
136
212
 
@@ -140,6 +216,34 @@ const config = new ChaosConfigBuilder()
140
216
  | `action` | `string` | Yes | `'disable'` \| `'hide'` \| `'remove'` |
141
217
  | `probability` | `number` | Yes | 0.0-1.0 chance of applying |
142
218
 
219
+ ### SSEConfig
220
+
221
+ ```ts
222
+ sse: {
223
+ drops: [{ urlPattern: '/events', eventType: 'token', probability: 0.1 }],
224
+ delays: [{ urlPattern: '/events', delayMs: 500, probability: 1 }],
225
+ corruptions: [{ urlPattern: '/events', strategy: 'truncate', probability: 0.05 }],
226
+ closes: [{ urlPattern: '/events', afterMs: 2000, probability: 0.02 }],
227
+ }
228
+ ```
229
+
230
+ `eventType` defaults to `message`; use a named event or `'*'` for all data events.
231
+
232
+ ### GraphQL operation matching
233
+
234
+ ```ts
235
+ network: {
236
+ failures: [{
237
+ urlPattern: '/graphql',
238
+ graphqlOperation: 'GetUser',
239
+ statusCode: 503,
240
+ probability: 1,
241
+ }],
242
+ }
243
+ ```
244
+
245
+ `graphqlOperation` is an additional matcher on top of `urlPattern` and `methods`.
246
+
143
247
  ## Event System
144
248
 
145
249
  ```ts
@@ -151,26 +255,62 @@ const log = chaos.getLog(); // all events since start
151
255
  chaos.clearLog();
152
256
  ```
153
257
 
154
- Event types: `network:failure`, `network:latency`, `network:abort`, `network:corruption`, `network:cors`, `ui:assault`
258
+ Event types: `network:failure`, `network:latency`, `network:abort`, `network:corruption`, `network:cors`, `ui:assault`, `websocket:drop`, `websocket:delay`, `websocket:corrupt`, `websocket:close`, `sse:drop`, `sse:delay`, `sse:corrupt`, `sse:close`
155
259
 
156
260
  ## Config Validation
157
261
 
158
- All configs are validated with Zod in strict mode. Unknown keys are rejected. Invalid values throw `ChaosConfigError` with descriptive messages.
262
+ All configs are validated with Zod in strict mode. Unknown keys are rejected by default. Invalid values throw `ChaosConfigError` whose `issues` is a `ValidationIssue[]` with structured `path` / `code` / `ruleType` / `message` / `expected` / `received`.
159
263
 
160
264
  ```ts
161
- import { validateConfig, ChaosConfigError } from '@chaos-maker/core';
265
+ import { validateChaosConfig, ChaosConfigError } from '@chaos-maker/core';
162
266
 
163
267
  try {
164
- validateConfig({ network: { failures: [{ urlPattern: '', statusCode: 999 }] } });
268
+ validateChaosConfig({
269
+ network: { failures: [{ urlPattern: '', statusCode: 999, probability: 2 }] },
270
+ });
165
271
  } catch (e) {
166
272
  if (e instanceof ChaosConfigError) {
167
- console.log(e.issues);
168
- // ['network.failures.0.urlPattern: urlPattern must not be empty',
169
- // 'network.failures.0.statusCode: Number must be less than or equal to 599']
273
+ for (const issue of e.issues) {
274
+ console.log(issue.path, issue.code, issue.message);
275
+ }
276
+ // legacy v0.4.x string array still available:
277
+ console.log(e.messages);
170
278
  }
171
279
  }
172
280
  ```
173
281
 
282
+ `validateChaosConfig(input, opts?)` accepts:
283
+
284
+ - `unknownFields: 'reject' | 'warn' | 'ignore'` — strict by default. `'warn'` and `'ignore'` strip unknowns from the returned config; `'warn'` emits exactly one aggregated `console.warn` per call.
285
+ - `customValidators: Partial<Record<RuleType, (rule, ctx) => ValidationIssue[] | void>>` — run extra checks per rule type.
286
+ - `onDeprecation: (issue) => void` — receive `ValidationIssue` events for deprecated fields (rails only in v0.5.0).
287
+
288
+ A JSON Schema artifact ships at `node_modules/@chaos-maker/core/dist/chaos-config.schema.json` for IDE / `"$schema"` autocomplete plus a sidecar `chaos-config.schema.notes.md` listing parity caveats. The artifact is a tooling approximation — runtime canonical validation is always Zod via `validateChaosConfig`.
289
+
290
+ See the [Rule Validation concept page](https://chaos-maker-dev.github.io/chaos-maker/concepts/validation/) for the full pipeline, brand semantics, and migration notes.
291
+
292
+ ## Service Worker chaos
293
+
294
+ Chaos applies to SW-originated fetches via the `@chaos-maker/core/sw` subpath. Zod + UI + builder are excluded from this bundle so it stays small enough for production SW deploys.
295
+
296
+ Classic SW (one line):
297
+
298
+ ```js
299
+ // user's sw.js
300
+ importScripts('/path/to/chaos-maker-sw.js'); // auto-installs
301
+ ```
302
+
303
+ Module SW:
304
+
305
+ ```js
306
+ import { installChaosSW } from '@chaos-maker/core/sw';
307
+ installChaosSW({ source: 'message' });
308
+ ```
309
+
310
+ Page-side config is delivered via `postMessage` + `MessageChannel` ack. Use the adapter helpers (`injectSWChaos` / `removeSWChaos` / `getSWChaosLog`) in `@chaos-maker/{playwright,cypress,webdriverio,puppeteer}`.
311
+
312
+ Limitations: `caches.match` hits bypass chaos (planned for v0.5.0); push/sync events not covered; cross-origin SWs not supported.
313
+
174
314
  ## License
175
315
 
176
316
  [MIT](../../LICENSE)