@suss/recognize 0.36.0 → 0.37.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/dist/ast.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CallOps } from '@suss/extractor';
2
- import { L as LinkFunction } from './chain-DYU9ZdzF.cjs';
2
+ import { L as LinkFunction } from './chain-CGjCQQ6-.cjs';
3
3
  import '@suss/behavioral-ir';
4
4
 
5
5
  /**
package/dist/ast.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CallOps } from '@suss/extractor';
2
- import { L as LinkFunction } from './chain-DYU9ZdzF.js';
2
+ import { L as LinkFunction } from './chain-CGjCQQ6-.js';
3
3
  import '@suss/behavioral-ir';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
2
- import { ReceiverOrigin, ValueOps, CallOps, UnsettledName } from '@suss/extractor';
2
+ import { ReceiverOrigin, UnsettledName, ValueOps, CallOps } from '@suss/extractor';
3
3
 
4
4
  /**
5
5
  * The chain of links every declared pack is written as.
@@ -380,13 +380,13 @@ interface SqlEnding {
380
380
  /**
381
381
  * Where the messages a call sends are written.
382
382
  *
383
- * A library either takes one message as the call's input or takes a
384
- * collection of them under a property. Which one applies depends on the
383
+ * A library takes one message as the call's input, or a collection of
384
+ * them on a property or as the input. Which one applies depends on the
385
385
  * command, so a library offering both gets two declarations. SQS has
386
386
  * `SendMessageCommand` and `SendMessageBatchCommand`, and their inputs
387
387
  * differ.
388
388
  */
389
- type MessageLocation = OneMessage | ManyIn;
389
+ type MessageLocation = OneMessage | ManyIn | ManyAsTheInput;
390
390
  /** The call's input is the message. */
