@whooshbang/contract-mock 2.2.0 → 2.3.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/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ recorded here.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 2.3.0
9
+
10
+ ### Added
11
+
12
+ - Match sender-selected interaction expiry, default deadlines and idempotent replay behavior using the 2.3.0 contracts (FXO-3088).
13
+
8
14
  ## 2.2.0
9
15
 
10
16
  ### Changed
package/dist/core.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { resolveInteractionExpiry, resolveInteractionRequest, } from "@whooshbang/contracts";
1
2
  import { contractVersion, validateAssertEmailConsentRequest, validateBindingSummary, validateMessageListPage, validateMessageDeliveryHistory, validateMessageNotificationImage, validateInteractionTimeline, validateCustomerEventDeliveryHistory, validateCustomerEventDeliveryAttempt, validateDeliveryHolds, validateMachineClientOperationsList, validateRecipientCopyCatalogue, validateUpdateEmailSenderRequest, validateCreateConnectionTestRequest, validateConnectionTest, validateConnectionTestCollection, } from "@whooshbang/contracts";
2
3
  import { Hono } from "hono";
3
4
  import customerOwnedSlackAppManifestFixture from "@whooshbang/contracts/fixtures/core-v1/success/customer-owned-slack-app-manifest.json" with { type: "json" };
@@ -2148,9 +2149,10 @@ function messageTemporalInputIsValid(request, acceptedAt) {
2148
2149
  }
2149
2150
  }
2150
2151
  if (request.interaction !== undefined) {
2151
- const interactionExpiresAtMilliseconds = Date.parse(request.interaction.expires_at);
2152
- if (interactionExpiresAtMilliseconds < acceptedAtMilliseconds + 30 * 1000 ||
2153
- interactionExpiresAtMilliseconds > latestMilliseconds) {
2152
+ try {
2153
+ resolveInteractionExpiry(new Date(acceptedAt), request.interaction);
2154
+ }
2155
+ catch {
2154
2156
  return false;
2155
2157
  }
2156
2158
  }
@@ -2165,12 +2167,16 @@ function interactionAnswer(interaction) {
2165
2167
  }
2166
2168
  return "synthetic pre-existing answer";
2167
2169
  }
2170
+ function resolvedMockInteraction(input, acceptedAt) {
2171
+ return resolveInteractionRequest(new Date(acceptedAt), input);
2172
+ }
2168
2173
  function createInteractionSummary(interaction, id, scenario, now) {
2169
2174
  const base = {
2170
2175
  ...(interaction.correlation_id === undefined
2171
2176
  ? {}
2172
2177
  : { correlation_id: interaction.correlation_id }),
2173
- expires_at: interaction.expires_at,
2178
+ expires_at: interaction.expires_at ??
2179
+ resolveInteractionExpiry(new Date(now), interaction),
2174
2180
  id,
2175
2181
  type: interaction.type,
2176
2182
  };
@@ -3295,7 +3301,7 @@ function expandGroupBroadcasts(state) {
3295
3301
  const now = state.now();
3296
3302
  const interaction = record.request.interaction === undefined
3297
3303
  ? undefined
3298
- : createInteractionSummary(record.request.interaction, state.idGenerator("interaction"), state.scenario, now);
3304
+ : createInteractionSummary(resolvedMockInteraction(record.request.interaction, record.broadcast.accepted_at), state.idGenerator("interaction"), state.scenario, now);
3299
3305
  const message = {
3300
3306
  purpose: record.request.purpose ?? "service",
3301
3307
  accepted_at: now,
@@ -3341,7 +3347,9 @@ function expandGroupBroadcasts(state) {
3341
3347
  content: clone(record.request.content),
3342
3348
  ...(record.request.interaction === undefined
3343
3349
  ? {}
3344
- : { interactionRequest: record.request.interaction }),
3350
+ : {
3351
+ interactionRequest: resolvedMockInteraction(record.request.interaction, record.broadcast.accepted_at),
3352
+ }),
3345
3353
  message,
3346
3354
  ownerOrganizationId: record.ownerOrganizationId,
3347
3355
  providerInFlight: false,
@@ -5669,13 +5677,13 @@ function addPublicRoutes(app, getState, options) {
5669
5677
  if ("response" in parsed)
5670
5678
  return parsed.response;
5671
5679
  const now = state.now();
5672
- if (!messageTemporalInputIsValid(parsed.value, now)) {
5673
- return requestInvalid(state);
5674
- }
5675
5680
  const requestFingerprint = fingerprint(parsed.value);
5676
5681
  const replay = idempotentReplay(state, identity, "createGroupBroadcast", idempotency.key, requestFingerprint);
5677
5682
  if (replay !== undefined)
5678
5683
  return replay;
5684
+ if (!messageTemporalInputIsValid(parsed.value, now)) {
5685
+ return requestInvalid(state);
5686
+ }
5679
5687
  if (identity.credential.environment === "live") {
5680
5688
  const org = identity.credential.organizationId;
5681
5689
  if (!state.billing
@@ -5693,6 +5701,11 @@ function addPublicRoutes(app, getState, options) {
5693
5701
  .map((record) => record.membership)
5694
5702
  .filter((membership) => membership.status === "active");
5695
5703
  const broadcast = {
5704
+ ...(parsed.value.interaction === undefined
5705
+ ? {}
5706
+ : {
5707
+ interaction_expires_at: resolveInteractionExpiry(new Date(now), parsed.value.interaction),
5708
+ }),
5696
5709
  accepted_at: now,
5697
5710
  aggregate: {
5698
5711
  audience: members.length,
@@ -6295,7 +6308,9 @@ function addPublicRoutes(app, getState, options) {
6295
6308
  content: clone(normalized.content),
6296
6309
  ...(normalized.interaction === undefined
6297
6310
  ? {}
6298
- : { interactionRequest: normalized.interaction }),
6311
+ : {
6312
+ interactionRequest: resolvedMockInteraction(normalized.interaction, now),
6313
+ }),
6299
6314
  ...(credential.kind === "machine"
6300
6315
  ? { machineClientId: credential.machineClientId }
6301
6316
  : {}),