@wooksjs/event-wf 0.7.13 → 0.7.15

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 (3) hide show
  1. package/dist/index.cjs +44 -216
  2. package/dist/index.mjs +8 -210
  3. package/package.json +10 -10
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let _wooksjs_event_core = require("@wooksjs/event-core");
3
3
  let _wooksjs_event_http = require("@wooksjs/event-http");
4
4
  let _wooksjs_http_body = require("@wooksjs/http-body");
5
- let node_crypto = require("node:crypto");
5
+ let _prostojs_wf_outlets = require("@prostojs/wf/outlets");
6
6
  let _prostojs_wf = require("@prostojs/wf");
7
7
  let wooks = require("wooks");
8
8
 
@@ -146,6 +146,7 @@ async function handleWfOutletRequest(config, deps) {
146
146
  const input = body?.input;
147
147
  const resolveStrategy = (id) => typeof config.state === "function" ? config.state(id) : config.state;
148
148
  let output;
149
+ let strategyReResolved = false;
149
150
  if (token) {
150
151
  const strategy = resolveStrategy(wfid ?? "");
151
152
  ctx.set(stateStrategyKey, strategy);
@@ -156,7 +157,10 @@ async function handleWfOutletRequest(config, deps) {
156
157
  }
157
158
  if (state.schemaId !== (wfid ?? "")) {
158
159
  const realStrategy = resolveStrategy(state.schemaId);
159
- ctx.set(stateStrategyKey, realStrategy);
160
+ if (realStrategy !== strategy) {
161
+ ctx.set(stateStrategyKey, realStrategy);
162
+ strategyReResolved = true;
163
+ }
160
164
  }
161
165
  output = await deps.resume(state, {
162
166
  input,
@@ -212,7 +216,8 @@ async function handleWfOutletRequest(config, deps) {
212
216
  ...output.state,
213
217
  meta: { outlet: outletReq.outlet }
214
218
  };
215
- const newToken = await strategy.persist(stateWithMeta, output.expires ? { ttl: output.expires - Date.now() } : void 0);
219
+ const reuseHandle = token && !strategyReResolved ? { handle: token } : void 0;
220
+ const newToken = await strategy.persist(stateWithMeta, output.expires ? { ttl: output.expires - Date.now() } : void 0, reuseHandle);
216
221
  const outOfBand = outletHandler.tokenDelivery === "out-of-band";
217
222
  if (tokenWrite === "cookie" && !outOfBand) response.setCookie(tokenName, newToken, {
218
223
  httpOnly: true,
@@ -315,213 +320,6 @@ function createOutletHandler(wfApp) {
315
320
  });
316
321
  }
317
322
 
318
- //#endregion
319
- //#region node_modules/.pnpm/@prostojs+wf@0.2.0/node_modules/@prostojs/wf/dist/outlets/index.mjs
320
- /**
321
- * Generic outlet request. Use for custom outlets.
322
- *
323
- * @example
324
- * return outlet('pending-task', {
325
- * payload: ApprovalForm,
326
- * target: managerId,
327
- * context: { orderId, amount },
328
- * })
329
- */
330
- function outlet(name, data) {
331
- return { inputRequired: {
332
- outlet: name,
333
- ...data
334
- } };
335
- }
336
- /**
337
- * Pause for HTTP form input. The outlet returns the payload (form definition)
338
- * and state token in the HTTP response.
339
- *
340
- * @example
341
- * return outletHttp(LoginForm)
342
- * return outletHttp(LoginForm, { error: 'Invalid credentials' })
343
- */
344
- function outletHttp(payload, context) {
345
- return outlet("http", {
346
- payload,
347
- context
348
- });
349
- }
350
- /**
351
- * Pause and send email with a magic link containing the state token.
352
- *
353
- * @example
354
- * return outletEmail('user@test.com', 'invite', { name: 'Alice' })
355
- */
356
- function outletEmail(target, template, context) {
357
- return outlet("email", {
358
- target,
359
- template,
360
- context
361
- });
362
- }
363
- /**
364
- * Self-contained AES-256-GCM encrypted state strategy.
365
- *
366
- * Workflow state is encrypted into a base64url token that travels with the
367
- * transport (cookie, URL param, hidden field). No server-side storage needed.
368
- *
369
- * Token format: `base64url(iv[12] + authTag[16] + ciphertext)`
370
- *
371
- * ## Security warning — replay
372
- *
373
- * This strategy is STATELESS. It cannot enforce single-use semantics:
374
- * `consume()` is a no-op alias for `retrieve()` because there is no
375
- * server-side record to delete. Anyone who obtains a copy of the token
376
- * (browser history, server logs, shoulder-surfing, intermediate proxy,
377
- * shared device) can replay it until the TTL expires.
378
- *
379
- * Use `EncapsulatedStateStrategy` ONLY when BOTH of the following hold:
380
- *
381
- * 1. Every workflow step is idempotent — re-executing a step with the same
382
- * input produces no harmful side effects (pure data collection,
383
- * validation-only steps).
384
- * 2. The flow is not security-sensitive — no credential changes, financial
385
- * operations, account provisioning, permission grants, or any other
386
- * privileged action.
387
- *
388
- * For auth flows (login, password reset, invite accept), financial
389
- * operations, or anything with meaningful side effects, use
390
- * `HandleStateStrategy` with a durable `WfStateStore`. `HandleStateStrategy`
391
- * supports true single-use tokens via atomic `getAndDelete` at the store
392
- * layer.
393
- *
394
- * @example
395
- * const strategy = new EncapsulatedStateStrategy({
396
- * secret: crypto.randomBytes(32),
397
- * defaultTtl: 3600_000, // 1 hour
398
- * });
399
- * const token = await strategy.persist(state);
400
- * const recovered = await strategy.retrieve(token);
401
- */
402
- var EncapsulatedStateStrategy = class {
403
- /** @throws if secret is not exactly 32 bytes */
404
- constructor(config) {
405
- this.config = config;
406
- this.key = typeof config.secret === "string" ? Buffer.from(config.secret, "hex") : config.secret;
407
- if (this.key.length !== 32) throw new Error("EncapsulatedStateStrategy: secret must be exactly 32 bytes");
408
- }
409
- /**
410
- * Encrypt workflow state into a self-contained token.
411
- * @param state — workflow state to persist
412
- * @param options.ttl — time-to-live in ms (overrides defaultTtl)
413
- * @returns base64url-encoded encrypted token
414
- */
415
- async persist(state, options) {
416
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
417
- const exp = ttl > 0 ? Date.now() + ttl : 0;
418
- const payload = JSON.stringify({
419
- s: state,
420
- e: exp
421
- });
422
- const iv = (0, node_crypto.randomBytes)(12);
423
- const cipher = (0, node_crypto.createCipheriv)("aes-256-gcm", this.key, iv);
424
- const encrypted = Buffer.concat([cipher.update(payload, "utf8"), cipher.final()]);
425
- const tag = cipher.getAuthTag();
426
- return Buffer.concat([
427
- iv,
428
- tag,
429
- encrypted
430
- ]).toString("base64url");
431
- }
432
- /** Decrypt and return workflow state. Returns null if token is invalid, expired, or tampered. */
433
- async retrieve(token) {
434
- return this.decrypt(token);
435
- }
436
- /**
437
- * Stateless — CANNOT invalidate the token. Returns identical result to
438
- * `retrieve()`. See the class-level security warning.
439
- *
440
- * This method exists only to satisfy the `WfStateStrategy` contract.
441
- * Callers that need true single-use semantics must use
442
- * `HandleStateStrategy`.
443
- */
444
- async consume(token) {
445
- return this.decrypt(token);
446
- }
447
- decrypt(token) {
448
- try {
449
- const buf = Buffer.from(token, "base64url");
450
- if (buf.length < 28) return null;
451
- const iv = buf.subarray(0, 12);
452
- const tag = buf.subarray(12, 28);
453
- const ciphertext = buf.subarray(28);
454
- const decipher = (0, node_crypto.createDecipheriv)("aes-256-gcm", this.key, iv);
455
- decipher.setAuthTag(tag);
456
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
457
- const { s: state, e: exp } = JSON.parse(decrypted.toString("utf8"));
458
- if (exp > 0 && Date.now() > exp) return null;
459
- return state;
460
- } catch {
461
- return null;
462
- }
463
- }
464
- };
465
- var HandleStateStrategy = class {
466
- constructor(config) {
467
- this.config = config;
468
- }
469
- async persist(state, options) {
470
- const handle = (this.config.generateHandle ?? node_crypto.randomUUID)();
471
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
472
- const expiresAt = ttl > 0 ? Date.now() + ttl : void 0;
473
- await this.config.store.set(handle, state, expiresAt);
474
- return handle;
475
- }
476
- async retrieve(token) {
477
- return (await this.config.store.get(token))?.state ?? null;
478
- }
479
- async consume(token) {
480
- return (await this.config.store.getAndDelete(token))?.state ?? null;
481
- }
482
- };
483
- /**
484
- * In-memory state store for development and testing.
485
- * State is lost on process restart.
486
- */
487
- var WfStateStoreMemory = class {
488
- constructor() {
489
- this.store = /* @__PURE__ */ new Map();
490
- }
491
- async set(handle, state, expiresAt) {
492
- this.store.set(handle, {
493
- state,
494
- expiresAt
495
- });
496
- }
497
- async get(handle) {
498
- const entry = this.store.get(handle);
499
- if (!entry) return null;
500
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
501
- this.store.delete(handle);
502
- return null;
503
- }
504
- return entry;
505
- }
506
- async delete(handle) {
507
- this.store.delete(handle);
508
- }
509
- async getAndDelete(handle) {
510
- const entry = await this.get(handle);
511
- if (entry) this.store.delete(handle);
512
- return entry;
513
- }
514
- async cleanup() {
515
- const now = Date.now();
516
- let count = 0;
517
- for (const [handle, entry] of this.store) if (entry.expiresAt && now > entry.expiresAt) {
518
- this.store.delete(handle);
519
- count++;
520
- }
521
- return count;
522
- }
523
- };
524
-
525
323
  //#endregion
526
324
  //#region packages/event-wf/src/workflow.ts
527
325
  /** Workflow engine that resolves steps via Wooks router lookup. */
@@ -706,15 +504,30 @@ function createWfApp(opts, wooks$2) {
706
504
  }
707
505
 
708
506
  //#endregion
709
- exports.EncapsulatedStateStrategy = EncapsulatedStateStrategy;
710
- exports.HandleStateStrategy = HandleStateStrategy;
507
+ Object.defineProperty(exports, 'EncapsulatedStateStrategy', {
508
+ enumerable: true,
509
+ get: function () {
510
+ return _prostojs_wf_outlets.EncapsulatedStateStrategy;
511
+ }
512
+ });
513
+ Object.defineProperty(exports, 'HandleStateStrategy', {
514
+ enumerable: true,
515
+ get: function () {
516
+ return _prostojs_wf_outlets.HandleStateStrategy;
517
+ }
518
+ });
711
519
  Object.defineProperty(exports, 'StepRetriableError', {
712
520
  enumerable: true,
713
521
  get: function () {
714
522
  return _prostojs_wf.StepRetriableError;
715
523
  }
716
524
  });
717
- exports.WfStateStoreMemory = WfStateStoreMemory;
525
+ Object.defineProperty(exports, 'WfStateStoreMemory', {
526
+ enumerable: true,
527
+ get: function () {
528
+ return _prostojs_wf_outlets.WfStateStoreMemory;
529
+ }
530
+ });
718
531
  exports.WooksWf = WooksWf;
719
532
  exports.createEmailOutlet = createEmailOutlet;
720
533
  exports.createHttpOutlet = createHttpOutlet;
@@ -722,9 +535,24 @@ exports.createOutletHandler = createOutletHandler;
722
535
  exports.createWfApp = createWfApp;
723
536
  exports.createWfContext = createWfContext;
724
537
  exports.handleWfOutletRequest = handleWfOutletRequest;
725
- exports.outlet = outlet;
726
- exports.outletEmail = outletEmail;
727
- exports.outletHttp = outletHttp;
538
+ Object.defineProperty(exports, 'outlet', {
539
+ enumerable: true,
540
+ get: function () {
541
+ return _prostojs_wf_outlets.outlet;
542
+ }
543
+ });
544
+ Object.defineProperty(exports, 'outletEmail', {
545
+ enumerable: true,
546
+ get: function () {
547
+ return _prostojs_wf_outlets.outletEmail;
548
+ }
549
+ });
550
+ Object.defineProperty(exports, 'outletHttp', {
551
+ enumerable: true,
552
+ get: function () {
553
+ return _prostojs_wf_outlets.outletHttp;
554
+ }
555
+ });
728
556
  exports.resumeKey = resumeKey;
729
557
  exports.resumeWfContext = resumeWfContext;
730
558
  Object.defineProperty(exports, 'useLogger', {
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createEventContext, current, defineEventKind, defineWook, key, slot, useLogger, useRouteParams } from "@wooksjs/event-core";
2
2
  import { useCookies, useResponse, useUrlParams } from "@wooksjs/event-http";
3
3
  import { useBody } from "@wooksjs/http-body";
4
- import { createCipheriv, createDecipheriv, randomBytes, randomUUID } from "node:crypto";
4
+ import { EncapsulatedStateStrategy, HandleStateStrategy, WfStateStoreMemory, outlet, outletEmail, outletHttp } from "@prostojs/wf/outlets";
5
5
  import { StepRetriableError, Workflow, createStep } from "@prostojs/wf";
6
6
  import { WooksAdapterBase } from "wooks";
7
7
 
@@ -145,6 +145,7 @@ async function handleWfOutletRequest(config, deps) {
145
145
  const input = body?.input;
146
146
  const resolveStrategy = (id) => typeof config.state === "function" ? config.state(id) : config.state;
147
147
  let output;
148
+ let strategyReResolved = false;
148
149
  if (token) {
149
150
  const strategy = resolveStrategy(wfid ?? "");
150
151
  ctx.set(stateStrategyKey, strategy);
@@ -155,7 +156,10 @@ async function handleWfOutletRequest(config, deps) {
155
156
  }
156
157
  if (state.schemaId !== (wfid ?? "")) {
157
158
  const realStrategy = resolveStrategy(state.schemaId);
158
- ctx.set(stateStrategyKey, realStrategy);
159
+ if (realStrategy !== strategy) {
160
+ ctx.set(stateStrategyKey, realStrategy);
161
+ strategyReResolved = true;
162
+ }
159
163
  }
160
164
  output = await deps.resume(state, {
161
165
  input,
@@ -211,7 +215,8 @@ async function handleWfOutletRequest(config, deps) {
211
215
  ...output.state,
212
216
  meta: { outlet: outletReq.outlet }
213
217
  };
214
- const newToken = await strategy.persist(stateWithMeta, output.expires ? { ttl: output.expires - Date.now() } : void 0);
218
+ const reuseHandle = token && !strategyReResolved ? { handle: token } : void 0;
219
+ const newToken = await strategy.persist(stateWithMeta, output.expires ? { ttl: output.expires - Date.now() } : void 0, reuseHandle);
215
220
  const outOfBand = outletHandler.tokenDelivery === "out-of-band";
216
221
  if (tokenWrite === "cookie" && !outOfBand) response.setCookie(tokenName, newToken, {
217
222
  httpOnly: true,
@@ -314,213 +319,6 @@ function createOutletHandler(wfApp) {
314
319
  });
315
320
  }
316
321
 
317
- //#endregion
318
- //#region node_modules/.pnpm/@prostojs+wf@0.2.0/node_modules/@prostojs/wf/dist/outlets/index.mjs
319
- /**
320
- * Generic outlet request. Use for custom outlets.
321
- *
322
- * @example
323
- * return outlet('pending-task', {
324
- * payload: ApprovalForm,
325
- * target: managerId,
326
- * context: { orderId, amount },
327
- * })
328
- */
329
- function outlet(name, data) {
330
- return { inputRequired: {
331
- outlet: name,
332
- ...data
333
- } };
334
- }
335
- /**
336
- * Pause for HTTP form input. The outlet returns the payload (form definition)
337
- * and state token in the HTTP response.
338
- *
339
- * @example
340
- * return outletHttp(LoginForm)
341
- * return outletHttp(LoginForm, { error: 'Invalid credentials' })
342
- */
343
- function outletHttp(payload, context) {
344
- return outlet("http", {
345
- payload,
346
- context
347
- });
348
- }
349
- /**
350
- * Pause and send email with a magic link containing the state token.
351
- *
352
- * @example
353
- * return outletEmail('user@test.com', 'invite', { name: 'Alice' })
354
- */
355
- function outletEmail(target, template, context) {
356
- return outlet("email", {
357
- target,
358
- template,
359
- context
360
- });
361
- }
362
- /**
363
- * Self-contained AES-256-GCM encrypted state strategy.
364
- *
365
- * Workflow state is encrypted into a base64url token that travels with the
366
- * transport (cookie, URL param, hidden field). No server-side storage needed.
367
- *
368
- * Token format: `base64url(iv[12] + authTag[16] + ciphertext)`
369
- *
370
- * ## Security warning — replay
371
- *
372
- * This strategy is STATELESS. It cannot enforce single-use semantics:
373
- * `consume()` is a no-op alias for `retrieve()` because there is no
374
- * server-side record to delete. Anyone who obtains a copy of the token
375
- * (browser history, server logs, shoulder-surfing, intermediate proxy,
376
- * shared device) can replay it until the TTL expires.
377
- *
378
- * Use `EncapsulatedStateStrategy` ONLY when BOTH of the following hold:
379
- *
380
- * 1. Every workflow step is idempotent — re-executing a step with the same
381
- * input produces no harmful side effects (pure data collection,
382
- * validation-only steps).
383
- * 2. The flow is not security-sensitive — no credential changes, financial
384
- * operations, account provisioning, permission grants, or any other
385
- * privileged action.
386
- *
387
- * For auth flows (login, password reset, invite accept), financial
388
- * operations, or anything with meaningful side effects, use
389
- * `HandleStateStrategy` with a durable `WfStateStore`. `HandleStateStrategy`
390
- * supports true single-use tokens via atomic `getAndDelete` at the store
391
- * layer.
392
- *
393
- * @example
394
- * const strategy = new EncapsulatedStateStrategy({
395
- * secret: crypto.randomBytes(32),
396
- * defaultTtl: 3600_000, // 1 hour
397
- * });
398
- * const token = await strategy.persist(state);
399
- * const recovered = await strategy.retrieve(token);
400
- */
401
- var EncapsulatedStateStrategy = class {
402
- /** @throws if secret is not exactly 32 bytes */
403
- constructor(config) {
404
- this.config = config;
405
- this.key = typeof config.secret === "string" ? Buffer.from(config.secret, "hex") : config.secret;
406
- if (this.key.length !== 32) throw new Error("EncapsulatedStateStrategy: secret must be exactly 32 bytes");
407
- }
408
- /**
409
- * Encrypt workflow state into a self-contained token.
410
- * @param state — workflow state to persist
411
- * @param options.ttl — time-to-live in ms (overrides defaultTtl)
412
- * @returns base64url-encoded encrypted token
413
- */
414
- async persist(state, options) {
415
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
416
- const exp = ttl > 0 ? Date.now() + ttl : 0;
417
- const payload = JSON.stringify({
418
- s: state,
419
- e: exp
420
- });
421
- const iv = randomBytes(12);
422
- const cipher = createCipheriv("aes-256-gcm", this.key, iv);
423
- const encrypted = Buffer.concat([cipher.update(payload, "utf8"), cipher.final()]);
424
- const tag = cipher.getAuthTag();
425
- return Buffer.concat([
426
- iv,
427
- tag,
428
- encrypted
429
- ]).toString("base64url");
430
- }
431
- /** Decrypt and return workflow state. Returns null if token is invalid, expired, or tampered. */
432
- async retrieve(token) {
433
- return this.decrypt(token);
434
- }
435
- /**
436
- * Stateless — CANNOT invalidate the token. Returns identical result to
437
- * `retrieve()`. See the class-level security warning.
438
- *
439
- * This method exists only to satisfy the `WfStateStrategy` contract.
440
- * Callers that need true single-use semantics must use
441
- * `HandleStateStrategy`.
442
- */
443
- async consume(token) {
444
- return this.decrypt(token);
445
- }
446
- decrypt(token) {
447
- try {
448
- const buf = Buffer.from(token, "base64url");
449
- if (buf.length < 28) return null;
450
- const iv = buf.subarray(0, 12);
451
- const tag = buf.subarray(12, 28);
452
- const ciphertext = buf.subarray(28);
453
- const decipher = createDecipheriv("aes-256-gcm", this.key, iv);
454
- decipher.setAuthTag(tag);
455
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
456
- const { s: state, e: exp } = JSON.parse(decrypted.toString("utf8"));
457
- if (exp > 0 && Date.now() > exp) return null;
458
- return state;
459
- } catch {
460
- return null;
461
- }
462
- }
463
- };
464
- var HandleStateStrategy = class {
465
- constructor(config) {
466
- this.config = config;
467
- }
468
- async persist(state, options) {
469
- const handle = (this.config.generateHandle ?? randomUUID)();
470
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
471
- const expiresAt = ttl > 0 ? Date.now() + ttl : void 0;
472
- await this.config.store.set(handle, state, expiresAt);
473
- return handle;
474
- }
475
- async retrieve(token) {
476
- return (await this.config.store.get(token))?.state ?? null;
477
- }
478
- async consume(token) {
479
- return (await this.config.store.getAndDelete(token))?.state ?? null;
480
- }
481
- };
482
- /**
483
- * In-memory state store for development and testing.
484
- * State is lost on process restart.
485
- */
486
- var WfStateStoreMemory = class {
487
- constructor() {
488
- this.store = /* @__PURE__ */ new Map();
489
- }
490
- async set(handle, state, expiresAt) {
491
- this.store.set(handle, {
492
- state,
493
- expiresAt
494
- });
495
- }
496
- async get(handle) {
497
- const entry = this.store.get(handle);
498
- if (!entry) return null;
499
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
500
- this.store.delete(handle);
501
- return null;
502
- }
503
- return entry;
504
- }
505
- async delete(handle) {
506
- this.store.delete(handle);
507
- }
508
- async getAndDelete(handle) {
509
- const entry = await this.get(handle);
510
- if (entry) this.store.delete(handle);
511
- return entry;
512
- }
513
- async cleanup() {
514
- const now = Date.now();
515
- let count = 0;
516
- for (const [handle, entry] of this.store) if (entry.expiresAt && now > entry.expiresAt) {
517
- this.store.delete(handle);
518
- count++;
519
- }
520
- return count;
521
- }
522
- };
523
-
524
322
  //#endregion
525
323
  //#region packages/event-wf/src/workflow.ts
526
324
  /** Workflow engine that resolves steps via Wooks router lookup. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wooksjs/event-wf",
3
- "version": "0.7.13",
3
+ "version": "0.7.15",
4
4
  "description": "@wooksjs/event-wf",
5
5
  "keywords": [
6
6
  "app",
@@ -37,22 +37,22 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "@prostojs/wf": "^0.2.0"
40
+ "@prostojs/wf": "^0.2.1"
41
41
  },
42
42
  "devDependencies": {
43
43
  "typescript": "^5.9.3",
44
44
  "vitest": "^3.2.4",
45
- "@wooksjs/event-core": "^0.7.13",
46
- "@wooksjs/event-http": "^0.7.13",
47
- "@wooksjs/http-body": "^0.7.13",
48
- "wooks": "^0.7.13"
45
+ "@wooksjs/event-core": "^0.7.15",
46
+ "@wooksjs/event-http": "^0.7.15",
47
+ "wooks": "^0.7.15",
48
+ "@wooksjs/http-body": "^0.7.15"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@prostojs/logger": "^0.4.3",
52
- "@wooksjs/event-core": "^0.7.13",
53
- "@wooksjs/http-body": "^0.7.13",
54
- "@wooksjs/event-http": "^0.7.13",
55
- "wooks": "^0.7.13"
52
+ "@wooksjs/event-core": "^0.7.15",
53
+ "wooks": "^0.7.15",
54
+ "@wooksjs/event-http": "^0.7.15",
55
+ "@wooksjs/http-body": "^0.7.15"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@wooksjs/event-http": {