@fjell/client-api 4.4.5 → 4.4.7

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.
@@ -0,0 +1,346 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ /**
3
+ * Simple Fjell-Client-API Example - Basic Client API Operations
4
+ *
5
+ * This example demonstrates the conceptual usage of fjell-client-api for HTTP-based
6
+ * data operations. It shows the patterns and API design for client-side operations.
7
+ *
8
+ * This is a conceptual guide showing:
9
+ * - How to create and configure client APIs (PItemApi and CItemApi)
10
+ * - Basic CRUD operations through HTTP endpoints
11
+ * - Primary and contained item patterns
12
+ * - Error handling and response management
13
+ *
14
+ * Run this example with: npx tsx examples/simple-example.ts
15
+ *
16
+ * Note: This is a conceptual example showing API patterns.
17
+ * In a real application, import from the built package:
18
+ * import { createPItemApi, createCItemApi } from '@fjell/client-api';
19
+ */
20
+
21
+ /**
22
+ * Conceptual demonstration of fjell-client-api usage patterns
23
+ * This example shows the API structure without full type implementation
24
+ */
25
+
26
+ // ===== Mock API Implementations =====
27
+
28
+ interface MockPItemApi {
29
+ all(query: any): Promise<any[]>;
30
+ create(item: any): Promise<any>;
31
+ get(key: any): Promise<any>;
32
+ update(key: any, updates: any): Promise<any>;
33
+ remove(key: any): Promise<boolean>;
34
+ action(key: any, action: string, body?: any): Promise<any>;
35
+ find(finder: string, params?: any): Promise<any[]>;
36
+ facet(key: any, facet: string, params?: any): Promise<any>;
37
+ allAction(action: string, body?: any): Promise<any[]>;
38
+ allFacet(facet: string, params?: any): Promise<any>;
39
+ }
40
+
41
+ interface MockCItemApi extends MockPItemApi {
42
+ all(query: any, locations?: any[]): Promise<any[]>;
43
+ create(item: any, locations?: any[]): Promise<any>;
44
+ find(finder: string, params?: any, locations?: any[]): Promise<any[]>;
45
+ allAction(action: string, body?: any, locations?: any[]): Promise<any[]>;
46
+ allFacet(facet: string, params?: any, locations?: any[]): Promise<any>;
47
+ }
48
+
49
+ // Mock implementation that logs operations
50
+ const createMockPItemApi = (itemType: string): MockPItemApi => ({
51
+ async all(query: any) {
52
+ console.log(`šŸ“Š PItemApi.all(${itemType}) - query:`, query);
53
+ return [
54
+ { id: '1', name: 'Item 1', keyType: itemType },
55
+ { id: '2', name: 'Item 2', keyType: itemType }
56
+ ];
57
+ },
58
+
59
+ async create(item: any) {
60
+ const created = { ...item, id: `${itemType}-${Date.now()}` };
61
+ console.log(`āž• PItemApi.create(${itemType}) - created:`, created.id);
62
+ return created;
63
+ },
64
+
65
+ async get(key: any) {
66
+ console.log(`šŸ” PItemApi.get(${itemType}) - key:`, key);
67
+ return { id: key.id, name: `${itemType} ${key.id}`, keyType: itemType };
68
+ },
69
+
70
+ async update(key: any, updates: any) {
71
+ console.log(`āœļø PItemApi.update(${itemType}) - key:`, key, 'updates:', updates);
72
+ return { id: key.id, ...updates, keyType: itemType };
73
+ },
74
+
75
+ async remove(key: any) {
76
+ console.log(`šŸ—‘ļø PItemApi.remove(${itemType}) - key:`, key);
77
+ return true;
78
+ },
79
+
80
+ async action(key: any, action: string, body?: any) {
81
+ console.log(`⚔ PItemApi.action(${itemType}) - action:`, action, 'on:', key.id);
82
+ return { success: true, action, result: body };
83
+ },
84
+
85
+ async find(finder: string, params?: any) {
86
+ console.log(`šŸ” PItemApi.find(${itemType}) - finder:`, finder, 'params:', params);
87
+ return [{ id: '1', name: 'Found Item', keyType: itemType }];
88
+ },
89
+
90
+ async facet(key: any, facet: string, params?: any) {
91
+ console.log(`šŸ“ˆ PItemApi.facet(${itemType}) - facet:`, facet, 'on:', key.id);
92
+ return { facet, data: { count: 42, stats: 'mock data' } };
93
+ },
94
+
95
+ async allAction(action: string, body?: any) {
96
+ console.log(`šŸ“¦ PItemApi.allAction(${itemType}) - action:`, action);
97
+ return [{ id: '1', result: 'updated' }, { id: '2', result: 'updated' }];
98
+ },
99
+
100
+ async allFacet(facet: string, params?: any) {
101
+ console.log(`šŸ“Š PItemApi.allFacet(${itemType}) - facet:`, facet);
102
+ return { facet, totalCount: 100, data: 'aggregated results' };
103
+ }
104
+ });
105
+
106
+ const createMockCItemApi = (itemType: string, parentType: string): MockCItemApi => ({
107
+ ...createMockPItemApi(itemType),
108
+
109
+ async all(query: any, locations?: any[]) {
110
+ console.log(`šŸ“Š CItemApi.all(${itemType}) - query:`, query, 'locations:', locations);
111
+ return [
112
+ { id: '1', name: `${itemType} 1`, keyType: itemType, parentId: locations?.[0] },
113
+ { id: '2', name: `${itemType} 2`, keyType: itemType, parentId: locations?.[0] }
114
+ ];
115
+ },
116
+
117
+ async create(item: any, locations?: any[]) {
118
+ const created = { ...item, id: `${itemType}-${Date.now()}`, parentId: locations?.[0] };
119
+ console.log(`āž• CItemApi.create(${itemType}) - created:`, created.id, 'in:', locations);
120
+ return created;
121
+ },
122
+
123
+ async find(finder: string, params?: any, locations?: any[]) {
124
+ console.log(`šŸ” CItemApi.find(${itemType}) - finder:`, finder, 'in:', locations);
125
+ return [{ id: '1', name: 'Found Item', keyType: itemType, parentId: locations?.[0] }];
126
+ },
127
+
128
+ async allAction(action: string, body?: any, locations?: any[]) {
129
+ console.log(`šŸ“¦ CItemApi.allAction(${itemType}) - action:`, action, 'in:', locations);
130
+ return [{ id: '1', result: 'updated' }, { id: '2', result: 'updated' }];
131
+ },
132
+
133
+ async allFacet(facet: string, params?: any, locations?: any[]) {
134
+ console.log(`šŸ“Š CItemApi.allFacet(${itemType}) - facet:`, facet, 'in:', locations);
135
+ return { facet, totalCount: 25, data: 'location-specific results' };
136
+ }
137
+ });
138
+
139
+ /**
140
+ * Demonstrates Primary Item API operations with User entity
141
+ * Primary items exist independently and have their own endpoints
142
+ */
143
+ async function demonstratePrimaryItemOperations() {
144
+ console.log('\nšŸš€ === Primary Item Operations (Users) ===');
145
+
146
+ // Conceptual: const userApi = createPItemApi<User, 'user'>('user', ['users'], apiConfig);
147
+ const userApi = createMockPItemApi('user');
148
+
149
+ try {
150
+ // 1. Get all users
151
+ console.log('\nšŸ“Š Getting all users...');
152
+ const users = await userApi.all({ filter: {} });
153
+ console.log(`Found ${users.length} users`);
154
+
155
+ // 2. Create a new user
156
+ console.log('\nāž• Creating a new user...');
157
+ const newUser = {
158
+ name: 'John Doe',
159
+ email: 'john.doe@example.com',
160
+ keyType: 'user'
161
+ };
162
+ const createdUser = await userApi.create(newUser);
163
+ console.log(`Created user: ${createdUser.name} (${createdUser.id})`);
164
+
165
+ // 3. Get specific user
166
+ console.log('\nšŸ” Getting specific user...');
167
+ const userId = { keyType: 'user', id: createdUser.id };
168
+ const retrievedUser = await userApi.get(userId);
169
+ console.log(`Retrieved user: ${retrievedUser?.name}`);
170
+
171
+ // 4. Update user
172
+ console.log('\nāœļø Updating user...');
173
+ const updates = { name: 'John Smith' };
174
+ const updatedUser = await userApi.update(userId, updates);
175
+ console.log(`Updated user name to: ${updatedUser?.name}`);
176
+
177
+ // 5. Execute action on user
178
+ console.log('\n⚔ Executing action on user...');
179
+ await userApi.action(userId, 'activate', { reason: 'manual activation' });
180
+ console.log(`Action result: User activated`);
181
+
182
+ // 6. Query with finder
183
+ console.log('\nšŸ” Finding users by email...');
184
+ const foundUsers = await userApi.find('byEmail', { email: 'john.smith@example.com' });
185
+ console.log(`Found ${foundUsers.length} users with matching email`);
186
+
187
+ // 7. Get facet data
188
+ console.log('\nšŸ“ˆ Getting user statistics...');
189
+ const userStats = await userApi.facet(userId, 'stats', {});
190
+ console.log(`User stats:`, userStats);
191
+
192
+ return createdUser.id;
193
+
194
+ } catch (error) {
195
+ console.error('āŒ Error in primary item operations:', error);
196
+ return null;
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Demonstrates Contained Item API operations with Task entity
202
+ * Contained items belong to a location/parent and have hierarchical endpoints
203
+ */
204
+ async function demonstrateContainedItemOperations(userId: string) {
205
+ console.log('\nšŸš€ === Contained Item Operations (Tasks) ===');
206
+
207
+ // Conceptual: const taskApi = createCItemApi<Task, 'task', 'user'>('task', ['users', 'tasks'], apiConfig);
208
+ const taskApi = createMockCItemApi('task', 'user');
209
+
210
+ try {
211
+ // Define user location for contained items
212
+ const userLocation = [userId];
213
+
214
+ // 1. Get all tasks for user
215
+ console.log('\nšŸ“Š Getting all tasks for user...');
216
+ const tasks = await taskApi.all({ filter: {} }, userLocation);
217
+ console.log(`Found ${tasks.length} tasks for user`);
218
+
219
+ // 2. Create a new task
220
+ console.log('\nāž• Creating a new task...');
221
+ const newTask = {
222
+ title: 'Complete Project Documentation',
223
+ description: 'Write comprehensive docs for the fjell-client-api',
224
+ completed: false,
225
+ userId: userId,
226
+ keyType: 'task'
227
+ };
228
+ const createdTask = await taskApi.create(newTask, userLocation);
229
+ console.log(`Created task: ${createdTask.title} (${createdTask.id})`);
230
+
231
+ // 3. Get specific task
232
+ console.log('\nšŸ” Getting specific task...');
233
+ const taskKey = { keyType: 'task', id: createdTask.id };
234
+ const retrievedTask = await taskApi.get(taskKey);
235
+ console.log(`Retrieved task: ${retrievedTask?.title}`);
236
+
237
+ // 4. Update task
238
+ console.log('\nāœļø Updating task...');
239
+ const updates = { completed: true };
240
+ const updatedTask = await taskApi.update(taskKey, updates);
241
+ console.log(`Task completed: ${updatedTask?.completed}`);
242
+
243
+ // 5. Execute action on task
244
+ console.log('\n⚔ Executing action on task...');
245
+ await taskApi.action(taskKey, 'setPriority', { priority: 'high' });
246
+ console.log(`Action result: Task priority set`);
247
+
248
+ // 6. Find tasks by status
249
+ console.log('\nšŸ” Finding completed tasks...');
250
+ const completedTasks = await taskApi.find('byStatus', { completed: true }, userLocation);
251
+ console.log(`Found ${completedTasks.length} completed tasks`);
252
+
253
+ // 7. Get task analytics
254
+ console.log('\nšŸ“ˆ Getting task analytics...');
255
+ const taskAnalytics = await taskApi.allFacet('analytics', { period: 'week' }, userLocation);
256
+ console.log(`Task analytics:`, taskAnalytics);
257
+
258
+ // 8. Remove task
259
+ console.log('\nšŸ—‘ļø Removing task...');
260
+ const removed = await taskApi.remove(taskKey);
261
+ console.log(`Task removed: ${removed}`);
262
+
263
+ } catch (error) {
264
+ console.error('āŒ Error in contained item operations:', error);
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Demonstrates advanced API features
270
+ */
271
+ async function demonstrateAdvancedFeatures() {
272
+ console.log('\nšŸš€ === Advanced API Features ===');
273
+
274
+ const userApi = createMockPItemApi('user');
275
+
276
+ try {
277
+ // 1. Batch operations
278
+ console.log('\nšŸ“¦ Executing batch action...');
279
+ const batchResult = await userApi.allAction('batchUpdate', {
280
+ updates: { lastLogin: new Date() }
281
+ });
282
+ console.log(`Batch updated ${batchResult.length} users`);
283
+
284
+ // 2. Complex facet queries
285
+ console.log('\nšŸ“Š Getting complex analytics...');
286
+ const analytics = await userApi.allFacet('analytics', {
287
+ startDate: new Date('2024-01-01'),
288
+ endDate: new Date(),
289
+ metrics: ['registrations', 'activity', 'retention']
290
+ });
291
+ console.log(`Analytics data:`, analytics);
292
+
293
+ // 3. Advanced queries
294
+ console.log('\nšŸ” Advanced user search...');
295
+ const activeUsers = await userApi.find('activeUsers', {
296
+ lastLoginAfter: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
297
+ includeMetrics: true
298
+ });
299
+ console.log(`Found ${activeUsers.length} active users`);
300
+
301
+ } catch (error) {
302
+ console.error('āŒ Error in advanced features:', error);
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Main function to run the simple example
308
+ */
309
+ export async function runSimpleExample() {
310
+ console.log('šŸŽÆ Fjell-Client-API Simple Example');
311
+ console.log('===================================');
312
+ console.log('Demonstrating basic client API operations with HTTP endpoints\n');
313
+
314
+ try {
315
+ // Run primary item operations
316
+ const userId = await demonstratePrimaryItemOperations();
317
+
318
+ if (userId) {
319
+ // Run contained item operations
320
+ await demonstrateContainedItemOperations(userId);
321
+ }
322
+
323
+ // Run advanced features
324
+ await demonstrateAdvancedFeatures();
325
+
326
+ console.log('\nāœ… Simple example completed successfully!');
327
+ console.log('\nKey Concepts Demonstrated:');
328
+ console.log('• Primary Item API (PItemApi) for independent entities');
329
+ console.log('• Contained Item API (CItemApi) for hierarchical data');
330
+ console.log('• CRUD operations through HTTP endpoints');
331
+ console.log('• Actions and facets for business logic');
332
+ console.log('• Query patterns and finders');
333
+ console.log('• Error handling and response management');
334
+ console.log('\nNote: This is a conceptual example showing API patterns.');
335
+ console.log('In production, use actual fjell-client-api with proper types.');
336
+
337
+ } catch (error) {
338
+ console.error('āŒ Example failed:', error);
339
+ throw error;
340
+ }
341
+ }
342
+
343
+ // Run the example if this file is executed directly
344
+ if (import.meta.url === `file://${process.argv[1]}`) {
345
+ runSimpleExample().catch(console.error);
346
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fjell/client-api",
3
3
  "description": "Client API for Fjell",
4
- "version": "4.4.5",
4
+ "version": "4.4.7",
5
5
  "keywords": [
6
6
  "client",
7
7
  "api",
@@ -17,26 +17,27 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@fjell/core": "^4.4.6",
21
- "@fjell/http-api": "^4.4.4",
22
- "@fjell/logging": "^4.4.6",
20
+ "@fjell/core": "^4.4.7",
21
+ "@fjell/http-api": "^4.4.5",
22
+ "@fjell/logging": "^4.4.7",
23
+ "@fjell/registry": "^4.4.7",
23
24
  "deepmerge": "^4.3.1"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@eslint/eslintrc": "^3.3.1",
27
- "@eslint/js": "^9.30.1",
28
- "@swc/core": "^1.12.11",
28
+ "@eslint/js": "^9.31.0",
29
+ "@swc/core": "^1.13.1",
29
30
  "@tsconfig/recommended": "^1.0.10",
30
- "@typescript-eslint/eslint-plugin": "^8.36.0",
31
- "@typescript-eslint/parser": "^8.36.0",
31
+ "@typescript-eslint/eslint-plugin": "^8.37.0",
32
+ "@typescript-eslint/parser": "^8.37.0",
32
33
  "@vitest/coverage-istanbul": "^3.2.4",
33
34
  "@vitest/coverage-v8": "^3.2.4",
34
35
  "@vitest/ui": "^3.2.4",
35
36
  "concurrently": "^9.2.0",
36
- "eslint": "^9.30.1",
37
+ "eslint": "^9.31.0",
37
38
  "rimraf": "^6.0.1",
38
39
  "typescript": "^5.8.3",
39
- "vite": "^7.0.3",
40
+ "vite": "^7.0.5",
40
41
  "vite-plugin-dts": "^4.5.4",
41
42
  "vite-plugin-node": "^7.0.0",
42
43
  "vitest": "^3.2.4"