@feelflow/ffid-sdk 0.1.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/index.cjs ADDED
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ var chunkYCMQXJOS_cjs = require('./chunk-YCMQXJOS.cjs');
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function withFFIDAuth(Component, options = {}) {
8
+ const WrappedComponent = (props) => {
9
+ const { isLoading, isAuthenticated, login } = chunkYCMQXJOS_cjs.useFFIDContext();
10
+ const hasRedirected = react.useRef(false);
11
+ react.useEffect(() => {
12
+ if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
13
+ hasRedirected.current = true;
14
+ login();
15
+ }
16
+ }, [isLoading, isAuthenticated, login]);
17
+ if (isLoading) {
18
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: options.loading ?? null });
19
+ }
20
+ if (!isAuthenticated) {
21
+ if (options.redirectToLogin) {
22
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: options.loading ?? null });
23
+ }
24
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: options.fallback ?? null });
25
+ }
26
+ return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
27
+ };
28
+ WrappedComponent.displayName = `withFFIDAuth(${Component.displayName ?? Component.name ?? "Component"})`;
29
+ return WrappedComponent;
30
+ }
31
+
32
+ Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
33
+ enumerable: true,
34
+ get: function () { return chunkYCMQXJOS_cjs.DEFAULT_API_BASE_URL; }
35
+ });
36
+ Object.defineProperty(exports, "FFIDLoginButton", {
37
+ enumerable: true,
38
+ get: function () { return chunkYCMQXJOS_cjs.FFIDLoginButton; }
39
+ });
40
+ Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
41
+ enumerable: true,
42
+ get: function () { return chunkYCMQXJOS_cjs.FFIDOrganizationSwitcher; }
43
+ });
44
+ Object.defineProperty(exports, "FFIDProvider", {
45
+ enumerable: true,
46
+ get: function () { return chunkYCMQXJOS_cjs.FFIDProvider; }
47
+ });
48
+ Object.defineProperty(exports, "FFIDSubscriptionBadge", {
49
+ enumerable: true,
50
+ get: function () { return chunkYCMQXJOS_cjs.FFIDSubscriptionBadge; }
51
+ });
52
+ Object.defineProperty(exports, "FFIDUserMenu", {
53
+ enumerable: true,
54
+ get: function () { return chunkYCMQXJOS_cjs.FFIDUserMenu; }
55
+ });
56
+ Object.defineProperty(exports, "useFFID", {
57
+ enumerable: true,
58
+ get: function () { return chunkYCMQXJOS_cjs.useFFID; }
59
+ });
60
+ Object.defineProperty(exports, "useSubscription", {
61
+ enumerable: true,
62
+ get: function () { return chunkYCMQXJOS_cjs.useSubscription; }
63
+ });
64
+ Object.defineProperty(exports, "withSubscription", {
65
+ enumerable: true,
66
+ get: function () { return chunkYCMQXJOS_cjs.withSubscription; }
67
+ });
68
+ exports.withFFIDAuth = withFFIDAuth;
@@ -0,0 +1,181 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType, FC } from 'react';
3
+ import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue } from './index-CtBBLbTn.cjs';
4
+ export { e as FFIDApiResponse, f as FFIDContextValue, g as FFIDLogger, h as FFIDLoginButton, i as FFIDOrganizationSwitcher, j as FFIDSessionResponse, k as FFIDSubscription, l as FFIDSubscriptionBadge, m as FFIDUserMenu } from './index-CtBBLbTn.cjs';
5
+
6
+ /**
7
+ * FFID SDK Shared Constants
8
+ *
9
+ * Constants shared across all SDK entry points (main client + legal client).
10
+ * Centralizing these prevents drift during domain/URL changes.
11
+ */
12
+ /** Default FFID API base URL (production) */
13
+ declare const DEFAULT_API_BASE_URL = "https://id.feelflow.co.jp";
14
+
15
+ /**
16
+ * Props for FFIDProvider component
17
+ */
18
+ interface FFIDProviderProps extends FFIDConfig {
19
+ /** Child components */
20
+ children: ReactNode;
21
+ }
22
+ /**
23
+ * FFIDProvider - Wrap your app to enable FFID authentication
24
+ *
25
+ * This provider handles:
26
+ * - Session management
27
+ * - User authentication state
28
+ * - Organization switching
29
+ * - Automatic session refresh
30
+ */
31
+ declare function FFIDProvider({ children, serviceCode, apiBaseUrl, debug, logger, refreshInterval, onAuthStateChange, onError, }: FFIDProviderProps): react_jsx_runtime.JSX.Element;
32
+
33
+ /**
34
+ * Return type for useFFID hook
35
+ */
36
+ interface UseFFIDReturn {
37
+ /** Current authenticated user (null if not logged in) */
38
+ user: FFIDUser | null;
39
+ /** List of user's organizations */
40
+ organizations: FFIDOrganization[];
41
+ /** Currently selected organization */
42
+ currentOrganization: FFIDOrganization | null;
43
+ /** Whether session is being loaded */
44
+ isLoading: boolean;
45
+ /** Whether user is authenticated */
46
+ isAuthenticated: boolean;
47
+ /** Any authentication error that occurred */
48
+ error: FFIDError | null;
49
+ /** Redirect to login page */
50
+ login: () => void;
51
+ /** Sign out */
52
+ logout: () => Promise<void>;
53
+ /** Switch current organization */
54
+ switchOrganization: (organizationId: string) => void;
55
+ /** Refresh session data */
56
+ refresh: () => Promise<void>;
57
+ }
58
+ /**
59
+ * Hook to access FFID authentication and user data
60
+ *
61
+ * Must be used within FFIDProvider
62
+ */
63
+ declare function useFFID(): UseFFIDReturn;
64
+
65
+ /**
66
+ * useSubscription Hook
67
+ *
68
+ * Access subscription/contract information for the current service
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * import { useSubscription } from '@feelflow/ffid-sdk'
73
+ *
74
+ * function PremiumFeature() {
75
+ * const { isActive, hasPlan, planCode } = useSubscription()
76
+ *
77
+ * if (!isActive) {
78
+ * return <div>契約が必要です</div>
79
+ * }
80
+ *
81
+ * if (!hasPlan(['pro', 'enterprise'])) {
82
+ * return <div>プロプラン以上が必要です</div>
83
+ * }
84
+ *
85
+ * return <div>Premium Content</div>
86
+ * }
87
+ * ```
88
+ */
89
+
90
+ /**
91
+ * Hook to access subscription information
92
+ *
93
+ * Must be used within FFIDProvider
94
+ */
95
+ declare function useSubscription(): FFIDSubscriptionContextValue;
96
+ /**
97
+ * HOC to require subscription for a component
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * import { withSubscription } from '@feelflow/ffid-sdk'
102
+ *
103
+ * const PremiumDashboard = withSubscription(Dashboard, {
104
+ * plans: ['pro', 'enterprise'],
105
+ * fallback: <UpgradePrompt />,
106
+ * })
107
+ * ```
108
+ */
109
+ interface WithSubscriptionOptions {
110
+ /** Required plans (any of these) */
111
+ plans?: string[];
112
+ /** Component to show when subscription check fails */
113
+ fallback?: ReactNode;
114
+ /** Component to show while loading */
115
+ loading?: ReactNode;
116
+ }
117
+ declare function withSubscription<P extends object>(Component: ComponentType<P>, options?: WithSubscriptionOptions): FC<P>;
118
+
119
+ /**
120
+ * withFFIDAuth HOC
121
+ *
122
+ * Wrap a component to require FFID authentication.
123
+ * Renders the wrapped component only when the user is authenticated.
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * import { withFFIDAuth } from '@feelflow/ffid-sdk'
128
+ *
129
+ * function Dashboard() {
130
+ * return <div>Protected Dashboard</div>
131
+ * }
132
+ *
133
+ * // Basic usage - renders nothing when not authenticated
134
+ * export default withFFIDAuth(Dashboard)
135
+ *
136
+ * // With redirect to login
137
+ * export default withFFIDAuth(Dashboard, {
138
+ * redirectToLogin: true,
139
+ * loading: <div>認証確認中...</div>,
140
+ * })
141
+ *
142
+ * // With fallback component
143
+ * export default withFFIDAuth(Dashboard, {
144
+ * fallback: <div>ログインが必要です</div>,
145
+ * })
146
+ * ```
147
+ */
148
+
149
+ /**
150
+ * Options for withFFIDAuth HOC
151
+ */
152
+ interface WithFFIDAuthOptions {
153
+ /** Automatically redirect to FFID login page when not authenticated (default: false) */
154
+ redirectToLogin?: boolean;
155
+ /** Component to show while authentication is being checked */
156
+ loading?: ReactNode;
157
+ /** Component to show when user is not authenticated (ignored if redirectToLogin is true) */
158
+ fallback?: ReactNode;
159
+ }
160
+ /**
161
+ * HOC to require FFID authentication for a component
162
+ *
163
+ * Renders the wrapped component only when the user is authenticated.
164
+ * While authentication is loading, shows the loading component (if provided).
165
+ * When not authenticated, either redirects to login or shows fallback.
166
+ *
167
+ * @example
168
+ * ```tsx
169
+ * // Redirect to login on unauthenticated
170
+ * const ProtectedPage = withFFIDAuth(MyPage, { redirectToLogin: true })
171
+ *
172
+ * // Show custom fallback
173
+ * const ProtectedPage = withFFIDAuth(MyPage, {
174
+ * fallback: <LoginPrompt />,
175
+ * loading: <Spinner />,
176
+ * })
177
+ * ```
178
+ */
179
+ declare function withFFIDAuth<P extends object>(Component: ComponentType<P>, options?: WithFFIDAuthOptions): FC<P>;
180
+
181
+ export { DEFAULT_API_BASE_URL, FFIDConfig, FFIDError, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSubscriptionContextValue, FFIDUser, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, useFFID, useSubscription, withFFIDAuth, withSubscription };
@@ -0,0 +1,181 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType, FC } from 'react';
3
+ import { F as FFIDConfig, a as FFIDUser, b as FFIDOrganization, c as FFIDError, d as FFIDSubscriptionContextValue } from './index-CtBBLbTn.js';
4
+ export { e as FFIDApiResponse, f as FFIDContextValue, g as FFIDLogger, h as FFIDLoginButton, i as FFIDOrganizationSwitcher, j as FFIDSessionResponse, k as FFIDSubscription, l as FFIDSubscriptionBadge, m as FFIDUserMenu } from './index-CtBBLbTn.js';
5
+
6
+ /**
7
+ * FFID SDK Shared Constants
8
+ *
9
+ * Constants shared across all SDK entry points (main client + legal client).
10
+ * Centralizing these prevents drift during domain/URL changes.
11
+ */
12
+ /** Default FFID API base URL (production) */
13
+ declare const DEFAULT_API_BASE_URL = "https://id.feelflow.co.jp";
14
+
15
+ /**
16
+ * Props for FFIDProvider component
17
+ */
18
+ interface FFIDProviderProps extends FFIDConfig {
19
+ /** Child components */
20
+ children: ReactNode;
21
+ }
22
+ /**
23
+ * FFIDProvider - Wrap your app to enable FFID authentication
24
+ *
25
+ * This provider handles:
26
+ * - Session management
27
+ * - User authentication state
28
+ * - Organization switching
29
+ * - Automatic session refresh
30
+ */
31
+ declare function FFIDProvider({ children, serviceCode, apiBaseUrl, debug, logger, refreshInterval, onAuthStateChange, onError, }: FFIDProviderProps): react_jsx_runtime.JSX.Element;
32
+
33
+ /**
34
+ * Return type for useFFID hook
35
+ */
36
+ interface UseFFIDReturn {
37
+ /** Current authenticated user (null if not logged in) */
38
+ user: FFIDUser | null;
39
+ /** List of user's organizations */
40
+ organizations: FFIDOrganization[];
41
+ /** Currently selected organization */
42
+ currentOrganization: FFIDOrganization | null;
43
+ /** Whether session is being loaded */
44
+ isLoading: boolean;
45
+ /** Whether user is authenticated */
46
+ isAuthenticated: boolean;
47
+ /** Any authentication error that occurred */
48
+ error: FFIDError | null;
49
+ /** Redirect to login page */
50
+ login: () => void;
51
+ /** Sign out */
52
+ logout: () => Promise<void>;
53
+ /** Switch current organization */
54
+ switchOrganization: (organizationId: string) => void;
55
+ /** Refresh session data */
56
+ refresh: () => Promise<void>;
57
+ }
58
+ /**
59
+ * Hook to access FFID authentication and user data
60
+ *
61
+ * Must be used within FFIDProvider
62
+ */
63
+ declare function useFFID(): UseFFIDReturn;
64
+
65
+ /**
66
+ * useSubscription Hook
67
+ *
68
+ * Access subscription/contract information for the current service
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * import { useSubscription } from '@feelflow/ffid-sdk'
73
+ *
74
+ * function PremiumFeature() {
75
+ * const { isActive, hasPlan, planCode } = useSubscription()
76
+ *
77
+ * if (!isActive) {
78
+ * return <div>契約が必要です</div>
79
+ * }
80
+ *
81
+ * if (!hasPlan(['pro', 'enterprise'])) {
82
+ * return <div>プロプラン以上が必要です</div>
83
+ * }
84
+ *
85
+ * return <div>Premium Content</div>
86
+ * }
87
+ * ```
88
+ */
89
+
90
+ /**
91
+ * Hook to access subscription information
92
+ *
93
+ * Must be used within FFIDProvider
94
+ */
95
+ declare function useSubscription(): FFIDSubscriptionContextValue;
96
+ /**
97
+ * HOC to require subscription for a component
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * import { withSubscription } from '@feelflow/ffid-sdk'
102
+ *
103
+ * const PremiumDashboard = withSubscription(Dashboard, {
104
+ * plans: ['pro', 'enterprise'],
105
+ * fallback: <UpgradePrompt />,
106
+ * })
107
+ * ```
108
+ */
109
+ interface WithSubscriptionOptions {
110
+ /** Required plans (any of these) */
111
+ plans?: string[];
112
+ /** Component to show when subscription check fails */
113
+ fallback?: ReactNode;
114
+ /** Component to show while loading */
115
+ loading?: ReactNode;
116
+ }
117
+ declare function withSubscription<P extends object>(Component: ComponentType<P>, options?: WithSubscriptionOptions): FC<P>;
118
+
119
+ /**
120
+ * withFFIDAuth HOC
121
+ *
122
+ * Wrap a component to require FFID authentication.
123
+ * Renders the wrapped component only when the user is authenticated.
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * import { withFFIDAuth } from '@feelflow/ffid-sdk'
128
+ *
129
+ * function Dashboard() {
130
+ * return <div>Protected Dashboard</div>
131
+ * }
132
+ *
133
+ * // Basic usage - renders nothing when not authenticated
134
+ * export default withFFIDAuth(Dashboard)
135
+ *
136
+ * // With redirect to login
137
+ * export default withFFIDAuth(Dashboard, {
138
+ * redirectToLogin: true,
139
+ * loading: <div>認証確認中...</div>,
140
+ * })
141
+ *
142
+ * // With fallback component
143
+ * export default withFFIDAuth(Dashboard, {
144
+ * fallback: <div>ログインが必要です</div>,
145
+ * })
146
+ * ```
147
+ */
148
+
149
+ /**
150
+ * Options for withFFIDAuth HOC
151
+ */
152
+ interface WithFFIDAuthOptions {
153
+ /** Automatically redirect to FFID login page when not authenticated (default: false) */
154
+ redirectToLogin?: boolean;
155
+ /** Component to show while authentication is being checked */
156
+ loading?: ReactNode;
157
+ /** Component to show when user is not authenticated (ignored if redirectToLogin is true) */
158
+ fallback?: ReactNode;
159
+ }
160
+ /**
161
+ * HOC to require FFID authentication for a component
162
+ *
163
+ * Renders the wrapped component only when the user is authenticated.
164
+ * While authentication is loading, shows the loading component (if provided).
165
+ * When not authenticated, either redirects to login or shows fallback.
166
+ *
167
+ * @example
168
+ * ```tsx
169
+ * // Redirect to login on unauthenticated
170
+ * const ProtectedPage = withFFIDAuth(MyPage, { redirectToLogin: true })
171
+ *
172
+ * // Show custom fallback
173
+ * const ProtectedPage = withFFIDAuth(MyPage, {
174
+ * fallback: <LoginPrompt />,
175
+ * loading: <Spinner />,
176
+ * })
177
+ * ```
178
+ */
179
+ declare function withFFIDAuth<P extends object>(Component: ComponentType<P>, options?: WithFFIDAuthOptions): FC<P>;
180
+
181
+ export { DEFAULT_API_BASE_URL, FFIDConfig, FFIDError, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSubscriptionContextValue, FFIDUser, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, useFFID, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ import { useFFIDContext } from './chunk-A63MX52D.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, useFFID, useSubscription, withSubscription } from './chunk-A63MX52D.js';
3
+ import { useRef, useEffect } from 'react';
4
+ import { jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function withFFIDAuth(Component, options = {}) {
7
+ const WrappedComponent = (props) => {
8
+ const { isLoading, isAuthenticated, login } = useFFIDContext();
9
+ const hasRedirected = useRef(false);
10
+ useEffect(() => {
11
+ if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
12
+ hasRedirected.current = true;
13
+ login();
14
+ }
15
+ }, [isLoading, isAuthenticated, login]);
16
+ if (isLoading) {
17
+ return /* @__PURE__ */ jsx(Fragment, { children: options.loading ?? null });
18
+ }
19
+ if (!isAuthenticated) {
20
+ if (options.redirectToLogin) {
21
+ return /* @__PURE__ */ jsx(Fragment, { children: options.loading ?? null });
22
+ }
23
+ return /* @__PURE__ */ jsx(Fragment, { children: options.fallback ?? null });
24
+ }
25
+ return /* @__PURE__ */ jsx(Component, { ...props });
26
+ };
27
+ WrappedComponent.displayName = `withFFIDAuth(${Component.displayName ?? Component.name ?? "Component"})`;
28
+ return WrappedComponent;
29
+ }
30
+
31
+ export { withFFIDAuth };
@@ -0,0 +1,180 @@
1
+ 'use strict';
2
+
3
+ // src/constants.ts
4
+ var DEFAULT_API_BASE_URL = "https://id.feelflow.co.jp";
5
+
6
+ // src/legal/ffid-legal-client.ts
7
+ var API_PREFIX = "/api/v1/legal/ext";
8
+ var SDK_LOG_PREFIX = "[FFID Legal SDK]";
9
+ var NO_CONTENT_STATUS = 204;
10
+ var FFID_LEGAL_ERROR_CODES = {
11
+ /** API key is missing */
12
+ MISSING_API_KEY: "MISSING_API_KEY",
13
+ /** Network request failed (fetch threw) */
14
+ NETWORK_ERROR: "NETWORK_ERROR",
15
+ /** Server returned non-JSON response */
16
+ PARSE_ERROR: "PARSE_ERROR",
17
+ /** Server returned error without structured error body */
18
+ UNKNOWN_ERROR: "UNKNOWN_ERROR",
19
+ /** Input validation failed (empty required parameters) */
20
+ VALIDATION_ERROR: "VALIDATION_ERROR"
21
+ };
22
+ var noopLogger = {
23
+ debug: () => {
24
+ },
25
+ info: () => {
26
+ },
27
+ warn: () => {
28
+ },
29
+ error: (...args) => console.error(SDK_LOG_PREFIX, ...args)
30
+ };
31
+ var consoleLogger = {
32
+ debug: (...args) => console.debug(SDK_LOG_PREFIX, ...args),
33
+ info: (...args) => console.info(SDK_LOG_PREFIX, ...args),
34
+ warn: (...args) => console.warn(SDK_LOG_PREFIX, ...args),
35
+ error: (...args) => console.error(SDK_LOG_PREFIX, ...args)
36
+ };
37
+ function createFFIDLegalClient(config) {
38
+ if (!config.apiKey) {
39
+ throw new Error("FFID Legal Client: apiKey \u304C\u672A\u8A2D\u5B9A\u3067\u3059");
40
+ }
41
+ const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
42
+ const logger = config.logger ?? (config.debug ? consoleLogger : noopLogger);
43
+ async function fetchWithApiKey(endpoint, options = {}) {
44
+ const url = `${baseUrl}${API_PREFIX}${endpoint}`;
45
+ logger.debug("Fetching:", url);
46
+ let response;
47
+ try {
48
+ response = await fetch(url, {
49
+ ...options,
50
+ headers: {
51
+ "Content-Type": "application/json",
52
+ "X-Service-Api-Key": config.apiKey,
53
+ ...options.headers
54
+ }
55
+ });
56
+ } catch (error) {
57
+ logger.error("Network error:", { url, error });
58
+ return {
59
+ error: {
60
+ code: FFID_LEGAL_ERROR_CODES.NETWORK_ERROR,
61
+ message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
62
+ }
63
+ };
64
+ }
65
+ if (response.status === NO_CONTENT_STATUS) {
66
+ logger.debug("Response: 204 No Content (unexpected)", { url });
67
+ return {
68
+ error: {
69
+ code: FFID_LEGAL_ERROR_CODES.UNKNOWN_ERROR,
70
+ message: "\u4E88\u671F\u3057\u306A\u3044\u30EC\u30B9\u30DD\u30F3\u30B9: \u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30B3\u30F3\u30C6\u30F3\u30C4\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
71
+ }
72
+ };
73
+ }
74
+ let data;
75
+ try {
76
+ data = await response.json();
77
+ } catch (parseError) {
78
+ logger.error("Parse error:", { url, status: response.status, parseError });
79
+ return {
80
+ error: {
81
+ code: FFID_LEGAL_ERROR_CODES.PARSE_ERROR,
82
+ message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
83
+ }
84
+ };
85
+ }
86
+ logger.debug("Response:", response.status, data);
87
+ if (!response.ok || !data.success) {
88
+ return {
89
+ error: data.error ?? {
90
+ code: FFID_LEGAL_ERROR_CODES.UNKNOWN_ERROR,
91
+ message: "\u4E0D\u660E\u306A\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
92
+ }
93
+ };
94
+ }
95
+ if (data.data === void 0) {
96
+ return {
97
+ error: {
98
+ code: FFID_LEGAL_ERROR_CODES.UNKNOWN_ERROR,
99
+ message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
100
+ }
101
+ };
102
+ }
103
+ return { data: data.data };
104
+ }
105
+ async function getDocuments() {
106
+ return fetchWithApiKey("/documents");
107
+ }
108
+ async function getDocument(documentId) {
109
+ if (!documentId) {
110
+ return {
111
+ error: {
112
+ code: FFID_LEGAL_ERROR_CODES.VALIDATION_ERROR,
113
+ message: "documentId is required"
114
+ }
115
+ };
116
+ }
117
+ return fetchWithApiKey(`/documents/${encodeURIComponent(documentId)}`);
118
+ }
119
+ async function recordAgreement(request) {
120
+ if (!request.externalUserId || !request.documentId) {
121
+ return {
122
+ error: {
123
+ code: FFID_LEGAL_ERROR_CODES.VALIDATION_ERROR,
124
+ message: "externalUserId and documentId are required"
125
+ }
126
+ };
127
+ }
128
+ return fetchWithApiKey("/agreements", {
129
+ method: "POST",
130
+ body: JSON.stringify(request)
131
+ });
132
+ }
133
+ async function checkAgreement(externalUserId, documentId) {
134
+ if (!externalUserId || !documentId) {
135
+ return {
136
+ error: {
137
+ code: FFID_LEGAL_ERROR_CODES.VALIDATION_ERROR,
138
+ message: "externalUserId and documentId are required"
139
+ }
140
+ };
141
+ }
142
+ const params = new URLSearchParams({
143
+ externalUserId,
144
+ documentId
145
+ });
146
+ return fetchWithApiKey(`/agreements/check?${params.toString()}`);
147
+ }
148
+ async function getPendingAgreements(externalUserId) {
149
+ if (!externalUserId) {
150
+ return {
151
+ error: {
152
+ code: FFID_LEGAL_ERROR_CODES.VALIDATION_ERROR,
153
+ message: "externalUserId is required"
154
+ }
155
+ };
156
+ }
157
+ const params = new URLSearchParams({ externalUserId });
158
+ return fetchWithApiKey(`/agreements/pending?${params.toString()}`);
159
+ }
160
+ return {
161
+ /** Get all legal documents available to this service */
162
+ getDocuments,
163
+ /** Get a specific legal document by ID */
164
+ getDocument,
165
+ /** Record a user's agreement to a legal document */
166
+ recordAgreement,
167
+ /** Check if a user has agreed to a specific document */
168
+ checkAgreement,
169
+ /** Get all documents that a user has not yet agreed to */
170
+ getPendingAgreements,
171
+ /** Resolved logger instance */
172
+ logger,
173
+ /** API base URL */
174
+ baseUrl
175
+ };
176
+ }
177
+
178
+ exports.DEFAULT_API_BASE_URL = DEFAULT_API_BASE_URL;
179
+ exports.FFID_LEGAL_ERROR_CODES = FFID_LEGAL_ERROR_CODES;
180
+ exports.createFFIDLegalClient = createFFIDLegalClient;