@fluentcommerce/fc-connect-sdk 0.1.52 → 0.1.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +530 -506
- package/README.md +52 -3
- package/dist/cjs/auth/index.d.ts +3 -0
- package/dist/cjs/auth/index.js +13 -0
- package/dist/cjs/auth/profile-loader.d.ts +18 -0
- package/dist/cjs/auth/profile-loader.js +208 -0
- package/dist/cjs/client-factory.d.ts +4 -0
- package/dist/cjs/client-factory.js +10 -0
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +8 -2
- package/dist/cjs/types/index.d.ts +1 -1
- package/dist/esm/auth/index.d.ts +3 -0
- package/dist/esm/auth/index.js +2 -0
- package/dist/esm/auth/profile-loader.d.ts +18 -0
- package/dist/esm/auth/profile-loader.js +169 -0
- package/dist/esm/client-factory.d.ts +4 -0
- package/dist/esm/client-factory.js +9 -0
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/auth/index.d.ts +3 -0
- package/dist/types/auth/profile-loader.d.ts +18 -0
- package/dist/types/client-factory.d.ts +4 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/types/index.d.ts +1 -1
- package/docs/02-CORE-GUIDES/api-reference/cli-profile-integration.md +377 -0
- package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +24 -15
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +38 -0
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +1 -1
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { loadFluentProfile, listFluentProfiles, getFluentProfileInfo, resolveProfileBaseDir, } from './profile-loader';
|
|
2
|
+
export type { FluentProfileOptions, FluentProfileInfo } from './profile-loader';
|
|
3
|
+
export { OAuth2AuthProvider, BearerTokenAuthProvider, AuthManager, VersoriConnectionAdapter, type VersoriConnection, } from './auth-provider';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FluentClientConfig } from '../types';
|
|
2
|
+
export interface FluentProfileOptions {
|
|
3
|
+
profileDir?: string;
|
|
4
|
+
retailer?: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
retryConfig?: FluentClientConfig['retryConfig'];
|
|
7
|
+
}
|
|
8
|
+
export interface FluentProfileInfo {
|
|
9
|
+
name: string;
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
accountId: string;
|
|
12
|
+
username: string;
|
|
13
|
+
retailers: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveProfileBaseDir(options?: FluentProfileOptions): string;
|
|
16
|
+
export declare function loadFluentProfile(profileName: string, options?: FluentProfileOptions): FluentClientConfig;
|
|
17
|
+
export declare function listFluentProfiles(options?: FluentProfileOptions): string[];
|
|
18
|
+
export declare function getFluentProfileInfo(profileName: string, options?: FluentProfileOptions): FluentProfileInfo | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FluentClient } from './clients/fluent-client';
|
|
2
2
|
import { FluentVersoriClient } from './versori/fluent-versori-client';
|
|
3
3
|
import { FluentClientConfig, Logger, ExecutionContext } from './types';
|
|
4
|
+
import { type FluentProfileOptions } from './auth/profile-loader';
|
|
4
5
|
export type ClientContext = {
|
|
5
6
|
fetch: typeof fetch;
|
|
6
7
|
log?: Logger;
|
|
@@ -24,3 +25,6 @@ export declare const isDirectContext: (context: ClientContext) => context is {
|
|
|
24
25
|
config: FluentClientConfig;
|
|
25
26
|
logger?: Logger;
|
|
26
27
|
};
|
|
28
|
+
export declare function createClientFromProfile(profileName: string, options?: FluentProfileOptions & CreateClientOptions & {
|
|
29
|
+
logger?: Logger;
|
|
30
|
+
}): Promise<FluentClient>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createClient, isHttpContext, isDirectContext } from './client-factory';
|
|
1
|
+
export { createClient, createClientFromProfile, isHttpContext, isDirectContext, } from './client-factory';
|
|
2
2
|
export type { ClientContext, CreateClientOptions } from './client-factory';
|
|
3
3
|
export { FluentClient } from './clients/fluent-client';
|
|
4
4
|
export { FluentVersoriClient } from './versori/fluent-versori-client';
|
|
@@ -14,6 +14,8 @@ export { DataSourceType } from './types';
|
|
|
14
14
|
export { parseAndValidateCsv, detectFileType, parseWebhookRequest, validateFluentEvent, validateGraphQLPayload, generateFileName, generateTimestampedFileName, generateFilePath, generateDateSubdirectories, extractFileName, extractFileExtension, replaceFileExtension, type FileNamingOptions, } from './utils';
|
|
15
15
|
export { detectPaginationVariables, extractConnection, extractCursor, hasMorePages, buildPaginationVariables, type PaginationVariables, } from './utils/pagination-helpers';
|
|
16
16
|
export { OAuth2AuthProvider, BearerTokenAuthProvider, AuthManager, VersoriConnectionAdapter, type VersoriConnection, } from './auth/auth-provider';
|
|
17
|
+
export { loadFluentProfile, listFluentProfiles, getFluentProfileInfo, resolveProfileBaseDir, } from './auth/profile-loader';
|
|
18
|
+
export type { FluentProfileOptions, FluentProfileInfo } from './auth/profile-loader';
|
|
17
19
|
export { type FileDiscoveryStrategy, type FileDiscoveryContext, type FileParserStrategy, type TransformationStrategy, type TransformationContext, type IngestionValidationResult, type BatchSubmissionStrategy, type BatchSubmissionContext, type BatchSubmissionResult, type JobManagementStrategy, type JobContext, type JobStatus, type IngestionStrategy, type StrategyFactory, } from './services/orchestration/strategies/ingestion-strategies';
|
|
18
20
|
export * from './errors/index';
|
|
19
21
|
export { ConfigurationError, AggregateIngestionError, IngestionErrorFactory, } from './errors/ingestion-errors';
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# Fluent CLI Profile Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The SDK can read profiles created by the official Fluent CLI (`fluent profile create`), allowing you to create a fully configured `FluentClient` without hardcoding any credentials. This is the recommended approach for standalone Node.js and Deno scripts that run outside the Versori platform.
|
|
6
|
+
|
|
7
|
+
Key benefits:
|
|
8
|
+
|
|
9
|
+
- **No hardcoded credentials.** Reuse the same profiles you already created with the Fluent CLI.
|
|
10
|
+
- **One-liner client creation.** `createClientFromProfile('MYPROFILE')` returns a ready-to-use `FluentClient`.
|
|
11
|
+
- **Multi-retailer support.** Pass a `retailer` option to automatically load the correct retailer ID and user credentials.
|
|
12
|
+
|
|
13
|
+
## How Fluent CLI Profiles Work
|
|
14
|
+
|
|
15
|
+
When you run `fluent profile create`, the CLI writes JSON files under `~/.fluentcommerce/`. Each profile is a directory containing credentials and optional retailer configurations.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
~/.fluentcommerce/
|
|
19
|
+
├── PROFILE_BETA/
|
|
20
|
+
│ ├── profile.json -> { id, baseUrl, clientSecret, user }
|
|
21
|
+
│ ├── retailer.RETAILER_ALPHA.json -> { id, ref, user }
|
|
22
|
+
│ └── user.profile_beta_admin.json -> { username, password }
|
|
23
|
+
└── PROFILE_ALPHA/
|
|
24
|
+
├── profile.json
|
|
25
|
+
└── user.profile_alpha_admin.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**File descriptions:**
|
|
29
|
+
|
|
30
|
+
| File | Purpose | Key Fields |
|
|
31
|
+
|------|---------|------------|
|
|
32
|
+
| `profile.json` | Account-level config | `id` (clientId), `baseUrl`, `clientSecret`, `user` (default username ref) |
|
|
33
|
+
| `retailer.<REF>.json` | Retailer-specific config | `id` (retailerId), `ref`, `user` (retailer-specific username ref) |
|
|
34
|
+
| `user.<name>.json` | User credentials | `username`, `password` |
|
|
35
|
+
|
|
36
|
+
**Loading chain:**
|
|
37
|
+
|
|
38
|
+
1. Read `profile.json` to get `baseUrl`, `clientId`, `clientSecret`, and the default user reference.
|
|
39
|
+
2. If a retailer is specified, read `retailer.<ref>.json` to get `retailerId` and an optional user override.
|
|
40
|
+
3. Read `user.<resolvedUser>.json` to get the final `username` and `password`.
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { createClientFromProfile, listFluentProfiles } from '@fluentcommerce/fc-connect-sdk';
|
|
46
|
+
|
|
47
|
+
// List available profiles
|
|
48
|
+
const profiles = listFluentProfiles();
|
|
49
|
+
console.log(profiles); // ['PROFILE_BETA', 'PROFILE_ALPHA']
|
|
50
|
+
|
|
51
|
+
// Create a client from a CLI profile
|
|
52
|
+
const client = await createClientFromProfile('PROFILE_ALPHA');
|
|
53
|
+
|
|
54
|
+
// Use it like any other FluentClient
|
|
55
|
+
const events = await client.getEvents({ eventType: 'ORCHESTRATION_AUDIT' });
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Retailer Override
|
|
59
|
+
|
|
60
|
+
When a profile has multiple retailers, the `retailer` option loads the correct retailer ID **and** switches to the retailer-specific user credentials automatically.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const client = await createClientFromProfile('PROFILE_BETA', { retailer: 'RETAILER_ALPHA' });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
What happens internally:
|
|
67
|
+
|
|
68
|
+
1. `profile.json` is read. Default user is `profile_beta_admin`.
|
|
69
|
+
2. `retailer.RETAILER_ALPHA.json` is read. It overrides the user to `retailer_alpha_admin` and provides `retailerId: '5'`.
|
|
70
|
+
3. `user.retailer_alpha_admin.json` is read for the final credentials.
|
|
71
|
+
4. The resulting `FluentClientConfig` contains `retailerId: '5'` and the `retailer_alpha_admin` credentials -- not the default `profile_beta_admin`.
|
|
72
|
+
|
|
73
|
+
Without the `retailer` option, the profile's default user is used and no `retailerId` is set.
|
|
74
|
+
|
|
75
|
+
## API Reference
|
|
76
|
+
|
|
77
|
+
All functions below are exported from the main SDK entry point:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import {
|
|
81
|
+
createClientFromProfile,
|
|
82
|
+
loadFluentProfile,
|
|
83
|
+
listFluentProfiles,
|
|
84
|
+
getFluentProfileInfo,
|
|
85
|
+
resolveProfileBaseDir,
|
|
86
|
+
} from '@fluentcommerce/fc-connect-sdk';
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### createClientFromProfile(profileName, options?)
|
|
90
|
+
|
|
91
|
+
Creates a `FluentClient` from a Fluent CLI profile. This is the primary entry point for most use cases.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
async function createClientFromProfile(
|
|
95
|
+
profileName: string,
|
|
96
|
+
options?: FluentProfileOptions & CreateClientOptions & { logger?: Logger }
|
|
97
|
+
): Promise<FluentClient>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Parameters:**
|
|
101
|
+
|
|
102
|
+
| Parameter | Type | Required | Description |
|
|
103
|
+
|-----------|------|----------|-------------|
|
|
104
|
+
| `profileName` | `string` | Yes | CLI profile name (directory name under `~/.fluentcommerce/`) |
|
|
105
|
+
| `options` | `object` | No | Merged options from `FluentProfileOptions`, `CreateClientOptions`, and `{ logger }` |
|
|
106
|
+
|
|
107
|
+
**Returns:** `Promise<FluentClient>` -- a fully configured client with OAuth2 credentials loaded from disk.
|
|
108
|
+
|
|
109
|
+
**Throws:** `Error` if the profile directory, `profile.json`, retailer file, or user credentials file is missing or malformed.
|
|
110
|
+
|
|
111
|
+
**Examples:**
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Basic usage
|
|
115
|
+
const client = await createClientFromProfile('PROFILE_ALPHA');
|
|
116
|
+
|
|
117
|
+
// With retailer and connection validation
|
|
118
|
+
const client = await createClientFromProfile('PROFILE_BETA', {
|
|
119
|
+
retailer: 'RETAILER_ALPHA',
|
|
120
|
+
validateConnection: true,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// With custom logger and timeout
|
|
124
|
+
const client = await createClientFromProfile('PROFILE_BETA', {
|
|
125
|
+
retailer: 'RETAILER_ALPHA',
|
|
126
|
+
timeout: 30000,
|
|
127
|
+
logger: myCustomLogger,
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
When `validateConnection: true` is set, the factory executes `query { me { ref } }` immediately after creating the client to verify that authentication works. If it fails, the error is thrown before any business logic runs.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### loadFluentProfile(profileName, options?)
|
|
136
|
+
|
|
137
|
+
Loads a CLI profile and returns a raw `FluentClientConfig` object without creating a client. Useful when you need the config for custom client construction.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
function loadFluentProfile(
|
|
141
|
+
profileName: string,
|
|
142
|
+
options?: FluentProfileOptions
|
|
143
|
+
): FluentClientConfig
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Parameters:**
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
|-----------|------|----------|-------------|
|
|
150
|
+
| `profileName` | `string` | Yes | CLI profile name |
|
|
151
|
+
| `options` | `FluentProfileOptions` | No | Profile directory, retailer, timeout, retry overrides |
|
|
152
|
+
|
|
153
|
+
**Returns:** `FluentClientConfig` with `baseUrl`, `clientId`, `clientSecret`, `username`, `password`, and optionally `retailerId`, `timeout`, `retryConfig`.
|
|
154
|
+
|
|
155
|
+
**Throws:** `Error` if any required file is missing or contains invalid data.
|
|
156
|
+
|
|
157
|
+
**Example:**
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const config = loadFluentProfile('PROFILE_BETA', { retailer: 'RETAILER_ALPHA' });
|
|
161
|
+
// config = {
|
|
162
|
+
// baseUrl: 'https://profile-beta.api.fluentcommerce.com',
|
|
163
|
+
// clientId: 'PROFILE_BETA',
|
|
164
|
+
// clientSecret: '...',
|
|
165
|
+
// username: 'retailer_alpha_admin',
|
|
166
|
+
// password: '...',
|
|
167
|
+
// retailerId: '5',
|
|
168
|
+
// }
|
|
169
|
+
|
|
170
|
+
// Use with a custom client setup
|
|
171
|
+
const client = new FluentClient(config, myLogger);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### listFluentProfiles(options?)
|
|
177
|
+
|
|
178
|
+
Lists all valid CLI profiles found on disk. A directory is considered a valid profile if it contains a `profile.json` file. Hidden directories (e.g., `.sessions`) are skipped.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
function listFluentProfiles(options?: FluentProfileOptions): string[]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Parameters:**
|
|
185
|
+
|
|
186
|
+
| Parameter | Type | Required | Description |
|
|
187
|
+
|-----------|------|----------|-------------|
|
|
188
|
+
| `options` | `FluentProfileOptions` | No | Only `profileDir` is relevant here |
|
|
189
|
+
|
|
190
|
+
**Returns:** Alphabetically sorted array of profile names. Returns an empty array if the base directory does not exist or contains no valid profiles.
|
|
191
|
+
|
|
192
|
+
**Example:**
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const profiles = listFluentProfiles();
|
|
196
|
+
// ['PROFILE_BETA', 'PROFILE_ALPHA']
|
|
197
|
+
|
|
198
|
+
// Custom directory
|
|
199
|
+
const profiles = listFluentProfiles({ profileDir: '/opt/fluent/profiles' });
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### getFluentProfileInfo(profileName, options?)
|
|
205
|
+
|
|
206
|
+
Returns metadata about a profile without loading credentials. Useful for building profile selection UIs or diagnostic tools.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
function getFluentProfileInfo(
|
|
210
|
+
profileName: string,
|
|
211
|
+
options?: FluentProfileOptions
|
|
212
|
+
): FluentProfileInfo | null
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Parameters:**
|
|
216
|
+
|
|
217
|
+
| Parameter | Type | Required | Description |
|
|
218
|
+
|-----------|------|----------|-------------|
|
|
219
|
+
| `profileName` | `string` | Yes | CLI profile name |
|
|
220
|
+
| `options` | `FluentProfileOptions` | No | Only `profileDir` is relevant here |
|
|
221
|
+
|
|
222
|
+
**Returns:** `FluentProfileInfo` object or `null` if the profile does not exist.
|
|
223
|
+
|
|
224
|
+
**FluentProfileInfo shape:**
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
interface FluentProfileInfo {
|
|
228
|
+
name: string; // Profile name (directory name)
|
|
229
|
+
baseUrl: string; // API base URL
|
|
230
|
+
accountId: string; // Account/client ID
|
|
231
|
+
username: string; // Default username reference
|
|
232
|
+
retailers: string[]; // Available retailer refs (from retailer.*.json files)
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Example:**
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const info = getFluentProfileInfo('PROFILE_BETA');
|
|
240
|
+
// {
|
|
241
|
+
// name: 'PROFILE_BETA',
|
|
242
|
+
// baseUrl: 'https://profile-beta.api.fluentcommerce.com',
|
|
243
|
+
// accountId: 'PROFILE_BETA',
|
|
244
|
+
// username: 'profile_beta_admin',
|
|
245
|
+
// retailers: ['RETAILER_ALPHA'],
|
|
246
|
+
// }
|
|
247
|
+
|
|
248
|
+
if (info && info.retailers.length > 0) {
|
|
249
|
+
console.log(`Profile has retailers: ${info.retailers.join(', ')}`);
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### resolveProfileBaseDir(options?)
|
|
256
|
+
|
|
257
|
+
Returns the base directory where CLI profiles are stored. Useful for debugging or custom profile discovery logic.
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
function resolveProfileBaseDir(options?: FluentProfileOptions): string
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Resolution order:**
|
|
264
|
+
|
|
265
|
+
1. `options.profileDir` if provided.
|
|
266
|
+
2. `FLUENT_PROFILE_DIR` environment variable if set.
|
|
267
|
+
3. `~/.fluentcommerce/` (default).
|
|
268
|
+
|
|
269
|
+
**Example:**
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const dir = resolveProfileBaseDir();
|
|
273
|
+
// '/home/user/.fluentcommerce'
|
|
274
|
+
|
|
275
|
+
const dir = resolveProfileBaseDir({ profileDir: '/opt/fluent/profiles' });
|
|
276
|
+
// '/opt/fluent/profiles'
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## FluentProfileOptions
|
|
280
|
+
|
|
281
|
+
All profile-related functions accept a `FluentProfileOptions` object:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
interface FluentProfileOptions {
|
|
285
|
+
profileDir?: string;
|
|
286
|
+
retailer?: string;
|
|
287
|
+
timeout?: number;
|
|
288
|
+
retryConfig?: FluentClientConfig['retryConfig'];
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
| Option | Type | Default | Description |
|
|
293
|
+
|--------|------|---------|-------------|
|
|
294
|
+
| `profileDir` | `string` | `~/.fluentcommerce/` | Override the base directory for profile discovery |
|
|
295
|
+
| `retailer` | `string` | `undefined` | Retailer ref (e.g., `'RETAILER_ALPHA'`). Loads retailer-specific `retailerId` and user credentials |
|
|
296
|
+
| `timeout` | `number` | `undefined` | Request timeout in milliseconds. Passed through to `FluentClientConfig` |
|
|
297
|
+
| `retryConfig` | `object` | `undefined` | Retry configuration. Passed through to `FluentClientConfig` |
|
|
298
|
+
|
|
299
|
+
`createClientFromProfile` additionally accepts:
|
|
300
|
+
|
|
301
|
+
| Option | Type | Default | Description |
|
|
302
|
+
|--------|------|---------|-------------|
|
|
303
|
+
| `validateConnection` | `boolean` | `false` | Execute a test query immediately to verify authentication |
|
|
304
|
+
| `logger` | `Logger` | `undefined` | Custom logger instance passed to the `FluentClient` constructor |
|
|
305
|
+
|
|
306
|
+
## Profile Directory Resolution
|
|
307
|
+
|
|
308
|
+
The SDK resolves the profile base directory in the following order:
|
|
309
|
+
|
|
310
|
+
1. **Explicit option:** `options.profileDir` takes highest priority.
|
|
311
|
+
2. **Environment variable:** `FLUENT_PROFILE_DIR`, useful for CI or non-standard installations.
|
|
312
|
+
3. **Default path:** `~/.fluentcommerce/`, which is where the Fluent CLI stores profiles by default.
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
// Use default (~/.fluentcommerce/)
|
|
316
|
+
const client = await createClientFromProfile('MYPROFILE');
|
|
317
|
+
|
|
318
|
+
// Use environment variable
|
|
319
|
+
// export FLUENT_PROFILE_DIR=/opt/fluent/profiles
|
|
320
|
+
const client = await createClientFromProfile('MYPROFILE');
|
|
321
|
+
|
|
322
|
+
// Explicit override (takes priority over env var)
|
|
323
|
+
const client = await createClientFromProfile('MYPROFILE', {
|
|
324
|
+
profileDir: '/opt/fluent/profiles',
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Error Handling
|
|
329
|
+
|
|
330
|
+
All profile functions throw descriptive errors with actionable messages. The error messages include the file path that was expected and, where possible, a list of available alternatives.
|
|
331
|
+
|
|
332
|
+
| Condition | Error Message Pattern |
|
|
333
|
+
|-----------|----------------------|
|
|
334
|
+
| Profile name is empty or not a string | `Profile name is required` |
|
|
335
|
+
| Profile directory does not exist | `Fluent CLI profile '<name>' not found at <path>. Available profiles: X, Y` |
|
|
336
|
+
| `profile.json` missing | `profile.json not found in <dir>. This directory may not be a valid Fluent CLI profile.` |
|
|
337
|
+
| Required field missing in `profile.json` | `Profile '<name>' is missing required field '<field>' in profile.json` |
|
|
338
|
+
| Retailer file not found | `Retailer '<ref>' not found for profile '<name>' at <path>. Available retailers: X, Y` |
|
|
339
|
+
| User credentials file missing | `User credentials file not found: <path>. Expected file for user '<user>' (set by retailer '<ref>').` |
|
|
340
|
+
| User credentials missing fields | `User credentials file <path> is missing 'username' or 'password' field` |
|
|
341
|
+
| JSON parse failure | `Failed to read <path>: <original error>` |
|
|
342
|
+
|
|
343
|
+
**Example: Handling missing profiles gracefully**
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import { listFluentProfiles, createClientFromProfile } from '@fluentcommerce/fc-connect-sdk';
|
|
347
|
+
|
|
348
|
+
const profiles = listFluentProfiles();
|
|
349
|
+
if (profiles.length === 0) {
|
|
350
|
+
console.error('No Fluent CLI profiles found. Run: fluent profile create <NAME>');
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
const client = await createClientFromProfile(profiles[0]);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
console.error('Failed to load profile:', err.message);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## When NOT to Use CLI Profiles
|
|
363
|
+
|
|
364
|
+
CLI profile integration is designed for local development and standalone scripts. It is **not** appropriate for every runtime context.
|
|
365
|
+
|
|
366
|
+
| Context | Recommended Approach |
|
|
367
|
+
|---------|---------------------|
|
|
368
|
+
| **Versori platform** | Use `createClient({ fetch, log, activation })`. Versori manages auth via connections. |
|
|
369
|
+
| **CI/CD pipelines** | Use environment variables (`FLUENT_CLIENT_ID`, `FLUENT_CLIENT_SECRET`, etc.) with `new FluentClient(config)`. |
|
|
370
|
+
| **Docker containers** | Use environment variables or mounted secrets, not host filesystem profiles. |
|
|
371
|
+
| **Local dev / standalone scripts** | Use `createClientFromProfile()`. This is its intended use case. |
|
|
372
|
+
|
|
373
|
+
## Source Files
|
|
374
|
+
|
|
375
|
+
- Implementation: `src/auth/profile-loader.ts`
|
|
376
|
+
- Factory integration: `src/client-factory.ts` (lines 284-296)
|
|
377
|
+
- Public exports: `src/index.ts`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Event API - Input/Output Reference Guide
|
|
2
2
|
|
|
3
|
-
> **Complete reference** for Event API request/response structures with live examples from
|
|
3
|
+
> **Complete reference** for Event API request/response structures with live examples from a profile-alpha test environment
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -118,6 +118,15 @@ interface FluentEventQueryParams {
|
|
|
118
118
|
}
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
> **Note:** Context parameters use dot-notation (`context.rootEntityType`). In JavaScript/TypeScript, keys with dots **must be quoted**:
|
|
122
|
+
> ```typescript
|
|
123
|
+
> // ✅ Correct - quotes required for dot-notation keys
|
|
124
|
+
> { 'context.rootEntityType': 'ORDER', eventType: 'ORCHESTRATION_AUDIT' }
|
|
125
|
+
>
|
|
126
|
+
> // ❌ Wrong - will cause syntax error
|
|
127
|
+
> { context.rootEntityType: 'ORDER' }
|
|
128
|
+
> ```
|
|
129
|
+
|
|
121
130
|
### Output: FluentEventLogResponse (SUCCESS)
|
|
122
131
|
|
|
123
132
|
```typescript
|
|
@@ -167,7 +176,7 @@ const result = await client.getEvents({
|
|
|
167
176
|
"id": "e2cc5040-360b-43e9-b3c0-07bbc1934f82",
|
|
168
177
|
"name": "BATCH_COMPLETE",
|
|
169
178
|
"type": "ORCHESTRATION_AUDIT",
|
|
170
|
-
"accountId": "
|
|
179
|
+
"accountId": "PROFILE_BETA",
|
|
171
180
|
"retailerId": "5",
|
|
172
181
|
"category": "BATCH",
|
|
173
182
|
"context": {
|
|
@@ -271,7 +280,7 @@ if (attrs) {
|
|
|
271
280
|
"id": "e2cc5040-360b-43e9-b3c0-07bbc1934f82",
|
|
272
281
|
"name": "BATCH_COMPLETE",
|
|
273
282
|
"type": "ORCHESTRATION_AUDIT",
|
|
274
|
-
"accountId": "
|
|
283
|
+
"accountId": "PROFILE_BETA",
|
|
275
284
|
"retailerId": "5",
|
|
276
285
|
"category": "BATCH",
|
|
277
286
|
"context": {
|
|
@@ -437,10 +446,10 @@ FluentValidationError {
|
|
|
437
446
|
### Test Environment Details
|
|
438
447
|
|
|
439
448
|
```yaml
|
|
440
|
-
Base URL: https://
|
|
449
|
+
Base URL: https://profile-alpha.test.api.fluentretail.com
|
|
441
450
|
Retailer ID: 2
|
|
442
|
-
Account ID:
|
|
443
|
-
Client ID:
|
|
451
|
+
Account ID: PROFILE_ALPHA
|
|
452
|
+
Client ID: PROFILE_ALPHA
|
|
444
453
|
```
|
|
445
454
|
|
|
446
455
|
### Example 1: Successful Async Event
|
|
@@ -465,11 +474,11 @@ POST /api/v4.1/event/async
|
|
|
465
474
|
**SDK Code:**
|
|
466
475
|
```typescript
|
|
467
476
|
const client = new FluentClient({
|
|
468
|
-
baseUrl: 'https://
|
|
469
|
-
clientId: '
|
|
470
|
-
clientSecret: '
|
|
471
|
-
username: '
|
|
472
|
-
password: '
|
|
477
|
+
baseUrl: 'https://profile-alpha.test.api.fluentretail.com',
|
|
478
|
+
clientId: 'PROFILE_ALPHA',
|
|
479
|
+
clientSecret: '<CLIENT_SECRET>',
|
|
480
|
+
username: 'profile_alpha_admin',
|
|
481
|
+
password: '<PASSWORD>',
|
|
473
482
|
retailerId: '2'
|
|
474
483
|
});
|
|
475
484
|
|
|
@@ -624,10 +633,10 @@ FluentValidationError: retailerId is required for Event API
|
|
|
624
633
|
```typescript
|
|
625
634
|
// Client WITHOUT retailerId configured
|
|
626
635
|
const client = new FluentClient({
|
|
627
|
-
baseUrl: 'https://
|
|
628
|
-
clientId: '
|
|
636
|
+
baseUrl: 'https://profile-alpha.test.api.fluentretail.com',
|
|
637
|
+
clientId: 'PROFILE_ALPHA',
|
|
629
638
|
clientSecret: '...',
|
|
630
|
-
username: '
|
|
639
|
+
username: 'profile_alpha_admin',
|
|
631
640
|
password: '...'
|
|
632
641
|
// retailerId: undefined ← Not set
|
|
633
642
|
});
|
|
@@ -1157,6 +1166,6 @@ try {
|
|
|
1157
1166
|
|
|
1158
1167
|
---
|
|
1159
1168
|
|
|
1160
|
-
**Generated from live test environments**:
|
|
1169
|
+
**Generated from live test environments**: profile-alpha.test.api.fluentretail.com, profile-beta.sandbox.api.fluentretail.com
|
|
1161
1170
|
**SDK Version**: 0.1.51
|
|
1162
1171
|
**Last Updated**: 2026-02-15
|
|
@@ -56,6 +56,44 @@ const client = await createClient(ctx);
|
|
|
56
56
|
|
|
57
57
|
- `Promise<FluentClient>` - Configured client instance
|
|
58
58
|
|
|
59
|
+
#### createClientFromProfile Function (Fluent CLI Integration)
|
|
60
|
+
|
|
61
|
+
Create a standalone `FluentClient` from an existing Fluent CLI profile in `~/.fluentcommerce`.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { createClientFromProfile } from '@fluentcommerce/fc-connect-sdk';
|
|
65
|
+
|
|
66
|
+
// Simple profile
|
|
67
|
+
const client = await createClientFromProfile('PROFILE_ALPHA');
|
|
68
|
+
|
|
69
|
+
// Multi-retailer profile
|
|
70
|
+
const retailerClient = await createClientFromProfile('PROFILE_BETA', {
|
|
71
|
+
retailer: 'RETAILER_ALPHA',
|
|
72
|
+
validateConnection: true, // Optional fail-fast auth check
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
|
|
78
|
+
- `profileName: string` - Fluent CLI profile directory name
|
|
79
|
+
- `options?: FluentProfileOptions & CreateClientOptions`
|
|
80
|
+
- `profileDir?: string` - Override profile base directory (default: `~/.fluentcommerce`)
|
|
81
|
+
- `retailer?: string` - Retailer ref to load `retailer.<REF>.json` (retailer ID + user override)
|
|
82
|
+
- `timeout?: number` - Override request timeout
|
|
83
|
+
- `retryConfig?: RetryConfig` - Override retry behavior
|
|
84
|
+
- `validateConnection?: boolean` - Validate auth immediately using `query { me { ref } }`
|
|
85
|
+
|
|
86
|
+
**Returns:**
|
|
87
|
+
|
|
88
|
+
- `Promise<FluentClient>` - Standalone OAuth2 client built from profile credentials
|
|
89
|
+
|
|
90
|
+
**Behavior Notes:**
|
|
91
|
+
|
|
92
|
+
- Loads in this order: `profile.json` → optional `retailer.<REF>.json` → `user.<name>.json`
|
|
93
|
+
- When `retailer` is provided, retailer-specific `user` override is respected
|
|
94
|
+
- Throws explicit errors for missing profile/user/retailer files
|
|
95
|
+
- For Versori runtime, use `createClient(ctx)` instead of profile-based loading
|
|
96
|
+
|
|
59
97
|
#### FluentClientConfig Interface
|
|
60
98
|
|
|
61
99
|
```typescript
|
|
@@ -24,7 +24,7 @@ This module clarifies the **TWO types of webhooks** that can come from Fluent Co
|
|
|
24
24
|
{
|
|
25
25
|
"id": "2a43a5d2-0c8f-484d-a0cf-c5353d040997",
|
|
26
26
|
"name": "order_webhook_status",
|
|
27
|
-
"accountId": "
|
|
27
|
+
"accountId": "PROFILE_ALPHA",
|
|
28
28
|
"retailerId": "2",
|
|
29
29
|
"entityId": "6469",
|
|
30
30
|
"entityRef": "HD_G_FROM_POSTMAN_WEBHOOK_TEST",
|
package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md
CHANGED
|
@@ -128,7 +128,7 @@ console.log(`Locations: ${result.data.locations.edges.length} records`);
|
|
|
128
128
|
|
|
129
129
|
## Live Test Results ✅
|
|
130
130
|
|
|
131
|
-
These examples were tested against a real Fluent Commerce API instance (`https://
|
|
131
|
+
These examples were tested against a real Fluent Commerce API instance (`https://profile-alpha.test.api.fluentretail.com`):
|
|
132
132
|
|
|
133
133
|
### Test 1: Products + Locations with connectionPath
|
|
134
134
|
|