totalum-api-sdk 3.0.5 → 3.0.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.
package/README.MD CHANGED
@@ -1,4 +1,4 @@
1
- ## Totalum API SDK (v3.0.5)
1
+ ## Totalum API SDK
2
2
 
3
3
  Official TypeScript/JavaScript SDK for the Totalum API. This library provides a fully typed, modern interface to interact with all Totalum endpoints.
4
4
 
@@ -8,16 +8,6 @@ Official TypeScript/JavaScript SDK for the Totalum API. This library provides a
8
8
  npm i totalum-api-sdk
9
9
  ```
10
10
 
11
- ## What's New in v3.0
12
-
13
- - **Native Fetch**: Removed `axios` dependency, now using native `fetch` API (works in Node.js 18+ and browsers)
14
- - **Typed Responses**: All methods return strongly-typed `TotalumApiResponse<T>` with proper TypeScript support
15
- - **Better Error Handling**: Introduced `TotalumError` class for structured error handling
16
- - **Renamed Methods**: More consistent naming (`getItems` → `getRecords`, `getItemById` → `getRecordById`, etc.)
17
- - **Improved Type Safety**: Full TypeScript support with detailed response types
18
- - **No Breaking Changes in API**: Same Totalum API, just better developer experience
19
-
20
-
21
11
  **Note:** v3.0 requires Node.js 18+ (for native fetch support). If you're using an older Node.js version, you'll need to polyfill `fetch` or upgrade to Node.js 18+.
22
12
 
23
13
  # Usage of TotalumApiSdk
@@ -32,7 +22,7 @@ If you are not programming in javascript, you can use the api directly, see <a h
32
22
 
33
23
  ## Authentication
34
24
 
35
- **Note:** If you use totalumSdk inside a totalum plugin, you don't need to authenticate, you can start using totalum like this: modules.totalumSdk.your.function();-> example: modules.totalumSdk.crud.getRecords('your_table', {})
25
+ **Note:** If you use totalumSdk inside a totalum plugin, you don't need to authenticate, you can start using totalum like this: modules.totalumSdk.your.function();-> example: modules.totalumSdk.crud.query('your_table')
36
26
 
37
27
  You can choose to use one of the two authentication methods offered by Totalum Sdk:
38
28
 
@@ -65,7 +55,7 @@ const options: AuthOptions = {
65
55
  const totalumClient = new TotalumApiSdk(options);
66
56
 
67
57
  // execute some TotalumApiSdk function
68
- const result = await totalumClient.crud.getRecords('your_table_name', {});
58
+ const result = await totalumClient.crud.query('your_table_name');
69
59
 
70
60
  ```
71
61
 
