Skip to content

Instantly share code, notes, and snippets.

@amaralli
Last active February 16, 2017 23:48
Show Gist options
  • Save amaralli/6c6502ed20d20111696cfeee06e9110e to your computer and use it in GitHub Desktop.
Save amaralli/6c6502ed20d20111696cfeee06e9110e to your computer and use it in GitHub Desktop.

Control Assign If

Assign a value based on the output of an expression.

Inputs

  • left-operand: The first operand in the expression.

  • operator: The operator to compare two values in an expression.

  • right-operand: The second operand in the expression.

  • valueIfFalse: The value that will be assigned as this module's "output", when the expression evaluates to false.

  • valueIfTrue: The value that will be assigned as this module's "output", when the expression evaluates to true.

Outputs

  • output: The value returned by the expression. If the expression evaluates to "true" and the "valueIfTrue" equals 5, then referring to [moduleID].output for this module will reference the value "5".

Control Continue If

Continue the flo if...

Inputs

  • left-operand: The first operand in the expression.

  • operator: The operator to compare two values in an expression.

  • otherwise.message: The message that will be set as this module's output value if the given expression evaluates to "false".

  • right-operand: The second operand in the expression.

Outputs

  • message: The message that was sent when the expression was evaluated to "false". To use this message in the rest of your method, use "[thisModuleID].output".

Control Let

Declare or rename variables in the local scope.

Examples


{
  "brick": "control.let",
  "id": "[idHere]",
  "inputs": {
    "[desiredVariableNameHere]" : "[desiredValueHere]"
  },
  "outputs": {}
}

Inputs

  • (User-Determined): The keys placed into "input" represent the new variables to assign values to. If "Foo" is set as a key in this module, with value "Baz", you may use "{{[moduleIDHere].Foo}}" throughout the rest of the method to refer to the value "Baz". You may assign as many variables inside "inputs" as you need.

Outputs

  • (Empty): The keys placed into "input" will be implicitly mirrored as output for this module. You may define items here, but it is not neccesary. If there are keys in this output that are not found in the input, your Connector will not compile.

Control Since

Saves a value that will persist through an execution of a FLO, to allow for later retrieval of that value. May take in an object and accompanying path to draw a value from. If no path or object are provided, this will save the current time, in the provided format. Should only be used in Polling Events.

Inputs

  • object: The object you want to parse your since from. Oftentimes you'll use this for situations where a service already has a way that it records timestamps, and you want to access it from an object it returns in the body of its response. Leave this field blank if you want to set your "since" value to be the current time.
  • path: The path inside of the object to find the desired "since" value. Leave this field blank if you want to set your "since" value to be the current time.
  • format: If you are not using an object and path to choose a "since" value, you may instead select a format in this input to generate a current timestamp in the provided format. You may leave this blank if grabbing your "since" value from an object and path. Available formats are "unix", "iso8601", "iso8601+0000", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "YYYY-MM-DD HH:mm:ss ZZ"

Outputs

  • output: The "since" value, that will persist between iterations of a Polling Event

Example 1:

This example will show a "since" value being pulled from an existing object. In a real example, the since value would often be pulled directly from the body of a response from your service, or pulled from the last item in a list returned by your service. In this example, we're just taking in an arbitrary object.

To grab a "since" value this way, fill in the "object" and "path" inputs, and leave "format" blank.

{
   "brick": "control.since",
   "id": "ID HERE",
   "inputs": {
      "object": {
      "_availableTypes": [
         "*"
      ],
      "_type": "object",
      "_array": false,
      "_value": {
          "servicesOwnTimestamp" : "XX:XX:XXXX"
       }
    },
    "path": {
         "_availableTypes": [
               "string"
         ],
         "_type": "string",
         "_array": false,
         "_value": "servicesOwnTimestamp"
    },
    "format": {
       "_availableTypes": [
           "string"
        ],
       "_type": "string",
      "_array": false,
      "_value": ""
   },
}
   "outputs": {
         "output": {
              "_type": "string",
              "_array": false
          }
     }
}

Output:

"output" : "XX:XX:XXXX"

Example 2

This example will show a "since" being generated based off the current time, in a given format.

To do this, leave the object field and path field blank, and fill in the "format" field with one of the approved formats.

{
 "brick": "control.since",
 "id": "ID HERE",
 "inputs": {
   "object": {
     "_availableTypes": [
       "*"
     ],
     "_type": "object",
     "_array": false,
     "_value": {}
   },
   "path": {
     "_availableTypes": [
       "string"
     ],
     "_type": "string",
     "_array": false,
     "_value": ""
   },
   "format": {
     "_availableTypes": [
       "string"
     ],
     "_type": "string",
     "_array": false,
     "_value": "yyyy-MM-dd HH:mm"
   },
 },
 "outputs": {
   "output": {
     "_type": "string",
     "_array": false
   }
 }
}

