@moostjs/event-wf 0.6.15 → 0.6.17

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/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let _wooksjs_event_wf = require("@wooksjs/event-wf");
3
3
  let moost = require("moost");
4
4
  let _prostojs_wf = require("@prostojs/wf");
5
- let node_crypto = require("node:crypto");
5
+ let _prostojs_wf_outlets = require("@prostojs/wf/outlets");
6
6
 
7
7
  //#region packages/event-wf/src/meta-types.ts
8
8
  function getWfMate() {
@@ -269,185 +269,18 @@ const CONTEXT_TYPE = "WF";
269
269
  };
270
270
 
271
271
  //#endregion
272
- //#region node_modules/.pnpm/@prostojs+wf@0.1.1/node_modules/@prostojs/wf/dist/outlets/index.mjs
273
- /**
274
- * Generic outlet request. Use for custom outlets.
275
- *
276
- * @example
277
- * return outlet('pending-task', {
278
- * payload: ApprovalForm,
279
- * target: managerId,
280
- * context: { orderId, amount },
281
- * })
282
- */
283
- function outlet(name, data) {
284
- return { inputRequired: {
285
- outlet: name,
286
- ...data
287
- } };
288
- }
289
- /**
290
- * Pause for HTTP form input. The outlet returns the payload (form definition)
291
- * and state token in the HTTP response.
292
- *
293
- * @example
294
- * return outletHttp(LoginForm)
295
- * return outletHttp(LoginForm, { error: 'Invalid credentials' })
296
- */
297
- function outletHttp(payload, context) {
298
- return outlet("http", {
299
- payload,
300
- context
301
- });
302
- }
303
- /**
304
- * Pause and send email with a magic link containing the state token.
305
- *
306
- * @example
307
- * return outletEmail('user@test.com', 'invite', { name: 'Alice' })
308
- */
309
- function outletEmail(target, template, context) {
310
- return outlet("email", {
311
- target,
312
- template,
313
- context
314
- });
315
- }
316
- /**
317
- * Self-contained AES-256-GCM encrypted state strategy.
318
- *
319
- * Workflow state is encrypted into a base64url token that travels with the
320
- * transport (cookie, URL param, hidden field). No server-side storage needed.
321
- *
322
- * Token format: `base64url(iv[12] + authTag[16] + ciphertext)`
323
- *
324
- * @example
325
- * const strategy = new EncapsulatedStateStrategy({
326
- * secret: crypto.randomBytes(32),
327
- * defaultTtl: 3600_000, // 1 hour
328
- * });
329
- * const token = await strategy.persist(state);
330
- * const recovered = await strategy.retrieve(token);
331
- */
332
- var EncapsulatedStateStrategy = class {
333
- /** @throws if secret is not exactly 32 bytes */
334
- constructor(config) {
335
- this.config = config;
336
- this.key = typeof config.secret === "string" ? Buffer.from(config.secret, "hex") : config.secret;
337
- if (this.key.length !== 32) throw new Error("EncapsulatedStateStrategy: secret must be exactly 32 bytes");
338
- }
339
- /**
340
- * Encrypt workflow state into a self-contained token.
341
- * @param state — workflow state to persist
342
- * @param options.ttl — time-to-live in ms (overrides defaultTtl)
343
- * @returns base64url-encoded encrypted token
344
- */
345
- async persist(state, options) {
346
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
347
- const exp = ttl > 0 ? Date.now() + ttl : 0;
348
- const payload = JSON.stringify({
349
- s: state,
350
- e: exp
351
- });
352
- const iv = (0, node_crypto.randomBytes)(12);
353
- const cipher = (0, node_crypto.createCipheriv)("aes-256-gcm", this.key, iv);
354
- const encrypted = Buffer.concat([cipher.update(payload, "utf8"), cipher.final()]);
355
- const tag = cipher.getAuthTag();
356
- return Buffer.concat([
357
- iv,
358
- tag,
359
- encrypted
360
- ]).toString("base64url");
361
- }
362
- /** Decrypt and return workflow state. Returns null if token is invalid, expired, or tampered. */
363
- async retrieve(token) {
364
- return this.decrypt(token);
365
- }
366
- /** Same as retrieve (stateless — cannot truly invalidate a token). */
367
- async consume(token) {
368
- return this.decrypt(token);
369
- }
370
- decrypt(token) {
371
- try {
372
- const buf = Buffer.from(token, "base64url");
373
- if (buf.length < 28) return null;
374
- const iv = buf.subarray(0, 12);
375
- const tag = buf.subarray(12, 28);
376
- const ciphertext = buf.subarray(28);
377
- const decipher = (0, node_crypto.createDecipheriv)("aes-256-gcm", this.key, iv);
378
- decipher.setAuthTag(tag);
379
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
380
- const { s: state, e: exp } = JSON.parse(decrypted.toString("utf8"));
381
- if (exp > 0 && Date.now() > exp) return null;
382
- return state;
383
- } catch {
384
- return null;
385
- }
386
- }
387
- };
388
- var HandleStateStrategy = class {
389
- constructor(config) {
390
- this.config = config;
391
- }
392
- async persist(state, options) {
393
- const handle = (this.config.generateHandle ?? node_crypto.randomUUID)();
394
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
395
- const expiresAt = ttl > 0 ? Date.now() + ttl : void 0;
396
- await this.config.store.set(handle, state, expiresAt);
397
- return handle;
398
- }
399
- async retrieve(token) {
400
- return (await this.config.store.get(token))?.state ?? null;
401
- }
402
- async consume(token) {
403
- return (await this.config.store.getAndDelete(token))?.state ?? null;
404
- }
405
- };
406
- /**
407
- * In-memory state store for development and testing.
408
- * State is lost on process restart.
409
- */
410
- var WfStateStoreMemory = class {
411
- constructor() {
412
- this.store = /* @__PURE__ */ new Map();
413
- }
414
- async set(handle, state, expiresAt) {
415
- this.store.set(handle, {
416
- state,
417
- expiresAt
418
- });
419
- }
420
- async get(handle) {
421
- const entry = this.store.get(handle);
422
- if (!entry) return null;
423
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
424
- this.store.delete(handle);
425
- return null;
426
- }
427
- return entry;
428
- }
429
- async delete(handle) {
430
- this.store.delete(handle);
431
- }
432
- async getAndDelete(handle) {
433
- const entry = await this.get(handle);
434
- if (entry) this.store.delete(handle);
435
- return entry;
436
- }
437
- async cleanup() {
438
- const now = Date.now();
439
- let count = 0;
440
- for (const [handle, entry] of this.store) if (entry.expiresAt && now > entry.expiresAt) {
441
- this.store.delete(handle);
442
- count++;
443
- }
444
- return count;
445
- }
446
- };
447
-
448
- //#endregion
449
- exports.EncapsulatedStateStrategy = EncapsulatedStateStrategy;
450
- exports.HandleStateStrategy = HandleStateStrategy;
272
+ Object.defineProperty(exports, 'EncapsulatedStateStrategy', {
273
+ enumerable: true,
274
+ get: function () {
275
+ return _prostojs_wf_outlets.EncapsulatedStateStrategy;
276
+ }
277
+ });
278
+ Object.defineProperty(exports, 'HandleStateStrategy', {
279
+ enumerable: true,
280
+ get: function () {
281
+ return _prostojs_wf_outlets.HandleStateStrategy;
282
+ }
283
+ });
451
284
  exports.MoostWf = MoostWf;
