@feelflow/ffid-sdk 2.5.2 → 2.7.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/dist/{chunk-ZBBRUQGX.cjs → chunk-I6MKRVUB.cjs} +130 -5
- package/dist/{chunk-DKWGMLCB.js → chunk-YQPG6Z7W.js} +130 -5
- package/dist/components/index.cjs +7 -7
- package/dist/components/index.js +1 -1
- package/dist/index.cjs +26 -22
- package/dist/index.d.cts +120 -20
- package/dist/index.d.ts +120 -20
- package/dist/index.js +6 -3
- package/dist/server/index.cjs +130 -5
- package/dist/server/index.d.cts +105 -19
- package/dist/server/index.d.ts +105 -19
- package/dist/server/index.js +130 -5
- package/package.json +2 -1
package/dist/server/index.d.cts
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
export { D as DEFAULT_API_BASE_URL } from '../constants-DvTGHPZn.cjs';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Newsletter types exposed by the FFID SDK.
|
|
5
|
+
*
|
|
6
|
+
* 2-layer newsletter model (#2078):
|
|
7
|
+
* - `inquiry_followup`: 問い合わせフォローアップ (Type A)
|
|
8
|
+
* - `general`: 定期ニュースレター (Type B)
|
|
9
|
+
*
|
|
10
|
+
* FFID account holders' preferences live in `user_marketing_preferences`;
|
|
11
|
+
* anonymous subscribers live in `newsletter_subscribers` with double
|
|
12
|
+
* opt-in required.
|
|
13
|
+
*/
|
|
14
|
+
declare const FFID_NEWSLETTER_TYPES: readonly ["inquiry_followup", "general"];
|
|
15
|
+
type FFIDNewsletterType = (typeof FFID_NEWSLETTER_TYPES)[number];
|
|
16
|
+
interface FFIDNewsletterSubscribeParams {
|
|
17
|
+
/** Subscriber email address */
|
|
18
|
+
email: string;
|
|
19
|
+
/** One or more newsletter types to opt in to */
|
|
20
|
+
types: FFIDNewsletterType[];
|
|
21
|
+
/** Origin string recorded on the subscriber row (e.g. your service code) */
|
|
22
|
+
source: string;
|
|
23
|
+
/** ISO 639-1 locale (e.g. 'ja', 'en') */
|
|
24
|
+
locale?: string;
|
|
25
|
+
}
|
|
26
|
+
interface FFIDNewsletterSubscribeResponse {
|
|
27
|
+
ok: true;
|
|
28
|
+
/** True when a double opt-in confirmation email was sent */
|
|
29
|
+
requiresConfirmation: boolean;
|
|
30
|
+
/** True when the email matched an existing FFID account; the caller
|
|
31
|
+
* must sign in to update preferences. Preferences are NOT modified. */
|
|
32
|
+
requiresSignIn: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface FFIDNewsletterConfirmParams {
|
|
35
|
+
/** Confirmation token received in the double opt-in email */
|
|
36
|
+
token: string;
|
|
37
|
+
}
|
|
38
|
+
interface FFIDNewsletterConfirmResponse {
|
|
39
|
+
ok: true;
|
|
40
|
+
}
|
|
41
|
+
interface FFIDNewsletterUnsubscribeParams {
|
|
42
|
+
/** Unsubscribe token received in the newsletter footer / List-Unsubscribe header */
|
|
43
|
+
token: string;
|
|
44
|
+
}
|
|
45
|
+
interface FFIDNewsletterUnsubscribeResponse {
|
|
46
|
+
ok: true;
|
|
47
|
+
}
|
|
48
|
+
|
|
3
49
|
/** Cache adapter interface for FFID SDK token verification */
|
|
4
50
|
/**
|
|
5
51
|
* Pluggable cache adapter interface.
|
|
@@ -23,6 +69,11 @@ interface FFIDCacheConfig {
|
|
|
23
69
|
|
|
24
70
|
/** Billing interval for subscriptions */
|
|
25
71
|
type FFIDBillingInterval = 'monthly' | 'yearly';
|
|
72
|
+
/**
|
|
73
|
+
* Supported currencies for billing responses.
|
|
74
|
+
* Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
|
|
75
|
+
*/
|
|
76
|
+
type FFIDSupportedCurrency = 'jpy' | 'usd';
|
|
26
77
|
/** Service information returned by plans endpoint */
|
|
27
78
|
interface FFIDServiceInfo {
|
|
28
79
|
id: string;
|
|
@@ -214,27 +265,56 @@ interface FFIDPlanChangeLineItem {
|
|
|
214
265
|
description: string;
|
|
215
266
|
amount: number;
|
|
216
267
|
}
|
|
268
|
+
/** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
|
|
269
|
+
interface FFIDPlanChangePreviewBase {
|
|
270
|
+
/** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
|
|
271
|
+
type: 'plan-change';
|
|
272
|
+
/** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
|
|
273
|
+
currentPlan: {
|
|
274
|
+
name: string;
|
|
275
|
+
price: number;
|
|
276
|
+
};
|
|
277
|
+
/** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
|
|
278
|
+
newPlan: {
|
|
279
|
+
name: string;
|
|
280
|
+
price: number;
|
|
281
|
+
};
|
|
282
|
+
billingInterval: FFIDBillingInterval;
|
|
283
|
+
isUpgrade: boolean;
|
|
284
|
+
/** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
|
|
285
|
+
nextInvoiceAmount: number;
|
|
286
|
+
nextInvoiceDate: string | null;
|
|
287
|
+
currency: FFIDSupportedCurrency;
|
|
288
|
+
/** true when amounts are estimated from local prices (no Stripe proration data) */
|
|
289
|
+
isEstimate: boolean;
|
|
290
|
+
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
291
|
+
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
292
|
+
lineItems: FFIDPlanChangeLineItem[];
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Plan change proration preview.
|
|
296
|
+
*
|
|
297
|
+
* `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
|
|
298
|
+
* - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
|
|
299
|
+
* the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
|
|
300
|
+
* billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
|
|
301
|
+
* - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
|
|
302
|
+
* (possibly Stripe-refined) day-basis difference.
|
|
303
|
+
*/
|
|
304
|
+
type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
|
|
305
|
+
willApplyAtPeriodEnd: true;
|
|
306
|
+
effectiveDate: string | null;
|
|
307
|
+
/** 0 on period-end-deferred changes; charge happens at the next invoice */
|
|
308
|
+
proratedAmount: 0;
|
|
309
|
+
} | {
|
|
310
|
+
willApplyAtPeriodEnd: false;
|
|
311
|
+
effectiveDate: null;
|
|
312
|
+
/** Prorated difference charged within the current billing period */
|
|
313
|
+
proratedAmount: number;
|
|
314
|
+
});
|
|
217
315
|
/** Response from plan change preview endpoint */
|
|
218
316
|
interface FFIDPlanChangePreviewResponse {
|
|
219
|
-
preview:
|
|
220
|
-
currentPlan: {
|
|
221
|
-
name: string;
|
|
222
|
-
price: number;
|
|
223
|
-
};
|
|
224
|
-
newPlan: {
|
|
225
|
-
name: string;
|
|
226
|
-
price: number;
|
|
227
|
-
};
|
|
228
|
-
billingInterval: FFIDBillingInterval;
|
|
229
|
-
isUpgrade: boolean;
|
|
230
|
-
proratedAmount: number;
|
|
231
|
-
nextInvoiceAmount: number;
|
|
232
|
-
nextInvoiceDate: string | null;
|
|
233
|
-
currency: string;
|
|
234
|
-
isEstimate: boolean;
|
|
235
|
-
estimateReason?: string;
|
|
236
|
-
lineItems: FFIDPlanChangeLineItem[];
|
|
237
|
-
};
|
|
317
|
+
preview: FFIDPlanChangePreview;
|
|
238
318
|
}
|
|
239
319
|
|
|
240
320
|
/**
|
|
@@ -745,6 +825,12 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
745
825
|
accessToken: string;
|
|
746
826
|
refreshToken: string;
|
|
747
827
|
}) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
|
|
828
|
+
/** Newsletter methods (subscribe / confirm / unsubscribe) */
|
|
829
|
+
newsletter: {
|
|
830
|
+
subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
|
|
831
|
+
confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
|
|
832
|
+
unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
|
|
833
|
+
};
|
|
748
834
|
/** Token store (token mode only) */
|
|
749
835
|
tokenStore: TokenStore;
|
|
750
836
|
/** Resolved auth mode */
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
export { D as DEFAULT_API_BASE_URL } from '../constants-DvTGHPZn.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Newsletter types exposed by the FFID SDK.
|
|
5
|
+
*
|
|
6
|
+
* 2-layer newsletter model (#2078):
|
|
7
|
+
* - `inquiry_followup`: 問い合わせフォローアップ (Type A)
|
|
8
|
+
* - `general`: 定期ニュースレター (Type B)
|
|
9
|
+
*
|
|
10
|
+
* FFID account holders' preferences live in `user_marketing_preferences`;
|
|
11
|
+
* anonymous subscribers live in `newsletter_subscribers` with double
|
|
12
|
+
* opt-in required.
|
|
13
|
+
*/
|
|
14
|
+
declare const FFID_NEWSLETTER_TYPES: readonly ["inquiry_followup", "general"];
|
|
15
|
+
type FFIDNewsletterType = (typeof FFID_NEWSLETTER_TYPES)[number];
|
|
16
|
+
interface FFIDNewsletterSubscribeParams {
|
|
17
|
+
/** Subscriber email address */
|
|
18
|
+
email: string;
|
|
19
|
+
/** One or more newsletter types to opt in to */
|
|
20
|
+
types: FFIDNewsletterType[];
|
|
21
|
+
/** Origin string recorded on the subscriber row (e.g. your service code) */
|
|
22
|
+
source: string;
|
|
23
|
+
/** ISO 639-1 locale (e.g. 'ja', 'en') */
|
|
24
|
+
locale?: string;
|
|
25
|
+
}
|
|
26
|
+
interface FFIDNewsletterSubscribeResponse {
|
|
27
|
+
ok: true;
|
|
28
|
+
/** True when a double opt-in confirmation email was sent */
|
|
29
|
+
requiresConfirmation: boolean;
|
|
30
|
+
/** True when the email matched an existing FFID account; the caller
|
|
31
|
+
* must sign in to update preferences. Preferences are NOT modified. */
|
|
32
|
+
requiresSignIn: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface FFIDNewsletterConfirmParams {
|
|
35
|
+
/** Confirmation token received in the double opt-in email */
|
|
36
|
+
token: string;
|
|
37
|
+
}
|
|
38
|
+
interface FFIDNewsletterConfirmResponse {
|
|
39
|
+
ok: true;
|
|
40
|
+
}
|
|
41
|
+
interface FFIDNewsletterUnsubscribeParams {
|
|
42
|
+
/** Unsubscribe token received in the newsletter footer / List-Unsubscribe header */
|
|
43
|
+
token: string;
|
|
44
|
+
}
|
|
45
|
+
interface FFIDNewsletterUnsubscribeResponse {
|
|
46
|
+
ok: true;
|
|
47
|
+
}
|
|
48
|
+
|
|
3
49
|
/** Cache adapter interface for FFID SDK token verification */
|
|
4
50
|
/**
|
|
5
51
|
* Pluggable cache adapter interface.
|
|
@@ -23,6 +69,11 @@ interface FFIDCacheConfig {
|
|
|
23
69
|
|
|
24
70
|
/** Billing interval for subscriptions */
|
|
25
71
|
type FFIDBillingInterval = 'monthly' | 'yearly';
|
|
72
|
+
/**
|
|
73
|
+
* Supported currencies for billing responses.
|
|
74
|
+
* Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
|
|
75
|
+
*/
|
|
76
|
+
type FFIDSupportedCurrency = 'jpy' | 'usd';
|
|
26
77
|
/** Service information returned by plans endpoint */
|
|
27
78
|
interface FFIDServiceInfo {
|
|
28
79
|
id: string;
|
|
@@ -214,27 +265,56 @@ interface FFIDPlanChangeLineItem {
|
|
|
214
265
|
description: string;
|
|
215
266
|
amount: number;
|
|
216
267
|
}
|
|
268
|
+
/** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
|
|
269
|
+
interface FFIDPlanChangePreviewBase {
|
|
270
|
+
/** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
|
|
271
|
+
type: 'plan-change';
|
|
272
|
+
/** Current plan display info. `price` is the total for the current quantity (unitPrice × quantity), not per-seat. */
|
|
273
|
+
currentPlan: {
|
|
274
|
+
name: string;
|
|
275
|
+
price: number;
|
|
276
|
+
};
|
|
277
|
+
/** New plan display info. `price` is the total for the effective quantity (unitPrice × quantity), not per-seat. */
|
|
278
|
+
newPlan: {
|
|
279
|
+
name: string;
|
|
280
|
+
price: number;
|
|
281
|
+
};
|
|
282
|
+
billingInterval: FFIDBillingInterval;
|
|
283
|
+
isUpgrade: boolean;
|
|
284
|
+
/** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
|
|
285
|
+
nextInvoiceAmount: number;
|
|
286
|
+
nextInvoiceDate: string | null;
|
|
287
|
+
currency: FFIDSupportedCurrency;
|
|
288
|
+
/** true when amounts are estimated from local prices (no Stripe proration data) */
|
|
289
|
+
isEstimate: boolean;
|
|
290
|
+
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
291
|
+
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
292
|
+
lineItems: FFIDPlanChangeLineItem[];
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Plan change proration preview.
|
|
296
|
+
*
|
|
297
|
+
* `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
|
|
298
|
+
* - `true`: period-end-deferred downgrade. `proratedAmount` is always 0; `effectiveDate` mirrors
|
|
299
|
+
* the subscription's `currentPeriodEnd` (may be `null` when the subscription has no active
|
|
300
|
+
* billing cycle yet — e.g. a pre-Stripe trial or a subscription whose billing cycle is unset).
|
|
301
|
+
* - `false`: immediate change. `effectiveDate` is always `null`; `proratedAmount` is the live
|
|
302
|
+
* (possibly Stripe-refined) day-basis difference.
|
|
303
|
+
*/
|
|
304
|
+
type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
|
|
305
|
+
willApplyAtPeriodEnd: true;
|
|
306
|
+
effectiveDate: string | null;
|
|
307
|
+
/** 0 on period-end-deferred changes; charge happens at the next invoice */
|
|
308
|
+
proratedAmount: 0;
|
|
309
|
+
} | {
|
|
310
|
+
willApplyAtPeriodEnd: false;
|
|
311
|
+
effectiveDate: null;
|
|
312
|
+
/** Prorated difference charged within the current billing period */
|
|
313
|
+
proratedAmount: number;
|
|
314
|
+
});
|
|
217
315
|
/** Response from plan change preview endpoint */
|
|
218
316
|
interface FFIDPlanChangePreviewResponse {
|
|
219
|
-
preview:
|
|
220
|
-
currentPlan: {
|
|
221
|
-
name: string;
|
|
222
|
-
price: number;
|
|
223
|
-
};
|
|
224
|
-
newPlan: {
|
|
225
|
-
name: string;
|
|
226
|
-
price: number;
|
|
227
|
-
};
|
|
228
|
-
billingInterval: FFIDBillingInterval;
|
|
229
|
-
isUpgrade: boolean;
|
|
230
|
-
proratedAmount: number;
|
|
231
|
-
nextInvoiceAmount: number;
|
|
232
|
-
nextInvoiceDate: string | null;
|
|
233
|
-
currency: string;
|
|
234
|
-
isEstimate: boolean;
|
|
235
|
-
estimateReason?: string;
|
|
236
|
-
lineItems: FFIDPlanChangeLineItem[];
|
|
237
|
-
};
|
|
317
|
+
preview: FFIDPlanChangePreview;
|
|
238
318
|
}
|
|
239
319
|
|
|
240
320
|
/**
|
|
@@ -745,6 +825,12 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
745
825
|
accessToken: string;
|
|
746
826
|
refreshToken: string;
|
|
747
827
|
}) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
|
|
828
|
+
/** Newsletter methods (subscribe / confirm / unsubscribe) */
|
|
829
|
+
newsletter: {
|
|
830
|
+
subscribe: (params: FFIDNewsletterSubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterSubscribeResponse>>;
|
|
831
|
+
confirm: (params: FFIDNewsletterConfirmParams) => Promise<FFIDApiResponse<FFIDNewsletterConfirmResponse>>;
|
|
832
|
+
unsubscribe: (params: FFIDNewsletterUnsubscribeParams) => Promise<FFIDApiResponse<FFIDNewsletterUnsubscribeResponse>>;
|
|
833
|
+
};
|
|
748
834
|
/** Token store (token mode only) */
|
|
749
835
|
tokenStore: TokenStore;
|
|
750
836
|
/** Resolved auth mode */
|
package/dist/server/index.js
CHANGED
|
@@ -98,9 +98,15 @@ function createTokenStore(storageType) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// src/client/oauth-userinfo.ts
|
|
101
|
-
var
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
var SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES = [
|
|
102
|
+
"trialing",
|
|
103
|
+
"active",
|
|
104
|
+
"past_due",
|
|
105
|
+
"canceled",
|
|
106
|
+
"paused"
|
|
107
|
+
];
|
|
108
|
+
function isSessionEligibleSubscriptionStatus(value) {
|
|
109
|
+
return typeof value === "string" && SESSION_ELIGIBLE_SUBSCRIPTION_STATUSES.includes(value);
|
|
104
110
|
}
|
|
105
111
|
function normalizeUserinfo(raw) {
|
|
106
112
|
return {
|
|
@@ -126,7 +132,7 @@ function normalizeUserinfo(raw) {
|
|
|
126
132
|
}
|
|
127
133
|
function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
|
|
128
134
|
const subscription = userinfo.subscription;
|
|
129
|
-
if (!subscription || !subscription.planCode || !
|
|
135
|
+
if (!subscription || !subscription.planCode || !isSessionEligibleSubscriptionStatus(subscription.status)) {
|
|
130
136
|
return [];
|
|
131
137
|
}
|
|
132
138
|
return [
|
|
@@ -610,7 +616,7 @@ function createMembersMethods(deps) {
|
|
|
610
616
|
}
|
|
611
617
|
|
|
612
618
|
// src/client/version-check.ts
|
|
613
|
-
var SDK_VERSION = "2.
|
|
619
|
+
var SDK_VERSION = "2.7.0";
|
|
614
620
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
615
621
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
616
622
|
function sdkHeaders() {
|
|
@@ -1541,6 +1547,118 @@ function createContractWizardMethods(deps) {
|
|
|
1541
1547
|
};
|
|
1542
1548
|
}
|
|
1543
1549
|
|
|
1550
|
+
// src/newsletter/ffid-newsletter-client.ts
|
|
1551
|
+
var EXT_SUBSCRIBE_ENDPOINT2 = "/api/v1/ext/newsletter/subscribe";
|
|
1552
|
+
var CONFIRM_ENDPOINT = "/api/newsletter/confirm";
|
|
1553
|
+
var UNSUBSCRIBE_ENDPOINT = "/api/newsletter/unsubscribe";
|
|
1554
|
+
function trimOrEmpty(s) {
|
|
1555
|
+
return typeof s === "string" ? s.trim() : "";
|
|
1556
|
+
}
|
|
1557
|
+
async function postPublic(url, init, opts) {
|
|
1558
|
+
let response;
|
|
1559
|
+
try {
|
|
1560
|
+
response = await fetch(url, init);
|
|
1561
|
+
} catch (err) {
|
|
1562
|
+
return {
|
|
1563
|
+
error: opts.createError(
|
|
1564
|
+
"NETWORK_ERROR",
|
|
1565
|
+
err instanceof Error ? err.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1566
|
+
)
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
if (!response.ok) {
|
|
1570
|
+
try {
|
|
1571
|
+
const body = await response.json();
|
|
1572
|
+
if (body?.error?.code || body?.error?.message) {
|
|
1573
|
+
return {
|
|
1574
|
+
error: opts.createError(
|
|
1575
|
+
body.error.code ?? "UNKNOWN_ERROR",
|
|
1576
|
+
body.error.message ?? `${opts.fallbackMessage} (status: ${response.status})`
|
|
1577
|
+
)
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
} catch {
|
|
1581
|
+
}
|
|
1582
|
+
return {
|
|
1583
|
+
error: opts.createError(
|
|
1584
|
+
"NETWORK_ERROR",
|
|
1585
|
+
`${opts.fallbackMessage} (status: ${response.status})`
|
|
1586
|
+
)
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
return { data: opts.success };
|
|
1590
|
+
}
|
|
1591
|
+
function createNewsletterMethods(deps) {
|
|
1592
|
+
const { fetchWithAuth, baseUrl, createError } = deps;
|
|
1593
|
+
async function subscribe(params) {
|
|
1594
|
+
const email = trimOrEmpty(params.email);
|
|
1595
|
+
const source = trimOrEmpty(params.source);
|
|
1596
|
+
if (!email) {
|
|
1597
|
+
return { error: createError("VALIDATION_ERROR", "email \u306F\u5FC5\u9808\u3067\u3059") };
|
|
1598
|
+
}
|
|
1599
|
+
if (!source) {
|
|
1600
|
+
return { error: createError("VALIDATION_ERROR", "source \u306F\u5FC5\u9808\u3067\u3059") };
|
|
1601
|
+
}
|
|
1602
|
+
if (!Array.isArray(params.types) || params.types.length === 0) {
|
|
1603
|
+
return {
|
|
1604
|
+
error: createError(
|
|
1605
|
+
"VALIDATION_ERROR",
|
|
1606
|
+
"types \u306B\u306F1\u3064\u4EE5\u4E0A\u306E newsletter \u7A2E\u5225\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
1607
|
+
)
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
return fetchWithAuth(
|
|
1611
|
+
EXT_SUBSCRIBE_ENDPOINT2,
|
|
1612
|
+
{
|
|
1613
|
+
method: "POST",
|
|
1614
|
+
body: JSON.stringify({
|
|
1615
|
+
email,
|
|
1616
|
+
types: params.types,
|
|
1617
|
+
source,
|
|
1618
|
+
locale: params.locale
|
|
1619
|
+
})
|
|
1620
|
+
}
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
async function confirm(params) {
|
|
1624
|
+
const token = trimOrEmpty(params.token);
|
|
1625
|
+
if (!token) {
|
|
1626
|
+
return { error: createError("VALIDATION_ERROR", "token \u306F\u5FC5\u9808\u3067\u3059") };
|
|
1627
|
+
}
|
|
1628
|
+
return postPublic(
|
|
1629
|
+
`${baseUrl}${CONFIRM_ENDPOINT}`,
|
|
1630
|
+
{
|
|
1631
|
+
method: "POST",
|
|
1632
|
+
headers: { "Content-Type": "application/json" },
|
|
1633
|
+
body: JSON.stringify({ token })
|
|
1634
|
+
},
|
|
1635
|
+
{
|
|
1636
|
+
success: { ok: true },
|
|
1637
|
+
createError,
|
|
1638
|
+
fallbackMessage: "\u78BA\u8A8D\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1639
|
+
}
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
async function unsubscribe(params) {
|
|
1643
|
+
const token = trimOrEmpty(params.token);
|
|
1644
|
+
if (!token) {
|
|
1645
|
+
return { error: createError("VALIDATION_ERROR", "token \u306F\u5FC5\u9808\u3067\u3059") };
|
|
1646
|
+
}
|
|
1647
|
+
const url = new URL(`${baseUrl}${UNSUBSCRIBE_ENDPOINT}`);
|
|
1648
|
+
url.searchParams.set("token", token);
|
|
1649
|
+
return postPublic(
|
|
1650
|
+
url.toString(),
|
|
1651
|
+
{ method: "POST" },
|
|
1652
|
+
{
|
|
1653
|
+
success: { ok: true },
|
|
1654
|
+
createError,
|
|
1655
|
+
fallbackMessage: "\u89E3\u9664\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1656
|
+
}
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
return { subscribe, confirm, unsubscribe };
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1544
1662
|
// src/client/ffid-client.ts
|
|
1545
1663
|
var UNAUTHORIZED_STATUS2 = 401;
|
|
1546
1664
|
var SDK_LOG_PREFIX = "[FFID SDK]";
|
|
@@ -1816,6 +1934,11 @@ function createFFIDClient(config) {
|
|
|
1816
1934
|
createError,
|
|
1817
1935
|
errorCodes: FFID_ERROR_CODES
|
|
1818
1936
|
});
|
|
1937
|
+
const newsletter = createNewsletterMethods({
|
|
1938
|
+
fetchWithAuth,
|
|
1939
|
+
baseUrl,
|
|
1940
|
+
createError
|
|
1941
|
+
});
|
|
1819
1942
|
const verifyAccessToken = createVerifyAccessToken({
|
|
1820
1943
|
authMode,
|
|
1821
1944
|
baseUrl,
|
|
@@ -1870,6 +1993,8 @@ function createFFIDClient(config) {
|
|
|
1870
1993
|
confirmPasswordReset,
|
|
1871
1994
|
sendOtp,
|
|
1872
1995
|
verifyOtp,
|
|
1996
|
+
/** Newsletter methods (subscribe / confirm / unsubscribe) */
|
|
1997
|
+
newsletter,
|
|
1873
1998
|
/** Token store (token mode only) */
|
|
1874
1999
|
tokenStore,
|
|
1875
2000
|
/** Resolved auth mode */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feelflow/ffid-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "FeelFlow ID Platform SDK for React/Next.js applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"feelflow",
|
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@testing-library/jest-dom": "^6.0.0",
|
|
99
99
|
"@testing-library/react": "^16.0.0",
|
|
100
|
+
"@types/node": "^22.19.17",
|
|
100
101
|
"@types/react": "^19.0.0",
|
|
101
102
|
"@types/react-dom": "^19.0.0",
|
|
102
103
|
"@typescript-eslint/eslint-plugin": "^8.58.0",
|