fireberry-api-client 1.0.0-beta.1
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 +441 -0
- package/dist/excludedFields-CGXgZN8Y.d.cts +278 -0
- package/dist/excludedFields-CGXgZN8Y.d.ts +278 -0
- package/dist/fieldTypes-BLzJTzpI.d.cts +67 -0
- package/dist/fieldTypes-BLzJTzpI.d.ts +67 -0
- package/dist/index.cjs +1597 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +871 -0
- package/dist/index.d.ts +871 -0
- package/dist/index.js +1586 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk/index.cjs +1041 -0
- package/dist/sdk/index.cjs.map +1 -0
- package/dist/sdk/index.d.cts +372 -0
- package/dist/sdk/index.d.ts +372 -0
- package/dist/sdk/index.js +1022 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/utils/index.cjs +796 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +73 -0
- package/dist/utils/index.d.ts +73 -0
- package/dist/utils/index.js +767 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +61 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1586 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/constants/excludedFields.ts
|
|
12
|
+
var excludedFields_exports = {};
|
|
13
|
+
__export(excludedFields_exports, {
|
|
14
|
+
EXCLUDED_FIELDS_FOR_STAR_QUERY: () => EXCLUDED_FIELDS_FOR_STAR_QUERY,
|
|
15
|
+
getExcludedFieldsForStarQuery: () => getExcludedFieldsForStarQuery,
|
|
16
|
+
isExcludedFromStarQuery: () => isExcludedFromStarQuery
|
|
17
|
+
});
|
|
18
|
+
function isExcludedFromStarQuery(objectType, fieldName) {
|
|
19
|
+
const objectTypeStr = String(objectType);
|
|
20
|
+
const excludedFields = EXCLUDED_FIELDS_FOR_STAR_QUERY[objectTypeStr];
|
|
21
|
+
return excludedFields ? excludedFields.includes(fieldName) : false;
|
|
22
|
+
}
|
|
23
|
+
function getExcludedFieldsForStarQuery(objectType) {
|
|
24
|
+
const objectTypeStr = String(objectType);
|
|
25
|
+
return EXCLUDED_FIELDS_FOR_STAR_QUERY[objectTypeStr] || [];
|
|
26
|
+
}
|
|
27
|
+
var EXCLUDED_FIELDS_FOR_STAR_QUERY;
|
|
28
|
+
var init_excludedFields = __esm({
|
|
29
|
+
"src/constants/excludedFields.ts"() {
|
|
30
|
+
EXCLUDED_FIELDS_FOR_STAR_QUERY = {
|
|
31
|
+
"7": ["deletedon", "deletedby"],
|
|
32
|
+
// Note
|
|
33
|
+
"8": ["deletedon", "deletedby"],
|
|
34
|
+
// Competitor
|
|
35
|
+
"114": ["deletedon", "deletedby"],
|
|
36
|
+
// Calendar Resource
|
|
37
|
+
"115": ["deletedon", "deletedby"],
|
|
38
|
+
// Customer Journey
|
|
39
|
+
"116": ["deletedon", "deletedby"],
|
|
40
|
+
// Profile
|
|
41
|
+
"117": ["deletedon", "deletedby"]
|
|
42
|
+
// Landing Page
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// src/errors.ts
|
|
48
|
+
var FireberryErrorCode = /* @__PURE__ */ ((FireberryErrorCode2) => {
|
|
49
|
+
FireberryErrorCode2["UNKNOWN"] = "UNKNOWN";
|
|
50
|
+
FireberryErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
51
|
+
FireberryErrorCode2["TIMEOUT"] = "TIMEOUT";
|
|
52
|
+
FireberryErrorCode2["AUTHENTICATION_FAILED"] = "AUTHENTICATION_FAILED";
|
|
53
|
+
FireberryErrorCode2["AUTHORIZATION_FAILED"] = "AUTHORIZATION_FAILED";
|
|
54
|
+
FireberryErrorCode2["NOT_FOUND"] = "NOT_FOUND";
|
|
55
|
+
FireberryErrorCode2["RATE_LIMITED"] = "RATE_LIMITED";
|
|
56
|
+
FireberryErrorCode2["INVALID_REQUEST"] = "INVALID_REQUEST";
|
|
57
|
+
FireberryErrorCode2["SERVER_ERROR"] = "SERVER_ERROR";
|
|
58
|
+
FireberryErrorCode2["ABORTED"] = "ABORTED";
|
|
59
|
+
FireberryErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
|
|
60
|
+
return FireberryErrorCode2;
|
|
61
|
+
})(FireberryErrorCode || {});
|
|
62
|
+
var FireberryError = class _FireberryError extends Error {
|
|
63
|
+
/** Error code */
|
|
64
|
+
code;
|
|
65
|
+
/** HTTP status code if applicable */
|
|
66
|
+
statusCode;
|
|
67
|
+
/** Original error that caused this error */
|
|
68
|
+
cause;
|
|
69
|
+
/** Additional context data */
|
|
70
|
+
context;
|
|
71
|
+
constructor(message, options) {
|
|
72
|
+
super(message);
|
|
73
|
+
this.name = "FireberryError";
|
|
74
|
+
this.code = options.code;
|
|
75
|
+
this.statusCode = options.statusCode;
|
|
76
|
+
this.cause = options.cause;
|
|
77
|
+
this.context = options.context;
|
|
78
|
+
if (Error.captureStackTrace) {
|
|
79
|
+
Error.captureStackTrace(this, _FireberryError);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a string representation of the error
|
|
84
|
+
*/
|
|
85
|
+
toString() {
|
|
86
|
+
let str = `${this.name} [${this.code}]: ${this.message}`;
|
|
87
|
+
if (this.statusCode) {
|
|
88
|
+
str += ` (HTTP ${this.statusCode})`;
|
|
89
|
+
}
|
|
90
|
+
return str;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Converts the error to a plain object for logging/serialization
|
|
94
|
+
*/
|
|
95
|
+
toJSON() {
|
|
96
|
+
return {
|
|
97
|
+
name: this.name,
|
|
98
|
+
message: this.message,
|
|
99
|
+
code: this.code,
|
|
100
|
+
statusCode: this.statusCode,
|
|
101
|
+
context: this.context,
|
|
102
|
+
stack: this.stack
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
function createErrorFromResponse(response, body) {
|
|
107
|
+
const status = response.status;
|
|
108
|
+
let code;
|
|
109
|
+
let message;
|
|
110
|
+
switch (status) {
|
|
111
|
+
case 400:
|
|
112
|
+
code = "INVALID_REQUEST" /* INVALID_REQUEST */;
|
|
113
|
+
message = "Invalid request parameters";
|
|
114
|
+
break;
|
|
115
|
+
case 401:
|
|
116
|
+
code = "AUTHENTICATION_FAILED" /* AUTHENTICATION_FAILED */;
|
|
117
|
+
message = "Authentication failed - invalid or missing API key";
|
|
118
|
+
break;
|
|
119
|
+
case 403:
|
|
120
|
+
code = "AUTHORIZATION_FAILED" /* AUTHORIZATION_FAILED */;
|
|
121
|
+
message = "Authorization failed - insufficient permissions";
|
|
122
|
+
break;
|
|
123
|
+
case 404:
|
|
124
|
+
code = "NOT_FOUND" /* NOT_FOUND */;
|
|
125
|
+
message = "Resource not found";
|
|
126
|
+
break;
|
|
127
|
+
case 429:
|
|
128
|
+
code = "RATE_LIMITED" /* RATE_LIMITED */;
|
|
129
|
+
message = "Rate limit exceeded - too many requests";
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
if (status >= 500) {
|
|
133
|
+
code = "SERVER_ERROR" /* SERVER_ERROR */;
|
|
134
|
+
message = `Server error (${status})`;
|
|
135
|
+
} else {
|
|
136
|
+
code = "UNKNOWN" /* UNKNOWN */;
|
|
137
|
+
message = `HTTP error ${status}`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (body && typeof body === "object") {
|
|
141
|
+
const bodyObj = body;
|
|
142
|
+
if (typeof bodyObj.message === "string") {
|
|
143
|
+
message = bodyObj.message;
|
|
144
|
+
} else if (typeof bodyObj.error === "string") {
|
|
145
|
+
message = bodyObj.error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return new FireberryError(message, {
|
|
149
|
+
code,
|
|
150
|
+
statusCode: status,
|
|
151
|
+
context: { body }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function createNetworkError(error) {
|
|
155
|
+
if (error.name === "AbortError") {
|
|
156
|
+
return new FireberryError("Request was aborted", {
|
|
157
|
+
code: "ABORTED" /* ABORTED */,
|
|
158
|
+
cause: error
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (error.name === "TimeoutError" || error.message.includes("timeout")) {
|
|
162
|
+
return new FireberryError("Request timed out", {
|
|
163
|
+
code: "TIMEOUT" /* TIMEOUT */,
|
|
164
|
+
cause: error
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return new FireberryError(`Network error: ${error.message}`, {
|
|
168
|
+
code: "NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
169
|
+
cause: error
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/utils/helpers.ts
|
|
174
|
+
function wait(ms) {
|
|
175
|
+
return new Promise((resolve) => {
|
|
176
|
+
setTimeout(resolve, ms);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function chunkArray(array, size) {
|
|
180
|
+
const result = [];
|
|
181
|
+
for (let i = 0; i < array.length; i += size) {
|
|
182
|
+
result.push(array.slice(i, i + size));
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/utils/queryBuilder.ts
|
|
188
|
+
function escapeQueryValue(value) {
|
|
189
|
+
if (!value) {
|
|
190
|
+
return "";
|
|
191
|
+
}
|
|
192
|
+
let escaped = value.replace(/\\/g, "\\\\");
|
|
193
|
+
escaped = escaped.replace(/\(/g, "\\(");
|
|
194
|
+
escaped = escaped.replace(/\)/g, "\\)");
|
|
195
|
+
escaped = escaped.replace(/\bor\b/gi, "\\or");
|
|
196
|
+
escaped = escaped.replace(/\band\b/gi, "\\and");
|
|
197
|
+
return escaped;
|
|
198
|
+
}
|
|
199
|
+
function sanitizeQuery(query) {
|
|
200
|
+
if (!query) {
|
|
201
|
+
return "";
|
|
202
|
+
}
|
|
203
|
+
query = query.replace(
|
|
204
|
+
/\(\s*([a-zA-Z0-9_]+)\s+(is-null|is-not-null)\s*\)/g,
|
|
205
|
+
"($1 __SPECIAL_OPERATOR__$2)"
|
|
206
|
+
);
|
|
207
|
+
query = query.replace(
|
|
208
|
+
/\(\s*([a-zA-Z0-9_]+)\s+(start-with|not-start-with)\s+([^)]+)\s*\)/g,
|
|
209
|
+
"($1 __TEXT_OPERATOR__$2 $3)"
|
|
210
|
+
);
|
|
211
|
+
query = query.replace(
|
|
212
|
+
/\(\s*([a-zA-Z0-9_]+(?:field|Field|system|System)[0-9]*)\s+(?!__SPECIAL_OPERATOR__|__TEXT_OPERATOR__)([^()<>=!]+)\s*\)/g,
|
|
213
|
+
"($1 = $2)"
|
|
214
|
+
);
|
|
215
|
+
query = query.replace(
|
|
216
|
+
/\(\s*([a-zA-Z0-9_]+)\s+(?!__SPECIAL_OPERATOR__|__TEXT_OPERATOR__|<=|>=|!=|<|>|=\s)([^()<>]+)\s*\)/g,
|
|
217
|
+
"($1 = $2)"
|
|
218
|
+
);
|
|
219
|
+
query = query.replace(/__SPECIAL_OPERATOR__/g, "");
|
|
220
|
+
query = query.replace(/__TEXT_OPERATOR__/g, "");
|
|
221
|
+
query = query.replace(/\(\s*(?:<=|>=|!=|<|>|=)\s*\)/g, "");
|
|
222
|
+
query = query.replace(/\(\s*(?:start-with|not-start-with)\s*\)/gi, "");
|
|
223
|
+
query = query.replace(/\(\s*(?:and|or)\s*\)/gi, "");
|
|
224
|
+
query = query.replace(/\(\s*\)/g, "");
|
|
225
|
+
query = query.replace(/^\s*(and|or)\s*/gi, "");
|
|
226
|
+
query = query.replace(/\s*(and|or)\s*$/gi, "");
|
|
227
|
+
const nestedPattern = /\(\s*\(([^()]+)\)\s*\)/g;
|
|
228
|
+
while (nestedPattern.test(query)) {
|
|
229
|
+
query = query.replace(nestedPattern, "($1)");
|
|
230
|
+
}
|
|
231
|
+
query = query.replace(/\s+/g, " ");
|
|
232
|
+
return query.trim();
|
|
233
|
+
}
|
|
234
|
+
var QueryBuilder = class {
|
|
235
|
+
conditions = [];
|
|
236
|
+
joinOperators = [];
|
|
237
|
+
currentField = null;
|
|
238
|
+
selectedFields = [];
|
|
239
|
+
objectTypeId = null;
|
|
240
|
+
sortByField = null;
|
|
241
|
+
sortDirection = "desc";
|
|
242
|
+
limitValue = null;
|
|
243
|
+
pageNumber = 1;
|
|
244
|
+
showRealValueFlag = true;
|
|
245
|
+
client = null;
|
|
246
|
+
/**
|
|
247
|
+
* Creates a new QueryBuilder
|
|
248
|
+
* @param client - Optional FireberryClient for executing queries
|
|
249
|
+
*/
|
|
250
|
+
constructor(client) {
|
|
251
|
+
this.client = client ?? null;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Sets the object type for the query
|
|
255
|
+
* @param objectType - Object type ID (e.g., '1' for Account)
|
|
256
|
+
*/
|
|
257
|
+
objectType(objectType) {
|
|
258
|
+
this.objectTypeId = String(objectType);
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Adds fields to select
|
|
263
|
+
* @param fields - Field names to select
|
|
264
|
+
*/
|
|
265
|
+
select(...fields) {
|
|
266
|
+
this.selectedFields.push(...fields);
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Starts a new WHERE condition
|
|
271
|
+
* @param field - Field name to filter on
|
|
272
|
+
*/
|
|
273
|
+
where(field) {
|
|
274
|
+
this.currentField = field;
|
|
275
|
+
return this.createConditionBuilder();
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Adds an AND logical operator
|
|
279
|
+
*/
|
|
280
|
+
and() {
|
|
281
|
+
if (this.conditions.length > 0) {
|
|
282
|
+
this.joinOperators.push("and");
|
|
283
|
+
}
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Adds an OR logical operator
|
|
288
|
+
*/
|
|
289
|
+
or() {
|
|
290
|
+
if (this.conditions.length > 0) {
|
|
291
|
+
this.joinOperators.push("or");
|
|
292
|
+
}
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Sets the sort field and direction
|
|
297
|
+
* @param field - Field to sort by
|
|
298
|
+
* @param direction - Sort direction ('asc' or 'desc')
|
|
299
|
+
*/
|
|
300
|
+
sortBy(field, direction = "desc") {
|
|
301
|
+
this.sortByField = field;
|
|
302
|
+
this.sortDirection = direction;
|
|
303
|
+
return this;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Sets the maximum number of records to return
|
|
307
|
+
* @param count - Maximum record count
|
|
308
|
+
*/
|
|
309
|
+
limit(count) {
|
|
310
|
+
this.limitValue = count;
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Sets the page number for pagination
|
|
315
|
+
* @param page - Page number (1-based)
|
|
316
|
+
*/
|
|
317
|
+
page(page) {
|
|
318
|
+
this.pageNumber = page;
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Controls whether to show real values (labels) for dropdown fields
|
|
323
|
+
* @param show - Whether to show real values (default: true)
|
|
324
|
+
*/
|
|
325
|
+
showRealValue(show) {
|
|
326
|
+
this.showRealValueFlag = show;
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Builds the query string from conditions
|
|
331
|
+
* @returns The built query string
|
|
332
|
+
*/
|
|
333
|
+
build() {
|
|
334
|
+
if (this.conditions.length === 0) {
|
|
335
|
+
return "";
|
|
336
|
+
}
|
|
337
|
+
const parts = [];
|
|
338
|
+
for (let i = 0; i < this.conditions.length; i++) {
|
|
339
|
+
const condition = this.conditions[i];
|
|
340
|
+
let conditionStr;
|
|
341
|
+
if (condition.operator === "is-null" || condition.operator === "is-not-null") {
|
|
342
|
+
conditionStr = `(${condition.field} ${condition.operator})`;
|
|
343
|
+
} else {
|
|
344
|
+
const escapedValue = escapeQueryValue(condition.value || "");
|
|
345
|
+
conditionStr = `(${condition.field} ${condition.operator} ${escapedValue})`;
|
|
346
|
+
}
|
|
347
|
+
parts.push(conditionStr);
|
|
348
|
+
if (i < this.joinOperators.length) {
|
|
349
|
+
parts.push(this.joinOperators[i]);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return parts.join(" ");
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Returns the selected fields array
|
|
356
|
+
* Useful for inspecting the query configuration
|
|
357
|
+
*/
|
|
358
|
+
getFields() {
|
|
359
|
+
return [...this.selectedFields];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Converts the query builder state to a payload compatible with @fireberry/sdk
|
|
363
|
+
*
|
|
364
|
+
* @returns Object with `fields` (comma-separated string) and `query` (filter string)
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```typescript
|
|
368
|
+
* import FireberryClientSDK from '@fireberry/sdk/client';
|
|
369
|
+
* import { QueryBuilder } from 'fireberry-api-client';
|
|
370
|
+
*
|
|
371
|
+
* const sdk = new FireberryClientSDK();
|
|
372
|
+
* await sdk.initializeContext();
|
|
373
|
+
*
|
|
374
|
+
* const payload = new QueryBuilder()
|
|
375
|
+
* .select('accountid', 'accountname')
|
|
376
|
+
* .where('statuscode').equals('1')
|
|
377
|
+
* .toSDKPayload();
|
|
378
|
+
*
|
|
379
|
+
* // Use with SDK
|
|
380
|
+
* const results = await sdk.api.query(1, payload);
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
toSDKPayload() {
|
|
384
|
+
const payload = {
|
|
385
|
+
fields: this.selectedFields.length > 0 ? this.selectedFields.join(",") : "*",
|
|
386
|
+
query: this.build()
|
|
387
|
+
};
|
|
388
|
+
if (this.limitValue !== null) {
|
|
389
|
+
payload.page_size = this.limitValue;
|
|
390
|
+
}
|
|
391
|
+
if (this.pageNumber > 1) {
|
|
392
|
+
payload.page_number = this.pageNumber;
|
|
393
|
+
}
|
|
394
|
+
return payload;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Executes the query (requires client to be set)
|
|
398
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
399
|
+
* @returns Query results
|
|
400
|
+
*/
|
|
401
|
+
async execute(signal) {
|
|
402
|
+
if (!this.client) {
|
|
403
|
+
throw new Error("QueryBuilder requires a client to execute queries. Pass a FireberryClient to the constructor.");
|
|
404
|
+
}
|
|
405
|
+
if (!this.objectTypeId) {
|
|
406
|
+
throw new Error("Object type is required. Use .objectType() before executing.");
|
|
407
|
+
}
|
|
408
|
+
const queryOptions = {
|
|
409
|
+
objectType: this.objectTypeId,
|
|
410
|
+
fields: this.selectedFields.length > 0 ? this.selectedFields : ["*"],
|
|
411
|
+
query: this.build(),
|
|
412
|
+
showRealValue: this.showRealValueFlag
|
|
413
|
+
};
|
|
414
|
+
if (this.sortByField) {
|
|
415
|
+
queryOptions.sortBy = this.sortByField;
|
|
416
|
+
queryOptions.sortType = this.sortDirection;
|
|
417
|
+
}
|
|
418
|
+
if (this.limitValue !== null) {
|
|
419
|
+
queryOptions.limit = this.limitValue;
|
|
420
|
+
}
|
|
421
|
+
if (this.pageNumber > 1) {
|
|
422
|
+
queryOptions.page = this.pageNumber;
|
|
423
|
+
}
|
|
424
|
+
if (signal) {
|
|
425
|
+
queryOptions.signal = signal;
|
|
426
|
+
}
|
|
427
|
+
return this.client.query(queryOptions);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Creates a condition builder for the current field
|
|
431
|
+
*/
|
|
432
|
+
createConditionBuilder() {
|
|
433
|
+
const field = this.currentField;
|
|
434
|
+
return {
|
|
435
|
+
equals: (value) => {
|
|
436
|
+
this.addCondition(field, "=", String(value));
|
|
437
|
+
return this;
|
|
438
|
+
},
|
|
439
|
+
notEquals: (value) => {
|
|
440
|
+
this.addCondition(field, "!=", String(value));
|
|
441
|
+
return this;
|
|
442
|
+
},
|
|
443
|
+
lessThan: (value) => {
|
|
444
|
+
this.addCondition(field, "<", String(value));
|
|
445
|
+
return this;
|
|
446
|
+
},
|
|
447
|
+
greaterThan: (value) => {
|
|
448
|
+
this.addCondition(field, ">", String(value));
|
|
449
|
+
return this;
|
|
450
|
+
},
|
|
451
|
+
lessThanOrEqual: (value) => {
|
|
452
|
+
this.addCondition(field, "<=", String(value));
|
|
453
|
+
return this;
|
|
454
|
+
},
|
|
455
|
+
greaterThanOrEqual: (value) => {
|
|
456
|
+
this.addCondition(field, ">=", String(value));
|
|
457
|
+
return this;
|
|
458
|
+
},
|
|
459
|
+
contains: (value) => {
|
|
460
|
+
this.addCondition(field, "start-with", `%${value}`);
|
|
461
|
+
return this;
|
|
462
|
+
},
|
|
463
|
+
notContains: (value) => {
|
|
464
|
+
this.addCondition(field, "not-start-with", `%${value}`);
|
|
465
|
+
return this;
|
|
466
|
+
},
|
|
467
|
+
startsWith: (value) => {
|
|
468
|
+
this.addCondition(field, "start-with", value);
|
|
469
|
+
return this;
|
|
470
|
+
},
|
|
471
|
+
notStartsWith: (value) => {
|
|
472
|
+
this.addCondition(field, "not-start-with", value);
|
|
473
|
+
return this;
|
|
474
|
+
},
|
|
475
|
+
isNull: () => {
|
|
476
|
+
this.addCondition(field, "is-null");
|
|
477
|
+
return this;
|
|
478
|
+
},
|
|
479
|
+
isNotNull: () => {
|
|
480
|
+
this.addCondition(field, "is-not-null");
|
|
481
|
+
return this;
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Adds a condition to the query
|
|
487
|
+
*/
|
|
488
|
+
addCondition(field, operator, value) {
|
|
489
|
+
this.conditions.push({ field, operator, value });
|
|
490
|
+
this.currentField = null;
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
// src/constants/fieldTypes.ts
|
|
495
|
+
var FIELD_TYPE_IDS = {
|
|
496
|
+
DROPDOWN: "b4919f2e-2996-48e4-a03c-ba39fb64386c",
|
|
497
|
+
LOOKUP: "a8fcdf65-91bc-46fd-82f6-1234758345a1",
|
|
498
|
+
EMAIL: "c713d2f7-8fa9-43c3-8062-f07486eaf567",
|
|
499
|
+
TEXT: "a1e7ed6f-5083-477b-b44c-9943a6181359",
|
|
500
|
+
URL: "c820d32f-44df-4c2a-9c1e-18734e864fd5",
|
|
501
|
+
LONG_TEXT: "80108f9d-1e75-40fa-9fa9-02be4ddc1da1",
|
|
502
|
+
DATETIME: "ce972d02-5013-46d4-9d1d-f09df1ac346a",
|
|
503
|
+
DATE: "83bf530c-e04c-462b-9ffc-a46f750fc072",
|
|
504
|
+
HTML: "ed2ad39d-32fc-4585-8f5b-2e93463f050a",
|
|
505
|
+
TELEPHONE: "3f62f67a-1cee-403a-bec6-aa02a9804edb",
|
|
506
|
+
NUMERIC: "6a34bfe3-fece-4da1-9136-a7b1e5ae3319"
|
|
507
|
+
};
|
|
508
|
+
var FIELD_TYPE_MAPPINGS = {
|
|
509
|
+
[FIELD_TYPE_IDS.DROPDOWN]: "Dropdown",
|
|
510
|
+
[FIELD_TYPE_IDS.EMAIL]: "Email",
|
|
511
|
+
[FIELD_TYPE_IDS.TEXT]: "Text",
|
|
512
|
+
[FIELD_TYPE_IDS.LOOKUP]: "Lookup",
|
|
513
|
+
[FIELD_TYPE_IDS.URL]: "URL",
|
|
514
|
+
[FIELD_TYPE_IDS.LONG_TEXT]: "Long Text",
|
|
515
|
+
[FIELD_TYPE_IDS.DATETIME]: "DateTime",
|
|
516
|
+
[FIELD_TYPE_IDS.DATE]: "Date",
|
|
517
|
+
[FIELD_TYPE_IDS.HTML]: "HTML",
|
|
518
|
+
[FIELD_TYPE_IDS.TELEPHONE]: "Telephone",
|
|
519
|
+
[FIELD_TYPE_IDS.NUMERIC]: "Number"
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// src/api/metadata.ts
|
|
523
|
+
var MetadataAPI = class {
|
|
524
|
+
constructor(client) {
|
|
525
|
+
this.client = client;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Gets all available objects/entity types from Fireberry
|
|
529
|
+
*
|
|
530
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
531
|
+
* @returns List of all objects
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* ```typescript
|
|
535
|
+
* const result = await client.metadata.getObjects();
|
|
536
|
+
* console.log(result.objects); // [{ objectType: 1, name: 'Account', ... }, ...]
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
async getObjects(signal) {
|
|
540
|
+
const cached = this.client.getCached("objects");
|
|
541
|
+
if (cached) {
|
|
542
|
+
return cached;
|
|
543
|
+
}
|
|
544
|
+
const response = await this.client.request({
|
|
545
|
+
method: "GET",
|
|
546
|
+
endpoint: "/metadata/records",
|
|
547
|
+
signal
|
|
548
|
+
});
|
|
549
|
+
const result = {
|
|
550
|
+
objects: response.data || [],
|
|
551
|
+
total: response.data?.length || 0,
|
|
552
|
+
success: true
|
|
553
|
+
};
|
|
554
|
+
this.client.setCache("objects", result);
|
|
555
|
+
return result;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Gets all fields for a specific object type
|
|
559
|
+
*
|
|
560
|
+
* @param objectType - The object type ID (e.g., '1' for Account)
|
|
561
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
562
|
+
* @returns List of fields with metadata
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* const result = await client.metadata.getFields('1');
|
|
567
|
+
* console.log(result.fields); // [{ fieldName: 'accountid', label: 'Account ID', ... }, ...]
|
|
568
|
+
* ```
|
|
569
|
+
*/
|
|
570
|
+
async getFields(objectType, signal) {
|
|
571
|
+
const objectTypeStr = String(objectType);
|
|
572
|
+
const cached = this.client.getCached("fields", objectTypeStr);
|
|
573
|
+
if (cached) {
|
|
574
|
+
return cached;
|
|
575
|
+
}
|
|
576
|
+
const response = await this.client.request({
|
|
577
|
+
method: "GET",
|
|
578
|
+
endpoint: `/metadata/records/${objectTypeStr}/fields`,
|
|
579
|
+
signal
|
|
580
|
+
});
|
|
581
|
+
const fields = (response.data || []).map((field) => ({
|
|
582
|
+
...field,
|
|
583
|
+
fieldType: FIELD_TYPE_MAPPINGS[field.systemFieldTypeId] || field.systemFieldTypeId
|
|
584
|
+
}));
|
|
585
|
+
const result = {
|
|
586
|
+
objectTypeId: objectTypeStr,
|
|
587
|
+
fields,
|
|
588
|
+
total: fields.length,
|
|
589
|
+
success: true
|
|
590
|
+
};
|
|
591
|
+
this.client.setCache("fields", objectTypeStr, result);
|
|
592
|
+
return result;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Gets all possible values for a dropdown field
|
|
596
|
+
*
|
|
597
|
+
* @param objectType - The object type ID
|
|
598
|
+
* @param fieldName - The field name
|
|
599
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
600
|
+
* @returns List of dropdown values
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* const result = await client.metadata.getFieldValues('1', 'statuscode');
|
|
605
|
+
* console.log(result.values); // [{ name: 'Active', value: '1' }, { name: 'Inactive', value: '2' }]
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
async getFieldValues(objectType, fieldName, signal) {
|
|
609
|
+
const objectTypeStr = String(objectType);
|
|
610
|
+
const cached = this.client.getCached(
|
|
611
|
+
"fieldValues",
|
|
612
|
+
objectTypeStr,
|
|
613
|
+
fieldName
|
|
614
|
+
);
|
|
615
|
+
if (cached) {
|
|
616
|
+
return cached;
|
|
617
|
+
}
|
|
618
|
+
const response = await this.client.request({
|
|
619
|
+
method: "GET",
|
|
620
|
+
endpoint: `/metadata/records/${objectTypeStr}/fields/${fieldName}/values`,
|
|
621
|
+
signal
|
|
622
|
+
});
|
|
623
|
+
const result = {
|
|
624
|
+
objectTypeId: objectTypeStr,
|
|
625
|
+
fieldName,
|
|
626
|
+
values: response.data?.values || [],
|
|
627
|
+
total: response.data?.values?.length || 0,
|
|
628
|
+
success: true
|
|
629
|
+
};
|
|
630
|
+
this.client.setCache("fieldValues", objectTypeStr, fieldName, result);
|
|
631
|
+
return result;
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
// src/constants/objectIds.ts
|
|
636
|
+
var OBJECT_ID_MAP = {
|
|
637
|
+
1: "accountid",
|
|
638
|
+
2: "contactid",
|
|
639
|
+
3: "leadid",
|
|
640
|
+
4: "opportunityid",
|
|
641
|
+
5: "casesid",
|
|
642
|
+
6: "activityid",
|
|
643
|
+
7: "noteid",
|
|
644
|
+
8: "competitorid",
|
|
645
|
+
9: "crmuserid",
|
|
646
|
+
10: "taskid",
|
|
647
|
+
13: "crmorderid",
|
|
648
|
+
14: "productid",
|
|
649
|
+
17: "crmorderitemid",
|
|
650
|
+
20: "emailtemplateid",
|
|
651
|
+
23: "businessunitid",
|
|
652
|
+
27: "printtemplateid",
|
|
653
|
+
28: "contractid",
|
|
654
|
+
33: "accountproductid",
|
|
655
|
+
46: "projectid",
|
|
656
|
+
67: "campaignid",
|
|
657
|
+
76: "articleid",
|
|
658
|
+
86: "invoiceid",
|
|
659
|
+
101: "attendanceclockid",
|
|
660
|
+
102: "activitylogid",
|
|
661
|
+
104: "conversationid",
|
|
662
|
+
114: "calendarresourceid"
|
|
663
|
+
};
|
|
664
|
+
function getObjectIdFieldName(objectTypeId) {
|
|
665
|
+
const objectTypeNum = typeof objectTypeId === "string" ? parseInt(objectTypeId, 10) : objectTypeId;
|
|
666
|
+
if (OBJECT_ID_MAP[objectTypeNum]) {
|
|
667
|
+
return OBJECT_ID_MAP[objectTypeNum];
|
|
668
|
+
}
|
|
669
|
+
if (objectTypeNum >= 1e3) {
|
|
670
|
+
return `customobject${objectTypeNum}id`;
|
|
671
|
+
}
|
|
672
|
+
return "id";
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// src/api/records.ts
|
|
676
|
+
var RecordsAPI = class {
|
|
677
|
+
constructor(client) {
|
|
678
|
+
this.client = client;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Creates a new record in Fireberry
|
|
682
|
+
*
|
|
683
|
+
* @param objectType - The object type ID (e.g., '1' for Account)
|
|
684
|
+
* @param data - Record data to create
|
|
685
|
+
* @param options - Optional settings
|
|
686
|
+
* @returns Created record data
|
|
687
|
+
*
|
|
688
|
+
* @example
|
|
689
|
+
* ```typescript
|
|
690
|
+
* const result = await client.records.create('1', {
|
|
691
|
+
* accountname: 'New Account',
|
|
692
|
+
* emailaddress1: 'contact@example.com',
|
|
693
|
+
* });
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
async create(objectType, data, options) {
|
|
697
|
+
const response = await this.client.request({
|
|
698
|
+
method: "POST",
|
|
699
|
+
endpoint: `/api/v2/record/${objectType}`,
|
|
700
|
+
body: data,
|
|
701
|
+
signal: options?.signal
|
|
702
|
+
});
|
|
703
|
+
return response.record;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Updates an existing record in Fireberry
|
|
707
|
+
*
|
|
708
|
+
* @param objectType - The object type ID
|
|
709
|
+
* @param recordId - The record ID to update
|
|
710
|
+
* @param data - Record data to update
|
|
711
|
+
* @param options - Optional settings
|
|
712
|
+
* @returns Updated record data
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```typescript
|
|
716
|
+
* const result = await client.records.update('1', 'abc123', {
|
|
717
|
+
* accountname: 'Updated Account Name',
|
|
718
|
+
* });
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
async update(objectType, recordId, data, options) {
|
|
722
|
+
const response = await this.client.request({
|
|
723
|
+
method: "PUT",
|
|
724
|
+
endpoint: `/api/v2/record/${objectType}/${recordId}`,
|
|
725
|
+
body: data,
|
|
726
|
+
signal: options?.signal
|
|
727
|
+
});
|
|
728
|
+
return response.record;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Deletes a record from Fireberry
|
|
732
|
+
*
|
|
733
|
+
* @param objectType - The object type ID
|
|
734
|
+
* @param recordId - The record ID to delete
|
|
735
|
+
* @param options - Optional settings
|
|
736
|
+
* @returns Success status
|
|
737
|
+
*
|
|
738
|
+
* @example
|
|
739
|
+
* ```typescript
|
|
740
|
+
* await client.records.delete('1', 'abc123');
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
async delete(objectType, recordId, options) {
|
|
744
|
+
await this.client.request({
|
|
745
|
+
method: "DELETE",
|
|
746
|
+
endpoint: `/api/record/${objectType}/${recordId}`,
|
|
747
|
+
signal: options?.signal
|
|
748
|
+
});
|
|
749
|
+
return {
|
|
750
|
+
success: true,
|
|
751
|
+
id: recordId
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Upserts a record (creates if not exists, updates if exists)
|
|
756
|
+
*
|
|
757
|
+
* @param objectType - The object type ID
|
|
758
|
+
* @param keyFields - Fields to use for matching existing records
|
|
759
|
+
* @param data - Record data to upsert
|
|
760
|
+
* @param options - Optional settings
|
|
761
|
+
* @returns Upsert result with operation type and record data
|
|
762
|
+
*
|
|
763
|
+
* @example
|
|
764
|
+
* ```typescript
|
|
765
|
+
* const result = await client.records.upsert('1', ['emailaddress1'], {
|
|
766
|
+
* accountname: 'Acme Corp',
|
|
767
|
+
* emailaddress1: 'contact@acme.com',
|
|
768
|
+
* });
|
|
769
|
+
* console.log(result.operationType); // 'create' or 'update'
|
|
770
|
+
* ```
|
|
771
|
+
*/
|
|
772
|
+
async upsert(objectType, keyFields, data, options) {
|
|
773
|
+
const objectTypeStr = String(objectType);
|
|
774
|
+
const upsertKeyValues = {};
|
|
775
|
+
for (const key of keyFields) {
|
|
776
|
+
if (!(key in data)) {
|
|
777
|
+
throw new Error(`Missing value for upsert key field: ${key}`);
|
|
778
|
+
}
|
|
779
|
+
upsertKeyValues[key] = data[key];
|
|
780
|
+
}
|
|
781
|
+
const queryConditions = keyFields.map((key) => `(${key} = ${data[key]})`);
|
|
782
|
+
const queryString = queryConditions.join(" and ");
|
|
783
|
+
const queryResult = await this.client.query({
|
|
784
|
+
objectType: objectTypeStr,
|
|
785
|
+
fields: "*",
|
|
786
|
+
query: queryString,
|
|
787
|
+
limit: 1,
|
|
788
|
+
showRealValue: true,
|
|
789
|
+
signal: options?.signal
|
|
790
|
+
});
|
|
791
|
+
const existingRecords = queryResult.records;
|
|
792
|
+
if (existingRecords.length > 0) {
|
|
793
|
+
const existingRecord = existingRecords[0];
|
|
794
|
+
const idFieldName = getObjectIdFieldName(objectTypeStr);
|
|
795
|
+
const recordId = String(existingRecord[idFieldName]);
|
|
796
|
+
const updatedRecord = await this.update(objectTypeStr, recordId, data, options);
|
|
797
|
+
return {
|
|
798
|
+
success: true,
|
|
799
|
+
operationType: "update",
|
|
800
|
+
upsertKeys: keyFields,
|
|
801
|
+
upsertKeyValues,
|
|
802
|
+
oldRecord: existingRecord,
|
|
803
|
+
newRecord: updatedRecord
|
|
804
|
+
};
|
|
805
|
+
} else {
|
|
806
|
+
const createdRecord = await this.create(objectTypeStr, data, options);
|
|
807
|
+
return {
|
|
808
|
+
success: true,
|
|
809
|
+
operationType: "create",
|
|
810
|
+
upsertKeys: keyFields,
|
|
811
|
+
upsertKeyValues,
|
|
812
|
+
oldRecord: null,
|
|
813
|
+
newRecord: createdRecord
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
// src/api/batch.ts
|
|
820
|
+
var BATCH_SIZE = 20;
|
|
821
|
+
var BatchAPI = class {
|
|
822
|
+
constructor(client) {
|
|
823
|
+
this.client = client;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Creates multiple records in batch
|
|
827
|
+
* Automatically chunks into batches of 20 records
|
|
828
|
+
*
|
|
829
|
+
* @param objectType - The object type ID
|
|
830
|
+
* @param records - Array of records to create
|
|
831
|
+
* @param options - Optional settings
|
|
832
|
+
* @returns Batch result with all created records
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const result = await client.batch.create('1', [
|
|
837
|
+
* { accountname: 'Account 1' },
|
|
838
|
+
* { accountname: 'Account 2' },
|
|
839
|
+
* ]);
|
|
840
|
+
* console.log(result.count); // 2
|
|
841
|
+
* ```
|
|
842
|
+
*/
|
|
843
|
+
async create(objectType, records, options) {
|
|
844
|
+
const objectTypeStr = String(objectType);
|
|
845
|
+
const batches = chunkArray(records, BATCH_SIZE);
|
|
846
|
+
const allResponses = [];
|
|
847
|
+
for (const batch of batches) {
|
|
848
|
+
if (options?.signal?.aborted) {
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
const response = await this.client.request({
|
|
852
|
+
method: "POST",
|
|
853
|
+
endpoint: `/api/v3/record/${objectTypeStr}/batch/create`,
|
|
854
|
+
body: { data: batch },
|
|
855
|
+
signal: options?.signal
|
|
856
|
+
});
|
|
857
|
+
if (response.data) {
|
|
858
|
+
if (Array.isArray(response.data)) {
|
|
859
|
+
allResponses.push(...response.data);
|
|
860
|
+
} else {
|
|
861
|
+
allResponses.push(response.data);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return {
|
|
866
|
+
success: true,
|
|
867
|
+
data: allResponses,
|
|
868
|
+
count: allResponses.length
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Updates multiple records in batch
|
|
873
|
+
* Automatically chunks into batches of 20 records
|
|
874
|
+
*
|
|
875
|
+
* @param objectType - The object type ID
|
|
876
|
+
* @param records - Array of records with ID and data to update
|
|
877
|
+
* @param options - Optional settings
|
|
878
|
+
* @returns Batch result with all updated records
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* const result = await client.batch.update('1', [
|
|
883
|
+
* { id: 'abc123', record: { accountname: 'Updated 1' } },
|
|
884
|
+
* { id: 'def456', record: { accountname: 'Updated 2' } },
|
|
885
|
+
* ]);
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
888
|
+
async update(objectType, records, options) {
|
|
889
|
+
const objectTypeStr = String(objectType);
|
|
890
|
+
const batches = chunkArray(records, BATCH_SIZE);
|
|
891
|
+
const allResponses = [];
|
|
892
|
+
for (const batch of batches) {
|
|
893
|
+
if (options?.signal?.aborted) {
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
const response = await this.client.request({
|
|
897
|
+
method: "POST",
|
|
898
|
+
endpoint: `/api/v3/record/${objectTypeStr}/batch/update`,
|
|
899
|
+
body: { data: batch },
|
|
900
|
+
signal: options?.signal
|
|
901
|
+
});
|
|
902
|
+
if (response.data) {
|
|
903
|
+
if (Array.isArray(response.data)) {
|
|
904
|
+
allResponses.push(...response.data);
|
|
905
|
+
} else {
|
|
906
|
+
allResponses.push(response.data);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return {
|
|
911
|
+
success: true,
|
|
912
|
+
data: allResponses,
|
|
913
|
+
count: allResponses.length
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Deletes multiple records in batch
|
|
918
|
+
* Automatically chunks into batches of 20 records
|
|
919
|
+
*
|
|
920
|
+
* @param objectType - The object type ID
|
|
921
|
+
* @param recordIds - Array of record IDs to delete
|
|
922
|
+
* @param options - Optional settings
|
|
923
|
+
* @returns Batch delete result with deleted IDs
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```typescript
|
|
927
|
+
* const result = await client.batch.delete('1', ['abc123', 'def456']);
|
|
928
|
+
* console.log(result.ids); // ['abc123', 'def456']
|
|
929
|
+
* ```
|
|
930
|
+
*/
|
|
931
|
+
async delete(objectType, recordIds, options) {
|
|
932
|
+
const objectTypeStr = String(objectType);
|
|
933
|
+
const batches = chunkArray(recordIds, BATCH_SIZE);
|
|
934
|
+
const allDeletedIds = [];
|
|
935
|
+
for (const batch of batches) {
|
|
936
|
+
if (options?.signal?.aborted) {
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
await this.client.request({
|
|
940
|
+
method: "POST",
|
|
941
|
+
endpoint: `/api/v3/record/${objectTypeStr}/batch/delete`,
|
|
942
|
+
body: { data: batch },
|
|
943
|
+
signal: options?.signal
|
|
944
|
+
});
|
|
945
|
+
allDeletedIds.push(...batch);
|
|
946
|
+
}
|
|
947
|
+
return {
|
|
948
|
+
success: true,
|
|
949
|
+
ids: allDeletedIds,
|
|
950
|
+
count: allDeletedIds.length
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
// src/api/fields.ts
|
|
956
|
+
var FIELD_TYPE_ENDPOINTS = {
|
|
957
|
+
text: "text",
|
|
958
|
+
email: "email",
|
|
959
|
+
url: "url",
|
|
960
|
+
phone: "phone",
|
|
961
|
+
number: "number",
|
|
962
|
+
textarea: "textarea",
|
|
963
|
+
html: "html",
|
|
964
|
+
date: "date",
|
|
965
|
+
datetime: "datetime",
|
|
966
|
+
lookup: "lookup",
|
|
967
|
+
summary: "summary",
|
|
968
|
+
formula: "formula",
|
|
969
|
+
picklist: "picklist"
|
|
970
|
+
};
|
|
971
|
+
var FieldsAPI = class {
|
|
972
|
+
constructor(client) {
|
|
973
|
+
this.client = client;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Creates a new custom field in a Fireberry object
|
|
977
|
+
*
|
|
978
|
+
* @param objectType - The object type ID
|
|
979
|
+
* @param options - Field creation options
|
|
980
|
+
* @returns Created field result
|
|
981
|
+
*
|
|
982
|
+
* @example
|
|
983
|
+
* ```typescript
|
|
984
|
+
* // Create a text field
|
|
985
|
+
* const result = await client.fields.create('1', {
|
|
986
|
+
* type: 'text',
|
|
987
|
+
* fieldName: 'pcf_custom_field',
|
|
988
|
+
* label: 'Custom Field',
|
|
989
|
+
* maxLength: 100,
|
|
990
|
+
* });
|
|
991
|
+
*
|
|
992
|
+
* // Create a picklist field
|
|
993
|
+
* const result = await client.fields.create('1', {
|
|
994
|
+
* type: 'picklist',
|
|
995
|
+
* fieldName: 'pcf_status',
|
|
996
|
+
* label: 'Status',
|
|
997
|
+
* values: [
|
|
998
|
+
* { name: 'Active', value: '1' },
|
|
999
|
+
* { name: 'Inactive', value: '2' },
|
|
1000
|
+
* ],
|
|
1001
|
+
* });
|
|
1002
|
+
*
|
|
1003
|
+
* // Create a lookup field
|
|
1004
|
+
* const result = await client.fields.create('2', {
|
|
1005
|
+
* type: 'lookup',
|
|
1006
|
+
* fieldName: 'pcf_related_account',
|
|
1007
|
+
* label: 'Related Account',
|
|
1008
|
+
* relatedObjectId: '1',
|
|
1009
|
+
* });
|
|
1010
|
+
* ```
|
|
1011
|
+
*/
|
|
1012
|
+
async create(objectType, options) {
|
|
1013
|
+
const objectTypeStr = String(objectType);
|
|
1014
|
+
const { type, fieldName, label, defaultValue, follow, autoComplete } = options;
|
|
1015
|
+
const fieldData = {
|
|
1016
|
+
fieldName,
|
|
1017
|
+
label
|
|
1018
|
+
};
|
|
1019
|
+
if (defaultValue !== void 0) {
|
|
1020
|
+
fieldData.defaultValue = defaultValue;
|
|
1021
|
+
}
|
|
1022
|
+
if (follow !== void 0) {
|
|
1023
|
+
fieldData.follow = follow;
|
|
1024
|
+
}
|
|
1025
|
+
if (autoComplete !== void 0 && ["text", "email", "url", "phone", "number"].includes(type)) {
|
|
1026
|
+
fieldData.autoComplete = autoComplete;
|
|
1027
|
+
}
|
|
1028
|
+
switch (type) {
|
|
1029
|
+
case "text":
|
|
1030
|
+
case "email":
|
|
1031
|
+
case "url": {
|
|
1032
|
+
const opts = options;
|
|
1033
|
+
if (opts.maxLength !== void 0 && opts.maxLength > 0) {
|
|
1034
|
+
fieldData.maxLength = opts.maxLength;
|
|
1035
|
+
}
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
case "number": {
|
|
1039
|
+
const opts = options;
|
|
1040
|
+
if (opts.precision !== void 0) {
|
|
1041
|
+
fieldData.precision = opts.precision;
|
|
1042
|
+
}
|
|
1043
|
+
break;
|
|
1044
|
+
}
|
|
1045
|
+
case "lookup": {
|
|
1046
|
+
const opts = options;
|
|
1047
|
+
fieldData.relatedObjectId = opts.relatedObjectId;
|
|
1048
|
+
break;
|
|
1049
|
+
}
|
|
1050
|
+
case "picklist": {
|
|
1051
|
+
const opts = options;
|
|
1052
|
+
fieldData.values = opts.values;
|
|
1053
|
+
break;
|
|
1054
|
+
}
|
|
1055
|
+
case "summary": {
|
|
1056
|
+
const opts = options;
|
|
1057
|
+
fieldData.summaryType = opts.summaryType;
|
|
1058
|
+
fieldData.relatedObjectId = opts.relatedObjectId;
|
|
1059
|
+
if (opts.summaryField) {
|
|
1060
|
+
fieldData.summaryField = opts.summaryField;
|
|
1061
|
+
}
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1064
|
+
case "formula": {
|
|
1065
|
+
const opts = options;
|
|
1066
|
+
fieldData.formula = opts.formula;
|
|
1067
|
+
fieldData.fieldType = opts.formulaFieldType;
|
|
1068
|
+
if (opts.formulaFieldType === "number" && opts.formulaPrecision !== void 0) {
|
|
1069
|
+
fieldData.precision = opts.formulaPrecision;
|
|
1070
|
+
}
|
|
1071
|
+
break;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
const endpoint = FIELD_TYPE_ENDPOINTS[type];
|
|
1075
|
+
if (!endpoint) {
|
|
1076
|
+
throw new Error(`Unsupported field type: ${type}`);
|
|
1077
|
+
}
|
|
1078
|
+
const response = await this.client.request({
|
|
1079
|
+
method: "POST",
|
|
1080
|
+
endpoint: `/api/v2/system-field/${objectTypeStr}/${endpoint}`,
|
|
1081
|
+
body: fieldData
|
|
1082
|
+
});
|
|
1083
|
+
return {
|
|
1084
|
+
objectTypeId: objectTypeStr,
|
|
1085
|
+
fieldType: type,
|
|
1086
|
+
fieldData: response,
|
|
1087
|
+
success: true
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
// src/api/files.ts
|
|
1093
|
+
var FilesAPI = class {
|
|
1094
|
+
constructor(client) {
|
|
1095
|
+
this.client = client;
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Uploads a file attachment to a Fireberry record
|
|
1099
|
+
*
|
|
1100
|
+
* @param objectType - The object type ID
|
|
1101
|
+
* @param recordId - The record ID to attach the file to
|
|
1102
|
+
* @param options - File upload options
|
|
1103
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
1104
|
+
* @returns Upload result
|
|
1105
|
+
*
|
|
1106
|
+
* @example
|
|
1107
|
+
* ```typescript
|
|
1108
|
+
* import { readFileSync } from 'fs';
|
|
1109
|
+
*
|
|
1110
|
+
* const fileBuffer = readFileSync('document.pdf');
|
|
1111
|
+
* const result = await client.files.upload('1', 'abc123', {
|
|
1112
|
+
* buffer: fileBuffer,
|
|
1113
|
+
* filename: 'document.pdf',
|
|
1114
|
+
* mimeType: 'application/pdf',
|
|
1115
|
+
* });
|
|
1116
|
+
* ```
|
|
1117
|
+
*/
|
|
1118
|
+
async upload(objectType, recordId, options, signal) {
|
|
1119
|
+
const objectTypeStr = String(objectType);
|
|
1120
|
+
const { buffer, filename, mimeType } = options;
|
|
1121
|
+
const config = this.client.getConfig();
|
|
1122
|
+
const url = `${config.baseUrl}/api/v2/record/${objectTypeStr}/${recordId}/files`;
|
|
1123
|
+
const boundary = `----FormBoundary${Date.now()}`;
|
|
1124
|
+
const formParts = [];
|
|
1125
|
+
const fileHeader = [
|
|
1126
|
+
`--${boundary}`,
|
|
1127
|
+
`Content-Disposition: form-data; name="file"; filename="${filename}"`,
|
|
1128
|
+
`Content-Type: ${mimeType}`,
|
|
1129
|
+
"",
|
|
1130
|
+
""
|
|
1131
|
+
].join("\r\n");
|
|
1132
|
+
formParts.push(Buffer.from(fileHeader));
|
|
1133
|
+
formParts.push(buffer);
|
|
1134
|
+
formParts.push(Buffer.from(`\r
|
|
1135
|
+
--${boundary}--\r
|
|
1136
|
+
`));
|
|
1137
|
+
const body = Buffer.concat(formParts);
|
|
1138
|
+
try {
|
|
1139
|
+
const response = await fetch(url, {
|
|
1140
|
+
method: "POST",
|
|
1141
|
+
headers: {
|
|
1142
|
+
Accept: "application/json",
|
|
1143
|
+
"Content-Type": `multipart/form-data; boundary=${boundary}`,
|
|
1144
|
+
tokenid: config.apiKey
|
|
1145
|
+
},
|
|
1146
|
+
body,
|
|
1147
|
+
signal
|
|
1148
|
+
});
|
|
1149
|
+
if (!response.ok) {
|
|
1150
|
+
throw new FireberryError(`File upload failed: ${response.statusText}`, {
|
|
1151
|
+
code: "INVALID_REQUEST" /* INVALID_REQUEST */,
|
|
1152
|
+
statusCode: response.status
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
const responseData = await response.json();
|
|
1156
|
+
return {
|
|
1157
|
+
success: true,
|
|
1158
|
+
objectType: objectTypeStr,
|
|
1159
|
+
recordId,
|
|
1160
|
+
fileName: filename,
|
|
1161
|
+
mimeType,
|
|
1162
|
+
fileSize: buffer.length,
|
|
1163
|
+
response: responseData
|
|
1164
|
+
};
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
if (error instanceof FireberryError) {
|
|
1167
|
+
throw error;
|
|
1168
|
+
}
|
|
1169
|
+
throw new FireberryError(`File upload failed: ${error.message}`, {
|
|
1170
|
+
code: "NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
1171
|
+
cause: error
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
};
|
|
1176
|
+
|
|
1177
|
+
// src/client.ts
|
|
1178
|
+
var FireberryClient = class {
|
|
1179
|
+
config;
|
|
1180
|
+
cacheStore;
|
|
1181
|
+
/** Metadata API operations */
|
|
1182
|
+
metadata;
|
|
1183
|
+
/** Records CRUD operations */
|
|
1184
|
+
records;
|
|
1185
|
+
/** Batch operations */
|
|
1186
|
+
batch;
|
|
1187
|
+
/** Field management operations */
|
|
1188
|
+
fields;
|
|
1189
|
+
/** File operations */
|
|
1190
|
+
files;
|
|
1191
|
+
/**
|
|
1192
|
+
* Creates a new FireberryClient instance
|
|
1193
|
+
*/
|
|
1194
|
+
constructor(config) {
|
|
1195
|
+
this.config = {
|
|
1196
|
+
apiKey: config.apiKey,
|
|
1197
|
+
baseUrl: config.baseUrl || "https://api.fireberry.com",
|
|
1198
|
+
timeout: config.timeout || 3e4,
|
|
1199
|
+
retryOn429: config.retryOn429 ?? true,
|
|
1200
|
+
maxRetries: config.maxRetries || 120,
|
|
1201
|
+
retryDelay: config.retryDelay || 1e3,
|
|
1202
|
+
cacheMetadata: config.cacheMetadata || false,
|
|
1203
|
+
cacheTTL: config.cacheTTL || 3e5
|
|
1204
|
+
// 5 minutes default
|
|
1205
|
+
};
|
|
1206
|
+
this.cacheStore = {
|
|
1207
|
+
fields: /* @__PURE__ */ new Map(),
|
|
1208
|
+
fieldValues: /* @__PURE__ */ new Map()
|
|
1209
|
+
};
|
|
1210
|
+
this.metadata = new MetadataAPI(this);
|
|
1211
|
+
this.records = new RecordsAPI(this);
|
|
1212
|
+
this.batch = new BatchAPI(this);
|
|
1213
|
+
this.fields = new FieldsAPI(this);
|
|
1214
|
+
this.files = new FilesAPI(this);
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Gets the client configuration
|
|
1218
|
+
*/
|
|
1219
|
+
getConfig() {
|
|
1220
|
+
return this.config;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Cache control methods
|
|
1224
|
+
*/
|
|
1225
|
+
cache = {
|
|
1226
|
+
clear: () => {
|
|
1227
|
+
this.cacheStore.objects = void 0;
|
|
1228
|
+
this.cacheStore.fields.clear();
|
|
1229
|
+
this.cacheStore.fieldValues.clear();
|
|
1230
|
+
},
|
|
1231
|
+
clearObjects: () => {
|
|
1232
|
+
this.cacheStore.objects = void 0;
|
|
1233
|
+
},
|
|
1234
|
+
clearFields: (objectType) => {
|
|
1235
|
+
this.cacheStore.fields.delete(objectType);
|
|
1236
|
+
},
|
|
1237
|
+
clearFieldValues: (objectType, fieldName) => {
|
|
1238
|
+
if (fieldName) {
|
|
1239
|
+
this.cacheStore.fieldValues.delete(`${objectType}:${fieldName}`);
|
|
1240
|
+
} else {
|
|
1241
|
+
for (const key of this.cacheStore.fieldValues.keys()) {
|
|
1242
|
+
if (key.startsWith(`${objectType}:`)) {
|
|
1243
|
+
this.cacheStore.fieldValues.delete(key);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
getCached(type, objectType, fieldName) {
|
|
1250
|
+
if (!this.config.cacheMetadata) {
|
|
1251
|
+
return void 0;
|
|
1252
|
+
}
|
|
1253
|
+
const now = Date.now();
|
|
1254
|
+
if (type === "objects") {
|
|
1255
|
+
const cached = this.cacheStore.objects;
|
|
1256
|
+
if (cached && now - cached.timestamp < this.config.cacheTTL) {
|
|
1257
|
+
return cached.data;
|
|
1258
|
+
}
|
|
1259
|
+
} else if (type === "fields" && objectType) {
|
|
1260
|
+
const cached = this.cacheStore.fields.get(objectType);
|
|
1261
|
+
if (cached && now - cached.timestamp < this.config.cacheTTL) {
|
|
1262
|
+
return cached.data;
|
|
1263
|
+
}
|
|
1264
|
+
} else if (type === "fieldValues" && objectType && fieldName) {
|
|
1265
|
+
const key = `${objectType}:${fieldName}`;
|
|
1266
|
+
const cached = this.cacheStore.fieldValues.get(key);
|
|
1267
|
+
if (cached && now - cached.timestamp < this.config.cacheTTL) {
|
|
1268
|
+
return cached.data;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return void 0;
|
|
1272
|
+
}
|
|
1273
|
+
setCache(type, objectTypeOrData, fieldNameOrData, data) {
|
|
1274
|
+
if (!this.config.cacheMetadata) {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
const now = Date.now();
|
|
1278
|
+
if (type === "objects") {
|
|
1279
|
+
this.cacheStore.objects = { data: objectTypeOrData, timestamp: now };
|
|
1280
|
+
} else if (type === "fields" && typeof objectTypeOrData === "string") {
|
|
1281
|
+
this.cacheStore.fields.set(objectTypeOrData, {
|
|
1282
|
+
data: fieldNameOrData,
|
|
1283
|
+
timestamp: now
|
|
1284
|
+
});
|
|
1285
|
+
} else if (type === "fieldValues" && typeof objectTypeOrData === "string" && typeof fieldNameOrData === "string") {
|
|
1286
|
+
const key = `${objectTypeOrData}:${fieldNameOrData}`;
|
|
1287
|
+
this.cacheStore.fieldValues.set(key, { data, timestamp: now });
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Creates a new QueryBuilder instance
|
|
1292
|
+
*/
|
|
1293
|
+
queryBuilder() {
|
|
1294
|
+
return new QueryBuilder(this);
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Executes a query against the Fireberry API
|
|
1298
|
+
*/
|
|
1299
|
+
async query(options) {
|
|
1300
|
+
const {
|
|
1301
|
+
objectType,
|
|
1302
|
+
fields,
|
|
1303
|
+
query,
|
|
1304
|
+
sortBy = "modifiedon",
|
|
1305
|
+
sortType = "desc",
|
|
1306
|
+
limit,
|
|
1307
|
+
page = 1,
|
|
1308
|
+
pageSize = 500,
|
|
1309
|
+
showRealValue = true,
|
|
1310
|
+
autoPage = true,
|
|
1311
|
+
signal
|
|
1312
|
+
} = options;
|
|
1313
|
+
let fieldsStr;
|
|
1314
|
+
if (Array.isArray(fields)) {
|
|
1315
|
+
fieldsStr = fields.join(",");
|
|
1316
|
+
} else if (typeof fields === "string") {
|
|
1317
|
+
fieldsStr = fields;
|
|
1318
|
+
} else {
|
|
1319
|
+
fieldsStr = "*";
|
|
1320
|
+
}
|
|
1321
|
+
if (fieldsStr === "*") {
|
|
1322
|
+
fieldsStr = await this.expandStarFields(objectType, signal);
|
|
1323
|
+
}
|
|
1324
|
+
if (autoPage) {
|
|
1325
|
+
return this.queryAllPages({
|
|
1326
|
+
objectType,
|
|
1327
|
+
fields: fieldsStr,
|
|
1328
|
+
query,
|
|
1329
|
+
sortBy,
|
|
1330
|
+
sortType,
|
|
1331
|
+
showRealValue,
|
|
1332
|
+
limit,
|
|
1333
|
+
signal
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
const body = {
|
|
1337
|
+
objecttype: objectType,
|
|
1338
|
+
fields: fieldsStr,
|
|
1339
|
+
query: query || "",
|
|
1340
|
+
sort_by: sortBy,
|
|
1341
|
+
sort_type: sortType,
|
|
1342
|
+
page_size: Math.min(pageSize, limit || 500),
|
|
1343
|
+
page_number: page,
|
|
1344
|
+
show_real_value: showRealValue ? 1 : 0
|
|
1345
|
+
};
|
|
1346
|
+
const response = await this.request({
|
|
1347
|
+
method: "POST",
|
|
1348
|
+
endpoint: "/api/query",
|
|
1349
|
+
body,
|
|
1350
|
+
signal
|
|
1351
|
+
});
|
|
1352
|
+
const records = response.data?.Data || [];
|
|
1353
|
+
return {
|
|
1354
|
+
records,
|
|
1355
|
+
total: records.length,
|
|
1356
|
+
success: true
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Fetches all pages of a query
|
|
1361
|
+
*/
|
|
1362
|
+
async queryAllPages(options) {
|
|
1363
|
+
const { objectType, fields, query, sortBy, sortType, showRealValue, limit, signal } = options;
|
|
1364
|
+
const maxPageSize = 500;
|
|
1365
|
+
const allRecords = [];
|
|
1366
|
+
let currentPage = 1;
|
|
1367
|
+
let hasMore = true;
|
|
1368
|
+
while (hasMore) {
|
|
1369
|
+
if (signal?.aborted) {
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
const body = {
|
|
1373
|
+
objecttype: objectType,
|
|
1374
|
+
fields,
|
|
1375
|
+
query: query || "",
|
|
1376
|
+
sort_by: sortBy,
|
|
1377
|
+
sort_type: sortType,
|
|
1378
|
+
page_size: maxPageSize,
|
|
1379
|
+
page_number: currentPage,
|
|
1380
|
+
show_real_value: showRealValue ? 1 : 0
|
|
1381
|
+
};
|
|
1382
|
+
const response = await this.request({
|
|
1383
|
+
method: "POST",
|
|
1384
|
+
endpoint: "/api/query",
|
|
1385
|
+
body,
|
|
1386
|
+
signal
|
|
1387
|
+
});
|
|
1388
|
+
const pageData = response.data?.Data || [];
|
|
1389
|
+
allRecords.push(...pageData);
|
|
1390
|
+
if (limit && allRecords.length >= limit) {
|
|
1391
|
+
allRecords.splice(limit);
|
|
1392
|
+
break;
|
|
1393
|
+
}
|
|
1394
|
+
if (pageData.length < maxPageSize) {
|
|
1395
|
+
hasMore = false;
|
|
1396
|
+
} else {
|
|
1397
|
+
currentPage++;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return {
|
|
1401
|
+
records: allRecords,
|
|
1402
|
+
total: allRecords.length,
|
|
1403
|
+
success: true
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Expands '*' fields to actual field names, excluding problematic fields for specific object types
|
|
1408
|
+
*/
|
|
1409
|
+
async expandStarFields(objectType, signal) {
|
|
1410
|
+
const { getExcludedFieldsForStarQuery: getExcludedFieldsForStarQuery2 } = await Promise.resolve().then(() => (init_excludedFields(), excludedFields_exports));
|
|
1411
|
+
const excludedFields = getExcludedFieldsForStarQuery2(objectType);
|
|
1412
|
+
if (excludedFields.length === 0) {
|
|
1413
|
+
return "*";
|
|
1414
|
+
}
|
|
1415
|
+
const fieldsResult = await this.metadata.getFields(objectType, signal);
|
|
1416
|
+
const allFieldNames = fieldsResult.fields.map((f) => f.fieldName);
|
|
1417
|
+
const filteredFields = allFieldNames.filter(
|
|
1418
|
+
(fieldName) => !excludedFields.includes(fieldName)
|
|
1419
|
+
);
|
|
1420
|
+
return filteredFields.join(",");
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Makes a raw API request to the Fireberry API
|
|
1424
|
+
*/
|
|
1425
|
+
async request(options) {
|
|
1426
|
+
const {
|
|
1427
|
+
method,
|
|
1428
|
+
endpoint,
|
|
1429
|
+
query: queryParams,
|
|
1430
|
+
body,
|
|
1431
|
+
headers: customHeaders,
|
|
1432
|
+
signal
|
|
1433
|
+
} = options;
|
|
1434
|
+
let url = `${this.config.baseUrl}${endpoint}`;
|
|
1435
|
+
if (queryParams && Object.keys(queryParams).length > 0) {
|
|
1436
|
+
const params = new URLSearchParams();
|
|
1437
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
1438
|
+
if (value !== void 0 && value !== null) {
|
|
1439
|
+
params.set(key, String(value));
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
url += `?${params.toString()}`;
|
|
1443
|
+
}
|
|
1444
|
+
const headers = {
|
|
1445
|
+
Accept: "application/json",
|
|
1446
|
+
tokenid: this.config.apiKey,
|
|
1447
|
+
...customHeaders
|
|
1448
|
+
};
|
|
1449
|
+
if (body) {
|
|
1450
|
+
headers["Content-Type"] = "application/json";
|
|
1451
|
+
}
|
|
1452
|
+
const fetchOptions = {
|
|
1453
|
+
method,
|
|
1454
|
+
headers,
|
|
1455
|
+
signal
|
|
1456
|
+
};
|
|
1457
|
+
if (body) {
|
|
1458
|
+
fetchOptions.body = JSON.stringify(body);
|
|
1459
|
+
}
|
|
1460
|
+
return this.executeWithRetry(url, fetchOptions);
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Executes a fetch request with retry logic for 429 errors
|
|
1464
|
+
*/
|
|
1465
|
+
async executeWithRetry(url, options, retryCount = 0) {
|
|
1466
|
+
try {
|
|
1467
|
+
const timeoutController = new AbortController();
|
|
1468
|
+
const timeoutId = setTimeout(() => {
|
|
1469
|
+
timeoutController.abort();
|
|
1470
|
+
}, this.config.timeout);
|
|
1471
|
+
const combinedSignal = options.signal ? this.combineSignals([options.signal, timeoutController.signal]) : timeoutController.signal;
|
|
1472
|
+
const response = await fetch(url, {
|
|
1473
|
+
...options,
|
|
1474
|
+
signal: combinedSignal
|
|
1475
|
+
});
|
|
1476
|
+
clearTimeout(timeoutId);
|
|
1477
|
+
if (response.status === 429 && this.config.retryOn429) {
|
|
1478
|
+
if (retryCount < this.config.maxRetries) {
|
|
1479
|
+
await wait(this.config.retryDelay);
|
|
1480
|
+
return this.executeWithRetry(url, options, retryCount + 1);
|
|
1481
|
+
}
|
|
1482
|
+
throw new FireberryError("Rate limit exceeded after max retries", {
|
|
1483
|
+
code: "RATE_LIMITED" /* RATE_LIMITED */,
|
|
1484
|
+
statusCode: 429,
|
|
1485
|
+
context: { retryCount }
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
let body;
|
|
1489
|
+
const contentType = response.headers.get("content-type");
|
|
1490
|
+
if (contentType?.includes("application/json")) {
|
|
1491
|
+
body = await response.json();
|
|
1492
|
+
} else {
|
|
1493
|
+
body = await response.text();
|
|
1494
|
+
}
|
|
1495
|
+
if (!response.ok) {
|
|
1496
|
+
throw createErrorFromResponse(response, body);
|
|
1497
|
+
}
|
|
1498
|
+
return body;
|
|
1499
|
+
} catch (error) {
|
|
1500
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1501
|
+
throw createNetworkError(error);
|
|
1502
|
+
}
|
|
1503
|
+
if (error instanceof FireberryError) {
|
|
1504
|
+
throw error;
|
|
1505
|
+
}
|
|
1506
|
+
throw createNetworkError(error);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Combines multiple abort signals into one
|
|
1511
|
+
*/
|
|
1512
|
+
combineSignals(signals) {
|
|
1513
|
+
const controller = new AbortController();
|
|
1514
|
+
for (const signal of signals) {
|
|
1515
|
+
if (signal.aborted) {
|
|
1516
|
+
controller.abort();
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
1520
|
+
}
|
|
1521
|
+
return controller.signal;
|
|
1522
|
+
}
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
// src/constants/objectNames.ts
|
|
1526
|
+
var OBJECT_NAME_MAP = {
|
|
1527
|
+
1: "accountname",
|
|
1528
|
+
// Account
|
|
1529
|
+
2: "fullname",
|
|
1530
|
+
// Contact
|
|
1531
|
+
3: "fullname",
|
|
1532
|
+
// Lead
|
|
1533
|
+
4: "name",
|
|
1534
|
+
// Opportunity
|
|
1535
|
+
5: "title",
|
|
1536
|
+
// Case
|
|
1537
|
+
6: "subject",
|
|
1538
|
+
// Activity
|
|
1539
|
+
7: "subject",
|
|
1540
|
+
// Note
|
|
1541
|
+
8: "name",
|
|
1542
|
+
// Competitor
|
|
1543
|
+
9: "fullname",
|
|
1544
|
+
// CRM User
|
|
1545
|
+
10: "subject",
|
|
1546
|
+
// Task
|
|
1547
|
+
13: "name",
|
|
1548
|
+
// CRM Order
|
|
1549
|
+
14: "productname",
|
|
1550
|
+
// Product
|
|
1551
|
+
17: "productname",
|
|
1552
|
+
// CRM Order Item
|
|
1553
|
+
20: "name",
|
|
1554
|
+
// Email Template
|
|
1555
|
+
23: "name",
|
|
1556
|
+
// Business Unit
|
|
1557
|
+
27: "name",
|
|
1558
|
+
// Print Template
|
|
1559
|
+
28: "name",
|
|
1560
|
+
// Contract
|
|
1561
|
+
33: "productname",
|
|
1562
|
+
// Account Product
|
|
1563
|
+
46: "name",
|
|
1564
|
+
// Project
|
|
1565
|
+
67: "name",
|
|
1566
|
+
// Campaign
|
|
1567
|
+
76: "title",
|
|
1568
|
+
// Article
|
|
1569
|
+
86: "name",
|
|
1570
|
+
// Invoice
|
|
1571
|
+
101: "name",
|
|
1572
|
+
// Attendance Clock
|
|
1573
|
+
102: "subject",
|
|
1574
|
+
// Activity Log
|
|
1575
|
+
104: "subject",
|
|
1576
|
+
// Conversation
|
|
1577
|
+
114: "name"
|
|
1578
|
+
// Calendar Resource
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
// src/constants/index.ts
|
|
1582
|
+
init_excludedFields();
|
|
1583
|
+
|
|
1584
|
+
export { EXCLUDED_FIELDS_FOR_STAR_QUERY, FIELD_TYPE_IDS, FIELD_TYPE_MAPPINGS, FireberryClient, FireberryError, FireberryErrorCode, OBJECT_ID_MAP, OBJECT_NAME_MAP, QueryBuilder, escapeQueryValue, sanitizeQuery };
|
|
1585
|
+
//# sourceMappingURL=index.js.map
|
|
1586
|
+
//# sourceMappingURL=index.js.map
|