writing-scripts

Write Celigo JavaScript hook scripts -- preSavePage, preMap, postMap, postSubmit, postResponseMap, filter, transform, branching, handleRequest. Use when creating or editing scripts, choosing the right hook point, understanding input/output data shapes, or debugging script behavior.

By celigo · 1,073 installs

npx skills add celigo/ai --skill writing-scripts

Source repository · Upstream listing

<! TIER:1 Writing Scripts A script is a JavaScript function that runs at a specific hook point in the Celigo data pipeline. Scripts handle logic that expressions, filters, and visual mappings cannot complex conditionals, cross record calculations, API calls within the pipeline, and custom routing. Concerns when writing a script: Choosing the right hook point which function type matches what you're trying to accomplish Input/output contracts what options contains and what the function must return (array length rules are strict) Expression alternative filter, transform, and output filter have expression based alternatives that don't require a script; prefer expressions when possible Available modules scripts can import three built in modules: integrator api (call Celigo APIs), dayjs (date/time manipulation), and sjcl (Stanford JavaScript Crypto Library for hashing/encryption) One script, many functions a single script resource can contain multiple exported functions, each wired independently to different hook points Used across flows, APIs, and tools. Hook Points Every script function runs at a specific point in the pipeline. Choose based on when you need to act and what data you need access to. Data Pipeline Hooks Hook Runs on When Input Must return preSavePage Export After retrieval, before pipeline options.data[] , errors[] , files[] , retryData{} { data[], errors[], abort, newErrorsAndRetryData[] } preMap Import Before field mapping options.data[] (unmapped records) Array matching data.length : { data } , { errors } , or {} to skip postMap Import After field mapping, before submit options.preMapData[] , postMapData[] Array matching postMapData.length : { data } , { errors } , or {} to skip postSubmit Import After destination submission options.preMapData[] , postMapData[] , responseData[] responseData[] (same length, modified) postAggregate Import After file aggregation upload options.postAggregateData: { success, json, code, message } void Record Level Processors (on export or import) Hook When Input Must return filter Per record, before processing options.record boolean (true = process) input filter Per record on lookup exports options.record boolean (true = include) transform Per record, reshaping before mapping options.record Transformed record filter and transform have expression based alternatives. Only use a script when the logic is too complex for an expression (multi field conditionals, date math, external lookups). Flow Level Hook Hook Runs on When Input Must return postResponseMap Page processor (flow/API/tool) After response mapping merges results options.postResponseMapData[] , responseData[] postResponseMapData[] (same length) Configured on the flow's pageProcessors[] entry, not on the export/import. Plan this hook when building the resource, but wire it at the flow level. Routing and Handlers Hook Runs on When Input Must return branching Router Per record routing decision options.record , settings number[] (branch indices, e.g., [0, 2] ) handleRequest API resource Incoming HTTP request (script mode API) options.method , headers , queryString , body , rawBody { statusCode, headers?, body } contentBasedFlowRouter AS2 connection EDI message routing options.httpHeaders , mimeHeaders , rawMessageBody { flowId, exportId } Quick Reference Hook Point Decision Matrix When you need to... Use hook Configured on Input / Output Transform or filter a batch after retrieval preSavePage Export Receives pages of records, returns pages (with optional errors) Filter individual records before processing filter Export or import Receives single record, returns boolean (true = keep) Filter records entering a lookup export input filter Export (lookup) Receives single record, returns boolean (true = include) Reshape records before mapping transform Export or import Receives single record, returns transformed record Transform records before field mapping preMap Import Receives unmapped records array, returns array (same length) Transform records after field mapping postMap Import Receives pre map + post map arrays, returns array (same length) Process API responses after submission postSubmit Import Receives pre map, post map, and response arrays, returns response array Handle results after file aggregation postAggregate Import (file) Receives aggregation result, returns void Post response processing (merge lookup/import results) postResponseMap Flow pageProcessors[] entry Receives merged records + response data, returns merged records (same length) Route records to branches branching Router in flow/tool Receives single record + settings, returns branch indices array Handle incoming HTTP requests (script mode API) handleRequest API resource Receives method, headers, query, body; returns { statusCode, headers?, body } Route EDI messages to flows contentBasedFlowRouter AS2 connection Receives HTTP/MIME headers + raw body, returns { flowId, exportId } Minimum Required Fields A script resource needs only two fields: name descriptive name (convention: <System <step <hookType , e.g., "Salesforce getBatchRecords postResponseMap" ) content the JavaScript source code as a string See [references/schemas/request.yml](references/schemas/request.yml) for the full create/update schema. Related Skills [configuring exports Quick Reference](../configuring exports/SKILL.md quick reference) export configuration, where preSavePage , filter , transform , and input filter hooks are wired [configuring imports Quick Reference](../configuring imports/SKILL.md quick reference) import configuration, where preMap , postMap , postSubmit , and postAggregate hooks are wired [building flows How to Build a Flow](../building flows/SKILL.md how to build a flow) flow construction, where postResponseMap and branching hooks are wired [writing handlebars Quick Reference](../writing handlebars/SKILL.md quick reference) Handlebars expressions for dynamic values in scripts and hook configurations <! TIER:2 Common Options Available to All Hooks Most hooks receive these context fields in options : flowId , integrationId , apiId , parentIntegrationId execution context IDs exportId or importId the step's resource ID connectionId the connection in use settings custom settings in scope for the resource testMode boolean, whether running in test/preview mode job the current job object Function Point Categories Scripts run at twelve function points, grouped into four categories. The [Hook Points]( hook points) tables above give each one's input/output contract; this is the mental model for which kind of point you're wiring and whether a non script alternative exists. Step level pipeline hooks (on the export or import) preSavePage , preMap , postMap , postSubmit , postAggregate Parent level response hook (on the flow/API/tool pageProcessors[] entry, not the step) postResponseMap Script mode replacements for declarative slots filter , input filter , transform , branching Resource specific function points contentBasedFlowRouter (on an AS2 connection) and handleRequest (on a script mode API) Script only points have no declarative equivalent: postSubmit , postResponseMap , postAggregate , contentBasedFlowRouter , and handleRequest . On those slots a script is the only option. The four script mode slots ( filter , input filter , transform , branching ) each hold either a declarative rule tree or a script never both so prefer the declarative path there unless the logic genuinely can't be expressed as rules (see [Declarative vs Script Mode]( declarative vs script mode)). Declarative vs Script Mode The four mode switchable slots filter , input filter , transform , and branching hold a declarative rule tree or a script reference at any one moment, not both. Because the slot's contents change, switching modes is a two part operation. From script mode to declarative mode (the common direction prototype with a script, then clean up): 1. Clear the script from the slot. The slot reverts to declarative mode by default. 2. Author the declarative rule for that slot (rules engine filter, Mapper 2.0 transform, or router input filter rule). From declarative mode to script mode (rarer the rules engine couldn't express what you need): 1. Wire a script into the slot. The declarative rules already there are replaced by the script reference automatically. Wiring a script and clearing it are mirror operations on the same slot. Recognize the mode swap in phrasing like "switch the filter to rules" , "convert this transform back to expressions" , or "use a script for this filter instead of rules" . How to Write a Script 1. Determine what you need to accomplish Map your goal to the right hook point using the [Hook Point Decision Matrix]( hook point decision matrix) above. 2. Check if an expression can handle it Filter, transform, and output filter all have expression based alternatives. Expressions are simpler to maintain and don't require a script resource. Use a script only when you need: Multi step logic or loops Cross record calculations (totals, deduplication) External API calls via integrator api Error handling with retry data Access to preMapData alongside postMapData 3. Check for existing scripts in the account 4. Create the script resource Build the script with the correct function name matching the hook point. A single script can contain multiple functions. See [references/schemas/request.yml](references/schemas/request.yml) for the create/update schema and [references/schemas/response.yml](references/schemas/response.yml) for the response shape. Key fields: name descriptive name (convention: <System <step <hookType , e.g., "Salesforce getBatchRecords postResponseMap" ) content the JavaScript source code 5. Wire the script to the resource Wiring depends on the hook type: Hook Wiring pattern Where preSavePage , preMap , postMap , postSubmit , postAggregate hooks.{hookType}: { scriptId, function } Export or import resource filter , input filter , transform {field}: { type: "script", script: { scriptId, function } } Export or import resource postResponseMap hooks.postResponseMap: { scriptId, function } Flow pageProcessors[] entry branching routeRecordsUsing: "script" + script reference Router in flow handleRequest script: { scriptId, function } + type: "script" API resource contentBasedFlowRouter as2.contentBasedFlowRouter: { scriptId, function } AS2 connection Hook based attachment (preSavePage, preMap, etc.) is additive adding a hook doesn't remove existing config. Replace based attachment (filter, transform) replaces the existing filter/transform expression. 6. Test and iterate Available Modules Scripts can import three built in modules: integrator api Call Celigo APIs from within the script run exports, read connections, trigger imports. Useful in preSavePage for enrichment, handleRequest for orchestration, and postSubmit for triggering downstream processes. dayjs Date and time manipulation. Handles parsing, formatting, diffing, and timezone conversions without manual date math. sjcl Stanford JavaS