fireberry-api-client 1.0.0-beta.2.3.4 → 1.0.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 +312 -7
- package/dist/{excludedFields-CfNC21h6.d.cts → excludedFields-CuQ8Dp-N.d.cts} +290 -1
- package/dist/{excludedFields-CfNC21h6.d.ts → excludedFields-CuQ8Dp-N.d.ts} +290 -1
- package/dist/index.cjs +1101 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -829
- package/dist/index.d.ts +3 -829
- package/dist/index.js +1095 -5
- package/dist/index.js.map +1 -1
- package/dist/relatedFieldMapping-Plja-OuE.d.ts +1079 -0
- package/dist/relatedFieldMapping-jprv6Lhg.d.cts +1079 -0
- package/dist/sdk/index.cjs +398 -20
- package/dist/sdk/index.cjs.map +1 -1
- package/dist/sdk/index.d.cts +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +398 -20
- package/dist/sdk/index.js.map +1 -1
- package/dist/utils/index.cjs +1179 -26
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +264 -2
- package/dist/utils/index.d.ts +264 -2
- package/dist/utils/index.js +1160 -27
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,10 +8,17 @@ A standalone, framework-agnostic TypeScript/JavaScript client for the Fireberry
|
|
|
8
8
|
- Zero runtime dependencies (uses native `fetch`)
|
|
9
9
|
- Supports both ESM and CommonJS
|
|
10
10
|
- Automatic retry on rate limits (429)
|
|
11
|
-
- Optional metadata caching
|
|
11
|
+
- Optional metadata and query result caching
|
|
12
|
+
- Smart cache invalidation on mutations (auto-clears query cache when records are modified)
|
|
13
|
+
- Request deduplication (concurrent identical queries share a single API call)
|
|
14
|
+
- Parallel query execution with `queryAll()`
|
|
15
|
+
- Cursor-based pagination with async iterators
|
|
12
16
|
- Lookup field relationship detection
|
|
13
|
-
- Fluent QueryBuilder API
|
|
17
|
+
- Fluent QueryBuilder API with date helpers and debugging
|
|
18
|
+
- Query explain/dry-run for analyzing queries before execution
|
|
14
19
|
- Batch operations with auto-chunking
|
|
20
|
+
- Schema generator for TypeScript types from live API metadata
|
|
21
|
+
- ERD generator for Mermaid diagrams
|
|
15
22
|
- AbortController support for cancellation
|
|
16
23
|
|
|
17
24
|
## Installation
|
|
@@ -67,7 +74,10 @@ const client = new FireberryClient({
|
|
|
67
74
|
maxRetries: 120, // Optional, max retry attempts
|
|
68
75
|
retryDelay: 1000, // Optional, delay between retries in ms
|
|
69
76
|
cacheMetadata: false, // Optional, enable metadata caching
|
|
70
|
-
cacheTTL: 300000, // Optional, cache TTL in ms (5 min default)
|
|
77
|
+
cacheTTL: 300000, // Optional, metadata cache TTL in ms (5 min default)
|
|
78
|
+
cacheQueryResults: false, // Optional, enable query result caching
|
|
79
|
+
queryResultCacheTTL: 60000, // Optional, query cache TTL in ms (1 min default)
|
|
80
|
+
invalidateCacheOnMutation: true, // Optional, auto-clear query cache on create/update/delete (default: true)
|
|
71
81
|
});
|
|
72
82
|
```
|
|
73
83
|
|
|
@@ -160,6 +170,192 @@ const contact = await client.queryBuilder()
|
|
|
160
170
|
// This ensures records from Jan 15 are included (API quirk workaround)
|
|
161
171
|
```
|
|
162
172
|
|
|
173
|
+
### QueryBuilder: Additional Methods
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// whereIn - query with multiple values (OR'd together)
|
|
177
|
+
const accounts = await client.queryBuilder()
|
|
178
|
+
.objectType(1)
|
|
179
|
+
.whereIn('statuscode', [1, 2, 3]) // (statuscode = 1) or (statuscode = 2) or (statuscode = 3)
|
|
180
|
+
.execute();
|
|
181
|
+
|
|
182
|
+
// first() - return single record or null
|
|
183
|
+
const account = await client.queryBuilder()
|
|
184
|
+
.objectType(1)
|
|
185
|
+
.where('accountname').equals('Acme Corp')
|
|
186
|
+
.first(); // Returns Record<string, unknown> | null
|
|
187
|
+
|
|
188
|
+
// count() - get total count without fetching records
|
|
189
|
+
const total = await client.queryBuilder()
|
|
190
|
+
.objectType(1)
|
|
191
|
+
.where('statuscode').equals('1')
|
|
192
|
+
.count(); // Returns number
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### QueryBuilder: Date Helpers
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Query records from today
|
|
199
|
+
const todaysRecords = await client.queryBuilder()
|
|
200
|
+
.objectType(1)
|
|
201
|
+
.whereDate('createdon').today()
|
|
202
|
+
.execute();
|
|
203
|
+
|
|
204
|
+
// Query records from this week
|
|
205
|
+
const thisWeeksRecords = await client.queryBuilder()
|
|
206
|
+
.objectType(1)
|
|
207
|
+
.whereDate('createdon').thisWeek()
|
|
208
|
+
.execute();
|
|
209
|
+
|
|
210
|
+
// Query records from this month
|
|
211
|
+
const thisMonthsRecords = await client.queryBuilder()
|
|
212
|
+
.objectType(1)
|
|
213
|
+
.whereDate('createdon').thisMonth()
|
|
214
|
+
.execute();
|
|
215
|
+
|
|
216
|
+
// Query records from N days ago
|
|
217
|
+
const last7Days = await client.queryBuilder()
|
|
218
|
+
.objectType(1)
|
|
219
|
+
.whereDate('createdon').daysAgo(7)
|
|
220
|
+
.execute();
|
|
221
|
+
|
|
222
|
+
// Query records between two dates
|
|
223
|
+
const dateRange = await client.queryBuilder()
|
|
224
|
+
.objectType(1)
|
|
225
|
+
.whereDate('createdon').between('2024-01-01', '2024-01-31')
|
|
226
|
+
.execute();
|
|
227
|
+
|
|
228
|
+
// Query records before/after a date
|
|
229
|
+
const beforeDate = await client.queryBuilder()
|
|
230
|
+
.objectType(1)
|
|
231
|
+
.whereDate('createdon').before('2024-06-01')
|
|
232
|
+
.execute();
|
|
233
|
+
|
|
234
|
+
const afterDate = await client.queryBuilder()
|
|
235
|
+
.objectType(1)
|
|
236
|
+
.whereDate('createdon').after('2024-01-01')
|
|
237
|
+
.execute();
|
|
238
|
+
|
|
239
|
+
// On or before/after (correctly handles API date quirks)
|
|
240
|
+
const onOrBefore = await client.queryBuilder()
|
|
241
|
+
.objectType(1)
|
|
242
|
+
.whereDate('createdon').onOrBefore('2024-06-30')
|
|
243
|
+
.execute();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### QueryBuilder: Debugging
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// Get query result with metadata for debugging
|
|
250
|
+
const result = await client.queryBuilder()
|
|
251
|
+
.objectType(1)
|
|
252
|
+
.select('accountid', 'accountname')
|
|
253
|
+
.where('statuscode').equals('1')
|
|
254
|
+
.limit(50)
|
|
255
|
+
.executeWithDebug();
|
|
256
|
+
|
|
257
|
+
console.log(result.metadata);
|
|
258
|
+
// {
|
|
259
|
+
// objectType: '1',
|
|
260
|
+
// fields: ['accountid', 'accountname'],
|
|
261
|
+
// queryString: '(statuscode = 1)',
|
|
262
|
+
// pageNumber: 1,
|
|
263
|
+
// pageSize: 500,
|
|
264
|
+
// autoPage: true,
|
|
265
|
+
// sortBy: 'modifiedon',
|
|
266
|
+
// sortType: 'desc',
|
|
267
|
+
// limit: 50,
|
|
268
|
+
// executionTimeMs: 234
|
|
269
|
+
// }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### QueryBuilder: Explain (Dry Run)
|
|
273
|
+
|
|
274
|
+
Analyze a query without executing it to understand its behavior and get optimization suggestions:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
const explanation = client.queryBuilder()
|
|
278
|
+
.objectType(1)
|
|
279
|
+
.select('*')
|
|
280
|
+
.where('statuscode').equals('1')
|
|
281
|
+
.limit(100)
|
|
282
|
+
.explain();
|
|
283
|
+
|
|
284
|
+
console.log(explanation);
|
|
285
|
+
// {
|
|
286
|
+
// objectType: '1',
|
|
287
|
+
// query: '(statuscode = 1)',
|
|
288
|
+
// fields: ['*'],
|
|
289
|
+
// usesWildcard: true,
|
|
290
|
+
// willAutoPage: true,
|
|
291
|
+
// limit: 100,
|
|
292
|
+
// pageSize: 500,
|
|
293
|
+
// sorting: { field: 'modifiedon', direction: 'desc' },
|
|
294
|
+
// estimatedApiCalls: 1,
|
|
295
|
+
// conditionCount: 1,
|
|
296
|
+
// showRealValue: false,
|
|
297
|
+
// warnings: ['Using wildcard (*) fields - consider specifying exact fields for better performance'],
|
|
298
|
+
// suggestions: ['Specify exact fields instead of * to reduce payload size']
|
|
299
|
+
// }
|
|
300
|
+
|
|
301
|
+
// Use explain to validate queries before execution
|
|
302
|
+
if (explanation.warnings.length > 0) {
|
|
303
|
+
console.warn('Query warnings:', explanation.warnings);
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Parallel Query Execution
|
|
308
|
+
|
|
309
|
+
Execute multiple queries in parallel with concurrency control:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const results = await client.queryAll([
|
|
313
|
+
{ objectType: '1', fields: ['accountid', 'accountname'] },
|
|
314
|
+
{ objectType: '2', fields: ['contactid', 'fullname'] },
|
|
315
|
+
{ objectType: '4', fields: ['opportunityid', 'name'] },
|
|
316
|
+
], {
|
|
317
|
+
concurrency: 5, // Optional, max parallel requests (default: 5)
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Results are returned in the same order as input queries
|
|
321
|
+
console.log(results[0].records); // Accounts
|
|
322
|
+
console.log(results[1].records); // Contacts
|
|
323
|
+
console.log(results[2].records); // Opportunities
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Streaming / Cursor-Based Pagination
|
|
327
|
+
|
|
328
|
+
Process large datasets without loading everything into memory:
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
// Process records in batches using async iterator
|
|
332
|
+
for await (const batch of client.queryStream({
|
|
333
|
+
objectType: '1',
|
|
334
|
+
fields: ['accountid', 'accountname'],
|
|
335
|
+
pageSize: 100,
|
|
336
|
+
})) {
|
|
337
|
+
console.log(`Processing ${batch.records.length} records (page ${batch.page})...`);
|
|
338
|
+
for (const record of batch.records) {
|
|
339
|
+
// Process each record
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Collect all records from stream
|
|
344
|
+
const allRecords: Record<string, unknown>[] = [];
|
|
345
|
+
for await (const batch of client.queryStream({ objectType: '1', fields: '*' })) {
|
|
346
|
+
allRecords.push(...batch.records);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// With limit
|
|
350
|
+
for await (const batch of client.queryStream({
|
|
351
|
+
objectType: '1',
|
|
352
|
+
fields: '*',
|
|
353
|
+
limit: 1000, // Stop after 1000 records
|
|
354
|
+
})) {
|
|
355
|
+
// Process batch
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
163
359
|
### CRUD Operations
|
|
164
360
|
|
|
165
361
|
```typescript
|
|
@@ -227,23 +423,38 @@ const fieldsOnly = await client.metadata.getFields('1', { includeLookupRelations
|
|
|
227
423
|
const values = await client.metadata.getFieldValues('1', 'statuscode');
|
|
228
424
|
```
|
|
229
425
|
|
|
230
|
-
###
|
|
426
|
+
### Caching
|
|
231
427
|
|
|
232
428
|
```typescript
|
|
233
429
|
const client = new FireberryClient({
|
|
234
430
|
apiKey: 'your-api-key',
|
|
235
431
|
cacheMetadata: true,
|
|
236
|
-
cacheTTL: 300000,
|
|
432
|
+
cacheTTL: 300000, // Metadata cache: 5 minutes
|
|
433
|
+
cacheQueryResults: true,
|
|
434
|
+
queryResultCacheTTL: 60000, // Query cache: 1 minute
|
|
237
435
|
});
|
|
238
436
|
|
|
239
437
|
// Metadata calls are cached
|
|
240
438
|
await client.metadata.getFields('1'); // Hits API
|
|
241
439
|
await client.metadata.getFields('1'); // Uses cache
|
|
242
440
|
|
|
441
|
+
// Query results are cached (when cacheQueryResults is enabled)
|
|
442
|
+
await client.query({ objectType: '1', fields: '*' }); // Hits API
|
|
443
|
+
await client.query({ objectType: '1', fields: '*' }); // Uses cache
|
|
444
|
+
|
|
445
|
+
// Request deduplication (always active)
|
|
446
|
+
// Concurrent identical queries share a single API call
|
|
447
|
+
const [result1, result2] = await Promise.all([
|
|
448
|
+
client.query({ objectType: '1', fields: '*' }), // Makes API call
|
|
449
|
+
client.query({ objectType: '1', fields: '*' }), // Shares same promise
|
|
450
|
+
]);
|
|
451
|
+
|
|
243
452
|
// Manual cache control
|
|
244
|
-
client.cache.clear();
|
|
245
|
-
client.cache.clearFields('1');
|
|
453
|
+
client.cache.clear(); // Clear all cache
|
|
454
|
+
client.cache.clearFields('1'); // Clear fields for object 1
|
|
246
455
|
client.cache.clearFieldValues('1', 'statuscode'); // Clear specific field values
|
|
456
|
+
client.cache.clearQueryResults(); // Clear all query result cache
|
|
457
|
+
client.cache.clearQueryResultsForObject('1'); // Clear query cache for object 1
|
|
247
458
|
```
|
|
248
459
|
|
|
249
460
|
### Custom API Calls
|
|
@@ -384,6 +595,100 @@ isDropdownField('5'); // true
|
|
|
384
595
|
isLookupField('6'); // true
|
|
385
596
|
```
|
|
386
597
|
|
|
598
|
+
## Schema Generator
|
|
599
|
+
|
|
600
|
+
Generate TypeScript interfaces from your Fireberry metadata:
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
import { generateSchema, schemaBuilder } from 'fireberry-api-client/utils';
|
|
604
|
+
|
|
605
|
+
// Simple generation
|
|
606
|
+
const result = await generateSchema(client);
|
|
607
|
+
console.log(result.typescript); // TypeScript code
|
|
608
|
+
console.log(result.metadata); // { totalObjects: 15, totalFields: 234 }
|
|
609
|
+
|
|
610
|
+
// Write to file
|
|
611
|
+
import fs from 'fs';
|
|
612
|
+
fs.writeFileSync('./fireberry-types.ts', result.typescript);
|
|
613
|
+
|
|
614
|
+
// Fluent builder with options
|
|
615
|
+
const result = await schemaBuilder(client)
|
|
616
|
+
.include([1, 2, 4]) // Only Account, Contact, Opportunity
|
|
617
|
+
.exclude([1000]) // Exclude custom object 1000
|
|
618
|
+
.withComments() // Include JSDoc comments
|
|
619
|
+
.withFieldTypes() // Include field type info
|
|
620
|
+
.withLookupInfo() // Include related object type for lookups
|
|
621
|
+
.withPrefix('FB') // Prefix interfaces: FBAccount, FBContact
|
|
622
|
+
.asReadonly() // Generate readonly interfaces
|
|
623
|
+
.generate();
|
|
624
|
+
|
|
625
|
+
// Generated output example:
|
|
626
|
+
// /**
|
|
627
|
+
// * Account (Object Type: 1)
|
|
628
|
+
// * System Name: Account
|
|
629
|
+
// */
|
|
630
|
+
// export interface FBAccount {
|
|
631
|
+
// /** Account Name @type text */
|
|
632
|
+
// accountname?: string;
|
|
633
|
+
// /** Status @type dropdown */
|
|
634
|
+
// statuscode?: string | number;
|
|
635
|
+
// /** Primary Contact @type lookup @relatedObjectType 2 */
|
|
636
|
+
// primarycontactid?: string;
|
|
637
|
+
// }
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
## ERD Generator
|
|
641
|
+
|
|
642
|
+
Generate Mermaid ERD diagrams from your Fireberry schema:
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
import { erdBuilder, generateFireberryERD } from 'fireberry-api-client/utils';
|
|
646
|
+
|
|
647
|
+
// Fluent builder API
|
|
648
|
+
const result = await erdBuilder(client)
|
|
649
|
+
.include([1, 2, 4, 9]) // Account, Contact, Opportunity, custom object
|
|
650
|
+
.exclude([1000]) // Exclude specific objects
|
|
651
|
+
.settings({
|
|
652
|
+
includeFields: true, // Show fields in entities
|
|
653
|
+
showFieldTypes: true, // Show field types (text, lookup, etc.)
|
|
654
|
+
onlyRelationshipFields: false, // Show only lookup fields
|
|
655
|
+
maxFieldsPerEntity: 10, // Limit fields per entity (0 = unlimited)
|
|
656
|
+
includeFieldLabels: false, // Include field labels as comments
|
|
657
|
+
title: 'My CRM Schema', // Diagram title
|
|
658
|
+
useDisplayNames: false, // Use system names (recommended)
|
|
659
|
+
includeFrontmatter: false, // Exclude YAML frontmatter
|
|
660
|
+
})
|
|
661
|
+
.generate();
|
|
662
|
+
|
|
663
|
+
console.log(result.mermaid); // Mermaid ERD code
|
|
664
|
+
console.log(result.objects); // Processed objects
|
|
665
|
+
console.log(result.relationships); // Found relationships
|
|
666
|
+
console.log(result.warnings); // Any warnings
|
|
667
|
+
|
|
668
|
+
// Direct function alternative
|
|
669
|
+
const result = await generateFireberryERD(client, {
|
|
670
|
+
include: [1, 2, 4],
|
|
671
|
+
settings: { includeFields: true, maxFieldsPerEntity: 5 },
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// Example Mermaid output:
|
|
675
|
+
// erDiagram
|
|
676
|
+
// Account {
|
|
677
|
+
// text accountname
|
|
678
|
+
// lookup primarycontactid FK
|
|
679
|
+
// dropdown statuscode
|
|
680
|
+
// }
|
|
681
|
+
// Contact {
|
|
682
|
+
// text fullname
|
|
683
|
+
// lookup accountid FK
|
|
684
|
+
// }
|
|
685
|
+
//
|
|
686
|
+
// Account }o--|| Contact : "primarycontactid"
|
|
687
|
+
// Contact }o--|| Account : "accountid"
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
Render the Mermaid code using any Mermaid-compatible viewer (VS Code extension, GitHub, Notion, etc.).
|
|
691
|
+
|
|
387
692
|
## Object Type Reference
|
|
388
693
|
|
|
389
694
|
| ID | Object | ID Field | Name Field |
|