@foir/sdk 0.14.0 → 0.15.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
@@ -108,6 +108,30 @@ nobody asking for `@foir/sdk` gets it early. The push that carries the commit to
108
108
 
109
109
  Changes on `dev` that have not been published to npm.
110
110
 
111
+ ## [0.15.0] — 2026-10-02
112
+
113
+ Published under npm's `next` tag from `dev`, because it calls parts of the
114
+ platform that production serves from the next promotion; `latest` moves to it
115
+ then.
116
+
117
+ ### Added
118
+
119
+ - **`notifications.setConsent` answers `confirmationPending`**, and takes
120
+ `givenElsewhere` and `locale` (`@foir/sdk/app`). A project can ask that an
121
+ opt-in an app collects in a category is confirmed by email before it counts.
122
+ In such a category an opt-in writes nothing: the platform sends the customer
123
+ one confirmation email, in the page's `locale` when they have stated no
124
+ language of their own, and the answer says `confirmationPending`. The
125
+ preference turns on when they follow the link. Everywhere else an opt-in is
126
+ applied at once, as before.
127
+ - A consent the app carries over from the system it was given in says
128
+ `givenElsewhere: true`, and is applied as it stands.
129
+
130
+ ### Changed
131
+
132
+ - `notifications.setConsent` asks the platform for `confirmationPending`, a
133
+ field a platform older than this release does not have.
134
+
111
135
  ## [0.14.0] — 2026-10-01
112
136
 
113
137
  Published under npm's `next` tag from `dev`, because it calls parts of the
@@ -183,6 +183,22 @@ export interface AppConsentChange {
183
183
  * answering `stale`.
184
184
  */
185
185
  sourceModifiedAt?: string;
186
+ /**
187
+ * True when the customer gave this consent in another system and the app is
188
+ * carrying it over (a mirror). It is applied as it stands.
189
+ *
190
+ * Left out, the app collected the consent itself (a sign-up form), and an
191
+ * opt-in is applied the way its category says: at once, or, in a category
192
+ * that confirms by email, only when the customer follows the link the
193
+ * platform sends them. Until then nothing is written and the answer says
194
+ * `confirmationPending`.
195
+ */
196
+ givenElsewhere?: boolean;
197
+ /**
198
+ * The language of the page the consent was collected on. The confirmation
199
+ * email is written in it when the customer has stated none of their own.
200
+ */
201
+ locale?: string;
186
202
  }
187
203
  /** What the calling token is, and what it is served. Read from the platform, never off the token. */
188
204
  export interface AppWhoami {
@@ -409,9 +425,16 @@ export interface AppClient {
409
425
  /**
410
426
  * Set a named customer's consent in an opt-in category. Needs
411
427
  * `notifications:consent`, which only an operation's token carries.
428
+ *
429
+ * `confirmationPending` is true when an opt-in the app collected was not
430
+ * applied because its category confirms by email first: the customer has
431
+ * been sent a link, or was sent one recently, and the preference turns on
432
+ * when they follow it. The answer is the same whether or not the address
433
+ * already had a customer.
412
434
  */
413
435
  setConsent(change: AppConsentChange): Promise<{
414
436
  stale: boolean;
437
+ confirmationPending: boolean;
415
438
  }>;
416
439
  };
417
440
  operations: {
package/dist/app.js CHANGED
@@ -825,13 +825,15 @@ function createAppClient(config) {
825
825
  enabled: change.enabled
826
826
  };
827
827
  if (change.sourceModifiedAt !== void 0) input.sourceModifiedAt = change.sourceModifiedAt;
828
+ if (change.givenElsewhere !== void 0) input.givenElsewhere = change.givenElsewhere;
829
+ if (change.locale !== void 0) input.locale = change.locale;
828
830
  const answer = await field(
829
831
  "setCustomerConsent",
830
- `mutation AppSetCustomerConsent($input: SetCustomerConsentInput!) { setCustomerConsent(input: $input) { stale } }`,
832
+ `mutation AppSetCustomerConsent($input: SetCustomerConsentInput!) { setCustomerConsent(input: $input) { stale confirmationPending } }`,
831
833
  { input }
832
834
  );
833
835
  if (!answer) return refuse("setCustomerConsent reported no error and answered nothing");
834
- return { stale: answer.stale === true };
836
+ return { stale: answer.stale === true, confirmationPending: answer.confirmationPending === true };
835
837
  }
836
838
  },
837
839
  operations: {
@@ -4,8 +4,8 @@
4
4
  * Used by config API backends (e.g., Hono servers) to query the platform
5
5
  * GraphQL API at runtime. Provisioning (models, operations, schedules) is
6
6
  * handled by `foir push`. Record writes from upstream sources go through
7
- * the scoped-token `upsertRecord` GraphQL mutation served by the
8
- * integrations gateway, not through this client.
7
+ * the scoped-token `upsertRecord` GraphQL mutation an app's token reaches
8
+ * (`@foir/sdk/app`), not through this client.
9
9
  *
10
10
  * Auth: All requests use an API key (x-api-key header).
11
11
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foir/sdk",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Official Foir SDK — editor iframe client + server-side platform helpers",
5
5
  "type": "module",
6
6
  "publishConfig": {