452
285
  exports.Step = Step;
453
286
  Object.defineProperty(exports, 'StepRetriableError', {
@@ -457,7 +290,12 @@ Object.defineProperty(exports, 'StepRetriableError', {
457
290
  }
458
291
  });
459
292
  exports.StepTTL = StepTTL;
460
- exports.WfStateStoreMemory = WfStateStoreMemory;
293
+ Object.defineProperty(exports, 'WfStateStoreMemory', {
294
+ enumerable: true,
295
+ get: function () {
296
+ return _prostojs_wf_outlets.WfStateStoreMemory;
297
+ }
298
+ });
461
299
  exports.Workflow = Workflow;
462
300
  exports.WorkflowParam = WorkflowParam;
463
301
  exports.WorkflowSchema = WorkflowSchema;
@@ -485,9 +323,24 @@ Object.defineProperty(exports, 'handleWfOutletRequest', {
485
323
  return _wooksjs_event_wf.handleWfOutletRequest;
486
324
  }
487
325
  });
488
- exports.outlet = outlet;
489
- exports.outletEmail = outletEmail;
490
- exports.outletHttp = outletHttp;
326
+ Object.defineProperty(exports, 'outlet', {
327
+ enumerable: true,
328
+ get: function () {
329
+ return _prostojs_wf_outlets.outlet;
330
+ }
331
+ });
332
+ Object.defineProperty(exports, 'outletEmail', {
333
+ enumerable: true,
334
+ get: function () {
335
+ return _prostojs_wf_outlets.outletEmail;
336
+ }
337
+ });
338
+ Object.defineProperty(exports, 'outletHttp', {
339
+ enumerable: true,
340
+ get: function () {
341
+ return _prostojs_wf_outlets.outletHttp;
342
+ }
343
+ });
491
344
  Object.defineProperty(exports, 'useWfFinished', {
492
345
  enumerable: true,
493
346
  get: function () {
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { WooksWf, createEmailOutlet, createHttpOutlet, createOutletHandler, createWfApp, handleWfOutletRequest, handleWfOutletRequest as handleWfOutletRequest$1, useWfFinished, useWfOutlet, useWfState, useWfState as useWfState$1, wfKind } from "@wooksjs/event-wf";
2
2
  import { Resolve, defineMoostEventHandler, getMoostInfact, getMoostMate, setControllerContext, useScopeId } from "moost";
3
3
  import { StepRetriableError } from "@prostojs/wf";
4
- import { createCipheriv, createDecipheriv, randomBytes, randomUUID } from "node:crypto";
4
+ import { EncapsulatedStateStrategy, HandleStateStrategy, WfStateStoreMemory, outlet, outletEmail, outletHttp } from "@prostojs/wf/outlets";
5
5
 
6
6
  //#region packages/event-wf/src/meta-types.ts
7
7
  function getWfMate() {
@@ -267,182 +267,5 @@ const CONTEXT_TYPE = "WF";
267
267
  }
268
268
  };
269
269
 
270
- //#endregion
271
- //#region node_modules/.pnpm/@prostojs+wf@0.1.1/node_modules/@prostojs/wf/dist/outlets/index.mjs
272
- /**
273
- * Generic outlet request. Use for custom outlets.
274
- *
275
- * @example
276
- * return outlet('pending-task', {
277
- * payload: ApprovalForm,
278
- * target: managerId,
279
- * context: { orderId, amount },
280
- * })
281
- */
282
- function outlet(name, data) {
283
- return { inputRequired: {
284
- outlet: name,
285
- ...data
286
- } };
287
- }
288
- /**
289
- * Pause for HTTP form input. The outlet returns the payload (form definition)
290
- * and state token in the HTTP response.
291
- *
292
- * @example
293
- * return outletHttp(LoginForm)
294
- * return outletHttp(LoginForm, { error: 'Invalid credentials' })
295
- */
296
- function outletHttp(payload, context) {
297
- return outlet("http", {
298
- payload,
299
- context
300
- });
301
- }
302
- /**
303
- * Pause and send email with a magic link containing the state token.
304
- *
305
- * @example
306
- * return outletEmail('user@test.com', 'invite', { name: 'Alice' })
307
- */
308
- function outletEmail(target, template, context) {
309
- return outlet("email", {
310
- target,
311
- template,
312
- context
313
- });
314
- }
315
- /**
316
- * Self-contained AES-256-GCM encrypted state strategy.
317
- *
318
- * Workflow state is encrypted into a base64url token that travels with the
319
- * transport (cookie, URL param, hidden field). No server-side storage needed.
320
- *
321
- * Token format: `base64url(iv[12] + authTag[16] + ciphertext)`
322
- *
323
- * @example
324
- * const strategy = new EncapsulatedStateStrategy({
325
- * secret: crypto.randomBytes(32),
326
- * defaultTtl: 3600_000, // 1 hour
327
- * });
328
- * const token = await strategy.persist(state);
329
- * const recovered = await strategy.retrieve(token);
330
- */
331
- var EncapsulatedStateStrategy = class {
332
- /** @throws if secret is not exactly 32 bytes */
333
- constructor(config) {
334
- this.config = config;
335
- this.key = typeof config.secret === "string" ? Buffer.from(config.secret, "hex") : config.secret;
336
- if (this.key.length !== 32) throw new Error("EncapsulatedStateStrategy: secret must be exactly 32 bytes");
337
- }
338
- /**
339
- * Encrypt workflow state into a self-contained token.
340
- * @param state — workflow state to persist
341
- * @param options.ttl — time-to-live in ms (overrides defaultTtl)
342
- * @returns base64url-encoded encrypted token
343
- */
344
- async persist(state, options) {
345
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
346
- const exp = ttl > 0 ? Date.now() + ttl : 0;
347
- const payload = JSON.stringify({
348
- s: state,
349
- e: exp
350
- });
351
- const iv = randomBytes(12);
352
- const cipher = createCipheriv("aes-256-gcm", this.key, iv);
353
- const encrypted = Buffer.concat([cipher.update(payload, "utf8"), cipher.final()]);
354
- const tag = cipher.getAuthTag();
355
- return Buffer.concat([
356
- iv,
357
- tag,
358
- encrypted
359
- ]).toString("base64url");
360
- }
361
- /** Decrypt and return workflow state. Returns null if token is invalid, expired, or tampered. */
362
- async retrieve(token) {
363
- return this.decrypt(token);
364
- }
365
- /** Same as retrieve (stateless — cannot truly invalidate a token). */
366
- async consume(token) {
367
- return this.decrypt(token);
368
- }
369
- decrypt(token) {
370
- try {
371
- const buf = Buffer.from(token, "base64url");
372
- if (buf.length < 28) return null;
373
- const iv = buf.subarray(0, 12);
374
- const tag = buf.subarray(12, 28);
375
- const ciphertext = buf.subarray(28);
376
- const decipher = createDecipheriv("aes-256-gcm", this.key, iv);
377
- decipher.setAuthTag(tag);
378
- const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
379
- const { s: state, e: exp } = JSON.parse(decrypted.toString("utf8"));
380
- if (exp > 0 && Date.now() > exp) return null;
381
- return state;
382
- } catch {
383
- return null;
384
- }
385
- }
386
- };
387
- var HandleStateStrategy = class {
388
- constructor(config) {
389
- this.config = config;
390
- }
391
- async persist(state, options) {
392
- const handle = (this.config.generateHandle ?? randomUUID)();
393
- const ttl = options?.ttl ?? this.config.defaultTtl ?? 0;
394
- const expiresAt = ttl > 0 ? Date.now() + ttl : void 0;
395
- await this.config.store.set(handle, state, expiresAt);
396
- return handle;
397
- }
398
- async retrieve(token) {
399
- return (await this.config.store.get(token))?.state ?? null;
400
- }
401
- async consume(token) {
402
- return (await this.config.store.getAndDelete(token))?.state ?? null;
403
- }
404
- };
405
- /**
406
- * In-memory state store for development and testing.
407
- * State is lost on process restart.
408
- */
409
- var WfStateStoreMemory = class {
410
- constructor() {
411
- this.store = /* @__PURE__ */ new Map();
412
- }
413
- async set(handle, state, expiresAt) {
414
- this.store.set(handle, {
415
- state,
416
- expiresAt
417
- });
418
- }
419
- async get(handle) {
420
- const entry = this.store.get(handle);
421
- if (!entry) return null;
422
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
423
- this.store.delete(handle);
424
- return null;
425
- }
426
- return entry;
427
- }
428
- async delete(handle) {
429
- this.store.delete(handle);
430
- }
431
- async getAndDelete(handle) {
432
- const entry = await this.get(handle);
433
- if (entry) this.store.delete(handle);
434
- return entry;
435
- }
436
- async cleanup() {
437
- const now = Date.now();
438
- let count = 0;
439
- for (const [handle, entry] of this.store) if (entry.expiresAt && now > entry.expiresAt) {
440
- this.store.delete(handle);
441
- count++;
442
- }
443
- return count;
444
- }
445
- };
446
-
447
270
  //#endregion
448
271
  export { EncapsulatedStateStrategy, HandleStateStrategy, MoostWf, Step, StepRetriableError, StepTTL, WfStateStoreMemory, Workflow, WorkflowParam, WorkflowSchema, createEmailOutlet, createHttpOutlet, createOutletHandler, handleWfOutletRequest, outlet, outletEmail, outletHttp, useWfFinished, useWfOutlet, useWfState, wfKind };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moostjs/event-wf",
3
- "version": "0.6.15",
3
+ "version": "0.6.17",
4
4
  "description": "@moostjs/event-wf",
5
5
  "keywords": [
6
6
  "composables",
@@ -38,8 +38,8 @@
38
38
  }
39
39
  },
40
40
  "dependencies": {
41
- "@prostojs/wf": "^0.1.1",
42
- "@wooksjs/event-wf": "^0.7.13"
41
+ "@prostojs/wf": "^0.2.1",
42
+ "@wooksjs/event-wf": "^0.7.15"
43
43
  },
44
44
  "devDependencies": {
45
45
  "vitest": "3.2.4"
@@ -47,9 +47,9 @@
47
47
  "peerDependencies": {
48
48
  "@prostojs/infact": "^0.4.1",
49
49
  "@prostojs/mate": "^0.4.0",
50
- "@wooksjs/event-core": "^0.7.13",
51
- "wooks": "^0.7.13",
52
- "moost": "^0.6.15"
50
+ "@wooksjs/event-core": "^0.7.15",
51
+ "wooks": "^0.7.15",
52
+ "moost": "^0.6.17"
53
53
  },
54
54
  "scripts": {
55
55
  "pub": "pnpm publish --access public",