@tangle-network/agent-app 0.42.6 → 0.42.7

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.
@@ -1,3 +1,8 @@
1
+ import {
2
+ generateInviteToken,
3
+ isInviteTokenShape,
4
+ validateInviteToken
5
+ } from "../chunk-3SVAA3MA.js";
1
6
  import {
2
7
  INVITATION_EXPIRY_DAYS,
3
8
  generateInvitationToken,
@@ -7,11 +12,6 @@ import {
7
12
  parseInvitationPermission,
8
13
  renderInvitationEmail
9
14
  } from "../chunk-WEBBJBDH.js";
10
- import {
11
- generateInviteToken,
12
- isInviteTokenShape,
13
- validateInviteToken
14
- } from "../chunk-3SVAA3MA.js";
15
15
  import {
16
16
  ASSIGNABLE_WORKSPACE_ROLES,
17
17
  ORGANIZATION_ROLES,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  SeatLimitError
3
3
  } from "../chunk-SWUVTGMR.js";
4
+ import "../chunk-3SVAA3MA.js";
4
5
  import {
5
6
  generateInvitationToken,
6
7
  getInvitationExpiresAt,
@@ -8,7 +9,6 @@ import {
8
9
  normalizeInvitationEmail,
9
10
  parseInvitationPermission
10
11
  } from "../chunk-WEBBJBDH.js";
11
- import "../chunk-3SVAA3MA.js";
12
12
  import {
13
13
  hasWorkspaceRole
14
14
  } from "../chunk-63CE7FEZ.js";
@@ -0,0 +1,36 @@
1
+ import { SendInvitationEmailSeam } from './invitations-api.js';
2
+ import '../invitations-CZ5G2tIn.js';
3
+ import '../roles-BC1n4t37.js';
4
+ import './members-api.js';
5
+ import '../access-BZ81Btt5.js';
6
+ import 'drizzle-orm/sqlite-core';
7
+ import '../invitations-schema-DaMO4hZE.js';
8
+
9
+ /**
10
+ * Opt-in Resend transport for the teams invitations `sendInvitationEmail` seam.
11
+ * Most adopters back the seam with Resend and hand-roll the same wrapper — and
12
+ * the same mistake: `resend.emails.send()` returns `{ data, error }` and does NOT
13
+ * throw on an API-level failure (unverified domain, rate limit, bad recipient),
14
+ * so a `try/catch` alone records a failed send as a success. This helper sends
15
+ * through the shared `renderInvitationEmail` template and returns a typed failure
16
+ * on BOTH a thrown error AND a non-null `result.error`.
17
+ *
18
+ * `resend` is an OPTIONAL peer, imported only here: apps not on Resend keep
19
+ * passing a raw seam, and the package core never pulls a mail dependency.
20
+ */
21
+
22
+ interface ResendInvitationSenderOptions {
23
+ /** RFC-5322 From header, e.g. `GTM Agent <noreply@gtm.tangle.tools>`. */
24
+ from: string;
25
+ /** Resend API key. Defaults to `process.env.RESEND_API_KEY`. */
26
+ apiKey?: string;
27
+ }
28
+ /**
29
+ * Build a `sendInvitationEmail` seam backed by Resend. Wire it into
30
+ * `createInvitationsApi({ sendInvitationEmail: createResendInvitationSender({ from }) })`.
31
+ * The client is built lazily on first send; with no key the seam fails typed
32
+ * (the invitation is still created — emailStatus becomes 'failed').
33
+ */
34
+ declare function createResendInvitationSender(opts: ResendInvitationSenderOptions): SendInvitationEmailSeam;
35
+
36
+ export { type ResendInvitationSenderOptions, createResendInvitationSender };
@@ -0,0 +1,38 @@
1
+ import {
2
+ renderInvitationEmail
3
+ } from "../chunk-WEBBJBDH.js";
4
+
5
+ // src/teams/resend.ts
6
+ import { Resend } from "resend";
7
+ function createResendInvitationSender(opts) {
8
+ let client = null;
9
+ function getClient() {
10
+ if (client) return client;
11
+ const key = opts.apiKey ?? (typeof process !== "undefined" ? process.env.RESEND_API_KEY : void 0);
12
+ if (!key) return null;
13
+ client = new Resend(key);
14
+ return client;
15
+ }
16
+ return async (input) => {
17
+ const resend = getClient();
18
+ if (!resend) return { succeeded: false, error: "RESEND_API_KEY is not configured" };
19
+ const msg = renderInvitationEmail(input, { fromAddress: opts.from });
20
+ try {
21
+ const result = await resend.emails.send({
22
+ from: msg.from,
23
+ to: input.to,
24
+ subject: msg.subject,
25
+ html: msg.html,
26
+ text: msg.text
27
+ });
28
+ if (result.error) return { succeeded: false, error: result.error.message };
29
+ return { succeeded: true };
30
+ } catch (err) {
31
+ return { succeeded: false, error: err instanceof Error ? err.message : "Invitation email failed to send" };
32
+ }
33
+ };
34
+ }
35
+ export {
36
+ createResendInvitationSender
37
+ };
38
+ //# sourceMappingURL=resend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/teams/resend.ts"],"sourcesContent":["/**\n * Opt-in Resend transport for the teams invitations `sendInvitationEmail` seam.\n * Most adopters back the seam with Resend and hand-roll the same wrapper — and\n * the same mistake: `resend.emails.send()` returns `{ data, error }` and does NOT\n * throw on an API-level failure (unverified domain, rate limit, bad recipient),\n * so a `try/catch` alone records a failed send as a success. This helper sends\n * through the shared `renderInvitationEmail` template and returns a typed failure\n * on BOTH a thrown error AND a non-null `result.error`.\n *\n * `resend` is an OPTIONAL peer, imported only here: apps not on Resend keep\n * passing a raw seam, and the package core never pulls a mail dependency.\n */\n\nimport { Resend } from 'resend'\nimport { renderInvitationEmail } from './invitations'\nimport type { SendInvitationEmailSeam } from './invitations-api'\n\nexport interface ResendInvitationSenderOptions {\n /** RFC-5322 From header, e.g. `GTM Agent <noreply@gtm.tangle.tools>`. */\n from: string\n /** Resend API key. Defaults to `process.env.RESEND_API_KEY`. */\n apiKey?: string\n}\n\n/**\n * Build a `sendInvitationEmail` seam backed by Resend. Wire it into\n * `createInvitationsApi({ sendInvitationEmail: createResendInvitationSender({ from }) })`.\n * The client is built lazily on first send; with no key the seam fails typed\n * (the invitation is still created — emailStatus becomes 'failed').\n */\nexport function createResendInvitationSender(opts: ResendInvitationSenderOptions): SendInvitationEmailSeam {\n let client: Resend | null = null\n\n function getClient(): Resend | null {\n if (client) return client\n const key = opts.apiKey ?? (typeof process !== 'undefined' ? process.env.RESEND_API_KEY : undefined)\n if (!key) return null\n client = new Resend(key)\n return client\n }\n\n return async (input) => {\n const resend = getClient()\n if (!resend) return { succeeded: false, error: 'RESEND_API_KEY is not configured' }\n\n const msg = renderInvitationEmail(input, { fromAddress: opts.from })\n try {\n const result = await resend.emails.send({\n from: msg.from,\n to: input.to,\n subject: msg.subject,\n html: msg.html,\n text: msg.text,\n })\n // Resend reports API-level failures in `result.error` WITHOUT throwing — a\n // try/catch alone would mark a failed send as a success.\n if (result.error) return { succeeded: false, error: result.error.message }\n return { succeeded: true }\n } catch (err) {\n return { succeeded: false, error: err instanceof Error ? err.message : 'Invitation email failed to send' }\n }\n }\n}\n"],"mappings":";;;;;AAaA,SAAS,cAAc;AAiBhB,SAAS,6BAA6B,MAA8D;AACzG,MAAI,SAAwB;AAE5B,WAAS,YAA2B;AAClC,QAAI,OAAQ,QAAO;AACnB,UAAM,MAAM,KAAK,WAAW,OAAO,YAAY,cAAc,QAAQ,IAAI,iBAAiB;AAC1F,QAAI,CAAC,IAAK,QAAO;AACjB,aAAS,IAAI,OAAO,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,UAAU;AACtB,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO,EAAE,WAAW,OAAO,OAAO,mCAAmC;AAElF,UAAM,MAAM,sBAAsB,OAAO,EAAE,aAAa,KAAK,KAAK,CAAC;AACnE,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,OAAO,KAAK;AAAA,QACtC,MAAM,IAAI;AAAA,QACV,IAAI,MAAM;AAAA,QACV,SAAS,IAAI;AAAA,QACb,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,MACZ,CAAC;AAGD,UAAI,OAAO,MAAO,QAAO,EAAE,WAAW,OAAO,OAAO,OAAO,MAAM,QAAQ;AACzE,aAAO,EAAE,WAAW,KAAK;AAAA,IAC3B,SAAS,KAAK;AACZ,aAAO,EAAE,WAAW,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,kCAAkC;AAAA,IAC3G;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.42.6",
3
+ "version": "0.42.7",
4
4
  "packageManager": "pnpm@10.33.4",
5
5
  "description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
6
6
  "keywords": [
@@ -254,6 +254,11 @@
254
254
  "import": "./dist/teams/invitations-api.js",
255
255
  "default": "./dist/teams/invitations-api.js"
256
256
  },
257
+ "./teams/resend": {
258
+ "types": "./dist/teams/resend.d.ts",
259
+ "import": "./dist/teams/resend.js",
260
+ "default": "./dist/teams/resend.js"
261
+ },
257
262
  "./teams-react": {
258
263
  "types": "./dist/teams-react/index.d.ts",
259
264
  "import": "./dist/teams-react/index.js",
@@ -351,6 +356,7 @@
351
356
  "react-dom": "^19.2.7",
352
357
  "react-konva": "^19.2.5",
353
358
  "react-router": "^7.15.1",
359
+ "resend": "^6.12.4",
354
360
  "tsup": "^8.0.0",
355
361
  "typescript": "^5.7.0",
356
362
  "vitest": "^3.0.0"
@@ -369,7 +375,8 @@
369
375
  "lucide-react": ">=1",
370
376
  "react": ">=18",
371
377
  "react-konva": ">=18",
372
- "react-router": ">=7"
378
+ "react-router": ">=7",
379
+ "resend": ">=6"
373
380
  },
374
381
  "peerDependenciesMeta": {
375
382
  "@huggingface/transformers": {
@@ -407,6 +414,9 @@
407
414
  },
408
415
  "@radix-ui/react-dialog": {
409
416
  "optional": true
417
+ },
418
+ "resend": {
419
+ "optional": true
410
420
  }
411
421
  },
412
422
  "dependencies": {