391
391
  interface OneMessage {
392
392
  readonly each: "theInput";
@@ -397,14 +397,28 @@ interface ManyIn {
397
397
  /** The property the collection is written on. */
398
398
  readonly property: string;
399
399
  }
400
+ /** The call's input is the list of messages, as in BullMQ's `addBulk([...])`. */
401
+ interface ManyAsTheInput {
402
+ readonly each: "inTheInput";
403
+ }
400
404
  /**
401
- * One part of the channel a message goes to, read off the message.
402
- *
403
- * A channel is one name on some wires and several on others. SQS has a
404
- * queue, EventBridge has a bus and a subject on it, and both are read
405
- * the same way, so a pack states the parts in the order they join.
405
+ * One part of the channel a message goes to. SQS has a queue, and
406
+ * EventBridge has a bus and a subject on it, so a pack states the parts
407
+ * in the order they join.
406
408
  */
407
- interface ChannelPart {
409
+ type ChannelPart = PropertyPart | ArgumentPart;
410
+ /**
411
+ * A part the call states as an argument, usually of a call next to it.
412
+ * A BullMQ queue takes its name when it is built, so the pack reads
413
+ * `{ of: [{ to: "receiver" }], at: 0 }`.
414
+ */
415
+ interface ArgumentPart {
416
+ readonly argument: OneArgument;
417
+ /** What a reader gives back when nothing in the source settles it. */
418
+ readonly unsettled?: UnsettledName;
419
+ }
420
+ /** A part the message, or the call's input, states as a property. */
421
+ interface PropertyPart {
408
422
  /**
409
423
  * The properties the message may state this part on, tried in order.
410
424
  * A library that lets one destination be written more than one way
@@ -442,14 +456,19 @@ interface MessageSendEnding {
442
456
  readonly channel: readonly ChannelPart[];
443
457
  /** What joins the parts, when there is more than one. */
444
458
  readonly channelSeparator?: string;
445
- /** The property the message states its body on, when the pack can say. */
446
- readonly body?: string;
447
459
  /**
448
- * The property whose literal value is recorded as the routing key. It
449
- * stays out of the channel, so a reader can filter on it but the two
450
- * sides do not pair on it.
460
+ * The property the message states its body on, or the whole message,
461
+ * when the pack can say. `queue.add(name, data)` hands the body over
462
+ * as its own argument, so the message is the body.
463
+ */
464
+ readonly body?: string | WholeMessage;
465
+ /**
466
+ * Where the literal value recorded as the routing key is: a property
467
+ * of the message, or an argument of the call. It stays out of the
468
+ * channel, so a reader can filter on it but the two sides do not
469
+ * pair on it.
451
470
  */
452
- readonly routingKey?: string;
471
+ readonly routingKey?: string | OneArgument;
453
472
  /**
454
473
  * What a reader gives back for a channel nothing in the source
455
474
  * settles. A queue URL only exists at deploy time, so the code writes
@@ -458,6 +477,10 @@ interface MessageSendEnding {
458
477
  */
459
478
  readonly unsettledName: UnsettledName;
460
479
  }
480
+ /** The message itself, as the body a send records. */
481
+ interface WholeMessage {
482
+ readonly whole: "message";
483
+ }
461
484
  /**
462
485
  * A call that hands a payload to one deployed unit, named on the call.
463
486
  *
@@ -492,4 +515,4 @@ interface Chain<TMeaning = MethodMeaning> {
492
515
  readonly example: string | null;
493
516
  }
494
517
 
495
- export type { ArgumentPick as A, StatedRule as B, Chain as C, StorageEnding as D, Ending as E, FromReceiver as F, SubjectLink as G, ToReceiver as H, InterpolatesLink as I, UnitInvokeEnding as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, ScopeLink as v, SelectorParamPick as w, SqlEnding as x, StartLink as y, StatedInputs as z };
518
+ export type { ArgumentPick as A, StartLink as B, Chain as C, StatedInputs as D, Ending as E, FromReceiver as F, StatedRule as G, StorageEnding as H, InterpolatesLink as I, SubjectLink as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, ToReceiver as N, OneArgument as O, PropertyPart as P, UnitInvokeEnding as Q, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, WholeMessage as W, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentPart as h, ArgumentsFrom as i, CallsLink as j, ContainerArgument as k, ContainerLink as l, ContainerRule as m, ContainersLink as n, InputLink as o, InputRule as p, Link as q, ManyAsTheInput as r, ManyIn as s, MatchStart as t, MessageSendEnding as u, MethodsLink as v, OneMessage as w, ScopeLink as x, SelectorParamPick as y, SqlEnding as z };
@@ -1,5 +1,5 @@
1
1
  import { MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
2
- import { ReceiverOrigin, ValueOps, CallOps, UnsettledName } from '@suss/extractor';
2
+ import { ReceiverOrigin, UnsettledName, ValueOps, CallOps } from '@suss/extractor';
3
3
 
4
4
  /**
5
5
  * The chain of links every declared pack is written as.
@@ -380,13 +380,13 @@ interface SqlEnding {
380
380
  /**
381
381
  * Where the messages a call sends are written.
382
382
  *
383
- * A library either takes one message as the call's input or takes a
384
- * collection of them under a property. Which one applies depends on the
383
+ * A library takes one message as the call's input, or a collection of
384
+ * them on a property or as the input. Which one applies depends on the
385
385
  * command, so a library offering both gets two declarations. SQS has
386
386
  * `SendMessageCommand` and `SendMessageBatchCommand`, and their inputs
387
387
  * differ.
388
388
  */
389
- type MessageLocation = OneMessage | ManyIn;
389
+ type MessageLocation = OneMessage | ManyIn | ManyAsTheInput;
390
390
  /** The call's input is the message. */
391
391
  interface OneMessage {
392
392
  readonly each: "theInput";
@@ -397,14 +397,28 @@ interface ManyIn {
397
397
  /** The property the collection is written on. */
398
398
  readonly property: string;
399
399
  }
400
+ /** The call's input is the list of messages, as in BullMQ's `addBulk([...])`. */
401
+ interface ManyAsTheInput {
402
+ readonly each: "inTheInput";
403
+ }
400
404
  /**
401
- * One part of the channel a message goes to, read off the message.
402
- *
403
- * A channel is one name on some wires and several on others. SQS has a
404
- * queue, EventBridge has a bus and a subject on it, and both are read
405
- * the same way, so a pack states the parts in the order they join.
405
+ * One part of the channel a message goes to. SQS has a queue, and
406
+ * EventBridge has a bus and a subject on it, so a pack states the parts
407
+ * in the order they join.
406
408
  */
407
- interface ChannelPart {
409
+ type ChannelPart = PropertyPart | ArgumentPart;
410
+ /**
411
+ * A part the call states as an argument, usually of a call next to it.
412
+ * A BullMQ queue takes its name when it is built, so the pack reads
413
+ * `{ of: [{ to: "receiver" }], at: 0 }`.
414
+ */
415
+ interface ArgumentPart {
416
+ readonly argument: OneArgument;
417
+ /** What a reader gives back when nothing in the source settles it. */
418
+ readonly unsettled?: UnsettledName;
419
+ }
420
+ /** A part the message, or the call's input, states as a property. */
421
+ interface PropertyPart {
408
422
  /**
409
423
  * The properties the message may state this part on, tried in order.
410
424
  * A library that lets one destination be written more than one way
@@ -442,14 +456,19 @@ interface MessageSendEnding {
442
456
  readonly channel: readonly ChannelPart[];
443
457
  /** What joins the parts, when there is more than one. */
444
458
  readonly channelSeparator?: string;
445
- /** The property the message states its body on, when the pack can say. */
446
- readonly body?: string;
447
459
  /**
448
- * The property whose literal value is recorded as the routing key. It
449
- * stays out of the channel, so a reader can filter on it but the two
450
- * sides do not pair on it.
460
+ * The property the message states its body on, or the whole message,
461
+ * when the pack can say. `queue.add(name, data)` hands the body over
462
+ * as its own argument, so the message is the body.
463
+ */
464
+ readonly body?: string | WholeMessage;
465
+ /**
466
+ * Where the literal value recorded as the routing key is: a property
467
+ * of the message, or an argument of the call. It stays out of the
468
+ * channel, so a reader can filter on it but the two sides do not
469
+ * pair on it.
451
470
  */
452
- readonly routingKey?: string;
471
+ readonly routingKey?: string | OneArgument;
453
472
  /**
454
473
  * What a reader gives back for a channel nothing in the source
455
474
  * settles. A queue URL only exists at deploy time, so the code writes
@@ -458,6 +477,10 @@ interface MessageSendEnding {
458
477
  */
459
478
  readonly unsettledName: UnsettledName;
460
479
  }
480
+ /** The message itself, as the body a send records. */
481
+ interface WholeMessage {
482
+ readonly whole: "message";
483
+ }
461
484
  /**
462
485
  * A call that hands a payload to one deployed unit, named on the call.
463
486
  *
@@ -492,4 +515,4 @@ interface Chain<TMeaning = MethodMeaning> {
492
515
  readonly example: string | null;
493
516
  }
494
517
 
495
- export type { ArgumentPick as A, StatedRule as B, Chain as C, StorageEnding as D, Ending as E, FromReceiver as F, SubjectLink as G, ToReceiver as H, InterpolatesLink as I, UnitInvokeEnding as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, ScopeLink as v, SelectorParamPick as w, SqlEnding as x, StartLink as y, StatedInputs as z };
518
+ export type { ArgumentPick as A, StartLink as B, Chain as C, StatedInputs as D, Ending as E, FromReceiver as F, StatedRule as G, StorageEnding as H, InterpolatesLink as I, SubjectLink as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, ToReceiver as N, OneArgument as O, PropertyPart as P, UnitInvokeEnding as Q, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, WholeMessage as W, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentPart as h, ArgumentsFrom as i, CallsLink as j, ContainerArgument as k, ContainerLink as l, ContainerRule as m, ContainersLink as n, InputLink as o, InputRule as p, Link as q, ManyAsTheInput as r, ManyIn as s, MatchStart as t, MessageSendEnding as u, MethodsLink as v, OneMessage as w, ScopeLink as x, SelectorParamPick as y, SqlEnding as z };
package/dist/index.cjs CHANGED
@@ -483,8 +483,8 @@ function messageSend(matched) {
483
483
  const sent = messages.length === 0 ? [NOTHING_STATED] : messages;
484
484
  const effects = [];
485
485
  for (const message of sent) {
486
- const channels = channelsOf({ message, input, ending });
487
- for (const channel of channels) {
486
+ const sending = { message, input, subject, ending };
487
+ for (const channel of channelsOf(sending)) {
488
488
  effects.push({
489
489
  type: "interaction",
490
490
  binding: (0, import_behavioral_ir.messageBusBinding)({
@@ -496,19 +496,20 @@ function messageSend(matched) {
496
496
  interaction: {
497
497
  class: "message-send",
498
498
  ...bodyOf(message, ending),
499
- ...routingKeyOf(message, ending)
499
+ ...routingKeyOf(sending)
500
500
  }
501
501
  });
502
502
  }
503
503
  }
504
504
  return effects;
505
505
  }
506
+ var MESSAGES_IN = {
507
+ theInput: (input) => [input],
508
+ in: (input, location) => input.property(location.property)?.items() ?? [],
509
+ inTheInput: (input) => input.items()
510
+ };
506
511
  function messagesIn(input, location) {
507
- if (location.each === "theInput") {
508
- return [input];
509
- }
510
- const collection = input.property(location.property);
511
- return collection === null ? [] : collection.items();
512
+ return MESSAGES_IN[location.each](input, location);
512
513
  }
513
514
  var CHANNEL_CAP = 16;
514
515
  function oneName(written, unsettled) {
@@ -544,14 +545,22 @@ function crossed(heads, values, separator) {
544
545
  );
545
546
  }
546
547
  function partValues(part, sending, read) {
548
+ const unsettled = part.unsettled ?? sending.ending.unsettledName;
549
+ if ("argument" in part) {
550
+ const stated = statedValue(sending.subject, part.argument);
551
+ return stated === null ? null : READ_PART[read](stated, unsettled);
552
+ }
547
553
  const holder = part.on === "theInput" ? sending.input : sending.message;
548
554
  const written = firstWritten(holder, part.property);
549
555
  if (written === null) {
550
556
  return part.whenAbsent === void 0 ? null : [part.whenAbsent];
551
557
  }
552
- const unsettled = part.unsettled ?? sending.ending.unsettledName;
553
- return read === "everyString" ? everyString(written, unsettled) : oneName(written, unsettled);
558
+ return READ_PART[read](written, unsettled);
554
559
  }
560
+ var READ_PART = {
561
+ everyString,
562
+ oneName
563
+ };
555
564
  function firstWritten(holder, properties) {
556
565
  for (const property of properties) {
557
566
  const written = holder.property(property);
@@ -565,16 +574,17 @@ function bodyOf(message, ending) {
565
574
  if (ending.body === void 0) {
566
575
  return {};
567
576
  }
568
- const stated = (0, import_extractor.unwrapJsonStringify)(
569
- message.property(ending.body)?.asArg() ?? null
570
- );
577
+ const written = typeof ending.body === "string" ? message.property(ending.body) : message;
578
+ const stated = (0, import_extractor.unwrapJsonStringify)(written?.asArg() ?? null);
571
579
  return stated === null ? {} : { body: stated };
572
580
  }
573
- function routingKeyOf(message, ending) {
574
- if (ending.routingKey === void 0) {
581
+ function routingKeyOf({ message, subject, ending }) {
582
+ const where = ending.routingKey;
583
+ if (where === void 0) {
575
584
  return {};
576
585
  }
577
- const stated = message.property(ending.routingKey)?.text() ?? null;
586
+ const written = typeof where === "string" ? message.property(where) : statedValue(subject, where);
587
+ const stated = written?.text() ?? null;
578
588
  return stated === null || stated === "" ? {} : { routingKey: stated };
579
589
  }
580
590
  function unitInvoke(matched) {
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConstructedFrom, DeclaredBy, CallOps, InvocationRecognizer, PatternPack, UnsettledName, ReceiverOrigin, ProjectHelpers, PackDeclarations } from '@suss/extractor';
2
2
  export { CallOps, ClassOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
3
- import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-DYU9ZdzF.cjs';
4
- export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-DYU9ZdzF.cjs';
3
+ import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, W as WholeMessage, O as OneArgument, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, U as UnitInvokeMethod } from './chain-CGjCQQ6-.cjs';
4
+ export { f as AccessKind, g as AccessPathLink, h as ArgumentPart, i as ArgumentsFrom, j as CallsLink, k as ContainerArgument, l as ContainerLink, m as ContainerRule, n as ContainersLink, E as Ending, F as FromReceiver, o as InputLink, p as InputRule, K as KindAsAsked, q as Link, r as ManyAsTheInput, s as ManyIn, t as MatchStart, u as MessageSendEnding, v as MethodsLink, w as OneMessage, P as PropertyPart, x as ScopeLink, y as SelectorParamPick, z as SqlEnding, B as StartLink, D as StatedInputs, G as StatedRule, H as StorageEnding, J as SubjectLink, T as ToArgument, N as ToReceiver, Q as UnitInvokeEnding } from './chain-CGjCQQ6-.cjs';
5
5
  import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
6
6
 
7
7
  /**
@@ -103,13 +103,14 @@ interface MessageSendsSpec {
103
103
  channel: readonly ChannelPart[];
104
104
  /** What joins the parts. Defaults to "#", as used between a bus and a subject. */
105
105
  channelSeparator?: string;
106
- /** The property a message states its body on. */
107
- body?: string;
106
+ /** The property a message states its body on, or the whole message. */
107
+ body?: string | WholeMessage;
108
108
  /**
109
- * The property whose literal value is recorded as the routing key. A
110
- * reader can filter on it, and it stays out of the channel name.
109
+ * Where the literal value recorded as the routing key is: a property
110
+ * of the message, or an argument of the call. A reader can filter on
111
+ * it, and it stays out of the channel name.
111
112
  */
112
- routingKey?: string;
113
+ routingKey?: string | OneArgument;
113
114
  /**
114
115
  * What a reader gives back for a channel nothing in the source
115
116
  * settles. Defaults to keeping the reference, because most queues get
@@ -375,4 +376,4 @@ interface UnitInvokes {
375
376
  /** A pack that recognizes a call invoking a deployed unit. */
376
377
  declare function unitInvokes(spec: UnitInvokesSpec): UnitInvokes;
377
378
 
378
- export { ArgumentPick, CallStep, Chain, ChannelPart, InterpolatesLink, LinkFunction, type Match, MessageLocation, MessageSendMethod, type MessageSends, type MessageSendsSpec, MethodMeaning, OneArgument, type PackSpec, type RanExample, type RunOverCode, SqlMethod, type SqlStatements, type SqlStatementsSpec, type StorageCalls, type StorageCallsSpec, StorageMethod, UnitInvokeMethod, type UnitInvokes, type UnitInvokesSpec, compile, constructedFrom, declarationsIn, declaredBy, examplesMissing, messageSends, opsIn, pack, runExamples, sqlStatements, storageCalls, unitInvokes };
379
+ export { ArgumentPick, CallStep, Chain, ChannelPart, InterpolatesLink, LinkFunction, type Match, MessageLocation, MessageSendMethod, type MessageSends, type MessageSendsSpec, MethodMeaning, OneArgument, type PackSpec, type RanExample, type RunOverCode, SqlMethod, type SqlStatements, type SqlStatementsSpec, type StorageCalls, type StorageCallsSpec, StorageMethod, UnitInvokeMethod, type UnitInvokes, type UnitInvokesSpec, WholeMessage, compile, constructedFrom, declarationsIn, declaredBy, examplesMissing, messageSends, opsIn, pack, runExamples, sqlStatements, storageCalls, unitInvokes };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConstructedFrom, DeclaredBy, CallOps, InvocationRecognizer, PatternPack, UnsettledName, ReceiverOrigin, ProjectHelpers, PackDeclarations } from '@suss/extractor';
2
2
  export { CallOps, ClassOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
3
- import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-DYU9ZdzF.js';
4
- export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-DYU9ZdzF.js';
3
+ import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, W as WholeMessage, O as OneArgument, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, U as UnitInvokeMethod } from './chain-CGjCQQ6-.js';
4
+ export { f as AccessKind, g as AccessPathLink, h as ArgumentPart, i as ArgumentsFrom, j as CallsLink, k as ContainerArgument, l as ContainerLink, m as ContainerRule, n as ContainersLink, E as Ending, F as FromReceiver, o as InputLink, p as InputRule, K as KindAsAsked, q as Link, r as ManyAsTheInput, s as ManyIn, t as MatchStart, u as MessageSendEnding, v as MethodsLink, w as OneMessage, P as PropertyPart, x as ScopeLink, y as SelectorParamPick, z as SqlEnding, B as StartLink, D as StatedInputs, G as StatedRule, H as StorageEnding, J as SubjectLink, T as ToArgument, N as ToReceiver, Q as UnitInvokeEnding } from './chain-CGjCQQ6-.js';
5
5
  import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
6
6
 
7
7
  /**
@@ -103,13 +103,14 @@ interface MessageSendsSpec {
103
103
  channel: readonly ChannelPart[];
104
104
  /** What joins the parts. Defaults to "#", as used between a bus and a subject. */
105
105
  channelSeparator?: string;
106
- /** The property a message states its body on. */
107
- body?: string;
106
+ /** The property a message states its body on, or the whole message. */
107
+ body?: string | WholeMessage;
108
108
  /**
109
- * The property whose literal value is recorded as the routing key. A
110
- * reader can filter on it, and it stays out of the channel name.
109
+ * Where the literal value recorded as the routing key is: a property
110
+ * of the message, or an argument of the call. A reader can filter on
111
+ * it, and it stays out of the channel name.
111
112
  */
112
- routingKey?: string;
113
+ routingKey?: string | OneArgument;
113
114
  /**
114
115
  * What a reader gives back for a channel nothing in the source
115
116
  * settles. Defaults to keeping the reference, because most queues get
@@ -375,4 +376,4 @@ interface UnitInvokes {
375
376
  /** A pack that recognizes a call invoking a deployed unit. */
376
377
  declare function unitInvokes(spec: UnitInvokesSpec): UnitInvokes;
377
378
 
378
- export { ArgumentPick, CallStep, Chain, ChannelPart, InterpolatesLink, LinkFunction, type Match, MessageLocation, MessageSendMethod, type MessageSends, type MessageSendsSpec, MethodMeaning, OneArgument, type PackSpec, type RanExample, type RunOverCode, SqlMethod, type SqlStatements, type SqlStatementsSpec, type StorageCalls, type StorageCallsSpec, StorageMethod, UnitInvokeMethod, type UnitInvokes, type UnitInvokesSpec, compile, constructedFrom, declarationsIn, declaredBy, examplesMissing, messageSends, opsIn, pack, runExamples, sqlStatements, storageCalls, unitInvokes };
379
+ export { ArgumentPick, CallStep, Chain, ChannelPart, InterpolatesLink, LinkFunction, type Match, MessageLocation, MessageSendMethod, type MessageSends, type MessageSendsSpec, MethodMeaning, OneArgument, type PackSpec, type RanExample, type RunOverCode, SqlMethod, type SqlStatements, type SqlStatementsSpec, type StorageCalls, type StorageCallsSpec, StorageMethod, UnitInvokeMethod, type UnitInvokes, type UnitInvokesSpec, WholeMessage, compile, constructedFrom, declarationsIn, declaredBy, examplesMissing, messageSends, opsIn, pack, runExamples, sqlStatements, storageCalls, unitInvokes };
package/dist/index.js CHANGED
@@ -451,8 +451,8 @@ function messageSend(matched) {
451
451
  const sent = messages.length === 0 ? [NOTHING_STATED] : messages;
452
452
  const effects = [];
453
453
  for (const message of sent) {
454
- const channels = channelsOf({ message, input, ending });
455
- for (const channel of channels) {
454
+ const sending = { message, input, subject, ending };
455
+ for (const channel of channelsOf(sending)) {
456
456
  effects.push({
457
457
  type: "interaction",
458
458
  binding: messageBusBinding({
@@ -464,19 +464,20 @@ function messageSend(matched) {
464
464
  interaction: {
465
465
  class: "message-send",
466
466
  ...bodyOf(message, ending),
467
- ...routingKeyOf(message, ending)
467
+ ...routingKeyOf(sending)
468
468
  }
469
469
  });
470
470
  }
471
471
  }
472
472
  return effects;
473
473
  }
474
+ var MESSAGES_IN = {
475
+ theInput: (input) => [input],
476
+ in: (input, location) => input.property(location.property)?.items() ?? [],
477
+ inTheInput: (input) => input.items()
478
+ };
474
479
  function messagesIn(input, location) {
475
- if (location.each === "theInput") {
476
- return [input];
477
- }
478
- const collection = input.property(location.property);
479
- return collection === null ? [] : collection.items();
480
+ return MESSAGES_IN[location.each](input, location);
480
481
  }
481
482
  var CHANNEL_CAP = 16;
482
483
  function oneName(written, unsettled) {
@@ -512,14 +513,22 @@ function crossed(heads, values, separator) {
512
513
  );
513
514
  }
514
515
  function partValues(part, sending, read) {
516
+ const unsettled = part.unsettled ?? sending.ending.unsettledName;
517
+ if ("argument" in part) {
518
+ const stated = statedValue(sending.subject, part.argument);
519
+ return stated === null ? null : READ_PART[read](stated, unsettled);
520
+ }
515
521
  const holder = part.on === "theInput" ? sending.input : sending.message;
516
522
  const written = firstWritten(holder, part.property);
517
523
  if (written === null) {
518
524
  return part.whenAbsent === void 0 ? null : [part.whenAbsent];
519
525
  }
520
- const unsettled = part.unsettled ?? sending.ending.unsettledName;
521
- return read === "everyString" ? everyString(written, unsettled) : oneName(written, unsettled);
526
+ return READ_PART[read](written, unsettled);
522
527
  }
528
+ var READ_PART = {
529
+ everyString,
530
+ oneName
531
+ };
523
532
  function firstWritten(holder, properties) {
524
533
  for (const property of properties) {
525
534
  const written = holder.property(property);
@@ -533,16 +542,17 @@ function bodyOf(message, ending) {
533
542
  if (ending.body === void 0) {
534
543
  return {};
535
544
  }
536
- const stated = unwrapJsonStringify(
537
- message.property(ending.body)?.asArg() ?? null
538
- );
545
+ const written = typeof ending.body === "string" ? message.property(ending.body) : message;
546
+ const stated = unwrapJsonStringify(written?.asArg() ?? null);
539
547
  return stated === null ? {} : { body: stated };
540
548
  }
541
- function routingKeyOf(message, ending) {
542
- if (ending.routingKey === void 0) {
549
+ function routingKeyOf({ message, subject, ending }) {
550
+ const where = ending.routingKey;
551
+ if (where === void 0) {
543
552
  return {};
544
553
  }
545
- const stated = message.property(ending.routingKey)?.text() ?? null;
554
+ const written = typeof where === "string" ? message.property(where) : statedValue(subject, where);
555
+ const stated = written?.text() ?? null;
546
556
  return stated === null || stated === "" ? {} : { routingKey: stated };
547
557
  }
548
558
  function unitInvoke(matched) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/recognize",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "description": "Teach suss to read a library you use, by writing a pack as data rather than code, which any language adapter can run.",
6
6
  "keywords": [
@@ -51,9 +51,9 @@
51
51
  "typecheck": "tsc --noEmit"
52
52
  },
53
53
  "dependencies": {
54
- "@suss/behavioral-ir": "0.36.0",
55
- "@suss/extractor": "0.36.0",
56
- "@suss/sql": "0.36.0"
54
+ "@suss/behavioral-ir": "0.37.0",
55
+ "@suss/extractor": "0.37.0",
56
+ "@suss/sql": "0.37.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "tsup": "*",