@forumone/throughline-email 0.2.12 → 0.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
@@ -1,5 +1,51 @@
1
1
  # @forumone/throughline-email
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 006ae30: A missing environment variable is reported together with every other one, in a
8
+ single error, instead of one plugin at a time.
9
+
10
+ The plugins that read the environment at init now declare what they cannot
11
+ start without, as data: `approvalsEnv` (`APPROVAL_TOKEN_SECRET`, 32+
12
+ characters), `emailEnv` (`RESEND_API_KEY`, `EMAIL_FROM_ADDRESS`) and `formsEnv`
13
+ (`FORMS_IP_HASH_SECRET`, 32+ characters). Each is a list of `EnvRequirement`
14
+ (`{ name, minLength?, why }`), a new type in `plugin-contract`, and each
15
+ plugin's own init check now reads the same entries, so the two cannot drift.
16
+ An empty or whitespace-only value now counts as missing in those checks.
17
+
18
+ Core exports `assertEnvironment(...checks)`. Call it first in
19
+ `payload.config.ts` with the plugins' lists and your own variables; it throws
20
+ one `EnvironmentError` whose first line reads "Configuration problem: N
21
+ environment variables are missing or invalid", followed by every missing or
22
+ too-short variable and why it is needed. Values are never printed. An argument
23
+ can also be a function, for a rule that is not "this name, this long", such as
24
+ a database URL accepted under several names. `checkEnvValue` is the one-value
25
+ check behind it, for a plugin's own backstop.
26
+
27
+ New projects call `assertEnvironment` at the top of `payload.config.ts` with
28
+ `approvalsEnv`, `emailEnv`, `formsEnv`, `PAYLOAD_SECRET` (32+ characters),
29
+ `NEXT_PUBLIC_SERVER_URL` and the database resolver, and `.env.example` marks
30
+ which variables are checked. An existing site can do the same and delete any
31
+ hand-kept copy of the plugins' requirements.
32
+
33
+ - ab623e1: The `payload` peer range moves from `^3.0.0` to `^3.89.0` for every package that has one. **A site on Payload older than 3.89.0 must upgrade Payload before upgrading these packages.**
34
+
35
+ Before 3.89.0, the `payload-mcp-api-keys` collection that `@payloadcms/plugin-mcp` adds registered Payload's API-key strategy on every REST route. Any key could then become `req.user` outside `/api/mcp` and pass access rules written as `Boolean(req.user)`. Every Throughline site runs that plugin, so the floor is the same for every package. No package's code changes with this bump.
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies [006ae30]
40
+ - Updated dependencies [549d292]
41
+ - Updated dependencies [70385c4]
42
+ - Updated dependencies [c8a86bf]
43
+ - Updated dependencies [ab623e1]
44
+ - Updated dependencies [ab623e1]
45
+ - Updated dependencies [36728c4]
46
+ - @forumone/throughline-plugin-contract@0.5.0
47
+ - @forumone/throughline-core@0.10.0
48
+
3
49
  ## 0.2.12
4
50
 
5
51
  ### Patch Changes
package/README.md CHANGED
@@ -18,7 +18,7 @@ After this package, the approval workflow is end-to-end: a marketer requests app
18
18
  pnpm add @forumone/throughline-email