Output:

"output" : "2017-02-15 8:58:00"

Control Spawn

Spawn a child flo and wait for the resulting output.

Inputs

  • flo: The FLO that you would like to call. Set _value to the name of the FLO that you woluld like to call, with proper casing and spelling. You must specify the _type as "flo", or else it will fail to compile.

Outputs

  • output: The result of the last step of the FLO called by this module. For example, if you call "methodName", and "methodName" ends with an obstruct.construct module, the output of this module will be the object constructed in "methodName".

Control Throw If

Throw an error if...

Inputs

  • left-operand: The first operand in the expression.

  • message: The message that will be shown in the console, as the error message

  • operator: The operator to compare two values in an expression.

  • right-operand: The second operand in the expression.

Outputs

  • (Empty): There is no output for this module. Note, because this module has no output, you cannot end a method with this module.

Control Throw If

Throw an error and end the flo if a condition is met.

Inputs

  • left-operand: The first operand in the expression.

  • message: The message that will be shown in the console, as the error message

  • operator: The operator to compare two values in an expression.

  • right-operand: The second operand in the expression.

Outputs

  • (Empty): There is no output for this module. Note, because this module has no output, you cannot end a method with this module.

Date Format

Formats a date into the format specified by an input string and input timezone.

Inputs

  • format: The format that you would like to parse the string into. Takes formats in this form.

  • start: The date you would like to parse into a string

  • zone: The timezone you would like to format your date into. Uses the "time zone identifier" format. For example, "America/Los_Angeles".

Outputs

  • output: The newly formatted string of the given date.

Date Generic

Formats a date into the format specified by an input object and input timezone. Returns an object.

Inputs

  • format: The format that you would like to parse the string into. Takes formats in this form.

  • start: The date you would like to parse into a string

  • zone: The timezone you would like to format your date into. Uses the "time zone identifier" format. For example, "America/Los_Angeles".

Outputs

  • day: The day of the month.

  • full: The given date, fully represented. Ex- October 6th, 2016 XX:XX:X.XXX

  • hour: The given hour.

  • millisecond: The given number of millliseconds.

  • minute: The minute of the given date object

  • month: The month.

  • second: The given second (with milliseconds truncated)

  • time: The given time, like HH:MM:s.SS

  • year: The given year


Date Now

Returns the current time.

Inputs

  • (Empty): There are no inputs for this module.

Outputs

  • date: The current date.

  • day: The current day of the month.

  • full: The current date, fully represented. Ex- October 6th, 2016 XX:XX:X.XXX

  • hour: The current hour.

  • iso: The current date in ISO format.

  • millisecond: The current number of millliseconds.

  • minute: The current minute.

  • month: The current month.

  • second: The current second (with milliseconds truncated)

  • time: The current time, like HH:MM:s.SS

  • year: The current year.


HTTP Call

Performs an HTTP request, returning the result of this request and the response headers. On input, takes a required URL input and optional auth, header, body, and query inputs. Each optional input can either be modeled by a singular object-typed input or by multiple keys with the appropriate group attribute. On output, returns an object with two keys, headers and output. The output key contains the response body, and the headers key contains the response header. More detailed information can be accessed about these by using multiple keys with the appropriate grouping.

Inputs

  • (Optional) body: The body being passed with the HTTP request.

  • (Optional) headers: The headers being passed with the HTTP request. If Basic Authentication is defined in the Authentication section of your Connector, you do not need to set an Authentication header. See "Authentication" in the documentation for more information. Can only an object, or a reference to an object (with Mustache).

  • (Optional) query: The query passed with the HTTP request. Can be a string or an object.

  • filterEmpty: A boolean value determining whether or not to filter out all "null" and "undefined" values from your HTTP request.

  • method: The method of the HTTP request. Can be "GET", "PUT", "POST", "DELETE".

  • url: The url for the HTTP request.

Outputs

  • rawBody: The response, in raw form, from the service.

  • statusCode: The status code response from the service.


HTTP Delete

Performs an HTTP DELETE request, returning the result of this request and the response headers. On input, takes a required URL input and optional auth, header, body, and query inputs. Each optional input can either be modeled by a singular object-typed input or by multiple keys with the appropriate group attribute. On output, returns an object with two keys, headers and output. The output key contains the response body, and the headers key contains the response header. More detailed information can be accessed about these by using multiple keys with the appropriate grouping.

