@unboundcx/sdk 4.5.0 → 4.6.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 +75 -0
- package/index.js +4 -0
- package/package.json +4 -1
- package/schemas/workflows/capabilities.js +57 -0
- package/schemas/workflows/editEntry.js +59 -0
- package/schemas/workflows/index.js +9 -0
- package/schemas/workflows/layout.js +61 -0
- package/schemas/workflows/lint.js +89 -0
- package/schemas/workflows/moduleSpec.js +87 -0
- package/schemas/workflows/port.js +22 -0
- package/schemas/workflows/primitives.js +44 -0
- package/schemas/workflows/settingsSchema.js +30 -0
- package/schemas/workflows/validate.js +18 -0
- package/services/documents.js +276 -0
- package/services/externalOAuth.js +22 -0
- package/services/fax.js +11 -1
- package/services/objects.js +151 -14
- package/services/permissions.js +111 -0
- package/services/storage.js +2 -2
- package/services/triggers.js +245 -0
- package/test-complete-coverage.js +1 -0
package/services/permissions.js
CHANGED
|
@@ -374,4 +374,115 @@ export class PermissionsService {
|
|
|
374
374
|
const result = await this.sdk._fetch('/permissions/scope-catalog', 'GET');
|
|
375
375
|
return result;
|
|
376
376
|
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Catalog of group-settable configuration keys, plus the never-settable list.
|
|
380
|
+
* @returns {Promise<Object>} { groupSettable: [{key,label,type,pillar,...}], neverSettable: [] }
|
|
381
|
+
*/
|
|
382
|
+
async getSettingsCatalog() {
|
|
383
|
+
return this.sdk._fetch('/permissions/settings/catalog', 'GET');
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Configuration values set at group level.
|
|
388
|
+
* @param {string|number} groupId - Group ID (required)
|
|
389
|
+
* @returns {Promise<Object>} { results: [{settingKey, value, updatedAt}] }
|
|
390
|
+
*/
|
|
391
|
+
async listGroupSettings(groupId) {
|
|
392
|
+
groupId = String(groupId);
|
|
393
|
+
this.sdk.validateParams({ groupId }, { groupId: { type: 'string', required: true } });
|
|
394
|
+
return this.sdk._fetch(`/permissions/groups/${groupId}/settings`, 'GET');
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Set one configuration value on a group. */
|
|
398
|
+
async setGroupSetting(groupId, settingKey, value) {
|
|
399
|
+
groupId = String(groupId);
|
|
400
|
+
settingKey = String(settingKey);
|
|
401
|
+
this.sdk.validateParams(
|
|
402
|
+
{ groupId, settingKey },
|
|
403
|
+
{
|
|
404
|
+
groupId: { type: 'string', required: true },
|
|
405
|
+
settingKey: { type: 'string', required: true },
|
|
406
|
+
},
|
|
407
|
+
);
|
|
408
|
+
return this.sdk._fetch(
|
|
409
|
+
`/permissions/groups/${groupId}/settings/${settingKey}`,
|
|
410
|
+
'PUT',
|
|
411
|
+
{ value },
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Unset one configuration value on a group (members revert to the next tier). */
|
|
416
|
+
async deleteGroupSetting(groupId, settingKey) {
|
|
417
|
+
groupId = String(groupId);
|
|
418
|
+
settingKey = String(settingKey);
|
|
419
|
+
this.sdk.validateParams(
|
|
420
|
+
{ groupId, settingKey },
|
|
421
|
+
{
|
|
422
|
+
groupId: { type: 'string', required: true },
|
|
423
|
+
settingKey: { type: 'string', required: true },
|
|
424
|
+
},
|
|
425
|
+
);
|
|
426
|
+
return this.sdk._fetch(
|
|
427
|
+
`/permissions/groups/${groupId}/settings/${settingKey}`,
|
|
428
|
+
'DELETE',
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Rank groups for same-key conflict resolution; first entry wins.
|
|
434
|
+
* @param {Array<string|number>} order - Group IDs, highest priority first
|
|
435
|
+
*/
|
|
436
|
+
async setGroupPriority(order) {
|
|
437
|
+
this.sdk.validateParams({ order }, { order: { type: 'array', required: true } });
|
|
438
|
+
return this.sdk._fetch('/permissions/groups/priority', 'PUT', {
|
|
439
|
+
order: order.map(String),
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Resolved configuration for a user: value, where it came from, and any
|
|
445
|
+
* losing group values for the same key.
|
|
446
|
+
* @returns {Promise<Object>} { [key]: { value, source: {tier, groupId, groupName}, conflicts: [] } }
|
|
447
|
+
*/
|
|
448
|
+
async getUserSettings(userId) {
|
|
449
|
+
userId = String(userId);
|
|
450
|
+
this.sdk.validateParams({ userId }, { userId: { type: 'string', required: true } });
|
|
451
|
+
return this.sdk._fetch(`/permissions/users/${userId}/settings`, 'GET');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/** Override one configuration value for a single user. */
|
|
455
|
+
async setUserSetting(userId, settingKey, value) {
|
|
456
|
+
userId = String(userId);
|
|
457
|
+
settingKey = String(settingKey);
|
|
458
|
+
this.sdk.validateParams(
|
|
459
|
+
{ userId, settingKey },
|
|
460
|
+
{
|
|
461
|
+
userId: { type: 'string', required: true },
|
|
462
|
+
settingKey: { type: 'string', required: true },
|
|
463
|
+
},
|
|
464
|
+
);
|
|
465
|
+
return this.sdk._fetch(
|
|
466
|
+
`/permissions/users/${userId}/settings/${settingKey}`,
|
|
467
|
+
'PUT',
|
|
468
|
+
{ value },
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/** Clear a user's override, reverting to the inherited value. */
|
|
473
|
+
async deleteUserSetting(userId, settingKey) {
|
|
474
|
+
userId = String(userId);
|
|
475
|
+
settingKey = String(settingKey);
|
|
476
|
+
this.sdk.validateParams(
|
|
477
|
+
{ userId, settingKey },
|
|
478
|
+
{
|
|
479
|
+
userId: { type: 'string', required: true },
|
|
480
|
+
settingKey: { type: 'string', required: true },
|
|
481
|
+
},
|
|
482
|
+
);
|
|
483
|
+
return this.sdk._fetch(
|
|
484
|
+
`/permissions/users/${userId}/settings/${settingKey}`,
|
|
485
|
+
'DELETE',
|
|
486
|
+
);
|
|
487
|
+
}
|
|
377
488
|
}
|
package/services/storage.js
CHANGED
|
@@ -463,7 +463,7 @@ Response:
|
|
|
463
463
|
* @param {string} [config.convertTo] - Convert uploaded file to this format before storing. Supported: 'pdf', 'tiff'. Input must be PDF, DOC, or DOCX.
|
|
464
464
|
* @param {Object} [config.convertOptions] - Options for file conversion (used with convertTo)
|
|
465
465
|
* @param {('fine'|'normal')} [config.convertOptions.resolution='fine'] - Fax resolution: 'fine' (204x196) or 'normal' (204x98)
|
|
466
|
-
* @param {('letter'|'a4')} [config.convertOptions.paperSize='letter'] - Paper size for conversion
|
|
466
|
+
* @param {('letter'|'legal'|'a4')} [config.convertOptions.paperSize='letter'] - Paper size for conversion
|
|
467
467
|
* @param {('g4'|'g3')} [config.convertOptions.compression='g4'] - TIFF compression: 'g4' (default) or 'g3' for older fax machines
|
|
468
468
|
* @param {Function} [config.onProgress] - Progress callback for browser uploads
|
|
469
469
|
* @param {Object} [config._options] - Internal options
|
|
@@ -1005,7 +1005,7 @@ Response:
|
|
|
1005
1005
|
* @param {string} config.convertTo - Target format: 'pdf' or 'tiff' (required)
|
|
1006
1006
|
* @param {Object} [config.convertOptions] - Options controlling the conversion output
|
|
1007
1007
|
* @param {('fine'|'normal')} [config.convertOptions.resolution='fine'] - Fax resolution: 'fine' (204x196 DPI) or 'normal' (204x98 DPI)
|
|
1008
|
-
* @param {('letter'|'a4')} [config.convertOptions.paperSize='letter'] - Paper size for conversion
|
|
1008
|
+
* @param {('letter'|'legal'|'a4')} [config.convertOptions.paperSize='letter'] - Paper size for conversion
|
|
1009
1009
|
* @param {('g4'|'g3')} [config.convertOptions.compression='g4'] - TIFF compression: 'g4' (modern, default) or 'g3' (legacy fax machines)
|
|
1010
1010
|
* @param {string} [config.classification] - Storage classification for the new file. Defaults to source file's classification.
|
|
1011
1011
|
* @param {string} [config.folder] - Folder path for the new file. Defaults to source file's folder.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Triggers Service — object-change automations (workflow or outbound webhook).
|
|
3
|
+
*
|
|
4
|
+
* Watch create/update/delete on a trigger-enabled object, filter on the
|
|
5
|
+
* current row and/or the field that changed, then run a workflow session
|
|
6
|
+
* or POST to a URL.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const { results } = await sdk.triggers.list({ objectName: 'people' });
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* await sdk.triggers.create({
|
|
13
|
+
* name: 'Hot lead',
|
|
14
|
+
* objectName: 'people',
|
|
15
|
+
* actions: ['update'],
|
|
16
|
+
* recordFilter: { type: { op: 'eq', value: 'lead' } },
|
|
17
|
+
* changeFilters: [{
|
|
18
|
+
* field: 'leadScore',
|
|
19
|
+
* previous: { op: 'lt', value: 20 },
|
|
20
|
+
* updated: { op: 'gt', value: 100 },
|
|
21
|
+
* }],
|
|
22
|
+
* actionType: 'workflow',
|
|
23
|
+
* actionConfig: { workflowVersionId: '052…' },
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
export class TriggersService {
|
|
27
|
+
constructor(sdk) {
|
|
28
|
+
this.sdk = sdk;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* List objects that may have triggers (`objectMetaData.triggersEnabled`).
|
|
33
|
+
*
|
|
34
|
+
* @returns {Promise<{results: Array<{id: string, name: string}>}>}
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const { results } = await sdk.triggers.listObjects();
|
|
38
|
+
*/
|
|
39
|
+
async listObjects() {
|
|
40
|
+
return this.sdk._fetch('/triggers/objects', 'GET', {});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* List triggers for the account.
|
|
45
|
+
*
|
|
46
|
+
* @param {object} [args]
|
|
47
|
+
* @param {string} [args.objectName] - Filter to one object (e.g. `'people'`)
|
|
48
|
+
* @param {('enabled'|'paused'|'disabled')} [args.status]
|
|
49
|
+
* @param {number} [args.limit=200]
|
|
50
|
+
* @returns {Promise<{results: object[]}>}
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* await sdk.triggers.list({ objectName: 'people', status: 'enabled' });
|
|
54
|
+
*/
|
|
55
|
+
async list({ objectName, status, limit } = {}) {
|
|
56
|
+
const query = {};
|
|
57
|
+
if (objectName) query.objectName = objectName;
|
|
58
|
+
if (status) query.status = status;
|
|
59
|
+
if (limit) query.limit = limit;
|
|
60
|
+
return this.sdk._fetch('/triggers/', 'GET', { query });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get a trigger by id.
|
|
65
|
+
*
|
|
66
|
+
* @param {string} id
|
|
67
|
+
* @returns {Promise<object>}
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const trigger = await sdk.triggers.get('173…');
|
|
71
|
+
*/
|
|
72
|
+
async get(id) {
|
|
73
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
74
|
+
return this.sdk._fetch(`/triggers/${id}`, 'GET', {});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Create a trigger.
|
|
79
|
+
*
|
|
80
|
+
* @param {object} args
|
|
81
|
+
* @param {string} args.name
|
|
82
|
+
* @param {string} [args.description]
|
|
83
|
+
* @param {string} args.objectName - Must have `triggersEnabled` (people, company, opportunities, projects, or custom `__c`)
|
|
84
|
+
* @param {Array<'create'|'update'|'delete'>} args.actions
|
|
85
|
+
* @param {('enabled'|'paused'|'disabled')} [args.status='enabled']
|
|
86
|
+
* @param {Object<string, {op: string, value: *}|*>} [args.recordFilter] - Current-row match (new row on create/update, old on delete)
|
|
87
|
+
* @param {Array<{field: string, previous?: {op: string, value: *}, updated?: {op: string, value: *}}>} [args.changeFilters] - Field must be in `changedFields`; optional previous/updated checks
|
|
88
|
+
* @param {('workflow'|'webhook')} args.actionType
|
|
89
|
+
* @param {object} args.actionConfig
|
|
90
|
+
* @param {string} [args.actionConfig.workflowVersionId] - Required when `actionType` is `'workflow'`
|
|
91
|
+
* @param {string} [args.actionConfig.workflowId]
|
|
92
|
+
* @param {string[]} [args.actionConfig.includeValues] - Field values to include (previous + updated). Empty = names only. `['*']` = every non-encrypted field. Encrypted columns are never sent.
|
|
93
|
+
* @param {string} [args.actionConfig.primaryUrl] - Required when `actionType` is `'webhook'`; must be `https://`
|
|
94
|
+
* @param {string} [args.actionConfig.secondaryUrl] - Failover URL; must be `https://` if set
|
|
95
|
+
* @param {string} [args.actionConfig.credentialId] - Stored webhook authorization id
|
|
96
|
+
* @param {number} [args.timeoutMinutes=15] - Queued-fire TTL, 1–1440
|
|
97
|
+
* @param {number} [args.retries=3] - Webhook retries, 0–5
|
|
98
|
+
* @returns {Promise<object>} Created trigger
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* await sdk.triggers.create({
|
|
102
|
+
* name: 'Notify CRM',
|
|
103
|
+
* objectName: 'people',
|
|
104
|
+
* actions: ['update'],
|
|
105
|
+
* actionType: 'webhook',
|
|
106
|
+
* actionConfig: {
|
|
107
|
+
* primaryUrl: 'https://example.com/hooks/lead',
|
|
108
|
+
* secondaryUrl: 'https://backup.example.com/hooks/lead',
|
|
109
|
+
* includeValues: ['leadScore', 'email'],
|
|
110
|
+
* },
|
|
111
|
+
* timeoutMinutes: 15,
|
|
112
|
+
* retries: 3,
|
|
113
|
+
* });
|
|
114
|
+
*/
|
|
115
|
+
async create({
|
|
116
|
+
name,
|
|
117
|
+
description,
|
|
118
|
+
objectName,
|
|
119
|
+
actions,
|
|
120
|
+
status,
|
|
121
|
+
recordFilter,
|
|
122
|
+
changeFilters,
|
|
123
|
+
actionType,
|
|
124
|
+
actionConfig,
|
|
125
|
+
timeoutMinutes,
|
|
126
|
+
retries,
|
|
127
|
+
recordTypeId,
|
|
128
|
+
}) {
|
|
129
|
+
const body = {
|
|
130
|
+
name,
|
|
131
|
+
description,
|
|
132
|
+
objectName,
|
|
133
|
+
actions,
|
|
134
|
+
status,
|
|
135
|
+
recordFilter,
|
|
136
|
+
changeFilters,
|
|
137
|
+
actionType,
|
|
138
|
+
actionConfig,
|
|
139
|
+
timeoutMinutes,
|
|
140
|
+
retries,
|
|
141
|
+
recordTypeId,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
this.sdk.validateParams(
|
|
145
|
+
{ name, objectName, actions, actionType, actionConfig },
|
|
146
|
+
{
|
|
147
|
+
name: { type: 'string', required: true },
|
|
148
|
+
objectName: { type: 'string', required: true },
|
|
149
|
+
actions: { type: 'object', required: true },
|
|
150
|
+
actionType: { type: 'string', required: true },
|
|
151
|
+
actionConfig: { type: 'object', required: true },
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
return this.sdk._fetch('/triggers/', 'POST', { body });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Update a trigger. Only provided fields are changed.
|
|
160
|
+
*
|
|
161
|
+
* @param {string} id
|
|
162
|
+
* @param {object} args - Same shape as {@link TriggersService#create}; all keys optional
|
|
163
|
+
* @returns {Promise<object>} Updated trigger
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* await sdk.triggers.update('173…', { status: 'paused' });
|
|
167
|
+
*/
|
|
168
|
+
async update(id, args = {}) {
|
|
169
|
+
this.sdk.validateParams(
|
|
170
|
+
{ id, args },
|
|
171
|
+
{
|
|
172
|
+
id: { type: 'string', required: true },
|
|
173
|
+
args: { type: 'object', required: true },
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
return this.sdk._fetch(`/triggers/${id}`, 'PUT', { body: args });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Soft-delete a trigger.
|
|
181
|
+
*
|
|
182
|
+
* @param {string} id
|
|
183
|
+
* @returns {Promise<{id: string, deleted: boolean}>}
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* await sdk.triggers.delete('173…');
|
|
187
|
+
*/
|
|
188
|
+
async delete(id) {
|
|
189
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
190
|
+
return this.sdk._fetch(`/triggers/${id}`, 'DELETE', {});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Alias of {@link TriggersService#delete}.
|
|
195
|
+
*
|
|
196
|
+
* @param {string} id
|
|
197
|
+
* @returns {Promise<{id: string, deleted: boolean}>}
|
|
198
|
+
*/
|
|
199
|
+
async remove(id) {
|
|
200
|
+
return this.delete(id);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Set trigger status without a full update.
|
|
205
|
+
*
|
|
206
|
+
* @param {string} id
|
|
207
|
+
* @param {('enabled'|'paused'|'disabled')} status
|
|
208
|
+
* @param {object} [opts]
|
|
209
|
+
* @param {string} [opts.pausedReason] - Stored when `status` is `'paused'`
|
|
210
|
+
* @returns {Promise<object>} Updated trigger
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* await sdk.triggers.setStatus('173…', 'paused', { pausedReason: 'rate limit' });
|
|
214
|
+
*/
|
|
215
|
+
async setStatus(id, status, { pausedReason } = {}) {
|
|
216
|
+
this.sdk.validateParams(
|
|
217
|
+
{ id, status },
|
|
218
|
+
{
|
|
219
|
+
id: { type: 'string', required: true },
|
|
220
|
+
status: { type: 'string', required: true },
|
|
221
|
+
},
|
|
222
|
+
);
|
|
223
|
+
return this.sdk._fetch(`/triggers/${id}/status`, 'POST', {
|
|
224
|
+
body: { status, pausedReason },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Recent execution log for a trigger (queued / fired / dropped / rejected / timeout).
|
|
230
|
+
*
|
|
231
|
+
* @param {string} id
|
|
232
|
+
* @param {object} [opts]
|
|
233
|
+
* @param {number} [opts.limit=50]
|
|
234
|
+
* @returns {Promise<{results: object[]}>}
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* const { results } = await sdk.triggers.listFires('173…', { limit: 20 });
|
|
238
|
+
*/
|
|
239
|
+
async listFires(id, { limit } = {}) {
|
|
240
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
241
|
+
const query = {};
|
|
242
|
+
if (limit) query.limit = limit;
|
|
243
|
+
return this.sdk._fetch(`/triggers/${id}/fires`, 'GET', { query });
|
|
244
|
+
}
|
|
245
|
+
}
|