|
@@ -0,0 +1,124 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * @node set-fields
|
|
|
|
|
+ * @name Set / Edit Fields
|
|
|
|
|
+ * @category data
|
|
|
|
|
+ * @version 1.0.0
|
|
|
|
|
+ * @description Build an output object from values and expressions, keeping or dropping everything else
|
|
|
|
|
+ * @icon pencil
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+const configSchema = {
|
|
|
|
|
+ type: 'object',
|
|
|
|
|
+ properties: {
|
|
|
|
|
+ mode: {
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ title: 'Mode',
|
|
|
|
|
+ description: 'Keep everything from the input and add these fields, or output only the fields set here',
|
|
|
|
|
+ enum: ['keep-all', 'only-set'],
|
|
|
|
|
+ default: 'keep-all'
|
|
|
|
|
+ },
|
|
|
|
|
+ fields: {
|
|
|
|
|
+ type: 'array',
|
|
|
|
|
+ title: 'Fields',
|
|
|
|
|
+ items: {
|
|
|
|
|
+ type: 'object',
|
|
|
|
|
+ properties: {
|
|
|
|
|
+ name: {
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ title: 'Name',
|
|
|
|
|
+ description: 'Field name, or a dotted path such as user.address.city'
|
|
|
|
|
+ },
|
|
|
|
|
+ value: {
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ title: 'Value',
|
|
|
|
|
+ description: 'A literal value, or an expression such as {{data.result.total}}'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ dropFields: {
|
|
|
|
|
+ type: 'array',
|
|
|
|
|
+ title: 'Fields to Remove',
|
|
|
|
|
+ description: 'Dotted paths to delete from the output',
|
|
|
|
|
+ items: { type: 'string' }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const inputSchema = {
|
|
|
|
|
+ type: 'object',
|
|
|
|
|
+ properties: {
|
|
|
|
|
+ data: { type: 'any' }
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const outputSchema = {
|
|
|
|
|
+ type: 'object',
|
|
|
|
|
+ properties: {
|
|
|
|
|
+ data: { type: 'any', description: 'The rebuilt object' }
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+function setByPath(target, path, value) {
|
|
|
|
|
+ const keys = String(path).split('.');
|
|
|
|
|
+ let cursor = target;
|
|
|
|
|
+ for (let i = 0; i < keys.length - 1; i++) {
|
|
|
|
|
+ const key = keys[i];
|
|
|
|
|
+ if (cursor[key] === null || typeof cursor[key] !== 'object') {
|
|
|
|
|
+ cursor[key] = {};
|
|
|
|
|
+ }
|
|
|
|
|
+ cursor = cursor[key];
|
|
|
|
|
+ }
|
|
|
|
|
+ cursor[keys[keys.length - 1]] = value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function deleteByPath(target, path) {
|
|
|
|
|
+ const keys = String(path).split('.');
|
|
|
|
|
+ let cursor = target;
|
|
|
|
|
+ for (let i = 0; i < keys.length - 1; i++) {
|
|
|
|
|
+ const key = keys[i];
|
|
|
|
|
+ if (cursor === null || typeof cursor !== 'object' || !(key in cursor)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ cursor = cursor[key];
|
|
|
|
|
+ }
|
|
|
|
|
+ if (cursor !== null && typeof cursor === 'object') {
|
|
|
|
|
+ delete cursor[keys[keys.length - 1]];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function execute(config, input, context) {
|
|
|
|
|
+ const mode = config.mode || 'keep-all';
|
|
|
|
|
+ const fields = Array.isArray(config.fields) ? config.fields : [];
|
|
|
|
|
+ const dropFields = Array.isArray(config.dropFields) ? config.dropFields : [];
|
|
|
|
|
+
|
|
|
|
|
+ const source = input && input.data !== undefined ? input.data : input;
|
|
|
|
|
+
|
|
|
|
|
+ let output;
|
|
|
|
|
+ if (mode === 'only-set') {
|
|
|
|
|
+ output = {};
|
|
|
|
|
+ } else {
|
|
|
|
|
+ output = source !== null && typeof source === 'object' && !Array.isArray(source)
|
|
|
|
|
+ ? JSON.parse(JSON.stringify(source))
|
|
|
|
|
+ : {};
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (const field of fields) {
|
|
|
|
|
+ if (!field || !field.name) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ setByPath(output, field.name, field.value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (const path of dropFields) {
|
|
|
|
|
+ if (path) {
|
|
|
|
|
+ deleteByPath(output, path);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ smartbotic.log.info('Set Fields: ' + fields.length + ' set, ' + dropFields.length + ' removed, mode ' + mode);
|
|
|
|
|
+
|
|
|
|
|
+ return output;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+module.exports = { configSchema, inputSchema, outputSchema, execute };
|