Inputs

  • (Optional) body: The body being passed with the HTTP request.

  • (Optional) headers: The headers being passed with the HTTP request. If Basic Authentication is defined in the Authentication section of your Connector, you do not need to set an Authentication header. See "Authentication" in the documentation for more information. Can only an object, or a reference to an object (with Mustache).

  • (Optional) query: The query passed with the HTTP request. Can be a string or an object.

  • filterEmpty: A boolean value determining whether or not to filter out all "null" and "undefined" values from your HTTP request.

  • url: The url for the HTTP request.

Outputs

  • body: The body of the HTTP response.

  • statusCode: The status code response from the service.


HTTP Get

Performs an HTTP GET request, returning the result of this request and the response headers. On input, takes a required URL input and optional auth, header, body, and query inputs. Each optional input can either be modeled by a singular object-typed input or by multiple keys with the appropriate group attribute. On output, returns an object with two keys, headers and output. The output key contains the response body, and the headers key contains the response header. More detailed information can be accessed about these by using multiple keys with the appropriate grouping.

Inputs

  • (Optional) body: The body being passed with the HTTP request.

  • (Optional) headers: The headers being passed with the HTTP request. If Basic Authentication is defined in the Authentication section of your Connector, you do not need to set an Authentication header. See "Authentication" in the documentation for more information. Can only an object, or a reference to an object (with Mustache).

  • (Optional) query: The query passed with the HTTP request. Can be a string or an object.

  • filterEmpty: A boolean value determining whether or not to filter out all "null" and "undefined" values from your HTTP request.

  • url: The url for the HTTP request.

Outputs

  • body: The body of the HTTP response.

  • statusCode: The status code response from the service.


HTTP Paginate

Inputs

  • object: The object that will be passed into the child flo denoted in the "flo" input as its variant key

  • path: After each each execution of the child FLO, the system will test the key in the output object identified by path. If it doesn’t exist, then the pagination is finished and the object is returned as the output of the http.pagination brick. If it does exist, then the pagination continues and the child FLO is invoked again with the new object.

  • flo: The FLO that will operate until pagination is complete. Fundamentally it functions like this:

function paginate(flo, object, path) {
  if (object[path] !== undefined) return paginate( flo, flo(object), path );
  else return object;
}

where flo(object) means "call flo with object as the input".

Outputs

  • output: The results from all the paged responses, compiled into one object.

Examples


A great example for pagination is the Zendesk API, as it has a very convenient paging system: it returns a next_page key in its response which is a full URL to the next page, or else is null. Other APIs return tokens, page numbers, record ranges, etc - usually it is a simple math or string operation to generate the next URL to call.

Here’s an overview of how we use pagination with an API like Zendesk:

  • Set up a seed object for use in the initial paginate call. This has a url key which is the first URL to call, and a list key which is where the output list will be stored, set to [].
  • Pass that into http.paginate, with path set to the url key.
  • The child FLO calls http.get with the url in the object, then generates a new output object. The url key of the output object is set to the next_page value from the http response, which is filtered out (i.e. will be undefined) if null. The list key collects the the output list by appending the new items to the input list from the input object - that’s why the seed object starts off as [].
  • After paginate completes, the full output list is in the output.list output.

Here’s a snippet from the Zendesk "Get Organization Tickets" action:

    {
      "brick": "object.construct",
      "id": "pageSeed",
      "inputs": {
        "url": {
          "_type": "string",
          "_array": false,
          "_value": "https://{{auth.subdomain}}.zendesk.com/api/v2/search.json?query=type:ticket organization:{{input.Get by.Organization ID}}"
        },
        "list": {
          "_type": "object",
          "_array": true,
          "_value": []
        }
      },
      "outputs": {
        "output": {
          "_type": "object",
          "_array": false
        }
      }
    },
    {
      "brick": "http.paginate",
      "id": "allPages",
      "item": "item",
      "inputs": {
        "object": {
          "_type": "object",
          "_array": false,
          "_value": "{{pageSeed.output}}"
        },
        "path": {
          "_type": "string",
          "_array": false,
          "_value": "url"
        },
        "flo": {
          "_type": "flo",
          "_array": false,
          "_value": "pagedGetOrganizationTickets"
        }
      },
      "outputs": {
        "output": {
          "_type": "object",
          "_array": false
        }
      }
    },
… and the next brick refers to the output list as "{{allPages.output.list}}"

And here’s the metadata method “pagedGetOrganizationTickets” that paginate calls:

