@halix/action-sdk 1.0.17 → 1.0.19
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 +40 -14
- package/lib/cjs/index.js +284 -187
- package/lib/cjs/types/index.d.ts +249 -205
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/index.mjs +269 -177
- package/lib/esm/types/index.d.ts +249 -205
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -39,29 +39,29 @@ export const handler = async (event) => {
|
|
|
39
39
|
// Refresh the object from the server
|
|
40
40
|
let fullObj;
|
|
41
41
|
try {
|
|
42
|
-
fullObj = await hx.getObject(
|
|
42
|
+
fullObj = await hx.getObject('exampleType', obj.objKey);
|
|
43
43
|
} catch (err) {
|
|
44
|
-
console.error(
|
|
45
|
-
return hx.prepareErrorResponse(
|
|
44
|
+
console.error('Error fetching object', err);
|
|
45
|
+
return hx.prepareErrorResponse('Failed to retrieve data');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// Perform updates or logic
|
|
49
|
-
fullObj.status =
|
|
49
|
+
fullObj.status = 'Updated';
|
|
50
50
|
|
|
51
51
|
// Save the updated object
|
|
52
52
|
let saved;
|
|
53
53
|
try {
|
|
54
|
-
saved = await hx.saveRelatedObject(
|
|
54
|
+
saved = await hx.saveRelatedObject('parentType', fullObj.parentKey, 'exampleType', fullObj);
|
|
55
55
|
} catch (err) {
|
|
56
|
-
console.error(
|
|
57
|
-
return hx.prepareErrorResponse(
|
|
56
|
+
console.error('Error saving object', err);
|
|
57
|
+
return hx.prepareErrorResponse('Failed to save data');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Return a success response
|
|
61
61
|
return hx.prepareSuccessResponse({
|
|
62
|
-
responseType:
|
|
62
|
+
responseType: 'formTemplateAction',
|
|
63
63
|
updatedSubject: saved,
|
|
64
|
-
successMessage:
|
|
64
|
+
successMessage: 'Object saved successfully',
|
|
65
65
|
isError: false
|
|
66
66
|
});
|
|
67
67
|
};
|
|
@@ -86,14 +86,40 @@ This action pattern is typical for use in Halix’s Lambda-style runtime environ
|
|
|
86
86
|
| Function | Description |
|
|
87
87
|
|----------|-------------|
|
|
88
88
|
| `initialize(event)` | Initializes the SDK with event context |
|
|
89
|
-
| `getObject(...)
|
|
90
|
-
| `
|
|
89
|
+
| `getObject(...)` / `getObjectAsObservable(...)` | Retrieve a single object |
|
|
90
|
+
| `getRelatedObjects(...)` / `getRelatedObjectsAsObservable(...)` | Retrieve related objects |
|
|
91
|
+
| `saveRelatedObject(...)` / `saveRelatedObjectAsObservable(...)` | Save objects and relationships |
|
|
92
|
+
| `deleteRelatedObject(...)` / `deleteRelatedObjectAsObservable(...)` | Delete a single related object |
|
|
93
|
+
| `deleteRelatedObjects(...)` / `deleteRelatedObjectsAsObservable(...)` | Delete multiple related objects (uses `keys` query param) |
|
|
91
94
|
| `prepareSuccessResponse(...)` | Create a success response |
|
|
92
95
|
| `prepareErrorResponse(...)` | Create an error response |
|
|
93
|
-
| `sortObjectArray(...)` | Utility to sort object arrays |
|
|
94
|
-
| `getValueFromObject(...)` | Access nested or relationship-based attributes |
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
Notes:
|
|
98
|
+
- Functions that interact with services require `initialize(event)` to have been called; they depend on `userContext`, `sandboxKey`, and `serviceAddress`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📦 Content Resource Helpers
|
|
103
|
+
|
|
104
|
+
These helpers simplify working with content resources and file uploads.
|
|
105
|
+
|
|
106
|
+
| Function | Description |
|
|
107
|
+
|----------|-------------|
|
|
108
|
+
| `getOrCreateResource(...)` / `getOrCreateResourceAsObservable(...)` | Retrieve an existing content resource by key or create a new one |
|
|
109
|
+
| `saveResource(...)` / `saveResourceAsObservable(...)` | Persist a content resource |
|
|
110
|
+
| `sendFileContents(resourceKey, file, publicFlag)` / `sendFileContentsAsObservable(...)` | Upload file contents (multipart/form-data) to a content resource |
|
|
111
|
+
| `createOrUpdateResource(resourceKey?, file, publicFlag, resourceType, tags)` / `createOrUpdateResourceAsObservable(...)` | Create or update a resource and upload the file in one call |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 🧪 Utilities
|
|
116
|
+
|
|
117
|
+
| Function | Description |
|
|
118
|
+
|----------|-------------|
|
|
119
|
+
| `getValueFromObject(object, attribute)` | Access nested or relationship-based attributes |
|
|
120
|
+
| `debounceFn(fn, wait?)` | Debounce utility for throttling calls |
|
|
121
|
+
| `compareValues(a, b, descending, caseInsensitive)` | Utility comparer for sorting |
|
|
122
|
+
| `sortObjectArray(array, sort)` | Utility to sort object arrays |
|
|
97
123
|
|
|
98
124
|
---
|
|
99
125
|
|
package/lib/cjs/index.js
CHANGED
|
@@ -21,18 +21,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.useBody = exports.params = exports.userContext = exports.actionSubject = exports.serviceAddress = exports.sandboxKey = exports.getAuthToken = void 0;
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
24
|
+
exports.initialize = initialize;
|
|
25
|
+
exports.prepareSuccessResponse = prepareSuccessResponse;
|
|
26
|
+
exports.prepareErrorResponse = prepareErrorResponse;
|
|
26
27
|
exports.getObject = getObject;
|
|
27
28
|
exports.getObjectAsObservable = getObjectAsObservable;
|
|
29
|
+
exports.getRelatedObjects = getRelatedObjects;
|
|
30
|
+
exports.getRelatedObjectsAsObservable = getRelatedObjectsAsObservable;
|
|
28
31
|
exports.saveRelatedObject = saveRelatedObject;
|
|
29
32
|
exports.saveRelatedObjectAsObservable = saveRelatedObjectAsObservable;
|
|
30
|
-
exports.
|
|
31
|
-
exports.
|
|
32
|
-
exports.
|
|
33
|
-
exports.
|
|
34
|
-
exports.prepareErrorResponse = prepareErrorResponse;
|
|
35
|
-
exports.initialize = initialize;
|
|
33
|
+
exports.deleteRelatedObject = deleteRelatedObject;
|
|
34
|
+
exports.deleteRelatedObjectAsObservable = deleteRelatedObjectAsObservable;
|
|
35
|
+
exports.deleteRelatedObjects = deleteRelatedObjects;
|
|
36
|
+
exports.deleteRelatedObjectsAsObservable = deleteRelatedObjectsAsObservable;
|
|
36
37
|
exports.getOrCreateResource = getOrCreateResource;
|
|
37
38
|
exports.getOrCreateResourceAsObservable = getOrCreateResourceAsObservable;
|
|
38
39
|
exports.saveResource = saveResource;
|
|
@@ -41,6 +42,9 @@ exports.sendFileContents = sendFileContents;
|
|
|
41
42
|
exports.sendFileContentsAsObservable = sendFileContentsAsObservable;
|
|
42
43
|
exports.createOrUpdateResource = createOrUpdateResource;
|
|
43
44
|
exports.createOrUpdateResourceAsObservable = createOrUpdateResourceAsObservable;
|
|
45
|
+
exports.sortObjectArray = sortObjectArray;
|
|
46
|
+
exports.compareValues = compareValues;
|
|
47
|
+
exports.getValueFromObject = getValueFromObject;
|
|
44
48
|
exports.debounceFn = debounceFn;
|
|
45
49
|
/**
|
|
46
50
|
* @module @halix/action-sdk
|
|
@@ -51,6 +55,115 @@ exports.debounceFn = debounceFn;
|
|
|
51
55
|
*/
|
|
52
56
|
const axios_1 = __importDefault(require("axios"));
|
|
53
57
|
const rxjs_1 = require("rxjs");
|
|
58
|
+
/**
|
|
59
|
+
* initialize initializes the SDK with event data. This should be called at the beginning of the
|
|
60
|
+
* action handler to set up the SDK with incoming information, including context information, input
|
|
61
|
+
* parameters, and authentication information needed to make API requests to the Halix service.
|
|
62
|
+
*
|
|
63
|
+
* @param event - The event object containing authentication and context information
|
|
64
|
+
*/
|
|
65
|
+
function initialize(event) {
|
|
66
|
+
let body = event;
|
|
67
|
+
if (event.body) {
|
|
68
|
+
body = event.body;
|
|
69
|
+
exports.useBody = true;
|
|
70
|
+
}
|
|
71
|
+
if (body) {
|
|
72
|
+
({ sandboxKey: exports.sandboxKey, serviceAddress: exports.serviceAddress, actionSubject: exports.actionSubject, userContext: exports.userContext, params: exports.params } = body);
|
|
73
|
+
if (body.authToken) {
|
|
74
|
+
exports.getAuthToken = () => (0, rxjs_1.of)(body.authToken);
|
|
75
|
+
}
|
|
76
|
+
else if (body.authTokenRetriever) {
|
|
77
|
+
exports.getAuthToken = body.authTokenRetriever;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ================================================================================
|
|
82
|
+
// RESPONSE HELPER FUNCTIONS
|
|
83
|
+
// ================================================================================
|
|
84
|
+
/**
|
|
85
|
+
* prepareSuccessResponse prepares a success response in the appropriate format. The action handler
|
|
86
|
+
* should return an ActionResponse response when the action is successful. If useBody is true, the
|
|
87
|
+
* response will be returned as an object with the HTTP response code and the ActionResponse in the
|
|
88
|
+
* body field. If useBody is false, the ActionResponse will be returned directly.
|
|
89
|
+
*
|
|
90
|
+
* @param successResponse - The value to return
|
|
91
|
+
*
|
|
92
|
+
* @returns Formatted success response; an ActionResponse unless useBody is true
|
|
93
|
+
*/
|
|
94
|
+
function prepareSuccessResponse(successResponse) {
|
|
95
|
+
if (exports.useBody) {
|
|
96
|
+
return {
|
|
97
|
+
statusCode: 200,
|
|
98
|
+
body: JSON.stringify(successResponse)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return successResponse;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* prepareErrorResponse prepares an error response in the appropriate format. The action handler
|
|
105
|
+
* should return an ErrorResponse response when the action is not successful. If useBody is true,
|
|
106
|
+
* the response will be returned as an object with the HTTP response code and the ErrorResponse in
|
|
107
|
+
* the body field. If useBody is false, the ErrorResponse will be returned directly.
|
|
108
|
+
*
|
|
109
|
+
* @param errorMessage - The error message
|
|
110
|
+
*
|
|
111
|
+
* @returns Formatted error response; an ErrorResponse unless useBody is true
|
|
112
|
+
*/
|
|
113
|
+
function prepareErrorResponse(errorMessage) {
|
|
114
|
+
if (exports.useBody) {
|
|
115
|
+
return {
|
|
116
|
+
statusCode: 400,
|
|
117
|
+
body: JSON.stringify({ errorMessage })
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return { errorMessage, responseType: "error" };
|
|
121
|
+
}
|
|
122
|
+
// ================================================================================
|
|
123
|
+
// DATA RETRIEVAL FUNCTIONS
|
|
124
|
+
// ================================================================================
|
|
125
|
+
/**
|
|
126
|
+
* getObject retrieves a single object from the database by its data element ID and key.
|
|
127
|
+
*
|
|
128
|
+
* @param dataElementId - The ID of the data element
|
|
129
|
+
* @param key - The key of the object
|
|
130
|
+
* @param fetchedRelationships - Optional array of relationships to fetch; if provided, the returned
|
|
131
|
+
* object will include the specified related objects as nested objects
|
|
132
|
+
* @returns Promise resolving to the object data
|
|
133
|
+
*/
|
|
134
|
+
function getObject(dataElementId, key, fetchedRelationships) {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
let params;
|
|
137
|
+
if (fetchedRelationships) {
|
|
138
|
+
let p = {};
|
|
139
|
+
if (fetchedRelationships) {
|
|
140
|
+
p.fetchedRelationships = fetchedRelationships.join(",");
|
|
141
|
+
}
|
|
142
|
+
params = new URLSearchParams(p);
|
|
143
|
+
}
|
|
144
|
+
let url = `${exports.serviceAddress}/schema/sandboxes/${exports.sandboxKey}/${dataElementId}/${key}`;
|
|
145
|
+
let authToken = yield (0, rxjs_1.lastValueFrom)((0, exports.getAuthToken)());
|
|
146
|
+
console.log("Sending GET request to " + url + " with token " + authToken);
|
|
147
|
+
let response = yield axios_1.default.get(url, {
|
|
148
|
+
headers: { "Authorization": `Bearer ${authToken}` },
|
|
149
|
+
params: params,
|
|
150
|
+
});
|
|
151
|
+
return response.data;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* getObjectAsObservable retrieves a single object from the database by its data element ID and key.
|
|
156
|
+
*
|
|
157
|
+
* @param dataElementId - The ID of the data element
|
|
158
|
+
* @param key - The key of the object
|
|
159
|
+
* @param fetchedRelationships - Optional array of relationships to fetch; if provided, the returned
|
|
160
|
+
* object will include the specified related objects as nested objects
|
|
161
|
+
*
|
|
162
|
+
* @returns Observable resolving to the object data
|
|
163
|
+
*/
|
|
164
|
+
function getObjectAsObservable(dataElementId, key, fetchedRelationships) {
|
|
165
|
+
return (0, rxjs_1.from)(getObject(dataElementId, key, fetchedRelationships));
|
|
166
|
+
}
|
|
54
167
|
/**
|
|
55
168
|
* getRelatedObjects retrieves an array of objects from the the database. The objects returned are
|
|
56
169
|
* related to a parent through a defined relationship in the schema. In a typical setup, action's
|
|
@@ -123,48 +236,9 @@ function getRelatedObjects(parentElementId, parentKey, elementId, filter, fetche
|
|
|
123
236
|
function getRelatedObjectsAsObservable(parentElementId, parentKey, elementId, filter, fetchedRelationships) {
|
|
124
237
|
return (0, rxjs_1.from)(getRelatedObjects(parentElementId, parentKey, elementId, filter, fetchedRelationships));
|
|
125
238
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* @param dataElementId - The ID of the data element
|
|
130
|
-
* @param key - The key of the object
|
|
131
|
-
* @param fetchedRelationships - Optional array of relationships to fetch; if provided, the returned
|
|
132
|
-
* object will include the specified related objects as nested objects
|
|
133
|
-
* @returns Promise resolving to the object data
|
|
134
|
-
*/
|
|
135
|
-
function getObject(dataElementId, key, fetchedRelationships) {
|
|
136
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
-
let params;
|
|
138
|
-
if (fetchedRelationships) {
|
|
139
|
-
let p = {};
|
|
140
|
-
if (fetchedRelationships) {
|
|
141
|
-
p.fetchedRelationships = fetchedRelationships.join(",");
|
|
142
|
-
}
|
|
143
|
-
params = new URLSearchParams(p);
|
|
144
|
-
}
|
|
145
|
-
let url = `${exports.serviceAddress}/schema/sandboxes/${exports.sandboxKey}/${dataElementId}/${key}`;
|
|
146
|
-
let authToken = yield (0, rxjs_1.lastValueFrom)((0, exports.getAuthToken)());
|
|
147
|
-
console.log("Sending GET request to " + url + " with token " + authToken);
|
|
148
|
-
let response = yield axios_1.default.get(url, {
|
|
149
|
-
headers: { "Authorization": `Bearer ${authToken}` },
|
|
150
|
-
params: params,
|
|
151
|
-
});
|
|
152
|
-
return response.data;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* getObjectAsObservable retrieves a single object from the database by its data element ID and key.
|
|
157
|
-
*
|
|
158
|
-
* @param dataElementId - The ID of the data element
|
|
159
|
-
* @param key - The key of the object
|
|
160
|
-
* @param fetchedRelationships - Optional array of relationships to fetch; if provided, the returned
|
|
161
|
-
* object will include the specified related objects as nested objects
|
|
162
|
-
*
|
|
163
|
-
* @returns Observable resolving to the object data
|
|
164
|
-
*/
|
|
165
|
-
function getObjectAsObservable(dataElementId, key, fetchedRelationships) {
|
|
166
|
-
return (0, rxjs_1.from)(getObject(dataElementId, key, fetchedRelationships));
|
|
167
|
-
}
|
|
239
|
+
// ================================================================================
|
|
240
|
+
// DATA SAVE FUNCTIONS
|
|
241
|
+
// ================================================================================
|
|
168
242
|
/**
|
|
169
243
|
* saveRelatedObject saves a related object to the database. The objectToSave is saved, and its
|
|
170
244
|
* relationship to the parent object is established based on the relationship specified in the
|
|
@@ -217,165 +291,87 @@ function saveRelatedObject(parentElementId, parentKey, elementId, objectToSave,
|
|
|
217
291
|
function saveRelatedObjectAsObservable(parentElementId, parentKey, elementId, objectToSave, opts) {
|
|
218
292
|
return (0, rxjs_1.from)(saveRelatedObject(parentElementId, parentKey, elementId, objectToSave, opts));
|
|
219
293
|
}
|
|
294
|
+
// ================================================================================
|
|
295
|
+
// DATA DELETE FUNCTIONS
|
|
296
|
+
// ================================================================================
|
|
220
297
|
/**
|
|
221
|
-
*
|
|
222
|
-
* attributes. Sorting by nested attributes in the form of a delimited attribute string are
|
|
223
|
-
* supported (e.g., "attribute.nestedAttribute").
|
|
298
|
+
* deleteRelatedObject deletes a single object related to a specific parent.
|
|
224
299
|
*
|
|
225
|
-
* @param
|
|
226
|
-
* @param
|
|
227
|
-
* @
|
|
300
|
+
* @param parentElementId - The ID of the parent element
|
|
301
|
+
* @param parentKey - The key of the parent object
|
|
302
|
+
* @param childElementId - The ID of the child element to delete
|
|
303
|
+
* @param childKey - The key of the child object to delete
|
|
304
|
+
*
|
|
305
|
+
* @returns Promise resolving to true if deletion was successful
|
|
228
306
|
*/
|
|
229
|
-
function
|
|
230
|
-
return
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
let valueA = getValueFromObject(a, s.attributeId);
|
|
234
|
-
let valueB = getValueFromObject(b, s.attributeId);
|
|
235
|
-
comparison = compareValues(valueA, valueB, !!s.descending, !!s.caseInsensitive);
|
|
236
|
-
if (comparison !== 0) {
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
307
|
+
function deleteRelatedObject(parentElementId, parentKey, childElementId, childKey) {
|
|
308
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
309
|
+
if (!exports.userContext) {
|
|
310
|
+
throw new Error("userContext is required but not available; check that the initialize function has been called");
|
|
239
311
|
}
|
|
240
|
-
|
|
312
|
+
let url = `${exports.serviceAddress}/schema/sandboxes/${exports.sandboxKey}/${parentElementId}/${parentKey}/${childElementId}/${childKey}`;
|
|
313
|
+
let authToken = yield (0, rxjs_1.lastValueFrom)((0, exports.getAuthToken)());
|
|
314
|
+
console.log("Sending DELETE request to " + url + " with token " + authToken);
|
|
315
|
+
let response = yield axios_1.default.delete(url, {
|
|
316
|
+
headers: { "Authorization": `Bearer ${authToken}` },
|
|
317
|
+
});
|
|
318
|
+
return response.status === 204;
|
|
241
319
|
});
|
|
242
320
|
}
|
|
243
321
|
/**
|
|
244
|
-
*
|
|
245
|
-
* are strings, the comparison is case-insensitive. If the values are numbers, the comparison is
|
|
246
|
-
* performed numerically.
|
|
322
|
+
* deleteRelatedObjectAsObservable deletes a single object related to a specific parent.
|
|
247
323
|
*
|
|
248
|
-
* @param
|
|
249
|
-
* @param
|
|
250
|
-
* @param
|
|
251
|
-
* @param
|
|
324
|
+
* @param parentElementId - The ID of the parent element
|
|
325
|
+
* @param parentKey - The key of the parent object
|
|
326
|
+
* @param childElementId - The ID of the child element to delete
|
|
327
|
+
* @param childKey - The key of the child object to delete
|
|
252
328
|
*
|
|
253
|
-
* @returns
|
|
329
|
+
* @returns Observable resolving to true if deletion was successful
|
|
254
330
|
*/
|
|
255
|
-
function
|
|
256
|
-
|
|
257
|
-
if (valueA && valueB) {
|
|
258
|
-
let comp = valueA.toLowerCase().localeCompare(valueB.toLowerCase());
|
|
259
|
-
if (descending) {
|
|
260
|
-
comp = comp * -1;
|
|
261
|
-
}
|
|
262
|
-
return comp;
|
|
263
|
-
}
|
|
264
|
-
else if (valueA && !valueB) {
|
|
265
|
-
return -1;
|
|
266
|
-
}
|
|
267
|
-
else if (!valueA && valueB) {
|
|
268
|
-
return 1;
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
return 0;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
if (valueA < valueB) {
|
|
276
|
-
return (descending ? 1 : -1);
|
|
277
|
-
}
|
|
278
|
-
if (valueA > valueB) {
|
|
279
|
-
return (descending ? -1 : 1);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
return 0;
|
|
331
|
+
function deleteRelatedObjectAsObservable(parentElementId, parentKey, childElementId, childKey) {
|
|
332
|
+
return (0, rxjs_1.from)(deleteRelatedObject(parentElementId, parentKey, childElementId, childKey));
|
|
283
333
|
}
|
|
284
334
|
/**
|
|
285
|
-
*
|
|
286
|
-
* path. The path can include relationships. Relationship IDs may include a colon delimiter (e.g.,
|
|
287
|
-
* "accountMember:ownerAccountMemberKey") to specify the key of the related object. This is useful
|
|
288
|
-
* when an element has more than one relationship to the same object type. Otherwise, if only one
|
|
289
|
-
* relationship to the same object type exists, the key may be specified without the relationship ID
|
|
290
|
-
* (e.g., simply, "accountMember").
|
|
335
|
+
* deleteRelatedObjects deletes multiple objects related to a specific parent.
|
|
291
336
|
*
|
|
292
|
-
* @param
|
|
293
|
-
* @param
|
|
337
|
+
* @param parentElementId - The ID of the parent element
|
|
338
|
+
* @param parentKey - The key of the parent object
|
|
339
|
+
* @param childElementId - The ID of the child element to delete
|
|
340
|
+
* @param childKeys - Array of keys of the child objects to delete
|
|
294
341
|
*
|
|
295
|
-
* @returns
|
|
342
|
+
* @returns Promise resolving to true if deletion was successful
|
|
296
343
|
*/
|
|
297
|
-
function
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (value) {
|
|
302
|
-
// If a relationship specifies a key, it will be in the format [datatype]:[key]. Otherwise the colon
|
|
303
|
-
// delimiter will not be present.
|
|
304
|
-
// The related value will be in a field named after the key. For example: accountMember:ownerAccountMemberKey
|
|
305
|
-
// the related owner account member will be in a field called "ownerAccountMember".
|
|
306
|
-
let compSplit = component.split(":");
|
|
307
|
-
if (compSplit.length > 1) {
|
|
308
|
-
let keyField = compSplit[1];
|
|
309
|
-
value = value[keyField.replace("Key", "")];
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
value = value[component];
|
|
313
|
-
}
|
|
344
|
+
function deleteRelatedObjects(parentElementId, parentKey, childElementId, childKeys) {
|
|
345
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
346
|
+
if (!exports.userContext) {
|
|
347
|
+
throw new Error("userContext is required but not available; check that the initialize function has been called");
|
|
314
348
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
* @param successResponse - The value to return
|
|
325
|
-
*
|
|
326
|
-
* @returns Formatted success response; an ActionResponse unless useBody is true
|
|
327
|
-
*/
|
|
328
|
-
function prepareSuccessResponse(successResponse) {
|
|
329
|
-
if (exports.useBody) {
|
|
330
|
-
return {
|
|
331
|
-
statusCode: 200,
|
|
332
|
-
body: JSON.stringify(successResponse)
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
return successResponse;
|
|
349
|
+
let url = `${exports.serviceAddress}/schema/sandboxes/${exports.sandboxKey}/${parentElementId}/${parentKey}/${childElementId}`;
|
|
350
|
+
let authToken = yield (0, rxjs_1.lastValueFrom)((0, exports.getAuthToken)());
|
|
351
|
+
console.log("Sending DELETE request to " + url + " with token " + authToken);
|
|
352
|
+
let response = yield axios_1.default.delete(url, {
|
|
353
|
+
headers: { "Authorization": `Bearer ${authToken}` },
|
|
354
|
+
params: { keys: childKeys.join(",") },
|
|
355
|
+
});
|
|
356
|
+
return response.status === 204;
|
|
357
|
+
});
|
|
336
358
|
}
|
|
337
359
|
/**
|
|
338
|
-
*
|
|
339
|
-
* should return an ErrorResponse response when the action is not successful. If useBody is true,
|
|
340
|
-
* the response will be returned as an object with the HTTP response code and the ErrorResponse in
|
|
341
|
-
* the body field. If useBody is false, the ErrorResponse will be returned directly.
|
|
342
|
-
*
|
|
343
|
-
* @param errorMessage - The error message
|
|
360
|
+
* deleteRelatedObjectsAsObservable deletes multiple objects related to a specific parent.
|
|
344
361
|
*
|
|
345
|
-
* @
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return {
|
|
350
|
-
statusCode: 400,
|
|
351
|
-
body: JSON.stringify({ errorMessage })
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return { errorMessage, responseType: "error" };
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* initialize initializes the SDK with event data. This should be called at the beginning of the
|
|
358
|
-
* action handler to set up the SDK with incoming information, including context information, input
|
|
359
|
-
* parameters, and authentication information needed to make API requests to the Halix service.
|
|
362
|
+
* @param parentElementId - The ID of the parent element
|
|
363
|
+
* @param parentKey - The key of the parent object
|
|
364
|
+
* @param childElementId - The ID of the child element to delete
|
|
365
|
+
* @param childKeys - Array of keys of the child objects to delete
|
|
360
366
|
*
|
|
361
|
-
* @
|
|
367
|
+
* @returns Observable resolving to true if deletion was successful
|
|
362
368
|
*/
|
|
363
|
-
function
|
|
364
|
-
|
|
365
|
-
if (event.body) {
|
|
366
|
-
body = event.body;
|
|
367
|
-
exports.useBody = true;
|
|
368
|
-
}
|
|
369
|
-
if (body) {
|
|
370
|
-
({ sandboxKey: exports.sandboxKey, serviceAddress: exports.serviceAddress, actionSubject: exports.actionSubject, userContext: exports.userContext, params: exports.params } = body);
|
|
371
|
-
if (body.authToken) {
|
|
372
|
-
exports.getAuthToken = () => (0, rxjs_1.of)(body.authToken);
|
|
373
|
-
}
|
|
374
|
-
else if (body.authTokenRetriever) {
|
|
375
|
-
exports.getAuthToken = body.authTokenRetriever;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
369
|
+
function deleteRelatedObjectsAsObservable(parentElementId, parentKey, childElementId, childKeys) {
|
|
370
|
+
return (0, rxjs_1.from)(deleteRelatedObjects(parentElementId, parentKey, childElementId, childKeys));
|
|
378
371
|
}
|
|
372
|
+
// ================================================================================
|
|
373
|
+
// CONTENT RESOURCE FUNCTIONS
|
|
374
|
+
// ================================================================================
|
|
379
375
|
/**
|
|
380
376
|
* getOrCreateResource retrieves an existing content resource by its key, or creates a new one
|
|
381
377
|
* if the key is not provided. If a resource key is provided, it attempts to fetch the existing
|
|
@@ -588,6 +584,107 @@ function createOrUpdateResource(resourceKey, fileToUpload, publicFlag, resourceT
|
|
|
588
584
|
function createOrUpdateResourceAsObservable(resourceKey, fileToUpload, publicFlag, resourceType, tags) {
|
|
589
585
|
return (0, rxjs_1.from)(createOrUpdateResource(resourceKey, fileToUpload, publicFlag, resourceType, tags));
|
|
590
586
|
}
|
|
587
|
+
// ================================================================================
|
|
588
|
+
// UTILITY FUNCTIONS
|
|
589
|
+
// ================================================================================
|
|
590
|
+
/**
|
|
591
|
+
* sortObjectArray is a helper function that sorts the passed array in place by the given
|
|
592
|
+
* attributes. Sorting by nested attributes in the form of a delimited attribute string are
|
|
593
|
+
* supported (e.g., "attribute.nestedAttribute").
|
|
594
|
+
*
|
|
595
|
+
* @param array - The array to sort
|
|
596
|
+
* @param sort - Array of sort field specifications
|
|
597
|
+
* @returns The sorted array
|
|
598
|
+
*/
|
|
599
|
+
function sortObjectArray(array, sort) {
|
|
600
|
+
return array.sort((a, b) => {
|
|
601
|
+
let comparison = 0;
|
|
602
|
+
for (let s of sort) {
|
|
603
|
+
let valueA = getValueFromObject(a, s.attributeId);
|
|
604
|
+
let valueB = getValueFromObject(b, s.attributeId);
|
|
605
|
+
comparison = compareValues(valueA, valueB, !!s.descending, !!s.caseInsensitive);
|
|
606
|
+
if (comparison !== 0) {
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return comparison;
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* compareValues is a helper function that compares two values for sorting purposes. If the values
|
|
615
|
+
* are strings, the comparison is case-insensitive. If the values are numbers, the comparison is
|
|
616
|
+
* performed numerically.
|
|
617
|
+
*
|
|
618
|
+
* @param valueA - First value to compare
|
|
619
|
+
* @param valueB - Second value to compare
|
|
620
|
+
* @param descending - Whether to sort in descending order
|
|
621
|
+
* @param caseInsensitive - Whether to perform case-insensitive comparison for strings
|
|
622
|
+
*
|
|
623
|
+
* @returns Comparison result (-1, 0, or 1)
|
|
624
|
+
*/
|
|
625
|
+
function compareValues(valueA, valueB, descending, caseInsensitive) {
|
|
626
|
+
if (caseInsensitive && (typeof valueA === 'string' || valueA instanceof String)) {
|
|
627
|
+
if (valueA && valueB) {
|
|
628
|
+
let comp = valueA.toLowerCase().localeCompare(valueB.toLowerCase());
|
|
629
|
+
if (descending) {
|
|
630
|
+
comp = comp * -1;
|
|
631
|
+
}
|
|
632
|
+
return comp;
|
|
633
|
+
}
|
|
634
|
+
else if (valueA && !valueB) {
|
|
635
|
+
return -1;
|
|
636
|
+
}
|
|
637
|
+
else if (!valueA && valueB) {
|
|
638
|
+
return 1;
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
return 0;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
if (valueA < valueB) {
|
|
646
|
+
return (descending ? 1 : -1);
|
|
647
|
+
}
|
|
648
|
+
if (valueA > valueB) {
|
|
649
|
+
return (descending ? -1 : 1);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return 0;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* getValueFromObject is a helper function that extracts a value from an object using a dot-notation
|
|
656
|
+
* path. The path can include relationships. Relationship IDs may include a colon delimiter (e.g.,
|
|
657
|
+
* "accountMember:ownerAccountMemberKey") to specify the key of the related object. This is useful
|
|
658
|
+
* when an element has more than one relationship to the same object type. Otherwise, if only one
|
|
659
|
+
* relationship to the same object type exists, the key may be specified without the relationship ID
|
|
660
|
+
* (e.g., simply, "accountMember").
|
|
661
|
+
*
|
|
662
|
+
* @param object - The object to extract value from
|
|
663
|
+
* @param attribute - The attribute path (e.g., "user.address.city")
|
|
664
|
+
*
|
|
665
|
+
* @returns The extracted value
|
|
666
|
+
*/
|
|
667
|
+
function getValueFromObject(object, attribute) {
|
|
668
|
+
let components = attribute.split(".");
|
|
669
|
+
let value = object;
|
|
670
|
+
for (let component of components) {
|
|
671
|
+
if (value) {
|
|
672
|
+
// If a relationship specifies a key, it will be in the format [datatype]:[key]. Otherwise the colon
|
|
673
|
+
// delimiter will not be present.
|
|
674
|
+
// The related value will be in a field named after the key. For example: accountMember:ownerAccountMemberKey
|
|
675
|
+
// the related owner account member will be in a field called "ownerAccountMember".
|
|
676
|
+
let compSplit = component.split(":");
|
|
677
|
+
if (compSplit.length > 1) {
|
|
678
|
+
let keyField = compSplit[1];
|
|
679
|
+
value = value[keyField.replace("Key", "")];
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
value = value[component];
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return value;
|
|
687
|
+
}
|
|
591
688
|
/**
|
|
592
689
|
* debounceFn is a utility function that debounces a function call. It is used to prevent multiple
|
|
593
690
|
* calls to the same function within a short period of time.
|