@fjell/client-api 4.4.7 → 4.4.10
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/docs/index.html +18 -0
- package/docs/package.json +35 -0
- package/docs/public/README.md +165 -0
- package/docs/public/api-reference.md +408 -0
- package/docs/public/examples-README.md +150 -0
- package/docs/public/fjell-icon.svg +1 -0
- package/docs/public/package.json +5 -0
- package/docs/src/App.css +1237 -0
- package/docs/src/App.test.tsx +49 -0
- package/docs/src/App.tsx +513 -0
- package/docs/src/index.css +34 -0
- package/docs/src/main.tsx +10 -0
- package/docs/src/test/setup.ts +1 -0
- package/docs/tsconfig.node.json +14 -0
- package/docs/vitest.config.ts +14 -0
- package/package.json +8 -7
package/docs/index.html
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<link rel="icon" type="image/svg+xml" href="/fjell-icon.svg" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
+
<title>Fjell Client API - TypeScript Client Library</title>
|
|
9
|
+
<meta name="description"
|
|
10
|
+
content="Client API for Fjell - A powerful TypeScript client library for service consumption">
|
|
11
|
+
</head>
|
|
12
|
+
|
|
13
|
+
<body>
|
|
14
|
+
<div id="root"></div>
|
|
15
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
16
|
+
</body>
|
|
17
|
+
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fjell-client-api-docs",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"test": "vitest run --coverage",
|
|
11
|
+
"test:watch": "vitest --watch"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"react": "^19.1.0",
|
|
15
|
+
"react-dom": "^19.1.0",
|
|
16
|
+
"react-markdown": "^10.1.0",
|
|
17
|
+
"react-syntax-highlighter": "^15.6.1",
|
|
18
|
+
"remark-gfm": "^4.0.1"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
22
|
+
"@testing-library/react": "^16.3.0",
|
|
23
|
+
"@testing-library/user-event": "^14.6.1",
|
|
24
|
+
"@types/react": "^19.1.8",
|
|
25
|
+
"@types/react-dom": "^19.1.6",
|
|
26
|
+
"@types/react-syntax-highlighter": "^15.5.13",
|
|
27
|
+
"@vitejs/plugin-react": "^4.6.0",
|
|
28
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
29
|
+
"@vitest/ui": "^3.2.4",
|
|
30
|
+
"jsdom": "^26.1.0",
|
|
31
|
+
"typescript": "^5.8.3",
|
|
32
|
+
"vite": "^7.0.0",
|
|
33
|
+
"vitest": "^3.2.4"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Fjell Client API
|
|
2
|
+
|
|
3
|
+
A comprehensive HTTP client library for the Fjell ecosystem. The Client API provides powerful abstractions for HTTP-based data operations, making it easy to build robust client applications that consume REST APIs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @fjell/client-api
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createPItemApi, createCItemApi } from '@fjell/client-api'
|
|
15
|
+
|
|
16
|
+
// Configure API endpoints
|
|
17
|
+
const apiConfig = {
|
|
18
|
+
baseUrl: 'https://api.example.com',
|
|
19
|
+
headers: { 'Authorization': 'Bearer token' }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Create Primary Item API (independent entities)
|
|
23
|
+
const userApi = createPItemApi<User, 'user'>('user', ['users'], apiConfig)
|
|
24
|
+
|
|
25
|
+
// Create Contained Item API (hierarchical entities)
|
|
26
|
+
const taskApi = createCItemApi<Task, 'task', 'user'>('task', ['users', 'tasks'], apiConfig)
|
|
27
|
+
|
|
28
|
+
// Basic operations
|
|
29
|
+
const users = await userApi.all(query)
|
|
30
|
+
const user = await userApi.create(userData)
|
|
31
|
+
const tasks = await taskApi.all(query, [userId]) // Location-based query
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Key Features
|
|
35
|
+
|
|
36
|
+
- **HTTP-based Operations**: Complete CRUD operations over HTTP
|
|
37
|
+
- **Type-safe APIs**: Full TypeScript support with generic type parameters
|
|
38
|
+
- **Hierarchical Data**: Support for nested resource relationships
|
|
39
|
+
- **Business Logic**: Actions and facets for complex operations
|
|
40
|
+
- **Authentication**: Built-in support for various auth patterns
|
|
41
|
+
- **Error Handling**: Comprehensive error handling and retry logic
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
The Client API is built around two main concepts:
|
|
46
|
+
|
|
47
|
+
### Primary Items (PItemApi)
|
|
48
|
+
Independent entities that exist at the top level of your API hierarchy. These represent resources that don't require parent context, such as Users, Products, or Organizations.
|
|
49
|
+
|
|
50
|
+
### Contained Items (CItemApi)
|
|
51
|
+
Entities that belong to parent resources and require location context. These represent hierarchical data like Tasks within Projects, OrderItems within Orders, or Comments within Posts.
|
|
52
|
+
|
|
53
|
+
This design mirrors RESTful API patterns while providing powerful abstractions for complex business operations.
|
|
54
|
+
|
|
55
|
+
## Core Concepts
|
|
56
|
+
|
|
57
|
+
### API Configuration
|
|
58
|
+
Configure your client with base URLs, authentication headers, and other options:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const config = {
|
|
62
|
+
baseUrl: 'https://api.example.com',
|
|
63
|
+
headers: {
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
'Authorization': 'Bearer your-token'
|
|
66
|
+
},
|
|
67
|
+
timeout: 5000
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Primary Item API
|
|
72
|
+
For independent resources:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const userApi = createPItemApi<User, 'user'>('user', ['users'], config)
|
|
76
|
+
|
|
77
|
+
// CRUD operations
|
|
78
|
+
const users = await userApi.all()
|
|
79
|
+
const user = await userApi.get(userKey)
|
|
80
|
+
const newUser = await userApi.create({ name: 'John', email: 'john@example.com' })
|
|
81
|
+
const updatedUser = await userApi.update(userKey, { name: 'John Smith' })
|
|
82
|
+
await userApi.remove(userKey)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Contained Item API
|
|
86
|
+
For hierarchical resources:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const taskApi = createCItemApi<Task, 'task', 'user'>('task', ['users', 'tasks'], config)
|
|
90
|
+
|
|
91
|
+
// Operations with location context
|
|
92
|
+
const userTasks = await taskApi.all({}, [userId])
|
|
93
|
+
const task = await taskApi.get(taskKey)
|
|
94
|
+
const newTask = await taskApi.create({ title: 'Complete project' }, [userId])
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Actions and Facets
|
|
98
|
+
Execute business logic and retrieve analytics:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// Actions - execute business operations
|
|
102
|
+
await userApi.action(userKey, 'activate', { reason: 'manual activation' })
|
|
103
|
+
await taskApi.action(taskKey, 'complete', { completedAt: new Date() })
|
|
104
|
+
|
|
105
|
+
// Facets - retrieve computed data and analytics
|
|
106
|
+
const userStats = await userApi.facet(userKey, 'activity-stats')
|
|
107
|
+
const taskMetrics = await taskApi.allFacet('completion-metrics', { period: 'monthly' })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Examples
|
|
111
|
+
|
|
112
|
+
See the `/examples` directory for comprehensive usage patterns:
|
|
113
|
+
|
|
114
|
+
- **Simple Example**: Basic CRUD operations and client setup
|
|
115
|
+
- **Multi-Level Keys**: Complex hierarchical data with nested relationships
|
|
116
|
+
- **Enterprise Example**: Complete business application with e-commerce workflows
|
|
117
|
+
|
|
118
|
+
## TypeScript Support
|
|
119
|
+
|
|
120
|
+
The Client API is built with TypeScript-first design, providing:
|
|
121
|
+
|
|
122
|
+
- Full type safety for API operations
|
|
123
|
+
- Generic type parameters for custom data models
|
|
124
|
+
- Compile-time validation of API method signatures
|
|
125
|
+
- IntelliSense support for better developer experience
|
|
126
|
+
|
|
127
|
+
## Error Handling
|
|
128
|
+
|
|
129
|
+
Built-in error handling with detailed error information:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
try {
|
|
133
|
+
const user = await userApi.get(userKey)
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error('API error:', error.message)
|
|
136
|
+
// Handle specific error types
|
|
137
|
+
if (error.status === 404) {
|
|
138
|
+
// Handle not found
|
|
139
|
+
} else if (error.status === 401) {
|
|
140
|
+
// Handle authentication error
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Advanced Features
|
|
146
|
+
|
|
147
|
+
### Authentication
|
|
148
|
+
Support for various authentication patterns including Bearer tokens, API keys, and custom headers.
|
|
149
|
+
|
|
150
|
+
### Request Configuration
|
|
151
|
+
Fine-tune requests with timeout settings, retry logic, and custom middleware.
|
|
152
|
+
|
|
153
|
+
### Response Processing
|
|
154
|
+
Automatic response parsing and error handling for consistent API interactions.
|
|
155
|
+
|
|
156
|
+
### Location-based Operations
|
|
157
|
+
Powerful location context system for hierarchical data operations.
|
|
158
|
+
|
|
159
|
+
## Contributing
|
|
160
|
+
|
|
161
|
+
This library is part of the Fjell ecosystem. For contributing guidelines and development setup, please refer to the main Fjell documentation.
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
Licensed under Apache-2.0. See LICENSE file for details.
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for all Client API interfaces and methods.
|
|
4
|
+
|
|
5
|
+
## Core Interfaces
|
|
6
|
+
|
|
7
|
+
### PItemApi<V, S>
|
|
8
|
+
|
|
9
|
+
Primary Item API for independent entities that exist at the top level of your API hierarchy.
|
|
10
|
+
|
|
11
|
+
**Type Parameters:**
|
|
12
|
+
- `V` - The value type returned from API operations
|
|
13
|
+
- `S` - The string literal type representing the item type
|
|
14
|
+
|
|
15
|
+
#### Methods
|
|
16
|
+
|
|
17
|
+
##### `all(query?: ItemQuery): Promise<V[]>`
|
|
18
|
+
Retrieve all items matching the query criteria.
|
|
19
|
+
|
|
20
|
+
**Parameters:**
|
|
21
|
+
- `query` (optional) - Query parameters for filtering and pagination
|
|
22
|
+
|
|
23
|
+
**Returns:** Promise resolving to an array of items
|
|
24
|
+
|
|
25
|
+
**Example:**
|
|
26
|
+
```typescript
|
|
27
|
+
const users = await userApi.all({ limit: 10, offset: 0 })
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
##### `create(item: Partial<Item<S>>): Promise<V>`
|
|
31
|
+
Create a new item.
|
|
32
|
+
|
|
33
|
+
**Parameters:**
|
|
34
|
+
- `item` - Partial item data for creation
|
|
35
|
+
|
|
36
|
+
**Returns:** Promise resolving to the created item
|
|
37
|
+
|
|
38
|
+
**Example:**
|
|
39
|
+
```typescript
|
|
40
|
+
const user = await userApi.create({
|
|
41
|
+
name: 'John Doe',
|
|
42
|
+
email: 'john@example.com'
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
##### `get(key: PriKey<S>): Promise<V>`
|
|
47
|
+
Retrieve a specific item by its key.
|
|
48
|
+
|
|
49
|
+
**Parameters:**
|
|
50
|
+
- `key` - Primary key identifying the item
|
|
51
|
+
|
|
52
|
+
**Returns:** Promise resolving to the item
|
|
53
|
+
|
|
54
|
+
**Example:**
|
|
55
|
+
```typescript
|
|
56
|
+
const user = await userApi.get(userKey)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
##### `update(key: PriKey<S>, updates: Partial<Item<S>>): Promise<V>`
|
|
60
|
+
Update an existing item.
|
|
61
|
+
|
|
62
|
+
**Parameters:**
|
|
63
|
+
- `key` - Primary key identifying the item
|
|
64
|
+
- `updates` - Partial updates to apply
|
|
65
|
+
|
|
66
|
+
**Returns:** Promise resolving to the updated item
|
|
67
|
+
|
|
68
|
+
**Example:**
|
|
69
|
+
```typescript
|
|
70
|
+
const updatedUser = await userApi.update(userKey, {
|
|
71
|
+
name: 'John Smith'
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
##### `remove(key: PriKey<S>): Promise<boolean>`
|
|
76
|
+
Delete an item.
|
|
77
|
+
|
|
78
|
+
**Parameters:**
|
|
79
|
+
- `key` - Primary key identifying the item
|
|
80
|
+
|
|
81
|
+
**Returns:** Promise resolving to true if deletion was successful
|
|
82
|
+
|
|
83
|
+
**Example:**
|
|
84
|
+
```typescript
|
|
85
|
+
const deleted = await userApi.remove(userKey)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
##### `action(key: PriKey<S>, action: string, body?: any): Promise<any>`
|
|
89
|
+
Execute a business action on a specific item.
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
- `key` - Primary key identifying the item
|
|
93
|
+
- `action` - Name of the action to execute
|
|
94
|
+
- `body` (optional) - Action parameters
|
|
95
|
+
|
|
96
|
+
**Returns:** Promise resolving to action result
|
|
97
|
+
|
|
98
|
+
**Example:**
|
|
99
|
+
```typescript
|
|
100
|
+
await userApi.action(userKey, 'activate', { reason: 'manual activation' })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
##### `find(finder: string, params?: any): Promise<V[]>`
|
|
104
|
+
Execute a custom finder operation.
|
|
105
|
+
|
|
106
|
+
**Parameters:**
|
|
107
|
+
- `finder` - Name of the finder
|
|
108
|
+
- `params` (optional) - Finder parameters
|
|
109
|
+
|
|
110
|
+
**Returns:** Promise resolving to an array of found items
|
|
111
|
+
|
|
112
|
+
**Example:**
|
|
113
|
+
```typescript
|
|
114
|
+
const activeUsers = await userApi.find('active-users', { since: '2024-01-01' })
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
##### `facet(key: PriKey<S>, facet: string, params?: any): Promise<any>`
|
|
118
|
+
Retrieve computed data or analytics for a specific item.
|
|
119
|
+
|
|
120
|
+
**Parameters:**
|
|
121
|
+
- `key` - Primary key identifying the item
|
|
122
|
+
- `facet` - Name of the facet
|
|
123
|
+
- `params` (optional) - Facet parameters
|
|
124
|
+
|
|
125
|
+
**Returns:** Promise resolving to facet data
|
|
126
|
+
|
|
127
|
+
**Example:**
|
|
128
|
+
```typescript
|
|
129
|
+
const userStats = await userApi.facet(userKey, 'activity-stats')
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
##### `allAction(action: string, body?: any): Promise<V[]>`
|
|
133
|
+
Execute a business action on all items or collections.
|
|
134
|
+
|
|
135
|
+
**Parameters:**
|
|
136
|
+
- `action` - Name of the action to execute
|
|
137
|
+
- `body` (optional) - Action parameters
|
|
138
|
+
|
|
139
|
+
**Returns:** Promise resolving to action results
|
|
140
|
+
|
|
141
|
+
**Example:**
|
|
142
|
+
```typescript
|
|
143
|
+
const results = await userApi.allAction('bulk-update', { status: 'active' })
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
##### `allFacet(facet: string, params?: any): Promise<any>`
|
|
147
|
+
Retrieve computed data or analytics for collections.
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
- `facet` - Name of the facet
|
|
151
|
+
- `params` (optional) - Facet parameters
|
|
152
|
+
|
|
153
|
+
**Returns:** Promise resolving to facet data
|
|
154
|
+
|
|
155
|
+
**Example:**
|
|
156
|
+
```typescript
|
|
157
|
+
const userAnalytics = await userApi.allFacet('engagement-metrics', { period: 'monthly' })
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### CItemApi<V, S, L1, L2, L3, L4, L5>
|
|
161
|
+
|
|
162
|
+
Contained Item API for hierarchical entities that belong to parent resources and require location context.
|
|
163
|
+
|
|
164
|
+
**Type Parameters:**
|
|
165
|
+
- `V` - The value type returned from API operations
|
|
166
|
+
- `S` - The string literal type representing the item type
|
|
167
|
+
- `L1, L2, L3, L4, L5` - Location hierarchy types (up to 5 levels)
|
|
168
|
+
|
|
169
|
+
**Extends:** All PItemApi methods plus location-aware variants
|
|
170
|
+
|
|
171
|
+
#### Location-Aware Methods
|
|
172
|
+
|
|
173
|
+
##### `all(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V[]>`
|
|
174
|
+
Retrieve all items within a specific location context.
|
|
175
|
+
|
|
176
|
+
**Parameters:**
|
|
177
|
+
- `query` - Query parameters
|
|
178
|
+
- `locations` (optional) - Array of location keys defining the context
|
|
179
|
+
|
|
180
|
+
**Returns:** Promise resolving to an array of items
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
```typescript
|
|
184
|
+
// Get all tasks for a specific user
|
|
185
|
+
const tasks = await taskApi.all({}, [userId])
|
|
186
|
+
|
|
187
|
+
// Get all employees in a specific department
|
|
188
|
+
const employees = await employeeApi.all({}, [orgId, deptId])
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
##### `create(item: Partial<Item<S>>, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V>`
|
|
192
|
+
Create a new item within a specific location context.
|
|
193
|
+
|
|
194
|
+
**Parameters:**
|
|
195
|
+
- `item` - Partial item data for creation
|
|
196
|
+
- `locations` (optional) - Array of location keys defining the context
|
|
197
|
+
|
|
198
|
+
**Returns:** Promise resolving to the created item
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
```typescript
|
|
202
|
+
const task = await taskApi.create({
|
|
203
|
+
title: 'Complete project'
|
|
204
|
+
}, [userId])
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
##### `find(finder: string, params?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V[]>`
|
|
208
|
+
Execute a custom finder within a location context.
|
|
209
|
+
|
|
210
|
+
##### `allAction(action: string, body?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V[]>`
|
|
211
|
+
Execute actions on collections within a location context.
|
|
212
|
+
|
|
213
|
+
##### `allFacet(facet: string, params?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<any>`
|
|
214
|
+
Retrieve analytics for collections within a location context.
|
|
215
|
+
|
|
216
|
+
## Configuration
|
|
217
|
+
|
|
218
|
+
### ApiConfig
|
|
219
|
+
|
|
220
|
+
Configuration object for API instances.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface ApiConfig {
|
|
224
|
+
baseUrl: string;
|
|
225
|
+
headers?: { [key: string]: string };
|
|
226
|
+
timeout?: number;
|
|
227
|
+
retries?: number;
|
|
228
|
+
readAuthenticated?: boolean;
|
|
229
|
+
writeAuthenticated?: boolean;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Properties:**
|
|
234
|
+
- `baseUrl` - Base URL for API endpoints
|
|
235
|
+
- `headers` (optional) - Default headers to include with requests
|
|
236
|
+
- `timeout` (optional) - Request timeout in milliseconds
|
|
237
|
+
- `retries` (optional) - Number of retry attempts for failed requests
|
|
238
|
+
- `readAuthenticated` (optional) - Whether read operations require authentication
|
|
239
|
+
- `writeAuthenticated` (optional) - Whether write operations require authentication
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
```typescript
|
|
243
|
+
const config: ApiConfig = {
|
|
244
|
+
baseUrl: 'https://api.example.com',
|
|
245
|
+
headers: {
|
|
246
|
+
'Content-Type': 'application/json',
|
|
247
|
+
'Authorization': 'Bearer token'
|
|
248
|
+
},
|
|
249
|
+
timeout: 5000,
|
|
250
|
+
retries: 3,
|
|
251
|
+
readAuthenticated: true,
|
|
252
|
+
writeAuthenticated: true
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Factory Functions
|
|
257
|
+
|
|
258
|
+
### createPItemApi
|
|
259
|
+
|
|
260
|
+
Creates a Primary Item API instance.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
function createPItemApi<V, S extends string>(
|
|
264
|
+
itemType: S,
|
|
265
|
+
pathSegments: string[],
|
|
266
|
+
config: ApiConfig
|
|
267
|
+
): PItemApi<V, S>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Parameters:**
|
|
271
|
+
- `itemType` - String literal identifying the item type
|
|
272
|
+
- `pathSegments` - Array of path segments for API endpoints
|
|
273
|
+
- `config` - API configuration
|
|
274
|
+
|
|
275
|
+
**Example:**
|
|
276
|
+
```typescript
|
|
277
|
+
const userApi = createPItemApi<User, 'user'>('user', ['users'], config)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### createCItemApi
|
|
281
|
+
|
|
282
|
+
Creates a Contained Item API instance.
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
function createCItemApi<V, S extends string, L1 extends string, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(
|
|
286
|
+
itemType: S,
|
|
287
|
+
pathSegments: string[],
|
|
288
|
+
config: ApiConfig
|
|
289
|
+
): CItemApi<V, S, L1, L2, L3, L4, L5>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**Parameters:**
|
|
293
|
+
- `itemType` - String literal identifying the item type
|
|
294
|
+
- `pathSegments` - Array of path segments for API endpoints (including parent segments)
|
|
295
|
+
- `config` - API configuration
|
|
296
|
+
|
|
297
|
+
**Example:**
|
|
298
|
+
```typescript
|
|
299
|
+
// Single-level containment
|
|
300
|
+
const taskApi = createCItemApi<Task, 'task', 'user'>('task', ['users', 'tasks'], config)
|
|
301
|
+
|
|
302
|
+
// Multi-level containment
|
|
303
|
+
const employeeApi = createCItemApi<Employee, 'employee', 'organization', 'department'>(
|
|
304
|
+
'employee',
|
|
305
|
+
['organizations', 'departments', 'employees'],
|
|
306
|
+
config
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Error Handling
|
|
311
|
+
|
|
312
|
+
The Client API provides comprehensive error handling with detailed error information.
|
|
313
|
+
|
|
314
|
+
### Error Types
|
|
315
|
+
|
|
316
|
+
- **NetworkError** - Network connectivity issues
|
|
317
|
+
- **AuthenticationError** - Authentication failures
|
|
318
|
+
- **AuthorizationError** - Authorization/permission issues
|
|
319
|
+
- **ValidationError** - Request validation failures
|
|
320
|
+
- **NotFoundError** - Resource not found
|
|
321
|
+
- **ServerError** - Server-side errors
|
|
322
|
+
|
|
323
|
+
### Error Handling Patterns
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
try {
|
|
327
|
+
const user = await userApi.get(userKey)
|
|
328
|
+
} catch (error) {
|
|
329
|
+
if (error instanceof NotFoundError) {
|
|
330
|
+
console.log('User not found')
|
|
331
|
+
} else if (error instanceof AuthenticationError) {
|
|
332
|
+
// Redirect to login
|
|
333
|
+
} else if (error instanceof ValidationError) {
|
|
334
|
+
// Handle validation errors
|
|
335
|
+
console.error('Validation errors:', error.details)
|
|
336
|
+
} else {
|
|
337
|
+
// Handle other errors
|
|
338
|
+
console.error('API error:', error.message)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Best Practices
|
|
344
|
+
|
|
345
|
+
### 1. Type Safety
|
|
346
|
+
Always provide proper TypeScript types for your data models:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
interface User {
|
|
350
|
+
id: string;
|
|
351
|
+
name: string;
|
|
352
|
+
email: string;
|
|
353
|
+
createdAt: Date;
|
|
354
|
+
updatedAt: Date;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const userApi = createPItemApi<User, 'user'>('user', ['users'], config)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 2. Error Handling
|
|
361
|
+
Implement comprehensive error handling:
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
const createUser = async (userData: Partial<User>) => {
|
|
365
|
+
try {
|
|
366
|
+
return await userApi.create(userData)
|
|
367
|
+
} catch (error) {
|
|
368
|
+
// Log error and handle appropriately
|
|
369
|
+
console.error('Failed to create user:', error)
|
|
370
|
+
throw error
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### 3. Configuration Management
|
|
376
|
+
Use environment-specific configuration:
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
const config = {
|
|
380
|
+
baseUrl: process.env.API_BASE_URL || 'http://localhost:3000',
|
|
381
|
+
headers: {
|
|
382
|
+
'Authorization': `Bearer ${process.env.API_TOKEN}`
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### 4. Location Context
|
|
388
|
+
Always provide proper location context for contained items:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
// Good - specific location context
|
|
392
|
+
const userTasks = await taskApi.all({}, [userId])
|
|
393
|
+
|
|
394
|
+
// Avoid - missing location context may return unexpected results
|
|
395
|
+
const allTasks = await taskApi.all({})
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 5. Query Optimization
|
|
399
|
+
Use appropriate queries and pagination:
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
const users = await userApi.all({
|
|
403
|
+
limit: 50,
|
|
404
|
+
offset: 0,
|
|
405
|
+
sort: 'createdAt:desc',
|
|
406
|
+
filter: 'status:active'
|
|
407
|
+
})
|
|
408
|
+
```
|