{
  "name": "pagedGetOrganizationTickets",
  "description": "Inner FLO for the paginate brick of action Get Organization Tickets",
  "kind": "metadata",
  "variant": {
    "_type": "object",
    "_key": "page",
    "_array": false,
    "_defaultValue": {}
  },
  "zebricks": [
    {
      "brick": "http.get",
      "id": "tickets",
      "inputs": {
        "url": "{{page.url}}",
        "auth": {
          "username": "{{{auth.username}}}",
          "password": "{{{auth.password}}}"
        }
      },
      "outputs": {
        "body": "string",
        "statusCode": "number",
        "headers": "object"
      }
    },
    {
      "brick": "list.union",
      "id": "union",
      "inputs": {
        "list1": {
          "_type": "object",
          "_array": true,
          "_value": "{{page.list}}"
        },
        "list2": {
          "_type": "object",
          "_array": true,
          "_value": "{{tickets.body.results}}"
        }
      },
      "outputs": {
        "union": {
          "_type": "object",
          "_array": true
        }
      }
    },
    {
      "brick": "object.construct",
      "id": "out",
      "inputs": {
        "url": {
          "_type": "string",
          "_array": false,
          "_value": "{{tickets.body.next_page}}"
        },
        "list": {
          "_type": "object",
          "_array": true,
          "_value": "{{union.union}}"
        }
      },
      "outputs": {
        "output": {
          "_type": "object",
          "_array": false
        }
      }
    },
    {
      "brick": "object.filter",
      "id": "SJbOE",
      "inputs": {
        "object": {
          "_type": "object",
          "_array": false,
          "_value": "{{out.output}}"
        }
      },
      "outputs": {
        "output": {
          "_type": "object",
          "_array": false
        }
      }
    }
  ]
}

HTTP Post

Performs an HTTP POST request, returning the result of this request and the response headers. On input, takes a required URL input and optional auth, header, body, and query inputs. Each optional input can either be modeled by a singular object-typed input or by multiple keys with the appropriate group attribute. On output, returns an object with two keys, headers and output. The output key contains the response body, and the headers key contains the response header. More detailed information can be accessed about these by using multiple keys with the appropriate grouping.

Inputs

  • (Optional) body: The body being passed with the HTTP request.

  • (Optional) headers: The headers being passed with the HTTP request. If Basic Authentication is defined in the Authentication section of your Connector, you do not need to set an Authentication header. See "Authentication" in the documentation for more information. Can only an object, or a reference to an object (with Mustache).

  • (Optional) query: The query passed with the HTTP request. Can be a string or an object.

  • filterEmpty: A boolean value determining whether or not to filter out all "null" and "undefined" values from your HTTP request.

  • url: The url for the HTTP request.

Outputs

  • body: The body of the HTTP response.

  • statusCode: The status code response from the service.


HTTP Put

Performs an HTTP PUT request, returning the result of this request and the response headers. On input, takes a required URL input and optional auth, header, body, and query inputs. Each optional input can either be modeled by a singular object-typed input or by multiple keys with the appropriate group attribute. On output, returns an object with two keys, headers and output. The output key contains the response body, and the headers key contains the response header. More detailed information can be accessed about these by using multiple keys with the appropriate grouping.

Inputs

  • (Optional) body: The body being passed with the HTTP request.

  • (Optional) headers: The headers being passed with the HTTP request. If Basic Authentication is defined in the Authentication section of your Connector, you do not need to set an Authentication header. See "Authentication" in the documentation for more information. Can only an object, or a reference to an object (with Mustache).

  • (Optional) query: The query passed with the HTTP request. Can be a string or an object.

  • filterEmpty: A boolean value determining whether or not to filter out all "null" and "undefined" values from your HTTP request.

  • url: The url for the HTTP request.

Outputs

  • body: The body of the HTTP response.

  • statusCode: The status code response from the service.


JSON Parse

Parses a JSON string into an object with an unspecified schema.

Inputs

  • string: The string you would like to parse into a JSON object.

Outputs

  • output: The created JSON object

JSON Render

Renders an object or string of mustache references into an object or string composed of those references.

Examples


{
  "brick": "json.render",
  "id": "HkIbD",
  "inputs": {
    "schema": {
      "_type": "object",
      "_array": false,
      "_defaultValue": null,
      "_value": {
        "Character": {
          "Name": "{{allInfo.body.name}}"
         }
       }
  }                                                                                                                                                    },
  "outputs": {
    "output": {
      "_type": "object",
      "_array": false,
      "_defaultValue": null,
      "_value": {}
    }
  }
}

Inputs

  • schema: The user-defined schema of the JSON object returned from this module.