@@ -94,7 +84,7 @@ const options = {
94
84
  const totalumClient = new totalum.TotalumApiSdk(options);
95
85
 
96
86
  // execute some TotalumApiSdk function
97
- const result = await totalumClient.crud.getRecords('your_table_name', {});
87
+ const result = await totalumClient.crud.query('your_table_name');
98
88
 
99
89
  ```
100
90
 
@@ -102,7 +92,7 @@ const result = await totalumClient.crud.getRecords('your_table_name', {});
102
92
 
103
93
  ```html
104
94
  <head>
105
- <script src="https://cdn.jsdelivr.net/npm/totalum-api-sdk@3.0.2/dist/totalum-sdk.min.js"></script>
95
+ <script src="https://cdn.jsdelivr.net/npm/totalum-api-sdk@3.0.7/dist/totalum-sdk.min.js"></script>
106
96
  </head>
107
97
  <script>
108
98
  //Example of use TotalumSdk in your custom html page
@@ -116,7 +106,7 @@ const result = await totalumClient.crud.getRecords('your_table_name', {});
116
106
  const tableName = 'your-table-name'; // replace with your table name
117
107
 
118
108
  //example of endpoint execution
119
- totalumClient.crud.getRecords(tableName, {}).then((result) => {
109
+ totalumClient.crud.query(tableName).then((result) => {
120
110
  if (result.errors) {
121
111
  console.error("ERROR:", result.errors);
122
112
  return;
@@ -210,14 +200,14 @@ console.log('Record:', record);
210
200
 
211
201
  ```
212
202
 
213
- ### Get records
203
+ ### Query records (Recommended)
204
+
205
+ `totalumClient.crud.query()` is the **recommended** method for reading data. It replaces `getRecords`, `getNestedData`, and `getManyToManyReferencesRecords`.
214
206
 
215
207
  ```javascript
216
208
 
217
209
  // Get records from a table (default: first 50 records)
218
- const tableName = 'users'; // replace with your table name
219
-
220
- const result = await totalumClient.crud.getRecords(tableName, {});
210
+ const result = await totalumClient.crud.query('users');
221
211
 
222
212
  if (result.errors) {
223
213
  console.error('Error:', result.errors.errorMessage);
@@ -229,168 +219,80 @@ console.log('Records:', records);
229
219
 
230
220
  ```
231
221
 
232
- ### Get nested items
222
+ ### Query with nested relations
233
223
 
234
224
  ```javascript
235
225
 
236
- // imagine that you have 3 tables, client, order and product, and you want to get some clients with all orders and the products of the orders
237
-
238
- const nestedQuery: NestedQuery = {
239
- client: {
240
- order: {
241
- product: {}
242
- },
226
+ // Get clients with all orders and the products of each order
227
+ const result = await totalumClient.crud.query('client', {
228
+ order: {
229
+ product: true
243
230
  }
244
- }
231
+ });
245
232
 
246
- const result = await totalumClient.crud.getNestedData(nestedQuery);
233
+ const clients = result.data;
247
234
 
248
235
  ```
249
236
 
250
- ### Get nested items and filter
237
+ ### Query with filters, sort, and pagination
251
238
 
252
239
  ```javascript
253
240
 
254
- // As before you have client, order, and product tables, but you now want to only get the client with name 'Jhon' and limit to 10 results
255
-
256
- const nestedQuery: NestedQuery = {
257
- client: {
258
- tableFilter: {
259
- filter: [{
260
- name: 'Jhon'
261
- }],
262
- sort: {
263
- name: 1
264
- },
265
- pagination: {
266
- limit: 10,
267
- page: 0,
268
- }
269
- },
270
- order: {
271
- product: {}
272
- },
273
- }
274
- }
275
-
276
- // if you want you can filter to all other nested tables in the same way (adding tableFilter property to the nested table)
277
-
278
- const result = await totalumClient.crud.getNestedData(nestedQuery);
241
+ // Get clients named 'John', sorted by name, limited to 10 results
242
+ const result = await totalumClient.crud.query('client', {
243
+ _filter: { name: 'John' },
244
+ _sort: { name: 'asc' },
245
+ _limit: 10
246
+ });
279
247
 
280
248
  ```
281
249
 
282
- ### Nested Filter
283
-
284
- get table items by Filtering others related tables. (like a join filter in sql)
285
-
286
- **The difference between getNestedData and nestedFilter is that nestedFilter only gets the items of the table that you specify in the tableNameToGet parameter that matches the nested filter.**
287
-
288
-
289
- **Use Case:**
290
-
291
- Imagine you have 3 tables, `client`, `order` and `product`, and you want to get the clients that have an order with state equal to completed and that order_date is from 2021-01-01 to 2021-01-31, and that order must have a product with a product with the name `Cocacola`. And you to get only the first 50 clients that match the filter.
250
+ ### Query with OR conditions
292
251
 
293
252
  ```javascript
294
253
 
295
- // you can filter in all tables for all the properties of the table if you want, in this example we are filtering only the order and product tables
296
- const nestedFilter = {
297
- client: {
298
- order: {
299
- tableFilter: [
300
- {
301
- state: 'completed'
302
- },
303
- {
304
- order_date: {
305
- gte: new Date('2021-01-01'),
306
- }
307
- },
308
- {
309
- order_date: {
310
- lte: new Date('2021-01-31')
311
- }
312
- }
313
- ],
314
- product: {
315
- tableFilter: [
316
- {
317
- name: 'Cocacola'
318
- }
319
- ]
320
- }
321
- },
254
+ const result = await totalumClient.crud.query('users', {
255
+ _filter: {
256
+ _or: [
257
+ { role: 'admin' },
258
+ { role: 'moderator' }
259
+ ]
322
260
  }
323
- }
324
-
325
- const filterOptions = {
326
- pagination: {
327
- limit: 60,
328
- page: 0
329
- },
330
- sort: {
331
- // you can sort by any field of contact, for example, sort by email
332
- email: -1
333
- }
334
- };
335
-
336
- // the table name to get the data that matches the filter
337
- const tableNameToGet = 'client';
338
-
339
- const result = await totalumClient.filter.nestedFilter(nestedFilter, tableNameToGet, filterOptions);
340
-
341
- const clients = result.data;
261
+ });
342
262
 
343
263
  ```
344
264
 
345
-
346
- **Another use case:**
347
-
348
- You can also get the tables that are not in top.
349
-
350
- Imagine you have 3 tables, `client`, `order` and `product`, and you want to get the products that have an order with state equal to completed, and that order must have a client with the name `Jhon`. And you to get only the first 50 products that match the filter.
265
+ ### Query with nested filters and counts
351
266
 
352
267
  ```javascript
353
268
 
354
- const nestedFilter = {
355
- client: {
356
- tableFilter: [
357
- {
358
- name: 'Jhon'
359
- }
360
- ],
361
- order: {
362
- tableFilter: [
363
- {
364
- state: 'completed'
365
- }
366
- ],
367
- product: {}
368
- },
269
+ // Get companies with active employees, count them, sort by name
270
+ const result = await totalumClient.crud.query('company', {
271
+ _filter: { country: 'Spain' },
272
+ _sort: { name: 'asc' },
273
+ _limit: 10,
274
+ employee: {
275
+ _filter: { status: 'active' },
276
+ _has: true,
277
+ _count: true,
278
+ task: { _sort: { createdAt: 'desc' }, _limit: 5 }
369
279
  }
370
- }
280
+ });
371
281
 
372
- const filterOptions = {
373
- pagination: {
374
- limit: 60,
375
- page: 0
376
- },
377
- sort: {
378
- // you can sort by any field of product
379
- name: -1
380
- }
381
- };
282
+ ```
382
283
 
383
- // the table name to get the data that matches the filter
384
- const tableNameToGet = 'product';
284
+ ### Query manyToMany relations
385
285
 
386
- const result = await totalumClient.filter.nestedFilter(nestedFilter, tableNameToGet, filterOptions);
286
+ ```javascript
387
287
 
388
- const products = result.data;
288
+ // Get students with their courses (manyToMany)
289
+ const result = await totalumClient.crud.query('students', {
290
+ courses: true
291
+ });
389
292
 
390
293
  ```
391
294
 
392
- You can do the same approach to get the orders.
393
-
295
+ For full query documentation see: [Read and Filter Data](https://docs.totalum.app/docs/api/filtrarDatos)
394
296
 
395
297
  ### Delete record by id
396
298
 
@@ -507,84 +409,30 @@ console.log('Reference removed successfully');
507
409
 
508
410
  ```
509
411
 
510
- ### Get many-to-many references (get all records with a many-to-many relationship)
412
+ ### Get many-to-many references
511
413
 
512
- ```javascript
513
-
514
- const tableName = 'students';
515
- const recordId = 'student-id-123';
516
- const propertyName = 'courses';
517
-
518
- // Optional query for filtering and sorting
519
- const query = {
520
- filter: [
521
- {
522
- 'courseName': { regex: 'Math', options: 'i' }
523
- },
524
- ],
525
- sort: {
526
- 'courseName': 1 // 1 for asc, -1 for desc
527
- },
528
- pagination: {
529
- limit: 50,
530
- page: 0,
531
- }
532
- };
533
-
534
- const result = await totalumClient.crud.getManyToManyReferencesRecords(tableName, recordId, propertyName, query);
535
-
536
- if (result.errors) {
537
- console.error('Error:', result.errors.errorMessage);
538
- return;
539
- }
540
-
541
- const relatedRecords = result.data;
542
- console.log('Related records:', relatedRecords);
543
-
544
- ```
414
+ > **Note:** For reading manyToMany data, prefer using `totalumClient.crud.query()` with the relation property expanded (see "Query manyToMany relations" above).
545
415
 
546
416
 
547
417
  ## Functions for filter data
548
418
 
419
+ > **Note:** All filtering examples below use `totalumClient.crud.query()`, the recommended method. See "Query records" section above for more details.
420
+
549
421
  ### Filter data using AND filter
550
422
 
551
423
  ```javascript
552
424
 
553
- const tableName = 'users';
554
-
555
425
  // Get records applying AND filter (all conditions must be true)
556
- const filter = {
557
- filter: [
558
- {
559
- 'name': 'John' // exact match
560
- },
561
- {
562
- 'email': { regex: '@example.com', options: 'i' } // regex with case insensitive
563
- },
564
- // Note: gte and lte operators are only for date or number properties
565
- {
566
- 'age': { gte: 18 } // greater than or equal to 18
567
- },
568
- {
569
- 'age': { lte: 65 } // less than or equal to 65
570
- },
571
- {
572
- 'createdAt': { gte: new Date('2024-01-01') } // created after date
573
- },
574
- {
575
- 'createdAt': { lte: new Date('2024-12-31') } // created before date
576
- }
577
- ],
578
- sort: {
579
- 'name': 1 // 1 for ascending, -1 for descending
426
+ const result = await totalumClient.crud.query('users', {
427
+ _filter: {
428
+ name: 'John',
429
+ email: { regex: '@example.com', options: 'i' },
430
+ age: { gte: 18, lte: 65 },
431
+ createdAt: { gte: new Date('2024-01-01'), lte: new Date('2024-12-31') }
580
432
  },
581
- pagination: {
582
- limit: 50,
583
- page: 0,
584
- }
585
- };
586
-
587
- const result = await totalumClient.crud.getRecords(tableName, filter);
433
+ _sort: { name: 'asc' },
434
+ _limit: 50
435
+ });
588
436
 
589
437
  if (result.errors) {
590
438
  console.error('Error:', result.errors.errorMessage);
@@ -600,35 +448,18 @@ console.log('Filtered records:', records);
600
448
 
601
449
  ```javascript
602
450
 
603
- const tableName = 'users';
604
-
605
451
  // Get records applying OR filter (at least one condition must be true)
606
- const filter = {
607
- filter: [
608
- {
609
- or: [
610
- {
611
- 'name': 'John'
612
- },
613
- {
614
- 'email': { regex: '@example.com', options: 'i' }
615
- },
616
- {
617
- 'age': { gte: 18 }
618
- },
619
- ]
620
- }
621
- ],
622
- sort: {
623
- 'name': 1 // 1 for ascending, -1 for descending
452
+ const result = await totalumClient.crud.query('users', {
453
+ _filter: {
454
+ _or: [
455
+ { name: 'John' },
456
+ { email: { regex: '@example.com', options: 'i' } },
457
+ { age: { gte: 18 } }
458
+ ]
624
459
  },
625
- pagination: {
626
- limit: 50,
627
- page: 0,
628
- }
629
- };
630
-
631
- const result = await totalumClient.crud.getRecords(tableName, filter);
460
+ _sort: { name: 'asc' },
461
+ _limit: 50
462
+ });
632
463
 
633
464
  if (result.errors) {
634
465
  console.error('Error:', result.errors.errorMessage);
@@ -644,35 +475,18 @@ console.log('Filtered records:', records);
644
475
 
645
476
  ```javascript
646
477
 
647
- const tableName = 'users';
648
-
649
478
  // Get records applying both OR and AND filters
650
- const filter = {
651
- filter: [
652
- {
653
- or: [
654
- {
655
- 'role': 'admin'
656
- },
657
- {
658
- 'role': 'moderator'
659
- },
660
- ],
661
- },
662
- {
663
- 'status': 'active' // AND this condition must be true
664
- }
665
- ],
666
- sort: {
667
- 'name': 1
479
+ const result = await totalumClient.crud.query('users', {
480
+ _filter: {
481
+ _or: [
482
+ { role: 'admin' },
483
+ { role: 'moderator' }
484
+ ],
485
+ status: 'active' // AND this condition must be true
668
486
  },
669
- pagination: {
670
- limit: 50,
671
- page: 0,
672
- }
673
- };
674
-
675
- const result = await totalumClient.crud.getRecords(tableName, filter);
487
+ _sort: { name: 'asc' },
488
+ _limit: 50
489
+ });
676
490
 
677
491
  if (result.errors) {
678
492
  console.error('Error:', result.errors.errorMessage);
@@ -895,7 +709,8 @@ if (result.errors) {
895
709
  return;
896
710
  }
897
711
 
898
- const fileUrl = result.data;
712
+ // result.data is an array like ["https://..."], extract the URL:
713
+ const fileUrl = result.data[0];
899
714
  console.log('Download URL:', fileUrl);
900
715
 
901
716
  ```
@@ -1278,28 +1093,50 @@ console.log('Tokens used:', chatCompletion.usage.total_tokens);
1278
1093
 
1279
1094
  ```javascript
1280
1095
 
1281
- // See OpenAI API docs: https://platform.openai.com/docs/api-reference/images
1282
- const body = {
1096
+ const result = await totalumClient.openai.generateImage({
1283
1097
  prompt: 'A beautiful sunset over the mountains',
1284
- size: '1024x1024', // '256x256' | '512x512' | '1024x1024'
1285
- fileName: 'sunset_image.png' // CAUTION: reusing names will overwrite files
1286
- };
1287
-
1288
- const result = await totalumClient.openai.generateImage(body);
1098
+ fileName: 'sunset_image',
1099
+ size: '1024x1024', // optional: '1024x1024', '1536x1024' (landscape), '1024x1536' (portrait), 'auto'
1100
+ quality: 'low', // optional: 'low' (fastest), 'medium', 'high', 'auto'
1101
+ output_format: 'png', // optional: 'png', 'jpeg', 'webp'
1102
+ background: 'auto' // optional: 'transparent' (requires png), 'opaque', 'auto'
1103
+ });
1289
1104
 
1290
1105
  if (result.errors) {
1291
1106
  console.error('Error:', result.errors.errorMessage);
1292
1107
  return;
1293
1108
  }
1294
1109
 
1295
- const imageFileName = result.data;
1296
- console.log('Image generated:', imageFileName);
1110
+ const { fileName, imageUrl } = result.data;
1111
+ console.log('Image file:', fileName);
1112
+ console.log('Image URL:', imageUrl); // signed URL to directly access the image
1113
+
1114
+ ```
1115
+
1116
+ ### Edit an image
1297
1117
 
1298
- // Get download URL to view/download the image
1299
- const urlResult = await totalumClient.files.getDownloadUrl(imageFileName);
1300
- if (!urlResult.errors) {
1301
- console.log('Image URL:', urlResult.data);
1118
+ Edit or transform existing images: change clothes, combine images, use as style reference, etc.
1119
+
1120
+ ```javascript
1121
+
1122
+ const result = await totalumClient.openai.editImage({
1123
+ prompt: 'Change ONLY the clothing to a blue suit. Keep the face and background the same.',
1124
+ imageUrls: ['https://example.com/photo.jpg'], // 1-16 image URLs
1125
+ fileName: 'edited-photo',
1126
+ input_fidelity: 'high', // 'high' preserves details (faces). 'low' allows creative freedom (style transfer).
1127
+ size: '1024x1024', // optional
1128
+ quality: 'low', // optional
1129
+ output_format: 'png' // optional
1130
+ });
1131
+
1132
+ if (result.errors) {
1133
+ console.error('Error:', result.errors.errorMessage);
1134
+ return;
1302
1135
  }
1303
1136
 
1137
+ const { fileName, imageUrl } = result.data;
1138
+ console.log('Edited image:', fileName);
1139
+ console.log('Image URL:', imageUrl);
1140
+
1304
1141
  ```
1305
1142
 
@@ -3,6 +3,7 @@ export declare const endpoints: {
3
3
  getObjectById: string;
4
4
  getObjects: string;
5
5
  getNestedData: string;
6
+ query: string;
6
7
  createObject: string;
7
8
  editObjectProperties: string;
8
9
  deleteObject: string;
@@ -43,6 +44,7 @@ export declare const endpoints: {
43
44
  createCompletion: string;
44
45
  createChatCompletion: string;
45
46
  generateImage: string;
47
+ editImage: string;
46
48
  };
47
49
  notifications: {
48
50
  createNotification: string;
@@ -53,4 +55,10 @@ export declare const endpoints: {
53
55
  email: {
54
56
  sendEmail: string;
55
57
  };
58
+ webScraper: {
59
+ scrape: string;
60
+ extract: string;
61
+ screenshot: string;
62
+ searchAndExtract: string;
63
+ };
56
64
  };
@@ -7,6 +7,7 @@ exports.endpoints = {
7
7
  getObjectById: 'api/v1/crud/:typeId/:id',
8
8
  getObjects: 'api/v1/crud/query/:typeId',
9
9
  getNestedData: 'api/v1/crud/nested',
10
+ query: 'api/v1/crud/advanced-query',
10
11
  createObject: 'api/v1/crud/:typeId',
11
12
  editObjectProperties: 'api/v1/crud/:typeId/:id',
12
13
  deleteObject: 'api/v1/crud/:typeId/:id',
@@ -47,6 +48,7 @@ exports.endpoints = {
47
48
  createCompletion: 'api/v1/openai/completion',
48
49
  createChatCompletion: 'api/v1/openai/chat-completion',
49
50
  generateImage: 'api/v1/openai/image',
51
+ editImage: 'api/v1/openai/image-edit',
50
52
  },
51
53
  notifications: {
52
54
  createNotification: 'api/v1/notifications',
@@ -56,5 +58,11 @@ exports.endpoints = {
56
58
  },
57
59
  email: {
58
60
  sendEmail: 'api/v1/startum/send-email-with-default-domain'
61
+ },
62
+ webScraper: {
63
+ scrape: 'api/v1/web-scraper/scrape',
64
+ extract: 'api/v1/web-scraper/extract',
65
+ screenshot: 'api/v1/web-scraper/screenshot',
66
+ searchAndExtract: 'api/v1/web-scraper/search-and-extract',
59
67
  }
60
68
  };