19
19
  ```
20
20
 
21
- Peers: `payload@^3.0.0`, `inngest@^4.0.0`, `react@^18 || ^19`. The plugin lazy-loads `resend` and `@react-email/render` on first send, so a misconfigured deploy fails on first email rather than at boot.
21
+ Peers: `payload@^3.89.0`, `inngest@^4.0.0`, `react@^18 || ^19`. The plugin lazy-loads `resend` and `@react-email/render` on first send, so a misconfigured deploy fails on first email rather than at boot.
22
22
 
23
23
  ## Usage
24
24
 
@@ -114,6 +114,10 @@ The approval-request notifier sends to every approver in `notifiedApprovers`. Ea
114
114
 
115
115
  Every email renders to both HTML and plaintext from the same React tree (React Email's `render(..., { plainText: true })`). Plaintext is required for accessibility (screen readers), deliverability (spam scores improve dramatically), and for clients that refuse HTML.
116
116
 
117
+ ## Environment
118
+
119
+ `emailEnv` declares what the plugin reads from the environment and refuses to start without — `RESEND_API_KEY` and `EMAIL_FROM_ADDRESS`, used when `apiKey` / `fromAddress` are omitted. Pass it to `assertEnvironment` from `@forumone/throughline-core` at the top of `payload.config.ts` so both are reported together with every other missing variable. The plugin's own init check reads the same declaration.
120
+
117
121
  ## Options reference
118
122
 
119
123
  | Option | Default | Notes |
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { createEmailClient } from './client.js';
3
3
  export type { EmailClient, EmailClientOptions, SendEmailParams, SendEmailResult, TemplateRenderer, } from './client.js';
4
4
  export { defaultTokens, mergeTokens } from './tokens.js';
5
5
  export type { EmailBrandTokens } from './tokens.js';
6
- export { DEFAULT_APPROVALS_COLLECTION_SLUG, validateOptions } from './options.js';
6
+ export { DEFAULT_APPROVALS_COLLECTION_SLUG, emailEnv, validateOptions } from './options.js';
7
7
  export type { ApprovalActionKind, BuildActionUrlArgs, EmailPluginOptions, ResolvedEmailEnv, ResolvedRecipient, } from './options.js';
8
8
  export { createNotifyApprovalRequestFunction, createNotifyApprovalDecisionFunction, createNotifyApprovalExpiredFunction, } from './functions/index.js';
9
9
  export { EmailLayout, ApprovalRequestEmail, ApprovalDecisionEmail, ApprovalExpiredEmail, } from './templates/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,iCAAiC,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACjF,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,iCAAiC,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC3F,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { emailPlugin, getEmailClient, getEmailFunctions } from './plugin.js';
2
2
  export { createEmailClient } from './client.js';
3
3
  export { defaultTokens, mergeTokens } from './tokens.js';
4
- export { DEFAULT_APPROVALS_COLLECTION_SLUG, validateOptions } from './options.js';
4
+ export { DEFAULT_APPROVALS_COLLECTION_SLUG, emailEnv, validateOptions } from './options.js';
5
5
  export { createNotifyApprovalRequestFunction, createNotifyApprovalDecisionFunction, createNotifyApprovalExpiredFunction, } from './functions/index.js';
6
6
  export { EmailLayout, ApprovalRequestEmail, ApprovalDecisionEmail, ApprovalExpiredEmail, } from './templates/index.js';
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAS/C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGxD,OAAO,EAAE,iCAAiC,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AASjF,OAAO,EACL,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAS/C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGxD,OAAO,EAAE,iCAAiC,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAS3F,OAAO,EACL,mCAAmC,EACnC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA"}
package/dist/options.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Inngest } from 'inngest';
2
- import type { BaseCorePluginOptions } from '@forumone/throughline-plugin-contract';
2
+ import type { BaseCorePluginOptions, EnvRequirement } from '@forumone/throughline-plugin-contract';
3
3
  import type { EmailBrandTokens } from './tokens.js';
4
4
  export type ApprovalActionKind = 'approve' | 'decline' | 'changes' | 'discuss';
5
5
  export interface ResolvedRecipient {
@@ -60,6 +60,15 @@ export interface EmailPluginOptions extends BaseCorePluginOptions {
60
60
  }) => Promise<string>;
61
61
  }
62
62
  export declare const DEFAULT_APPROVALS_COLLECTION_SLUG = "approvals";
63
+ /**
64
+ * What `emailPlugin` reads from the environment when the matching option is
65
+ * omitted, and refuses to start without. Hand it to `assertEnvironment` from
66
+ * `@forumone/throughline-core` so a site reports it with everything else.
67
+ *
68
+ * Leave it out if you pass `apiKey` and `fromAddress` yourself. The optional
69
+ * `EMAIL_FROM_NAME` and `EMAIL_REPLY_TO` are not requirements.
70
+ */
71
+ export declare const emailEnv: readonly EnvRequirement[];
63
72
  export interface ResolvedEmailEnv {
64
73
  apiKey: string;
65
74
  fromAddress: string;
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAE9E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB;IAC/D,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAA;IAChB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClC,uDAAuD;IACvD,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC;;;;OAIG;IACH,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACtE,kEAAkE;IAClE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACvE;;;;OAIG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QACvB,gBAAgB,EAAE,MAAM,CAAA;QACxB,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;KACnB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACtB;AAED,eAAO,MAAM,iCAAiC,cAAc,CAAA;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG;IAC5D,OAAO,EAAE,kBAAkB,CAAA;IAC3B,GAAG,EAAE,gBAAgB,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAwCA"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AAClG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAE9E,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB;IAC/D,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAA;IAChB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClC,uDAAuD;IACvD,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC;;;;OAIG;IACH,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACtE,kEAAkE;IAClE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACvE;;;;OAIG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC7D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QACvB,gBAAgB,EAAE,MAAM,CAAA;QACxB,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;KACnB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACtB;AAED,eAAO,MAAM,iCAAiC,cAAc,CAAA;AAY5D;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,cAAc,EAAoC,CAAA;AAElF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG;IAC5D,OAAO,EAAE,kBAAkB,CAAA;IAC3B,GAAG,EAAE,gBAAgB,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CA0CA"}
package/dist/options.js CHANGED
@@ -1,4 +1,22 @@
1
+ import { checkEnvValue } from '@forumone/throughline-core';
1
2
  export const DEFAULT_APPROVALS_COLLECTION_SLUG = 'approvals';
3
+ const API_KEY_ENV = {
4
+ name: 'RESEND_API_KEY',
5
+ why: 'Sends approval and form notification email through Resend; emailPlugin will not start without it.',
6
+ };
7
+ const FROM_ADDRESS_ENV = {
8
+ name: 'EMAIL_FROM_ADDRESS',
9
+ why: 'The From address on every email. It must be a verified sender on your Resend domain.',
10
+ };
11
+ /**
12
+ * What `emailPlugin` reads from the environment when the matching option is
13
+ * omitted, and refuses to start without. Hand it to `assertEnvironment` from
14
+ * `@forumone/throughline-core` so a site reports it with everything else.
15
+ *
16
+ * Leave it out if you pass `apiKey` and `fromAddress` yourself. The optional
17
+ * `EMAIL_FROM_NAME` and `EMAIL_REPLY_TO` are not requirements.
18
+ */
19
+ export const emailEnv = [API_KEY_ENV, FROM_ADDRESS_ENV];
2
20
  /**
3
21
  * Validates options at plugin init. Resolves the Resend secrets via env
4
22
  * fallback so missing configuration surfaces immediately rather than on the
@@ -8,13 +26,15 @@ export function validateOptions(options) {
8
26
  if (!options.inngest) {
9
27
  throw new Error('emailPlugin requires an Inngest client (`options.inngest`).');
10
28
  }
11
- const apiKey = options.apiKey ?? process.env['RESEND_API_KEY'];
12
- if (!apiKey) {
13
- throw new Error('emailPlugin requires `options.apiKey` or the RESEND_API_KEY env var.');
29
+ // The backstop for a site that does not call `assertEnvironment`, driven by
30
+ // the same declarations it would have passed.
31
+ const apiKey = options.apiKey ?? process.env[API_KEY_ENV.name];
32
+ if (apiKey === undefined || checkEnvValue(API_KEY_ENV, apiKey)) {
33
+ throw new Error(`emailPlugin requires \`options.apiKey\` or the ${API_KEY_ENV.name} env var.`);
14
34
  }