Outputs

  • output: The JSON object rendered by this module.

List Construct

Constructs an array with values stored at numbered keys.

Examples


{
  "brick": "list.construct",
  "id": "BJ5s2",
  "inputs": {
    "2": {
      "_type": "object",
      "_array": false,
      "_value": {
        "item" : "Thing2"
      }
    },
    "0" : {
      "item" : "Thing0"
    }
  },
  "outputs": {
    "list": {
      "_type": "object",
      "_array": true
    }
  }
}

Resulting list:
"list": [
    {
      "item": "Thing0"
    },
    null,
    {
      "item": "Thing2"
    }
  ]

Here's an example that illustrates how your keys and values are set up in a List.Construct. In this case, the keys are intentionally out of order, to illustrate that list order is determined by the key used. Also, illustrates that undefined indices within the constructed list are automatically set to null.

Inputs

  • (User-Defined): Here, you will set up the structure of your list, by creating a schema with indices and values. The keys for each item must be the index that you want it placed in within your new list. The highest number integer specified in your schema will be the latest populated index, with all previous values set to null, unless otherwise specified.

Outputs

  • list: The list that was created as the result of this module. Note- the output defualts to an array of object, if you would like to change the type, change the "_type" key.

List Filter

Filter a collection by applying a flo to each element. Each flo invokation that returns false will remove the associated element from the output array.

Inputs

  • concurrency: The concurrency rate that the filtering occurs with

  • flo: The flo that will serve to filter the specified list. This flo must end with a true or false value. All items that run through this flo and result as "false" are removed from the list.

  • list: The list that will have the specified filtering operations performed on it.

Outputs

  • list: The resulting, filtered list

List Filter By

Filter a collection by comparing the value for each element at a path to a provided value. The comparison is dictated by an input operation: one of ==, !=, >, <, >=, or <=.

Inputs

  • comparison: The value that will be used to compare against each item in the provided list.

  • list: The list that will have the specified filtering operations performed on it.

  • operator: The operator that will be used to compare the given path of each item in the provided list against a comparison value.

  • path: The path inside of each item in the list that will be used to filter against.

Outputs

  • list: The resulting, filtered list

List Find

Find an element in a collection by applying a flo to each one in series and returning the first element for which the associated flo returns true.

Inputs

  • flo: The flo that will serve to search through the specified list. This flo must end with a true or false value. The first item to return as true will be set as the output for this module.

  • list: The list that will be searched.

Outputs

  • item: The first item in the provided list that returns from the subFLO as "true"

List Find By

Find an element in a collection by comparing the value for each element at a path to a provided value. The comparison is dictated by an input operation: one of ==, !=, >, <, >=, or <=.

Inputs

  • comparison: The value that will be used to compare against each item in the provided list.

  • list: The list that will have the specified filtering operations performed on it.

  • operator: The operator that will be used to compare the given path of each item in the provided list against a comparison value.

  • path: The path inside of each item in the list that will be used to filter against.

Outputs

  • item: The first value inside the provided list that results as "true" with the given tests.

List Flatten

Create a recursively flattened array from an array of possibly embedded arrays.

Inputs

  • lists: An array of lists you would like to flatten into one list. You may place any number of lists in this array, either through a comma-separated list of Mustache references or through specifically enumerated lists.

Outputs

  • list: The resulting, flattened list.

List Join

Concatenate the elements of an array into a string, combined by a delimiting string.

Inputs

  • delimiter: The string you would like to use in-between each item from your list in the newly composed string.

  • list: The list of items that you would like to join together as a string.

Outputs

  • string: The resulting string, that contains each item of your provided list, separated by the delimiter string input.

List Map

Map a collection to another collection by processing each element with a flo and storing the resulting output. The output array will have the result of each inner flo in the same order as the input array.

Examples


{ "brick": "list.map", "id": "ID", "item": "itemName", "inputs": { "list": { "_availableTypes": [ "*" ], "_type": "object", "_array": true, "_value": "{{listNameHere}}" }, "flo": { "_type": "flo", "_array": false, "_value": { "brick": "object.construct", "id": "ID", "inputs": { "NewFormat" : "{{itemName.path}}" }, "outputs": { "output": { "_type": "object", "_array": false } } } }, "concurrency": { "_type": "number", "_array": false, "_value": 0 } }, "outputs": { "new list": { "_type": "object", "_array": true } } }


{ 
  "name": "[metadataMethodName]", 
  "kind": "metadata", 
  "variant": { 
    "_type": "object", 
    "_key": "itemName", 
    "_array": false
  }, 
  "zebricks": [ 
    { 
     //modules you create will go here 
    } 
  ] 
}

