@feelflow/ffid-sdk 2.15.0 → 2.16.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/README.md CHANGED
@@ -266,6 +266,28 @@ const { data: updated, error: updateError } = await client.updateProfile({
266
266
 
267
267
  `updateProfile` に空オブジェクト `{}` を渡すと `VALIDATION_ERROR` が返ります(無意味なラウンドトリップを防止)。
268
268
 
269
+ #### フィールドのクリア(null を渡す)
270
+
271
+ optional フィールドに `null` を渡すと、FFID backend 側で該当カラムを SQL NULL にクリアします(v2.16.0〜 / #2354)。
272
+
273
+ ```tsx
274
+ // 会社名と部署をクリア
275
+ await client.updateProfile({
276
+ companyName: null,
277
+ department: null,
278
+ })
279
+ ```
280
+
281
+ 値のセマンティクス:
282
+
283
+ | 渡す値 | FFID backend の挙動 |
284
+ | --- | --- |
285
+ | `undefined` / キー未指定 | 未変更(partial update) |
286
+ | `null` | クリア(SQL NULL を書き込む) |
287
+ | `""`(空文字列) | 空文字リテラルをそのまま保存(`null` 扱いには**ならない**) |
288
+
289
+ 対応フィールド: `displayName` / `phone` / `companyName` / `department` / `jobTitle` / `preferences`。`timezone` / `locale` は application-level invariant(サーバー側 normalization が string 前提)のため null 非許容。クリアは不可 — キー未指定で現状維持、もしくは新しい有効な値を渡す。
290
+
269
291
  ## 型定義
270
292
 
271
293
  ```typescript
@@ -808,7 +808,7 @@ function createProfileMethods(deps) {
808
808
  }
809
809
 
810
810
  // src/client/version-check.ts
811
- var SDK_VERSION = "2.15.0";
811
+ var SDK_VERSION = "2.16.0";
812
812
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
813
813
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
814
814
  function sdkHeaders() {
@@ -810,7 +810,7 @@ function createProfileMethods(deps) {
810
810
  }
811
811
 
812
812
  // src/client/version-check.ts
813
- var SDK_VERSION = "2.15.0";
813
+ var SDK_VERSION = "2.16.0";
814
814
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
815
815
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
816
816
  function sdkHeaders() {
@@ -1,34 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunk6XEWLARZ_cjs = require('../chunk-6XEWLARZ.cjs');
3
+ var chunkPA6S2M7C_cjs = require('../chunk-PA6S2M7C.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunk6XEWLARZ_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunk6XEWLARZ_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDInquiryForm", {
16
16
  enumerable: true,
17
- get: function () { return chunk6XEWLARZ_cjs.FFIDInquiryForm; }
17
+ get: function () { return chunkPA6S2M7C_cjs.FFIDInquiryForm; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDLoginButton", {
20
20
  enumerable: true,
21
- get: function () { return chunk6XEWLARZ_cjs.FFIDLoginButton; }
21
+ get: function () { return chunkPA6S2M7C_cjs.FFIDLoginButton; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
24
24
  enumerable: true,
25
- get: function () { return chunk6XEWLARZ_cjs.FFIDOrganizationSwitcher; }
25
+ get: function () { return chunkPA6S2M7C_cjs.FFIDOrganizationSwitcher; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
28
28
  enumerable: true,
29
- get: function () { return chunk6XEWLARZ_cjs.FFIDSubscriptionBadge; }
29
+ get: function () { return chunkPA6S2M7C_cjs.FFIDSubscriptionBadge; }
30
30
  });
31
31
  Object.defineProperty(exports, "FFIDUserMenu", {
32
32
  enumerable: true,
33
- get: function () { return chunk6XEWLARZ_cjs.FFIDUserMenu; }
33
+ get: function () { return chunkPA6S2M7C_cjs.FFIDUserMenu; }
34
34
  });
@@ -1,3 +1,3 @@
1
- export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-LPTvxtgt.cjs';
1
+ export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-DbEyptzr.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-LPTvxtgt.js';
1
+ export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-DbEyptzr.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-OOGFUCRJ.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-4IWCKZJV.js';
@@ -497,24 +497,42 @@ interface FFIDProfileCallOptions {
497
497
  *
498
498
  * Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
499
499
  * optional — only the supplied keys will be updated (partial update semantics).
500
+ *
501
+ * Per-field value semantics:
502
+ * - `undefined` / key omitted → field is untouched (partial update)
503
+ * - `null` → clears the field (stores SQL NULL in the DB)
504
+ * - `""` (empty string) → stored as a literal empty string, **not** treated as
505
+ * a clear. Use `null` when you want the DB value to become NULL
506
+ *
507
+ * `timezone` and `locale` are intentionally modeled as non-null in this
508
+ * request type (application-level invariant — the DB columns have DEFAULT
509
+ * values but no NOT NULL constraint, yet the server-side normalization
510
+ * pipeline assumes a string is always present). Pass a string to update the
511
+ * value, or omit the key to leave the current value in place. Do not pass
512
+ * `null` to clear — there is no meaningful "no timezone" state for a user.
513
+ *
514
+ * `preferences: null` is accepted and clears the column. Subsequent reads
515
+ * return `{}` because the FFID backend normalizes a null `preferences` column
516
+ * to an empty object (`toUserProfile` helper) before serializing the response —
517
+ * the SDK itself does not transform the payload.
500
518
  */
501
519
  interface FFIDUpdateUserProfileRequest {
502
- /** Display name */
503
- displayName?: string;
504
- /** Phone number */
505
- phone?: string;
506
- /** Company name */
507
- companyName?: string;
508
- /** Department */
509
- department?: string;
510
- /** Job title */
511
- jobTitle?: string;
512
- /** IANA timezone */
520
+ /** Display name (null clears the field) */
521
+ displayName?: string | null;
522
+ /** Phone number (null clears the field) */
523
+ phone?: string | null;
524
+ /** Company name (null clears the field) */
525
+ companyName?: string | null;
526
+ /** Department (null clears the field) */
527
+ department?: string | null;
528
+ /** Job title (null clears the field) */
529
+ jobTitle?: string | null;
530
+ /** IANA timezone (non-null; omit the key to leave unchanged) */
513
531
  timezone?: string;
514
- /** Locale */
532
+ /** Locale (non-null; omit the key to leave unchanged) */
515
533
  locale?: string;
516
- /** Arbitrary user preferences bag */
517
- preferences?: Record<string, unknown>;
534
+ /** Arbitrary user preferences bag (null clears the column; reads return {}) */
535
+ preferences?: Record<string, unknown> | null;
518
536
  }
519
537
  /**
520
538
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
@@ -497,24 +497,42 @@ interface FFIDProfileCallOptions {
497
497
  *
498
498
  * Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
499
499
  * optional — only the supplied keys will be updated (partial update semantics).
500
+ *
501
+ * Per-field value semantics:
502
+ * - `undefined` / key omitted → field is untouched (partial update)
503
+ * - `null` → clears the field (stores SQL NULL in the DB)
504
+ * - `""` (empty string) → stored as a literal empty string, **not** treated as
505
+ * a clear. Use `null` when you want the DB value to become NULL
506
+ *
507
+ * `timezone` and `locale` are intentionally modeled as non-null in this
508
+ * request type (application-level invariant — the DB columns have DEFAULT
509
+ * values but no NOT NULL constraint, yet the server-side normalization
510
+ * pipeline assumes a string is always present). Pass a string to update the
511
+ * value, or omit the key to leave the current value in place. Do not pass
512
+ * `null` to clear — there is no meaningful "no timezone" state for a user.
513
+ *
514
+ * `preferences: null` is accepted and clears the column. Subsequent reads
515
+ * return `{}` because the FFID backend normalizes a null `preferences` column
516
+ * to an empty object (`toUserProfile` helper) before serializing the response —
517
+ * the SDK itself does not transform the payload.
500
518
  */
501
519
  interface FFIDUpdateUserProfileRequest {
502
- /** Display name */
503
- displayName?: string;
504
- /** Phone number */
505
- phone?: string;
506
- /** Company name */
507
- companyName?: string;
508
- /** Department */
509
- department?: string;
510
- /** Job title */
511
- jobTitle?: string;
512
- /** IANA timezone */
520
+ /** Display name (null clears the field) */
521
+ displayName?: string | null;
522
+ /** Phone number (null clears the field) */
523
+ phone?: string | null;
524
+ /** Company name (null clears the field) */
525
+ companyName?: string | null;
526
+ /** Department (null clears the field) */
527
+ department?: string | null;
528
+ /** Job title (null clears the field) */
529
+ jobTitle?: string | null;
530
+ /** IANA timezone (non-null; omit the key to leave unchanged) */
513
531
  timezone?: string;
514
- /** Locale */
532
+ /** Locale (non-null; omit the key to leave unchanged) */
515
533
  locale?: string;
516
- /** Arbitrary user preferences bag */
517
- preferences?: Record<string, unknown>;
534
+ /** Arbitrary user preferences bag (null clears the column; reads return {}) */
535
+ preferences?: Record<string, unknown> | null;
518
536
  }
519
537
  /**
520
538
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunk6XEWLARZ_cjs = require('./chunk-6XEWLARZ.cjs');
3
+ var chunkPA6S2M7C_cjs = require('./chunk-PA6S2M7C.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -46,7 +46,7 @@ function createKVCacheAdapter(kv) {
46
46
  }
47
47
  function withFFIDAuth(Component, options = {}) {
48
48
  const WrappedComponent = (props) => {
49
- const { isLoading, isAuthenticated, login } = chunk6XEWLARZ_cjs.useFFIDContext();
49
+ const { isLoading, isAuthenticated, login } = chunkPA6S2M7C_cjs.useFFIDContext();
50
50
  const hasRedirected = react.useRef(false);
51
51
  react.useEffect(() => {
52
52
  if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
@@ -74,107 +74,107 @@ var FFID_NEWSLETTER_TYPES = ["inquiry_followup", "general"];
74
74
 
75
75
  Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
76
76
  enumerable: true,
77
- get: function () { return chunk6XEWLARZ_cjs.DEFAULT_API_BASE_URL; }
77
+ get: function () { return chunkPA6S2M7C_cjs.DEFAULT_API_BASE_URL; }
78
78
  });
79
79
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
80
80
  enumerable: true,
81
- get: function () { return chunk6XEWLARZ_cjs.FFIDAnnouncementBadge; }
81
+ get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementBadge; }
82
82
  });
83
83
  Object.defineProperty(exports, "FFIDAnnouncementList", {
84
84
  enumerable: true,
85
- get: function () { return chunk6XEWLARZ_cjs.FFIDAnnouncementList; }
85
+ get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementList; }
86
86
  });
87
87
  Object.defineProperty(exports, "FFIDInquiryForm", {
88
88
  enumerable: true,
89
- get: function () { return chunk6XEWLARZ_cjs.FFIDInquiryForm; }
89
+ get: function () { return chunkPA6S2M7C_cjs.FFIDInquiryForm; }
90
90
  });
91
91
  Object.defineProperty(exports, "FFIDLoginButton", {
92
92
  enumerable: true,
93
- get: function () { return chunk6XEWLARZ_cjs.FFIDLoginButton; }
93
+ get: function () { return chunkPA6S2M7C_cjs.FFIDLoginButton; }
94
94
  });
95
95
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
96
96
  enumerable: true,
97
- get: function () { return chunk6XEWLARZ_cjs.FFIDOrganizationSwitcher; }
97
+ get: function () { return chunkPA6S2M7C_cjs.FFIDOrganizationSwitcher; }
98
98
  });
99
99
  Object.defineProperty(exports, "FFIDProvider", {
100
100
  enumerable: true,
101
- get: function () { return chunk6XEWLARZ_cjs.FFIDProvider; }
101
+ get: function () { return chunkPA6S2M7C_cjs.FFIDProvider; }
102
102
  });
103
103
  Object.defineProperty(exports, "FFIDSDKError", {
104
104
  enumerable: true,
105
- get: function () { return chunk6XEWLARZ_cjs.FFIDSDKError; }
105
+ get: function () { return chunkPA6S2M7C_cjs.FFIDSDKError; }
106
106
  });
107
107
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
108
108
  enumerable: true,
109
- get: function () { return chunk6XEWLARZ_cjs.FFIDSubscriptionBadge; }
109
+ get: function () { return chunkPA6S2M7C_cjs.FFIDSubscriptionBadge; }
110
110
  });
111
111
  Object.defineProperty(exports, "FFIDUserMenu", {
112
112
  enumerable: true,
113
- get: function () { return chunk6XEWLARZ_cjs.FFIDUserMenu; }
113
+ get: function () { return chunkPA6S2M7C_cjs.FFIDUserMenu; }
114
114
  });
115
115
  Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
116
116
  enumerable: true,
117
- get: function () { return chunk6XEWLARZ_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
117
+ get: function () { return chunkPA6S2M7C_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
118
118
  });
119
119
  Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES", {
120
120
  enumerable: true,
121
- get: function () { return chunk6XEWLARZ_cjs.FFID_INQUIRY_CATEGORIES; }
121
+ get: function () { return chunkPA6S2M7C_cjs.FFID_INQUIRY_CATEGORIES; }
122
122
  });
123
123
  Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES_SITE_2026", {
124
124
  enumerable: true,
125
- get: function () { return chunk6XEWLARZ_cjs.FFID_INQUIRY_CATEGORIES_SITE_2026; }
125
+ get: function () { return chunkPA6S2M7C_cjs.FFID_INQUIRY_CATEGORIES_SITE_2026; }
126
126
  });
127
127
  Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
128
128
  enumerable: true,
129
- get: function () { return chunk6XEWLARZ_cjs.createFFIDAnnouncementsClient; }
129
+ get: function () { return chunkPA6S2M7C_cjs.createFFIDAnnouncementsClient; }
130
130
  });
131
131
  Object.defineProperty(exports, "createFFIDClient", {
132
132
  enumerable: true,
133
- get: function () { return chunk6XEWLARZ_cjs.createFFIDClient; }
133
+ get: function () { return chunkPA6S2M7C_cjs.createFFIDClient; }
134
134
  });
135
135
  Object.defineProperty(exports, "createTokenStore", {
136
136
  enumerable: true,
137
- get: function () { return chunk6XEWLARZ_cjs.createTokenStore; }
137
+ get: function () { return chunkPA6S2M7C_cjs.createTokenStore; }
138
138
  });
139
139
  Object.defineProperty(exports, "generateCodeChallenge", {
140
140
  enumerable: true,
141
- get: function () { return chunk6XEWLARZ_cjs.generateCodeChallenge; }
141
+ get: function () { return chunkPA6S2M7C_cjs.generateCodeChallenge; }
142
142
  });
143
143
  Object.defineProperty(exports, "generateCodeVerifier", {
144
144
  enumerable: true,
145
- get: function () { return chunk6XEWLARZ_cjs.generateCodeVerifier; }
145
+ get: function () { return chunkPA6S2M7C_cjs.generateCodeVerifier; }
146
146
  });
147
147
  Object.defineProperty(exports, "isFFIDInquiryCategorySite2026", {
148
148
  enumerable: true,
149
- get: function () { return chunk6XEWLARZ_cjs.isFFIDInquiryCategorySite2026; }
149
+ get: function () { return chunkPA6S2M7C_cjs.isFFIDInquiryCategorySite2026; }
150
150
  });
151
151
  Object.defineProperty(exports, "normalizeRedirectUri", {
152
152
  enumerable: true,
153
- get: function () { return chunk6XEWLARZ_cjs.normalizeRedirectUri; }
153
+ get: function () { return chunkPA6S2M7C_cjs.normalizeRedirectUri; }
154
154
  });
155
155
  Object.defineProperty(exports, "retrieveCodeVerifier", {
156
156
  enumerable: true,
157
- get: function () { return chunk6XEWLARZ_cjs.retrieveCodeVerifier; }
157
+ get: function () { return chunkPA6S2M7C_cjs.retrieveCodeVerifier; }
158
158
  });
159
159
  Object.defineProperty(exports, "storeCodeVerifier", {
160
160
  enumerable: true,
161
- get: function () { return chunk6XEWLARZ_cjs.storeCodeVerifier; }
161
+ get: function () { return chunkPA6S2M7C_cjs.storeCodeVerifier; }
162
162
  });
163
163
  Object.defineProperty(exports, "useFFID", {
164
164
  enumerable: true,
165
- get: function () { return chunk6XEWLARZ_cjs.useFFID; }
165
+ get: function () { return chunkPA6S2M7C_cjs.useFFID; }
166
166
  });
167
167
  Object.defineProperty(exports, "useFFIDAnnouncements", {
168
168
  enumerable: true,
169
- get: function () { return chunk6XEWLARZ_cjs.useFFIDAnnouncements; }
169
+ get: function () { return chunkPA6S2M7C_cjs.useFFIDAnnouncements; }
170
170
  });
171
171
  Object.defineProperty(exports, "useSubscription", {
172
172
  enumerable: true,
173
- get: function () { return chunk6XEWLARZ_cjs.useSubscription; }
173
+ get: function () { return chunkPA6S2M7C_cjs.useSubscription; }
174
174
  });
175
175
  Object.defineProperty(exports, "withSubscription", {
176
176
  enumerable: true,
177
- get: function () { return chunk6XEWLARZ_cjs.withSubscription; }
177
+ get: function () { return chunkPA6S2M7C_cjs.withSubscription; }
178
178
  });
179
179
  exports.FFID_NEWSLETTER_TYPES = FFID_NEWSLETTER_TYPES;
180
180
  exports.createKVCacheAdapter = createKVCacheAdapter;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-LPTvxtgt.cjs';
2
- export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-LPTvxtgt.cjs';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-DbEyptzr.cjs';
2
+ export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-DbEyptzr.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-LPTvxtgt.js';
2
- export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-LPTvxtgt.js';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-DbEyptzr.js';
2
+ export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-DbEyptzr.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-OOGFUCRJ.js';
2
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-OOGFUCRJ.js';
1
+ import { useFFIDContext } from './chunk-4IWCKZJV.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-4IWCKZJV.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -806,7 +806,7 @@ function createProfileMethods(deps) {
806
806
  }
807
807
 
808
808
  // src/client/version-check.ts
809
- var SDK_VERSION = "2.15.0";
809
+ var SDK_VERSION = "2.16.0";
810
810
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
811
811
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
812
812
  function sdkHeaders() {
@@ -851,24 +851,42 @@ interface FFIDProfileCallOptions {
851
851
  *
852
852
  * Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
853
853
  * optional — only the supplied keys will be updated (partial update semantics).
854
+ *
855
+ * Per-field value semantics:
856
+ * - `undefined` / key omitted → field is untouched (partial update)
857
+ * - `null` → clears the field (stores SQL NULL in the DB)
858
+ * - `""` (empty string) → stored as a literal empty string, **not** treated as
859
+ * a clear. Use `null` when you want the DB value to become NULL
860
+ *
861
+ * `timezone` and `locale` are intentionally modeled as non-null in this
862
+ * request type (application-level invariant — the DB columns have DEFAULT
863
+ * values but no NOT NULL constraint, yet the server-side normalization
864
+ * pipeline assumes a string is always present). Pass a string to update the
865
+ * value, or omit the key to leave the current value in place. Do not pass
866
+ * `null` to clear — there is no meaningful "no timezone" state for a user.
867
+ *
868
+ * `preferences: null` is accepted and clears the column. Subsequent reads
869
+ * return `{}` because the FFID backend normalizes a null `preferences` column
870
+ * to an empty object (`toUserProfile` helper) before serializing the response —
871
+ * the SDK itself does not transform the payload.
854
872
  */
855
873
  interface FFIDUpdateUserProfileRequest {
856
- /** Display name */
857
- displayName?: string;
858
- /** Phone number */
859
- phone?: string;
860
- /** Company name */
861
- companyName?: string;
862
- /** Department */
863
- department?: string;
864
- /** Job title */
865
- jobTitle?: string;
866
- /** IANA timezone */
874
+ /** Display name (null clears the field) */
875
+ displayName?: string | null;
876
+ /** Phone number (null clears the field) */
877
+ phone?: string | null;
878
+ /** Company name (null clears the field) */
879
+ companyName?: string | null;
880
+ /** Department (null clears the field) */
881
+ department?: string | null;
882
+ /** Job title (null clears the field) */
883
+ jobTitle?: string | null;
884
+ /** IANA timezone (non-null; omit the key to leave unchanged) */
867
885
  timezone?: string;
868
- /** Locale */
886
+ /** Locale (non-null; omit the key to leave unchanged) */
869
887
  locale?: string;
870
- /** Arbitrary user preferences bag */
871
- preferences?: Record<string, unknown>;
888
+ /** Arbitrary user preferences bag (null clears the column; reads return {}) */
889
+ preferences?: Record<string, unknown> | null;
872
890
  }
873
891
  /**
874
892
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
@@ -851,24 +851,42 @@ interface FFIDProfileCallOptions {
851
851
  *
852
852
  * Mirrors the FFID backend `UpdateUserProfileRequest` shape. All fields are
853
853
  * optional — only the supplied keys will be updated (partial update semantics).
854
+ *
855
+ * Per-field value semantics:
856
+ * - `undefined` / key omitted → field is untouched (partial update)
857
+ * - `null` → clears the field (stores SQL NULL in the DB)
858
+ * - `""` (empty string) → stored as a literal empty string, **not** treated as
859
+ * a clear. Use `null` when you want the DB value to become NULL
860
+ *
861
+ * `timezone` and `locale` are intentionally modeled as non-null in this
862
+ * request type (application-level invariant — the DB columns have DEFAULT
863
+ * values but no NOT NULL constraint, yet the server-side normalization
864
+ * pipeline assumes a string is always present). Pass a string to update the
865
+ * value, or omit the key to leave the current value in place. Do not pass
866
+ * `null` to clear — there is no meaningful "no timezone" state for a user.
867
+ *
868
+ * `preferences: null` is accepted and clears the column. Subsequent reads
869
+ * return `{}` because the FFID backend normalizes a null `preferences` column
870
+ * to an empty object (`toUserProfile` helper) before serializing the response —
871
+ * the SDK itself does not transform the payload.
854
872
  */
855
873
  interface FFIDUpdateUserProfileRequest {
856
- /** Display name */
857
- displayName?: string;
858
- /** Phone number */
859
- phone?: string;
860
- /** Company name */
861
- companyName?: string;
862
- /** Department */
863
- department?: string;
864
- /** Job title */
865
- jobTitle?: string;
866
- /** IANA timezone */
874
+ /** Display name (null clears the field) */
875
+ displayName?: string | null;
876
+ /** Phone number (null clears the field) */
877
+ phone?: string | null;
878
+ /** Company name (null clears the field) */
879
+ companyName?: string | null;
880
+ /** Department (null clears the field) */
881
+ department?: string | null;
882
+ /** Job title (null clears the field) */
883
+ jobTitle?: string | null;
884
+ /** IANA timezone (non-null; omit the key to leave unchanged) */
867
885
  timezone?: string;
868
- /** Locale */
886
+ /** Locale (non-null; omit the key to leave unchanged) */
869
887
  locale?: string;
870
- /** Arbitrary user preferences bag */
871
- preferences?: Record<string, unknown>;
888
+ /** Arbitrary user preferences bag (null clears the column; reads return {}) */
889
+ preferences?: Record<string, unknown> | null;
872
890
  }
873
891
  /**
874
892
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
@@ -805,7 +805,7 @@ function createProfileMethods(deps) {
805
805
  }
806
806
 
807
807
  // src/client/version-check.ts
808
- var SDK_VERSION = "2.15.0";
808
+ var SDK_VERSION = "2.16.0";
809
809
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
810
810
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
811
811
  function sdkHeaders() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",