15
- const fromAddress = options.fromAddress ?? process.env['EMAIL_FROM_ADDRESS'];
16
- if (!fromAddress) {
17
- throw new Error('emailPlugin requires `options.fromAddress` or the EMAIL_FROM_ADDRESS env var.');
35
+ const fromAddress = options.fromAddress ?? process.env[FROM_ADDRESS_ENV.name];
36
+ if (fromAddress === undefined || checkEnvValue(FROM_ADDRESS_ENV, fromAddress)) {
37
+ throw new Error(`emailPlugin requires \`options.fromAddress\` or the ${FROM_ADDRESS_ENV.name} env var.`);
18
38
  }
19
39
  if (typeof options.resolveApprover !== 'function' || typeof options.resolveRequester !== 'function') {
20
40
  throw new Error('emailPlugin requires `options.resolveApprover` and `options.resolveRequester` so the plugin can map user IDs to email addresses without coupling to a specific user-model schema.');
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAkEA,MAAM,CAAC,MAAM,iCAAiC,GAAG,WAAW,CAAA;AAS5D;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAA2B;IAKzD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAChF,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAA;IACzF,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAC5E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAA;IACH,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,eAAe,KAAK,UAAU,IAAI,OAAO,OAAO,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACpG,MAAM,IAAI,KAAK,CACb,mLAAmL,CACpL,CAAA;IACH,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2HAA2H,CAC5H,CAAA;IACH,CAAC;IAED,MAAM,SAAS,GACb,OAAO,CAAC,QAAQ;QAChB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9B,OAAO,CAAC,MAAM,EAAE,SAAS;QACzB,WAAW,CAAA;IAEb,MAAM,GAAG,GAAqB;QAC5B,MAAM;QACN,WAAW;QACX,QAAQ,EAAE,SAAS;KACpB,CAAA;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChE,IAAI,OAAO;QAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAA;IAElC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;AACpC,CAAC"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAmE1D,MAAM,CAAC,MAAM,iCAAiC,GAAG,WAAW,CAAA;AAE5D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,gBAAgB;IACtB,GAAG,EAAE,mGAAmG;CACvE,CAAA;AAEnC,MAAM,gBAAgB,GAAG;IACvB,IAAI,EAAE,oBAAoB;IAC1B,GAAG,EAAE,sFAAsF;CAC1D,CAAA;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAA8B,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;AASlF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAA2B;IAKzD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAChF,CAAC;IACD,4EAA4E;IAC5E,8CAA8C;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC9D,IAAI,MAAM,KAAK,SAAS,IAAI,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,kDAAkD,WAAW,CAAC,IAAI,WAAW,CAAC,CAAA;IAChG,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAC7E,IAAI,WAAW,KAAK,SAAS,IAAI,aAAa,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CACb,uDAAuD,gBAAgB,CAAC,IAAI,WAAW,CACxF,CAAA;IACH,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,eAAe,KAAK,UAAU,IAAI,OAAO,OAAO,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACpG,MAAM,IAAI,KAAK,CACb,mLAAmL,CACpL,CAAA;IACH,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2HAA2H,CAC5H,CAAA;IACH,CAAC;IAED,MAAM,SAAS,GACb,OAAO,CAAC,QAAQ;QAChB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9B,OAAO,CAAC,MAAM,EAAE,SAAS;QACzB,WAAW,CAAA;IAEb,MAAM,GAAG,GAAqB;QAC5B,MAAM;QACN,WAAW;QACX,QAAQ,EAAE,SAAS;KACpB,CAAA;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChE,IAAI,OAAO;QAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAA;IAElC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;AACpC,CAAC"}
@@ -11,5 +11,5 @@ export interface ApprovalDecisionEmailProps {
11
11
  previewUrl: string;
12
12
  tokens: EmailBrandTokens;
13
13
  }
14
- export declare function ApprovalDecisionEmail(props: ApprovalDecisionEmailProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function ApprovalDecisionEmail(props: ApprovalDecisionEmailProps): import("react").JSX.Element;
15
15
  //# sourceMappingURL=ApprovalDecision.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApprovalDecision.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalDecision.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,GAAG,mBAAmB,CAAA;AAE/E,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAA;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAwBD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,2CAwEtE"}
1
+ {"version":3,"file":"ApprovalDecision.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalDecision.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,GAAG,mBAAmB,CAAA;AAE/E,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAA;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAwBD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,+BAwEtE"}
@@ -6,5 +6,5 @@ export interface ApprovalExpiredEmailProps {
6
6
  requestedAt: string;
7
7
  tokens: EmailBrandTokens;
8
8
  }
9
- export declare function ApprovalExpiredEmail(props: ApprovalExpiredEmailProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function ApprovalExpiredEmail(props: ApprovalExpiredEmailProps): import("react").JSX.Element;
10
10
  //# sourceMappingURL=ApprovalExpired.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApprovalExpired.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalExpired.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,2CAuBpE"}
1
+ {"version":3,"file":"ApprovalExpired.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalExpired.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,+BAuBpE"}
@@ -20,5 +20,5 @@ export interface ApprovalRequestEmailProps {
20
20
  expiresAt: string;
21
21
  tokens: EmailBrandTokens;
22
22
  }
23
- export declare function ApprovalRequestEmail(props: ApprovalRequestEmailProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function ApprovalRequestEmail(props: ApprovalRequestEmailProps): import("react").JSX.Element;
24
24
  //# sourceMappingURL=ApprovalRequest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApprovalRequest.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalRequest.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEzD,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,UAAU,EAAE,kBAAkB,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,2CA6HpE"}
1
+ {"version":3,"file":"ApprovalRequest.d.ts","sourceRoot":"","sources":["../../src/templates/ApprovalRequest.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEzD,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,UAAU,EAAE,kBAAkB,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,+BA6HpE"}
@@ -13,5 +13,5 @@ export interface EmailLayoutProps {
13
13
  * `Section`) keeps Outlook / Gmail / Apple Mail rendering consistent;
14
14
  * raw `<div>` + CSS is where compatibility nightmares live.
15
15
  */
16
- export declare function EmailLayout({ preview, tokens, children }: EmailLayoutProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function EmailLayout({ preview, tokens, children }: EmailLayoutProps): import("react").JSX.Element;
17
17
  //# sourceMappingURL=_layout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_layout.d.ts","sourceRoot":"","sources":["../../src/templates/_layout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAgD1E"}
1
+ {"version":3,"file":"_layout.d.ts","sourceRoot":"","sources":["../../src/templates/_layout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,gBAAgB,+BAgD1E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-email",
3
- "version": "0.2.12",
3
+ "version": "0.3.0",
4
4
  "description": "Transactional email system for the Throughline framework. Resend wrapper, themeable React Email templates, and Inngest functions that subscribe to the approval-workflow notification events.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -42,7 +42,7 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "inngest": "^4.0.0",
45
- "payload": "^3.0.0",
45
+ "payload": "^3.89.0",
46
46
  "react": "^18.0.0 || ^19.0.0"
47
47
  },
48
48
  "dependencies": {
@@ -50,13 +50,13 @@
50
50
  "@react-email/render": "^1.3.2",
51
51
  "resend": "^6.1.4",
52
52
  "zod": "^3.23.0",
53
- "@forumone/throughline-core": "0.9.1",
54
- "@forumone/throughline-plugin-contract": "0.4.1"
53
+ "@forumone/throughline-core": "0.10.0",
54
+ "@forumone/throughline-plugin-contract": "0.5.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/node": "^24.13.2",
58
58
  "@types/react": "^19.2.0",
59
- "eslint": "^9.15.0",
59
+ "eslint": "^10.11.0",
60
60
  "inngest": "^4.2.0",
61
61
  "payload": "^3.83.0",
62
62
  "react": "^19.2.0",