@relayfile/relay-helpers 0.3.36 → 0.3.37

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/slack.d.ts CHANGED
@@ -1,5 +1,19 @@
1
1
  import type { IntegrationClientOptions } from '@relayfile/adapter-core/vfs-client';
2
2
  import { type ProviderClient } from './provider-client.js';
3
+ /**
4
+ * The delivered Slack message ts off a writeback receipt. The writeback worker
5
+ * records the real `chat.postMessage` ts as the receipt's `externalId` (the
6
+ * idempotency-replay path also mirrors it onto `ts`); only older/non-message
7
+ * receipts fall back to `created`/`id`. Returning the actual message ts is what
8
+ * lets callers thread a reply onto a post — reading `created`/`id` alone gave an
9
+ * empty (or non-ts) value, so threaded replies silently failed.
10
+ */
11
+ export declare function slackReceiptTs(receipt: {
12
+ externalId?: string;
13
+ ts?: unknown;
14
+ created?: string;
15
+ id?: string;
16
+ } | undefined): string;
3
17
  export interface SlackClient extends ProviderClient<'slack'> {
4
18
  /** Post a message to a channel. */
5
19
  post(channel: string, text: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAO3E,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC1D,mCAAmC;IACnC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,6BAA6B;IAC7B,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,yBAAyB;IACzB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjG,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,wBAA6B,GAAG,WAAW,CAmB5E"}
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAO3E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACxF,MAAM,CAIR;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC1D,mCAAmC;IACnC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,6BAA6B;IAC7B,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,yBAAyB;IACzB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjG,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,wBAA6B,GAAG,WAAW,CAmB5E"}
package/dist/slack.js CHANGED
@@ -3,6 +3,20 @@ import { providerClient } from './provider-client.js';
3
3
  function tsParam(ts) {
4
4
  return ts.replace(/\./g, '_');
5
5
  }
6
+ /**
7
+ * The delivered Slack message ts off a writeback receipt. The writeback worker
8
+ * records the real `chat.postMessage` ts as the receipt's `externalId` (the
9
+ * idempotency-replay path also mirrors it onto `ts`); only older/non-message
10
+ * receipts fall back to `created`/`id`. Returning the actual message ts is what
11
+ * lets callers thread a reply onto a post — reading `created`/`id` alone gave an
12
+ * empty (or non-ts) value, so threaded replies silently failed.
13
+ */
14
+ export function slackReceiptTs(receipt) {
15
+ if (!receipt)
16
+ return '';
17
+ const replayTs = typeof receipt.ts === 'string' ? receipt.ts : undefined;
18
+ return receipt.externalId ?? replayTs ?? receipt.created ?? receipt.id ?? '';
19
+ }
6
20
  /**
7
21
  * Ergonomic Slack client over the writeback-path catalog, plus the uniform
8
22
  * resource-keyed access (`.messages`, `.["direct-messages"]`, `.replies`, `.reactions`).
@@ -12,15 +26,15 @@ export function slackClient(opts = {}) {
12
26
  return Object.assign(base, {
13
27
  async post(channel, text) {
14
28
  const result = await base.messages.write({ channelId: channel }, { text });
15
- return { channel, ts: result.receipt?.created ?? result.receipt?.id ?? '' };
29
+ return { channel, ts: slackReceiptTs(result.receipt) };
16
30
  },
17
31
  async dm(user, text) {
18
32
  const result = await base['direct-messages'].write({ userId: user }, { text });
19
- return { user, ts: result.receipt?.created ?? result.receipt?.id ?? '' };
33
+ return { user, ts: slackReceiptTs(result.receipt) };
20
34
  },
21
35
  async reply(channel, threadTs, text) {
22
36
  const result = await base.replies.write({ channelId: channel, messageTs: tsParam(threadTs) }, { text });
23
- return { channel, ts: result.receipt?.created ?? result.receipt?.id ?? '' };
37
+ return { channel, ts: slackReceiptTs(result.receipt) };
24
38
  },
25
39
  async react(channel, messageTs, emoji) {
26
40
  await base.reactions.write({ channelId: channel, messageTs: tsParam(messageTs) }, { emoji });
package/dist/slack.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"slack.js","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAuB,MAAM,sBAAsB,CAAC;AAE3E,8EAA8E;AAC9E,SAAS,OAAO,CAAC,EAAU;IACzB,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAChC,CAAC;AAaD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAiC,EAAE;IAC7D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QACzB,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,IAAY;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QAC9E,CAAC;QACD,KAAK,CAAC,EAAE,CAAC,IAAY,EAAE,IAAY;YACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3E,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,QAAgB,EAAE,IAAY;YACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACxG,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QAC9E,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAa;YAC3D,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/F,CAAC;KACF,CAAgB,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAuB,MAAM,sBAAsB,CAAC;AAE3E,8EAA8E;AAC9E,SAAS,OAAO,CAAC,EAAU;IACzB,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyF;IAEzF,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,OAAO,OAAO,CAAC,UAAU,IAAI,QAAQ,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;AAC/E,CAAC;AAaD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAiC,EAAE;IAC7D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QACzB,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,IAAY;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,EAAE,CAAC,IAAY,EAAE,IAAY;YACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,QAAgB,EAAE,IAAY;YACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACxG,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAa;YAC3D,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/F,CAAC;KACF,CAAgB,CAAC;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=slack.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.test.d.ts","sourceRoot":"","sources":["../src/slack.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+ import { slackReceiptTs } from './slack.js';
4
+ test('slackReceiptTs prefers the Slack message ts (externalId) so replies thread', () => {
5
+ // A chat.postMessage receipt: the worker records the message ts as externalId.
6
+ // Older behaviour returned `created` (a non-ts value) and broke threading.
7
+ assert.equal(slackReceiptTs({ externalId: '1733512345.001900', created: '2026-06-16T20:35:00.000Z', id: 'op-1' }), '1733512345.001900');
8
+ });
9
+ test('slackReceiptTs uses the replay `ts` mirror when externalId is absent', () => {
10
+ assert.equal(slackReceiptTs({ ts: '1733512345.001900' }), '1733512345.001900');
11
+ });
12
+ test('slackReceiptTs falls back to created/id for non-message receipts', () => {
13
+ assert.equal(slackReceiptTs({ id: 'ISS-1' }), 'ISS-1');
14
+ assert.equal(slackReceiptTs({ created: '2026-06-16T20:35:00.000Z' }), '2026-06-16T20:35:00.000Z');
15
+ });
16
+ test('slackReceiptTs returns empty when there is no usable receipt', () => {
17
+ assert.equal(slackReceiptTs(undefined), '');
18
+ assert.equal(slackReceiptTs({}), '');
19
+ });
20
+ test('slackReceiptTs ignores a non-string ts', () => {
21
+ assert.equal(slackReceiptTs({ ts: 12345, created: 'c' }), 'c');
22
+ });
23
+ //# sourceMappingURL=slack.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.test.js","sourceRoot":"","sources":["../src/slack.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,IAAI,CAAC,4EAA4E,EAAE,GAAG,EAAE;IACtF,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAM,CAAC,KAAK,CACV,cAAc,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,0BAA0B,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EACpG,mBAAmB,CACpB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sEAAsE,EAAE,GAAG,EAAE;IAChF,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;AACjF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC5E,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,EAAE,0BAA0B,CAAC,CAAC;AACpG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;IACxE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/relay-helpers",
3
- "version": "0.3.36",
3
+ "version": "0.3.37",
4
4
  "description": "Ergonomic, catalog-backed provider clients for Relayfile integration handlers",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "prepublishOnly": "npm run build"
32
32
  },
33
33
  "dependencies": {
34
- "@relayfile/adapter-core": "^0.3.51",
35
- "@relayfile/adapter-linear": "^0.3.17"
34
+ "@relayfile/adapter-core": "^0.3.52",
35
+ "@relayfile/adapter-linear": "^0.3.18"
36
36
  }
37
37
  }