This is an example of a List.Map module that uses a separate metadata method to perform an operation on each item in a list. This technique should be used when the operation you want to perform requires more than a couple of modules to complete. If the operation would only be one or two modules, you might consider using in-line modules. See the other List.Map for more details if this is the case.

Using List.Map with a separate metadata method for processing requires you to add a "variant" flag in the metadata method you will be using. Information about this can be found in the Forge Documentation under "Metadata Methods: Metadata Method Classes". Here is an example of a variant flag in a metadata method. To be able to refer to each item in the list, you must set a name for each item. To do so, select the name of your metadata method on the left-hand menu. Then place the "variant" object as a top-level item. Inside the "variant" object, set the "_key" object to the name you would like to use. After this has been set, you may refer to the item throughout that metadata method by using a Mustache reference with the name, like so: {{itemName}}. Depending on what each item in the list you are iterating over is, you may have to change _type and _array to match accordingly.

Inputs

  • concurrency: The concurrency of the map operation.

  • flo: The FLO that will process each item in your given list. You may set "_value" to either another method's name (See example 1), or you can place a module inline for simple tasks (See example 2).

  • list: The list of items that will be iterated over and changed with the provided FLO.

Outputs

  • new list: The list of items after they have been processed by the given FLO.

List Map Filter

Filter a collection by applying a flo to each element. Each flo invokation that returns false will remove the associated element from the output array. However, instead of returning the filtered input collection this will return the filtered output collection. This is analagous to a map followed by a filter.

Inputs

  • concurrency: The concurrency of this filter operation.

  • flo: The flo that will test each item in the provided list. If an item in this list does not pass the test in this flo (returns "false"), that item will be omitted from the new list that is returned from this module. The subFLO selected for this input must return a boolean value.

  • list: The list that will be filtered.

Outputs

  • new list: The new list that contains only the items from the original list that passed the filter test.

List Reduce

Reduce a collection to an object or other data type by applying a flo to each element in series. This is based on the traditional 'reduce' operation in a functional programming language.

Inputs

  • flo: The subFLO that will handle the reduction process. You must add a "memo" object to your subFLO. See following example or the "Metadata Method: Metadata Method Classes" section in the documentation for more information.

  • list: The list that will be reduced.

  • memo: The object (or other data type) that the list will be reduced into. Often, the memo will be an object that other objects from a list are added into. To refer to the memo object in the subFLO, you must add a "memo" object inside of your metadata method. See following example or the "Metadata Method: Metadata Method Classes" section in the documentation for more information.

Outputs

  • item: The object (or other data type) that the list has been reduced into.

Examples

This example will use the List.Reduce module to take in a list, and then reduces that list's items into a single object. In this particular case we're going through a list where each item has a field called "in". This field determines where that item should be stored. Here's that list:

[
  {
      "name": "item1",
      "in": "A",
      "field" : "value1"
  },
  {
      "name": "item2",
      "in": "B",
      "field" : "value2"
  },
  {
      "name": "item3",
      "in": "B",
      "field" : "value3"
  }
]

And here's what the final result will be:

{
  "A" : [
    {
      "name": "item1",
      "field" : "value1",
      "in" : "A"
    }
  ],
  "B" : [
    {
      "name": "item2",
      "field" : "value2",
      "in" : "B"
    },
    {
      "name": "item3",
      "field" : "value3",
      "in" : "B"
    }
  ]
}

Seeing both of these, we know a couple of things before we even get started:

  • We will need our memo to start off as an empty object, that we then build on as we iterate through the list
  • While iterating over our original list, we will then create or update the lists inside of our memo object ("A" and "B")

The first thing we will need to define is the List.Reduce module that will kick off this operation. In this example, it will look like:

{
  "brick": "list.reduce",
  "id": "REDUCE",
  "inputs": {
    "list": {
      "_availableTypes": [
        "*"
      ],
      "_type": "object",
      "_array": true,
      "_value": <list reference here>
    },
    "memo": {
      "_availableTypes": [
        "*"
      ],
      "_type": "object",
      "_array": false,
      "_value": {}
    },
    "flo": {
      "_type": "flo",
      "_array": false,
      "_value": "reduceToObject"
    }
  },
  "outputs": {
    "item": {
      "_type": "object",
      "_array": false
    }
  }
}

Next, we will need to add two top-level keys to the child FLO we will be using to process each item in the original list (reduceToObject). One will be the 'memo', that we will build on as we iterate through our list. The other is the 'variant' that will represent the item we are currently processing as we iterate through our list. We'll define them like this:

"variant": {
  "_type": "object",
  "_key": "item",
  "_array": false
},
"memo": {
  "_type": "object",
  "_array": false
}

Now, onto the actual implementation. A couple of notes:

  • We will be able to refer to and change the memo by using "{{memo}}". At the end of each run of this child FLO, we will want to make sure that we've altered the memo, or else the List.Reduce function will just return an empty object.
  • I've named my 'variant' 'item', as seen in the "_key" field above.

Here is the inner child FLO, with all bricks underneath:

  1. Start by checking to see where this item needs to be placed in our memo object with an object.get that reads the item's "in" field.
{
  "brick": "object.get",
  "id": "IN",
  "inputs": {
    "object": {
      "_type": "object",
      "_array": false,
      "_value": "{{item}}"
    },
    "path": {
      "_type": "string",
      "_array": false,
      "_value": "in"
    }
  },
  "outputs": {
    "output": {
      "_type": "string",
      "_array": false
    }
  }
}
  1. Then we grab the memo and see what's stored at the item's "in" value. For example, if the item has "in" set to "A", we need to grab the "A" key from the memo.
{
  "brick": "object.get",
  "id": "GRAB LIST",
  "inputs": {
    "object": {
      "_type": "object",
      "_array": false,
      "_value": "{{memo}}"
    },
    "path": {
      "_type": "string",
      "_array": false,
      "_value": <item's "in" value>
    }
  },
  "outputs": {
    "output": {
      "_type": "object",
      "_array": true
    }
  }
}
  1. We then need to take whatever list was stored at the "in" key for our memo, and add our 'item' to it
{
  "brick": "list.push",
  "id": "UPDATED",
  "inputs": {
    "item": {
      "_availableTypes": [
        "*"
      ],
      "_type": "object",
      "_array": false,
      "_value": "{{item}}"
    },
    "list": {
      "_availableTypes": [
        "*"
      ],
      "_type": "object",
      "_array": true,
      "_value": "{{GRAB LIST.output}}"
    }
  },
  "outputs": {
    "list": {
      "_type": "object",
      "_array": true
    }
  }
}
  1. Finally, we just need to update the whole memo item with our updated inner list
{
  "brick": "object.set",
  "id": "NEW MEMO VAL",
  "inputs": {
    "object": {
      "_type": "object",
      "_array": false,
      "_value": "{{memo}}"
    },
    "path": {
      "_type": "string",
      "_array": false,
      "_value": "{{item.in}}"
    },
    "value": {
      "_availableTypes": [
        "*"
      ],
      "_type": "object",
      "_array": true,
      "_value": "{{UPDATED.list}}"
    }
  },
  "outputs": {
    "output": {
      "_type": "object",
      "_array": false
    }
  }
}

After each iteration, we will now have an updated memo! This completed object is then available as the output from the List.Reduce module.


List Sort By

Sort a collection by the value stored at a given path in each element.

Inputs

  • list: The list that will be sorted

  • path: The path that will be used to determine sorting order

Outputs

  • sorted list: The sorted list.

List Zip

Takes two arrays of equal length, A and B, and combines them into an array where index i is an array of the form [A[i], B[i]].

Inputs

  • list1: A list to zip together. All items in this list will precede an item in "list2". This list must be the same length as "list2"

  • list2: A list to zip together. All items in this list will follow an item in "list1". This list must be the same length as "list1"

Outputs

  • list: The resulting list. This list will be in this form: [list1[i], list2[i]]

Object Construct

Constructs an object with values stored at input keys.

Examples


Setting up the object inside the Object.Construct module:

{
  "brick": "object.construct",
  "id": "12345",
  "inputs": {
    "Example Top Level Object" : {
        "InnerObject" : {
            "Key" : "{{reference to a value here}}""
        }
    }
  },
  "outputs": {
    "output": {
      "_type": "object",
      "_array": false
    }
  }


Resulting object:

"Example Top Level Object" : {
    "InnerObject" : {
        "Key" : "resulting value"
    }
}

This will be one of your most-used modules in Forge. This module will help you shape data into the forms you need- which is often used to render data into the format needed to display your Connector in Azuqua's Designer. In this example, you'll see the desired object shape and how one would declare this shape in the Object.Construct module.

Inputs

  • User-Defined: This input object will contain the schema that you want your constructed object to be set to. See example for more information.

Outputs

  • output: The constructed object.

Object Filter

Filter empty values from an object and return the new object.

Inputs

  • object: The object that you would like to filter keys with empty values out of.

Outputs

  • output: The object that no longer has keys with empty values.

Object Get

Reads the value stored in an object at a given path, with embedded paths delimited by a dot.

Inputs

  • object: The object that you would like to grab a value from.

  • path: The path that you would like to grab the value from within the given object.

Outputs

  • output: The value at the given path within the given object.

Object Pick

Build a new object by picking select values from another object.

Examples


{
  "brick": "object.pick",
  "id": "IDHere",
  "inputs": {
    "object": {
      "_type": "object",
      "_array": false,
      "_value": "{{object.name}}"
    }
  },
  "outputs": {
    "pathName1" : {
      "_type" : "<insert the type of this path's value here>",
      "_array" : "<insert true if this path's value is a collection, false otherwise>"
    },
    "pathName2" : {
      "_type" : "<insert the type of this path's value here>",
      "_array" : "<insert true if this path's value is a collection, false otherwise>"
    }
  }
}

To use this module, you need to choose the object that you would like to pick from first. After this, choose the keys you would like to put into a new object by defining them in this module's "outputs" section. You must define the appropriate type and collection state of each key, in accordance with that key's type/state.

Inputs

  • object: The object that you would like to pick objects from.

Outputs

  • User-Defined: The items you would like to pick out from the given object. You must define which items you would like to have be output from this function. See example for details.

Object Process

Inputs

  • object: The object you would like to process

  • flo: The FLO that will handle the processing of your object

  • concurrency: The concurrency at which your subFLO will operate at over the items inside the provided object.

Outputs

  • output: The newly processed object.

Examples


{
  "brick": "object.process",
  "id": "ryEhp",
  "inputs": {
    "object": {
      "_type": "object",
      "_array": false,
      "_value": {
        "key": 1,
        "key2": 2,
        "key3": 3
      }
    },
    "flo": {
      "_type": "flo",
      "_array": false,
      "_value": "addOne"
    },
    "concurrency": {
      "_type": "number",
      "_array": false,
      "_value": 1
    }
  },
  "outputs": {
    "output": {
      "_type": "object",
      "_array": false
    }
  }
}

Here's an example method that will perform an operation on both the key and value for each item inside of an object. In this case, the end goal is to go over each key and increment it's corresponding value, and to append that new value onto the key's name.

If our starting list is:

{
        "key": 1,
        "key2": 2,
        "key3": 3
}

Then the ending list will be:

{
        "key2" : 2,
        "key3" : 3,
        "key4" : 4
}

The metadata method contains two modules, add and construct, which accomplish the actual goal of our method. These work the same as any metadata method with a variant (like List.map), with the exception how we declare the variant.

There are two variant values in this case, the key and the value. In map, we're used to using just one value called key, but with Object.process, we need to be able acess both the key and the value. To enable this, you now declare both in a variant array, that contains both key and value. You can then refer to these values within the core array for that metadata method.

{
  "name": "addOne",
  "description": "No description provided.",
  "kind": "metadata",
  "variant": [
    {
      "_key": "key",
      "_type": "string",
      "_defaultValue": ""
    },
    {
      "_key": "value",
      "_type": "number",
      "_defaultValue": 0
    }
  ],
  "zebricks": [
    {
      "brick": "math.add",
      "id": "add",
      "inputs": {
        "a": {
          "_type": "number",
          "_array": false,
          "_value": "{{value}}"
        },
        "b": {
          "_type": "number",
          "_array": false,
          "_value": 1
        }
      },
      "outputs": {
        "output": {
          "_type": "number",
          "_array": false
        }
      }
    },
    {
      "brick": "object.construct",
      "id": "r1Yc0",
      "inputs": {
        "key": "{{key}}",
        "value": "{{add.output}}"
      },
      "outputs": {
        "output": {
          "_type": "object",
          "_array": false
        }
      }
    }
  ]
}

If you wanted to do this inline, you would instead declare "item" as an array in the parent module, like so:

 "item": [
   "key",
   "value"
 ]

XML Build

Convert an object to an XML string.

Inputs

  • doctype: The desired doctype of your XML document, may be left blank.

  • encoding: This value determines the character encoding used in this XML document. Defaults to UTF-8

  • indent: This value determines how an indent is defined in your XML document, may be left blank.

  • newline: This value determines how a newline is defined in your XML document, may be left blank.

  • object: The object you would like to interpret into XML.

  • pretty: This value determines whether or not you want this XML document to rendered in "pretty" style.

  • rootName: The root name of your XML document, may be left blank.

  • standalone: Determines whether or not this XML document has an internal DTD. If false, the XML document has an external DTD.

  • version: This value determines what version of XML standard this will use. Defaults to 1.0

Outputs

  • xml: The processed and returned XML object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment