@use-handled/ipaas-react-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/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # @use-handled/ipaas-react-sdk
2
+
3
+ Embedded iPaaS SDK for React. Let your users connect their e-commerce platforms (Shopify, Amazon, WooCommerce, etc.) directly from your application.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @use-handled/ipaas-react-sdk
9
+ # or
10
+ yarn add @use-handled/ipaas-react-sdk
11
+ # or
12
+ pnpm add @use-handled/ipaas-react-sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ### 1. Wrap your app with the provider
18
+
19
+ ```tsx
20
+ import { HandledProvider } from '@use-handled/ipaas-react-sdk'
21
+
22
+ function App() {
23
+ // Your app knows which brand/merchant is logged in
24
+ const currentBrand = getCurrentBrand() // { handledAccountId: "123" }
25
+
26
+ return (
27
+ <HandledProvider
28
+ clientId="your-client-id" // Your iPaaS client ID
29
+ accountId={currentBrand.handledAccountId} // Brand's Handled account ID
30
+ >
31
+ <YourApp />
32
+ </HandledProvider>
33
+ )
34
+ }
35
+ ```
36
+
37
+ ### 2. Use the pre-built IntegrationHub
38
+
39
+ ```tsx
40
+ import { IntegrationHub } from '@use-handled/ipaas-react-sdk'
41
+
42
+ function SettingsPage() {
43
+ return (
44
+ <IntegrationHub
45
+ title="Connect Your Stores"
46
+ description="Link your e-commerce platforms to sync orders and inventory."
47
+ onConnect={(connection) => {
48
+ console.log('Connected:', connection.integration.name)
49
+ }}
50
+ onDisconnect={(connectionId) => {
51
+ console.log('Disconnected:', connectionId)
52
+ }}
53
+ />
54
+ )
55
+ }
56
+ ```
57
+
58
+ ### 3. Or build a custom UI
59
+
60
+ ```tsx
61
+ import { useHandled } from '@use-handled/ipaas-react-sdk'
62
+
63
+ function CustomIntegrations() {
64
+ const { integrations, connections, connect, disconnect, isLoading } = useHandled()
65
+
66
+ return (
67
+ <div>
68
+ <h2>Available Integrations</h2>
69
+ <div className="grid">
70
+ {integrations.map((integration) => {
71
+ const isConnected = connections.some(c => c.integrationId === integration.id)
72
+
73
+ return (
74
+ <div key={integration.id} className="card">
75
+ <img src={integration.logoUrl} alt={integration.name} />
76
+ <h3>{integration.name}</h3>
77
+
78
+ {isConnected ? (
79
+ <button onClick={() => {
80
+ const conn = connections.find(c => c.integrationId === integration.id)
81
+ if (conn) disconnect(conn.id)
82
+ }}>
83
+ Disconnect
84
+ </button>
85
+ ) : (
86
+ <button onClick={() => connect(integration.id)}>
87
+ Connect
88
+ </button>
89
+ )}
90
+ </div>
91
+ )
92
+ })}
93
+ </div>
94
+ </div>
95
+ )
96
+ }
97
+ ```
98
+
99
+ ## API Reference
100
+
101
+ ### HandledProvider
102
+
103
+ The provider component that initializes the SDK.
104
+
105
+ ```tsx
106
+ <HandledProvider
107
+ clientId="your-client-id" // Required: Your iPaaS client ID
108
+ accountId="brand-account-id" // Required: Brand's Handled account ID
109
+ apiBaseUrl="https://api.usehandled.io" // Optional: Custom API URL
110
+ onConnect={(connection) => {}} // Optional: Called when integration connected
111
+ onDisconnect={(connectionId) => {}} // Optional: Called when disconnected
112
+ onError={(error) => {}} // Optional: Called on errors
113
+ >
114
+ {children}
115
+ </HandledProvider>
116
+ ```
117
+
118
+ ### useHandled Hook
119
+
120
+ Access the SDK context from any component.
121
+
122
+ ```tsx
123
+ const {
124
+ isReady, // SDK is initialized
125
+ isLoading, // Operation in progress
126
+ integrations, // Available integrations (Shopify, Amazon, etc.)
127
+ connections, // Brand's connected integrations
128
+ connect, // Connect an integration (opens OAuth popup)
129
+ disconnect, // Disconnect an integration
130
+ refreshConnections, // Refresh the connections list
131
+ error, // Any error that occurred
132
+ accountId, // Current account ID
133
+ } = useHandled()
134
+ ```
135
+
136
+ ### IntegrationHub
137
+
138
+ Pre-built UI component for managing integrations.
139
+
140
+ ```tsx
141
+ <IntegrationHub
142
+ title="Integrations" // Optional: Custom title
143
+ description="Connect your platforms" // Optional: Custom description
144
+ categories={['ecommerce', 'marketplace']} // Optional: Filter by category
145
+ integrationIds={[1, 2, 3]} // Optional: Show specific integrations
146
+ hideConnected={false} // Optional: Hide connected section
147
+ onConnect={(connection) => {}} // Optional: Connection callback
148
+ onDisconnect={(connectionId) => {}} // Optional: Disconnect callback
149
+ onError={(error) => {}} // Optional: Error callback
150
+ className="custom-class" // Optional: CSS class
151
+ style={{ maxWidth: '600px' }} // Optional: Inline styles
152
+ />
153
+ ```
154
+
155
+ ## How It Works
156
+
157
+ ```
158
+ ┌─────────────────────────────────────────────────────────────────┐
159
+ │ Your Application │
160
+ │ ┌───────────────────────────────────────────────────────────┐ │
161
+ │ │ <HandledProvider clientId="xxx" accountId="brand_123"> │ │
162
+ │ │ │ │
163
+ │ │ ┌─────────────────────────────────────────────────┐ │ │
164
+ │ │ │ IntegrationHub Component │ │ │
165
+ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
166
+ │ │ │ │ Shopify │ │ Amazon │ │ Woo │ │ │ │
167
+ │ │ │ │ Connect │ │ Connect │ │ Connect │ │ │ │
168
+ │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │
169
+ │ │ └─────────────────────────────────────────────────┘ │ │
170
+ │ │ │ │
171
+ │ └───────────────────────────────────────────────────────────┘ │
172
+ └──────────────────────────────┬──────────────────────────────────┘
173
+
174
+
175
+ ┌──────────────────────┐
176
+ │ Handled API │
177
+ │ api.usehandled.io │
178
+ └──────────┬───────────┘
179
+
180
+ ┌────────────────────┼────────────────────┐
181
+ ▼ ▼ ▼
182
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
183
+ │ Shopify │ │ Amazon │ │ Woo │
184
+ └──────────┘ └──────────┘ └──────────┘
185
+ ```
186
+
187
+ 1. **Developer** signs up for Handled iPaaS and gets `clientId`
188
+ 2. **Developer** creates child accounts for their brands/merchants
189
+ 3. **Developer** embeds SDK with brand's `accountId`
190
+ 4. **Brand user** clicks "Connect Shopify" → OAuth popup opens
191
+ 5. **Handled** creates `account_integration` for that brand
192
+ 6. **Developer** can now access brand's data via Handled's unified API
193
+
194
+ ## TypeScript
195
+
196
+ This package is fully typed. Import types as needed:
197
+
198
+ ```tsx
199
+ import type {
200
+ Integration,
201
+ Connection,
202
+ ConnectResult,
203
+ IntegrationHubProps,
204
+ } from '@use-handled/ipaas-react-sdk'
205
+ ```
206
+
207
+ ## Integration Categories
208
+
209
+ | Category | Examples |
210
+ |----------|----------|
211
+ | `ecommerce` | Shopify, WooCommerce, BigCommerce, Magento |
212
+ | `marketplace` | Amazon, eBay, Walmart, Etsy |
213
+ | `shipping` | ShipStation, EasyPost, Shippo |
214
+ | `accounting` | QuickBooks, Xero, NetSuite |
215
+
216
+ ## License
217
+
218
+ MIT
@@ -0,0 +1,284 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+
4
+ interface HandledConfig {
5
+ /** Developer's iPaaS client ID from the Handled dashboard */
6
+ clientId: string;
7
+ /** The brand's account ID in Handled (child account) */
8
+ accountId: string;
9
+ /** Custom API base URL (defaults to https://api.usehandled.io) */
10
+ apiBaseUrl?: string;
11
+ }
12
+ interface IntegrationInputField {
13
+ label?: string;
14
+ type?: 'text' | 'password' | 'email' | 'select' | 'date';
15
+ required?: boolean;
16
+ placeholder?: string;
17
+ description?: string;
18
+ default?: string;
19
+ sort_order?: number;
20
+ options?: Array<{
21
+ name: string;
22
+ value: string;
23
+ }>;
24
+ }
25
+ interface Integration {
26
+ id: number;
27
+ name: string;
28
+ displayName?: string;
29
+ type: string;
30
+ description?: string;
31
+ logoUrl?: string;
32
+ category: 'ecommerce' | 'marketplace' | 'shipping' | 'accounting' | 'other';
33
+ authType: 'oauth' | 'oauth2' | 'oauth1' | 'api_key' | 'basic_auth' | 'bearer_token' | 'credentials';
34
+ status: 'available' | 'coming_soon' | 'beta';
35
+ inputFields?: Record<string, IntegrationInputField>;
36
+ }
37
+ interface Connection {
38
+ id: number;
39
+ integrationId: number;
40
+ integration: Integration;
41
+ accountId: number;
42
+ storeName?: string;
43
+ storeUrl?: string;
44
+ status: 'active' | 'inactive' | 'error' | 'pending';
45
+ connectedAt: string;
46
+ lastSyncAt?: string;
47
+ error?: string;
48
+ }
49
+ interface ConnectOptions {
50
+ /** Integration ID or type to connect */
51
+ integrationId: number | string;
52
+ /** Custom redirect after OAuth (optional) */
53
+ redirectUrl?: string;
54
+ /** Credentials for non-OAuth integrations */
55
+ credentials?: Record<string, string>;
56
+ /** Name for the account integration */
57
+ accountIntegrationName?: string;
58
+ }
59
+ interface ConnectResult {
60
+ success: boolean;
61
+ connection?: Connection;
62
+ error?: string;
63
+ }
64
+ interface HandledContextValue {
65
+ /** Whether the SDK is initialized and ready */
66
+ isReady: boolean;
67
+ /** Whether operations are in progress */
68
+ isLoading: boolean;
69
+ /** Available integrations from Handled */
70
+ integrations: Integration[];
71
+ /** Brand's connected integrations */
72
+ connections: Connection[];
73
+ /** Connect a new integration (opens OAuth popup or submits credentials) */
74
+ connect: (integrationId: number | string, options?: {
75
+ credentials?: Record<string, string>;
76
+ accountIntegrationName?: string;
77
+ }) => Promise<ConnectResult>;
78
+ /** Disconnect an integration */
79
+ disconnect: (connectionId: number) => Promise<void>;
80
+ /** Refresh connections list */
81
+ refreshConnections: () => Promise<void>;
82
+ /** Any error that occurred */
83
+ error: Error | null;
84
+ /** The account ID being used */
85
+ accountId: string;
86
+ }
87
+ interface IntegrationsResponse {
88
+ integrations: Integration[];
89
+ }
90
+ interface ConnectionsResponse {
91
+ connections: Connection[];
92
+ }
93
+ interface ConnectResponse {
94
+ /** OAuth auth URL (only for OAuth integrations) */
95
+ authUrl?: string;
96
+ /** Redirect URL for OAuth (alias for authUrl) */
97
+ redirect_url?: string;
98
+ /** Connection ID for status checking */
99
+ connectionId?: number;
100
+ /** Whether the connection was successful (for non-OAuth) */
101
+ success?: boolean;
102
+ /** The created connection (for non-OAuth) */
103
+ connection?: Connection;
104
+ /** The created account integration */
105
+ account_integration?: Connection;
106
+ /** Error message if failed */
107
+ message?: string;
108
+ }
109
+ interface HandledEventMap {
110
+ 'connection:created': Connection;
111
+ 'connection:deleted': {
112
+ connectionId: number;
113
+ };
114
+ 'connection:error': {
115
+ connectionId: number;
116
+ error: string;
117
+ };
118
+ 'integration:connected': Connection;
119
+ 'integration:disconnected': {
120
+ connectionId: number;
121
+ };
122
+ }
123
+ type HandledEventType = keyof HandledEventMap;
124
+ interface IntegrationHubProps {
125
+ /** Called when an integration is connected */
126
+ onConnect?: (connection: Connection) => void;
127
+ /** Called when an integration is disconnected */
128
+ onDisconnect?: (connectionId: number) => void;
129
+ /** Called when an error occurs */
130
+ onError?: (error: Error) => void;
131
+ /** Custom class name for the container */
132
+ className?: string;
133
+ /** Custom styles */
134
+ style?: React.CSSProperties;
135
+ /** Filter integrations by category */
136
+ categories?: Integration['category'][];
137
+ /** Show only specific integrations by ID */
138
+ integrationIds?: number[];
139
+ /** Hide the connected integrations section */
140
+ hideConnected?: boolean;
141
+ /** Custom title */
142
+ title?: string;
143
+ /** Custom description */
144
+ description?: string;
145
+ }
146
+ interface IntegrationCardProps {
147
+ integration: Integration;
148
+ connection?: Connection;
149
+ onConnect: () => void;
150
+ onDisconnect: () => void;
151
+ isLoading?: boolean;
152
+ }
153
+ interface ConnectionCardProps {
154
+ connection: Connection;
155
+ onDisconnect: () => void;
156
+ isLoading?: boolean;
157
+ }
158
+ interface ConnectionModalProps {
159
+ /** Whether the modal is open */
160
+ isOpen: boolean;
161
+ /** Function to close the modal */
162
+ onClose: () => void;
163
+ /** The integration to connect */
164
+ integration: Integration;
165
+ /** Called when connection succeeds */
166
+ onSuccess: (connection: Connection) => void;
167
+ /** Called when connection fails */
168
+ onError: (error: string) => void;
169
+ }
170
+
171
+ interface HandledProviderProps {
172
+ /** Developer's iPaaS client ID */
173
+ clientId: string;
174
+ /** Brand's account ID in Handled */
175
+ accountId: string;
176
+ /** Custom API base URL (defaults to https://api.usehandled.io) */
177
+ apiBaseUrl?: string;
178
+ /** Called when an integration is connected */
179
+ onConnect?: (connection: Connection) => void;
180
+ /** Called when an integration is disconnected */
181
+ onDisconnect?: (connectionId: number) => void;
182
+ /** Called when an error occurs */
183
+ onError?: (error: Error) => void;
184
+ /** React children */
185
+ children: React$1.ReactNode;
186
+ }
187
+ declare function HandledProvider({ clientId, accountId, apiBaseUrl, onConnect, onDisconnect, onError, children, }: HandledProviderProps): react_jsx_runtime.JSX.Element;
188
+
189
+ /**
190
+ * Pre-built UI component for managing integrations.
191
+ * Displays available integrations and connected accounts.
192
+ *
193
+ * @example
194
+ * ```tsx
195
+ * <HandledProvider clientId="xxx" accountId="123">
196
+ * <IntegrationHub
197
+ * onConnect={(conn) => console.log('Connected:', conn)}
198
+ * onDisconnect={(id) => console.log('Disconnected:', id)}
199
+ * />
200
+ * </HandledProvider>
201
+ * ```
202
+ */
203
+ declare function IntegrationHub({ onConnect, onDisconnect, onError, className, style, categories, integrationIds, hideConnected, title, description, }: IntegrationHubProps): react_jsx_runtime.JSX.Element;
204
+
205
+ /**
206
+ * Modal component for connecting to an integration.
207
+ * Handles OAuth and credential-based authentication flows.
208
+ */
209
+ declare function ConnectionModal({ isOpen, onClose, integration, onSuccess, onError, }: ConnectionModalProps): react_jsx_runtime.JSX.Element | null;
210
+
211
+ /**
212
+ * Hook to access the Handled SDK context.
213
+ *
214
+ * @example
215
+ * ```tsx
216
+ * function MyComponent() {
217
+ * const { integrations, connections, connect, disconnect } = useHandled()
218
+ *
219
+ * return (
220
+ * <div>
221
+ * <h2>Available Integrations</h2>
222
+ * {integrations.map(integration => (
223
+ * <button
224
+ * key={integration.id}
225
+ * onClick={() => connect(integration.id)}
226
+ * >
227
+ * Connect {integration.name}
228
+ * </button>
229
+ * ))}
230
+ *
231
+ * <h2>Connected</h2>
232
+ * {connections.map(connection => (
233
+ * <div key={connection.id}>
234
+ * {connection.integration.name}
235
+ * <button onClick={() => disconnect(connection.id)}>
236
+ * Disconnect
237
+ * </button>
238
+ * </div>
239
+ * ))}
240
+ * </div>
241
+ * )
242
+ * }
243
+ * ```
244
+ */
245
+ declare function useHandled(): HandledContextValue;
246
+
247
+ declare class HandledApiClient {
248
+ private config;
249
+ constructor(config: HandledConfig);
250
+ private get baseUrl();
251
+ private get headers();
252
+ private request;
253
+ /**
254
+ * Get list of available integrations
255
+ */
256
+ getIntegrations(): Promise<Integration[]>;
257
+ /**
258
+ * Get list of connections for the current account
259
+ */
260
+ getConnections(): Promise<Connection[]>;
261
+ /**
262
+ * Initiate connection to an integration
263
+ * Returns an auth URL to open in a popup for OAuth, or creates connection directly for other auth types
264
+ */
265
+ connect(integrationId: number | string, options?: {
266
+ credentials?: Record<string, string>;
267
+ accountIntegrationName?: string;
268
+ redirectUrl?: string;
269
+ }): Promise<ConnectResponse>;
270
+ /**
271
+ * Disconnect an integration
272
+ */
273
+ disconnect(connectionId: number): Promise<void>;
274
+ /**
275
+ * Get a specific connection
276
+ */
277
+ getConnection(connectionId: number): Promise<Connection>;
278
+ /**
279
+ * Check connection status (used after OAuth popup closes)
280
+ */
281
+ checkConnectionStatus(connectionId: number): Promise<Connection>;
282
+ }
283
+
284
+ export { type ConnectOptions, type ConnectResponse, type ConnectResult, type Connection, type ConnectionCardProps, ConnectionModal, type ConnectionModalProps, type ConnectionsResponse, HandledApiClient, type HandledConfig, type HandledContextValue, type HandledEventMap, type HandledEventType, HandledProvider, type HandledProviderProps, type Integration, type IntegrationCardProps, IntegrationHub, type IntegrationHubProps, type IntegrationInputField, type IntegrationsResponse, useHandled };