writing-scripts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!-- TIER:1 -->
<!-- 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 contains and what the function must return (array length rules are strict)
options - 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 three built-in modules:
import(call Celigo APIs),integrator-api(date/time manipulation), anddayjs(Stanford JavaScript Crypto Library for hashing/encryption)sjcl - 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.
脚本是一种JavaScript函数,会在Celigo数据管道中的特定钩子点运行。脚本可处理表达式、过滤器和可视化映射无法实现的逻辑——复杂条件判断、跨记录计算、管道内API调用以及自定义路由。
编写脚本时需要注意的事项:
- 选择合适的钩子点——哪种函数类型与你的目标匹配
- 输入/输出约定——包含的内容以及函数必须返回的值(数组长度规则严格)
options - 表达式替代方案——filter、transform和output filter有基于表达式的替代方案,无需使用脚本;尽可能优先使用表达式
- 可用模块——脚本可以三个内置模块:
import(调用Celigo APIs)、integrator-api(日期/时间处理)和dayjs(用于哈希/加密的Stanford JavaScript Crypto Library)sjcl - 单脚本多函数——单个脚本资源可包含多个导出函数,每个函数可独立关联到不同的钩子点
适用于流程、API和各类工具。
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 |
|---|---|---|---|---|
| Export | After retrieval, before pipeline | | |
| Import | Before field mapping | | Array matching |
| Import | After field mapping, before submit | | Array matching |
| Import | After destination submission | | |
| Import | After file aggregation upload | | void |
| 钩子 | 运行场景 | 触发时机 | 输入 | 必须返回 |
|---|---|---|---|---|
| 导出 | 数据检索后、管道处理前 | | |
| 导入 | 字段映射前 | | 与 |
| 导入 | 字段映射后、提交前 | | 与 |
| 导入 | 目标端提交后 | | |
| 导入 | 文件聚合上传后 | | void |
Record-Level Processors (on export or import)
记录级处理器(导出或导入时)
| Hook | When | Input | Must return |
|---|---|---|---|
| Per-record, before processing | | |
| Per-record on lookup exports | | |
| Per-record, reshaping before mapping | | 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).
| 钩子 | 触发时机 | 输入 | 必须返回 |
|---|---|---|---|
| 每条记录处理前 | | |
| 查找导出时的每条记录 | | |
| 每条记录处理前、映射前重构 | | 转换后的记录 |
filter和transform有基于表达式的替代方案。只有当逻辑过于复杂(多字段条件、日期运算、外部查找)无法用表达式实现时,才使用脚本。
Flow-Level Hook
流程级钩子
| Hook | Runs on | When | Input | Must return |
|---|---|---|---|---|
| Page processor (flow/API/tool) | After response mapping merges results | | |
Configured on the flow's entry, not on the export/import. Plan this hook when building the resource, but wire it at the flow level.
pageProcessors[]| 钩子 | 运行场景 | 触发时机 | 输入 | 必须返回 |
|---|---|---|---|---|
| 页面处理器(流程/API/工具) | 响应映射合并结果后 | | |
配置在流程的条目上,而非导出/导入步骤。在构建资源时规划该钩子,但在流程层面关联配置。
pageProcessors[]Routing and Handlers
路由与处理器
| Hook | Runs on | When | Input | Must return |
|---|---|---|---|---|
| Router | Per-record routing decision | | |
| API resource | Incoming HTTP request (script-mode API) | | |
| AS2 connection | EDI message routing | | |
| 钩子 | 运行场景 | 触发时机 | 输入 | 必须返回 |
|---|---|---|---|---|
| 路由器 | 每条记录的路由决策 | | |
| API资源 | 传入的HTTP请求(脚本模式API) | | |
| AS2连接 | EDI消息路由 | | |
Quick Reference
快速参考
Hook Point Decision Matrix
钩子点决策矩阵
| When you need to... | Use hook | Configured on | Input / Output |
|---|---|---|---|
| Transform or filter a batch after retrieval | | Export | Receives pages of records, returns pages (with optional errors) |
| Filter individual records before processing | | Export or import | Receives single record, returns boolean (true = keep) |
| Filter records entering a lookup export | | Export (lookup) | Receives single record, returns boolean (true = include) |
| Reshape records before mapping | | Export or import | Receives single record, returns transformed record |
| Transform records before field mapping | | Import | Receives unmapped records array, returns array (same length) |
| Transform records after field mapping | | Import | Receives pre-map + post-map arrays, returns array (same length) |
| Process API responses after submission | | Import | Receives pre-map, post-map, and response arrays, returns response array |
| Handle results after file aggregation | | Import (file) | Receives aggregation result, returns void |
| Post-response processing (merge lookup/import results) | | Flow | Receives merged records + response data, returns merged records (same length) |
| Route records to branches | | Router in flow/tool | Receives single record + settings, returns branch indices array |
| Handle incoming HTTP requests (script-mode API) | | API resource | Receives method, headers, query, body; returns |
| Route EDI messages to flows | | AS2 connection | Receives HTTP/MIME headers + raw body, returns |
| 当你需要... | 使用钩子 | 配置位置 | 输入/输出 |
|---|---|---|---|
| 检索后转换或过滤批量数据 | | 导出 | 接收记录分页,返回分页结果(可包含错误信息) |
| 处理前过滤单条记录 | | 导出或导入 | 接收单条记录,返回布尔值(true = 保留) |
| 过滤进入查找导出的记录 | | 导出(查找) | 接收单条记录,返回布尔值(true = 包含) |
| 映射前重构记录 | | 导出或导入 | 接收单条记录,返回转换后的记录 |
| 字段映射前转换记录 | | 导入 | 接收未映射记录数组,返回长度相同的数组 |
| 字段映射后转换记录 | | 导入 | 接收映射前+映射后数组,返回长度相同的数组 |
| 提交后处理API响应 | | 导入 | 接收映射前、映射后和响应数组,返回响应数组 |
| 文件聚合后处理结果 | | 导入(文件) | 接收聚合结果,无返回值 |
| 响应后处理(合并查找/导入结果) | | 流程 | 接收合并记录+响应数据,返回长度相同的合并记录 |
| 将路由记录到分支 | | 流程/工具中的路由器 | 接收单条记录+设置,返回分支索引数组 |
| 处理传入的HTTP请求(脚本模式API) | | API资源 | 接收方法、头信息、查询参数、请求体;返回 |
| 将EDI消息路由到流程 | | AS2连接 | 接收HTTP/MIME头信息+原始请求体,返回 |
Minimum Required Fields
必填字段
A script resource needs only two fields:
- -- descriptive name (convention:
name, e.g.,<System> - <step> - <hookType>)"Salesforce - getBatchRecords - postResponseMap" - -- the JavaScript source code as a string
content
See references/schemas/request.yml for the full create/update schema.
脚本资源仅需两个字段:
- ——描述性名称(惯例:
name,例如<系统> - <步骤> - <钩子类型>)"Salesforce - getBatchRecords - postResponseMap" - ——字符串格式的JavaScript源代码
content
完整的创建/更新 schema 请参考references/schemas/request.yml。
Related Skills
相关技能
- configuring-exports > Quick Reference -- export configuration, where ,
preSavePage,filter, andtransformhooks are wiredinput_filter - configuring-imports > Quick Reference -- import configuration, where ,
preMap,postMap, andpostSubmithooks are wiredpostAggregate - building-flows > How to Build a Flow -- flow construction, where and
postResponseMaphooks are wiredbranching - writing-handlebars > Quick Reference -- Handlebars expressions for dynamic values in scripts and hook configurations
- configuring-exports > Quick Reference——导出配置,、
preSavePage、filter和transform钩子在此关联input_filter - configuring-imports > Quick Reference——导入配置,、
preMap、postMap和postSubmit钩子在此关联postAggregate - building-flows > How to Build a Flow——流程构建,和
postResponseMap钩子在此关联branching - writing-handlebars > Quick Reference——用于脚本和钩子配置中动态值的Handlebars表达式
Common Options Available to All Hooks
所有钩子通用的选项
Most hooks receive these context fields in :
options- ,
_flowId,_integrationId,_apiId-- execution context IDs_parentIntegrationId - or
_exportId-- the step's resource ID_importId - -- the connection in use
_connectionId - -- custom settings in scope for the resource
settings - -- boolean, whether running in test/preview mode
testMode - -- the current job object
job
大多数钩子的中会包含以下上下文字段:
options- ,
_flowId,_integrationId,_apiId——执行上下文ID_parentIntegrationId - 或
_exportId——步骤的资源ID_importId - ——正在使用的连接ID
_connectionId - ——资源范围内的自定义设置
settings - ——布尔值,是否处于测试/预览模式
testMode - ——当前作业对象
job
Function Point Categories
函数点分类
Scripts run at twelve function points, grouped into four categories. The 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,postSubmitpostAggregate - Parent-level response hook (on the flow/API/tool entry, not the step) --
pageProcessors[]postResponseMap - Script-mode replacements for declarative slots -- ,
filter,input_filter,transformbranching - Resource-specific function points -- (on an AS2 connection) and
contentBasedFlowRouter(on a script-mode API)handleRequest
Script-only points have no declarative equivalent: , , , , and . On those slots a script is the only option. The four script-mode slots (, , , ) 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).
postSubmitpostResponseMappostAggregatecontentBasedFlowRouterhandleRequestfilterinput_filtertransformbranching脚本在12个函数点运行,分为4类。上述钩子点表格列出了每个函数点的输入/输出约定;以下是关于你要关联的函数点类型以及是否存在非脚本替代方案的思维模型。
- 步骤级管道钩子(在导出或导入步骤)——、
preSavePage、preMap、postMap、postSubmitpostAggregate - 父级响应钩子(在流程/API/工具的条目,而非步骤)——
pageProcessors[]postResponseMap - 声明式插槽的脚本模式替代方案——、
filter、input_filter、transformbranching - 资源特定函数点——(在AS2连接)和
contentBasedFlowRouter(在脚本模式API)handleRequest
仅脚本可用的点没有声明式等效方案:、、、和。在这些插槽中,脚本是唯一选项。四个脚本模式插槽(、、、)每个只能容纳声明式规则树或脚本——不能同时存在,因此除非逻辑确实无法用规则表达(请参阅声明式 vs 脚本模式),否则优先选择声明式方式。
postSubmitpostResponseMappostAggregatecontentBasedFlowRouterhandleRequestfilterinput_filtertransformbranchingDeclarative vs Script Mode
声明式 vs 脚本模式
The four mode-switchable slots -- , , , and -- 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.
filterinput_filtertransformbranchingFrom script mode to declarative mode (the common direction -- prototype with a script, then clean up):
- Clear the script from the slot. The slot reverts to declarative mode by default.
- 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):
- 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".
四个可切换模式的插槽——、、和——在任何时候只能容纳声明式规则树或脚本引用,不能同时存在。由于插槽内容会变化,切换模式需要两步操作。
filterinput_filtertransformbranching从脚本模式切换到声明式模式(常见方向——用脚本原型开发,然后优化):
- 清除插槽中的脚本。插槽默认恢复为声明式模式。
- 为该插槽编写声明式规则(规则引擎过滤器、Mapper 2.0转换器或路由器输入过滤规则)。
从声明式模式切换到脚本模式(较少见——规则引擎无法表达需求):
- 将脚本关联到插槽。已有的声明式规则会自动被脚本引用替换。
关联脚本和清除脚本是同一插槽的镜像操作。可以通过以下表述识别模式切换:"将过滤器切换为规则"、"将此转换器转换回表达式"或"使用脚本替代规则实现此过滤器"。
How to Write a Script
如何编写脚本
1. Determine what you need to accomplish
1. 明确目标
Map your goal to the right hook point using the Hook Point Decision Matrix above.
使用上述钩子点决策矩阵将你的目标映射到合适的钩子点。
2. Check if an expression can handle it
2. 检查是否可用表达式实现
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 alongside
preMapDatapostMapData
Filter、transform和output filter都有基于表达式的替代方案。表达式更易于维护,且无需脚本资源。仅当你需要以下功能时才使用脚本:
- 多步骤逻辑或循环
- 跨记录计算(总计、去重)
- 通过调用外部API
integrator-api - 带重试数据的错误处理
- 同时访问和
preMapDatapostMapData
3. Check for existing scripts in the account
3. 检查账户中已有的脚本
bash
celigo scripts list
celigo scripts get <id> # content is only returned on individual GETbash
celigo scripts list
celigo scripts get <id> # 仅单个GET请求会返回content内容4. Create the script resource
4. 创建脚本资源
Build the script with the correct function name matching the hook point. A single script can contain multiple functions.
See references/schemas/request.yml for the create/update schema and references/schemas/response.yml for the response shape.
Key fields:
- -- descriptive name (convention:
name, e.g.,<System> - <step> - <hookType>)"Salesforce - getBatchRecords - postResponseMap" - -- the JavaScript source code
content
编写脚本时,使用与钩子点匹配的正确函数名。单个脚本可包含多个函数。
创建/更新 schema 请参考references/schemas/request.yml,响应结构请参考references/schemas/response.yml。
关键字段:
- ——描述性名称(惯例:
name,例如<系统> - <步骤> - <钩子类型>)"Salesforce - getBatchRecords - postResponseMap" - ——JavaScript源代码
content
5. Wire the script to the resource
5. 将脚本关联到资源
Wiring depends on the hook type:
| Hook | Wiring pattern | Where |
|---|---|---|
| | Export or import resource |
| | Export or import resource |
| | Flow |
| | Router in flow |
| | API resource |
| | 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.
关联方式取决于钩子类型:
| 钩子 | 关联模式 | 位置 |
|---|---|---|
| | 导出或导入资源 |
| | 导出或导入资源 |
| | 流程 |
| | 流程中的路由器 |
| | API资源 |
| | AS2连接 |
基于钩子的关联(preSavePage、preMap等)是叠加式的——添加钩子不会移除现有配置。替代式关联(filter、transform)会替换现有的过滤器/转换表达式。
6. Test and iterate
6. 测试与迭代
bash
undefinedbash
undefinedEnable debug logging on the script
启用脚本的调试日志
celigo scripts enable-debug <script-id>
celigo scripts enable-debug <script-id>
Run the flow or API that triggers the script
运行触发脚本的流程或API
celigo flows run <flow-id> -y
celigo flows run <flow-id> -y
Check debug logs
查看调试日志
celigo scripts debug-logs <script-id> --since 30
celigo scripts debug-logs <script-id> --since 30
Check execution logs
查看执行日志
celigo scripts debug-logs <script-id> --level error --limit 20
celigo scripts debug-logs <script-id> --level error --limit 20
Disable debug when done
测试完成后禁用调试
celigo scripts disable-debug <script-id>
undefinedceligo scripts disable-debug <script-id>
undefinedAvailable Modules
可用模块
Scripts can import three built-in modules:
脚本可以导入三个内置模块:
integrator-api
integrator-api
Call Celigo APIs from within the script -- run exports, read connections, trigger imports.
javascript
import { exports, imports, connections } from 'integrator-api'
const result = exports.run({ _id: 'exportId' })
const conn = connections.get({ _id: 'connectionId' })Useful in for enrichment, for orchestration, and for triggering downstream processes.
preSavePagehandleRequestpostSubmit在脚本内调用Celigo APIs——运行导出、读取连接、触发导入。
javascript
import { exports, imports, connections } from 'integrator-api'
const result = exports.run({ _id: 'exportId' })
const conn = connections.get({ _id: 'connectionId' })适用于中的数据增强、中的编排以及中的下游流程触发。
preSavePagehandleRequestpostSubmitdayjs
dayjs
Date and time manipulation. Handles parsing, formatting, diffing, and timezone conversions without manual date math.
javascript
import dayjs from 'dayjs'
const formatted = dayjs(record.createdAt).format('YYYY-MM-DD')
const isRecent = dayjs().diff(dayjs(record.updatedAt), 'day') < 7日期和时间处理。无需手动日期运算即可处理解析、格式化、差值计算和时区转换。
javascript
import dayjs from 'dayjs'
const formatted = dayjs(record.createdAt).format('YYYY-MM-DD')
const isRecent = dayjs().diff(dayjs(record.updatedAt), 'day') < 7sjcl
sjcl
Stanford JavaScript Crypto Library for hashing, encryption, and HMAC generation.
javascript
import sjcl from 'sjcl'
const hash = sjcl.hash.sha256.hash(payload)
const hexDigest = sjcl.codec.hex.fromBits(hash)用于哈希、加密和HMAC生成的Stanford JavaScript Crypto Library。
javascript
import sjcl from 'sjcl'
const hash = sjcl.hash.sha256.hash(payload)
const hexDigest = sjcl.codec.hex.fromBits(hash)CLI Commands
CLI命令
CRUD
CRUD操作
bash
celigo scripts list
celigo scripts get <id>
celigo scripts create < script.json
celigo scripts update <id> < script.json
celigo scripts set <id> name="New Name"
celigo scripts delete <id>bash
celigo scripts list
celigo scripts get <id>
celigo scripts create < script.json
celigo scripts update <id> < script.json
celigo scripts set <id> name="New Name"
celigo scripts delete <id>Logs and Debugging
日志与调试
bash
celigo scripts debug-logs <id> [--limit N] [--offset N] [--level error|warn|info|debug] [--start-date ISO] [--end-date ISO]
celigo scripts enable-debug <id> [--duration <minutes>]
celigo scripts disable-debug <id>
celigo scripts debug-logs <id> [--since <minutes>] [--flow-id <id>]bash
celigo scripts debug-logs <id> [--limit N] [--offset N] [--level error|warn|info|debug] [--start-date ISO] [--end-date ISO]
celigo scripts enable-debug <id> [--duration <minutes>]
celigo scripts disable-debug <id>
celigo scripts debug-logs <id> [--since <minutes>] [--flow-id <id>]Authoring Against Sample Data
基于示例数据编写脚本
Script logic is runtime-dependent -- it only works against the specific shape of data it handles -- so a script is written and validated against a sample input. The sample comes from the step's recent runs, a / capture on the parent flow, or a JSON example you supply. A script written without sample data is written blind.
testrunTreat authoring as a loop, not a one-shot:
- Generate or edit the function against the sample input.
- Run it against that sample.
- Check the output for errors or obviously-wrong results.
- Iterate -- refine and re-run until it passes.
A script that fails on the first pass isn't a failure; it's the first turn of the loop -- the runtime error and the code are both visible, so the next pass is informed by what went wrong. When no sample is available (the step has never run and no parent provided records), supply a JSON example before writing the script; a user-supplied sample plays the same validation role as captured runtime data.
脚本逻辑依赖运行时环境——仅能处理特定结构的数据——因此脚本需基于示例输入编写和验证。示例数据来自步骤的近期运行记录、父流程的/捕获结果,或你提供的JSON示例。未基于示例数据编写的脚本相当于盲写。
testrun将编写过程视为循环,而非一次性操作:
- 生成或编辑针对示例输入的函数。
- 运行脚本处理该示例数据。
- 检查输出是否存在错误或明显错误的结果。
- 迭代——优化并重新运行,直到通过测试。
首次运行失败的脚本并非失败;这只是循环的第一轮——运行时错误和代码都可见,因此下一轮可以根据错误信息进行优化。当没有可用示例数据时(步骤从未运行且父流程未提供记录),编写脚本前先提供JSON示例;用户提供的示例与捕获的运行时数据具有相同的验证作用。
Execution Logs and the Debug Window
执行日志与调试窗口
Scripts write to a per-script execution log using standard methods. What gets captured depends on the level:
console- ,
console.error(),console.warn(), andconsole.info()are always captured -- no setup, no toggle (console.log()andinfoare equivalent).log - is gated: its output is persisted only while a time-bounded debug window is open on the script. When the window is closed,
console.debug()still runs but its output is dropped.console.debug()
"Debugging a script" here means exactly this -- turning on capture for a window. It is not breakpoint-style debugging; there is no pausing or stepping through code. Open a window only when you need output; for "why did this fail?" / "what errors happened?", the always-captured error/warn/info/log entries are usually enough.
console.debug()console.debug()The debug window is time-bounded and expires automatically -- it defaults to a short window (15 minutes) and is opened with . There's no need to close it manually, though ends it early.
celigo scripts enable-debug <id> [--duration <minutes>]celigo scripts disable-debug <id>Each log entry records its time, level ( / / / ), the message, and two locating fields:
INFOWARNERRORDEBUG- -- which hook produced the entry (
functionType,preMap, etc.)postSubmit - -- the export or import that ran the hook
_resourceId
Because one script can carry many functions across many hook sites, an unfiltered log stream interleaves entries from every consumer. Filter aggressively when reading -- by flow (), by time ( / / ), and by level (). The practical query is "logs for this script, in this flow, on this step, during this window."
<!-- TIER:3 -->--flow-id--since--start-date--end-date--level脚本使用标准方法写入每个脚本专属的执行日志。捕获的内容取决于日志级别:
console- 、
console.error()、console.warn()和console.info()始终会被捕获——无需设置或切换(console.log()和info等效)。log - 受限制:仅当脚本的限时调试窗口开启时,其输出才会被持久化。窗口关闭后,
console.debug()仍会执行,但输出会被丢弃。console.debug()
此处的"调试脚本"特指——为脚本开启捕获窗口。这并非断点式调试;无法暂停或单步执行代码。仅当需要输出时才开启窗口;对于"为什么失败?" / "发生了什么错误?",始终捕获的error/warn/info/log条目通常足够。
console.debug()console.debug()调试窗口是限时的,会自动过期——默认短窗口(15分钟),可通过开启。无需手动关闭,不过可提前结束。
celigo scripts enable-debug <id> [--duration <minutes>]celigo scripts disable-debug <id>每条日志条目会记录时间、级别( / / / )、消息以及两个定位字段:
INFOWARNERRORDEBUG- ——生成条目的钩子类型(
functionType、preMap等)postSubmit - ——运行该钩子的导出或导入步骤ID
_resourceId
由于一个脚本可包含多个函数并用于多个钩子点,未过滤的日志流会交错显示所有使用该脚本的条目。读取时需严格过滤——按流程()、时间( / / )和级别()。常用查询为"该脚本在指定流程、指定步骤、指定时间范围内的日志"。
<!-- TIER:3 -->--flow-id--since--start-date--end-date--levelPre-Submit Checklist
提交前检查清单
Before creating or updating a script, verify:
- Hook point is correct -- the function name matches the hook type being wired (e.g., function for a
preSavePagereference)hooks.preSavePage - Return value matches contract -- batch hooks (,
preMap,postMap,postSubmit) return arrays that match the input array length exactlypostResponseMap - Error handling uses return pattern, not throw -- per-record errors use return values, not thrown exceptions (which fail the entire page)
{ errors: [...] } - Expression alternative considered -- filter, transform, and output filter can use expressions; only use a script when expressions cannot handle the logic
- field is included on PUT -- omitting
contenton update erases the code; always GET first, modify, then PUTcontent - Debug mode is disabled after testing -- to avoid log noise in production
celigo scripts disable-debug <id>
创建或更新脚本前,请验证:
- 钩子点正确——函数名与要关联的钩子类型匹配(例如函数对应
preSavePage引用)hooks.preSavePage - 返回值符合约定——批量钩子(、
preMap、postMap、postSubmit)返回的数组必须与输入数组长度完全一致postResponseMap - 错误处理使用返回模式而非抛出异常——单条记录的错误使用返回值,而非抛出异常(会导致整个分页失败)
{ errors: [...] } - 已考虑表达式替代方案——filter、transform和output filter可使用表达式;仅当表达式无法处理逻辑时才使用脚本
- PUT请求包含字段——更新时省略
content会清除代码;始终先GET、修改,再PUTcontent - 测试后已禁用调试模式——执行避免生产环境日志冗余
celigo scripts disable-debug <id>
Gotchas
注意事项
- Array length contracts are strict. ,
preMap, andpostMapreturn arrays MUST match the input array length. Returning fewer or more elements fails the entire page silently or with cryptic errors.postResponseMap - stops pagination, not the flow. In
abort: true, settingpreSavePagetells the export to stop generating new pages. It does NOT stop the flow or cancel processing of the current page's records.abort: true - Script is not returned in list responses.
contentshows metadata only. You mustceligo scripts listto see the actual JavaScript code.celigo scripts get <id> - PUT erases if omitted. Always GET the script first, modify, then PUT the complete object. The
contentcommand handles this automatically.set - One script resource can contain multiple functions. A single script with both and
preSavePagefunctions can be wired to different resources by specifying thepreMapname in each hook reference.function - Throwing an exception fails the entire page. In batch hooks (preSavePage, preMap, postMap, postSubmit), an unhandled exception fails ALL records on that page, not just one. Use the error return pattern () for per-record errors.
{ errors: [...] } - lives on the flow, not the resource. The hook is configured on the
postResponseMapentry in the flow/API/tool, even though it processes export or import response data.pageProcessors[] - filter/transform scripts replace expression-based alternatives. Wiring a script filter replaces any existing expression filter. They cannot coexist on the same resource.
- output goes to script logs, not stdout. Use
console.log()to see output. Logs require debug mode to be enabled for debug-level messages.celigo scripts debug-logs - Only needs the debug window.
console.debug()/error/warn/infoare always captured;logoutput is persisted only while a time-bounded debug window is open (debug). A closed window silently dropsceligo scripts enable-debugoutput.console.debug() - Shared-script logs interleave across hook sites. One script can hold many functions used by many exports/imports, so its log stream mixes entries from every consumer. Filter by flow, level, and time when reading; each entry's and
functionTypeidentify where it came from._resourceId - Clearing a script-mode filter/transform reverts the slot to declarative mode. The four mode-switchable slots (,
filter,input_filter,transform) hold a rule tree or a script, never both -- removing the script drops the slot back to rules, and wiring a script replaces the rules.branching
- 数组长度约定严格。、
preMap和postMap返回的数组必须与输入数组长度一致。返回元素过多或过少会导致整个分页静默失败或出现模糊错误。postResponseMap - 停止分页而非流程。在
abort: true中设置preSavePage会告知导出停止生成新分页。但不会停止流程或取消当前分页记录的处理。abort: true - 脚本不会在列表响应中返回。
content仅显示元数据。必须执行celigo scripts list才能查看实际JavaScript代码。celigo scripts get <id> - PUT请求若省略会清除内容。始终先GET脚本、修改,再PUT完整对象。
content命令会自动处理此操作。set - 单个脚本资源可包含多个函数。同时包含和
preSavePage函数的单个脚本可通过在每个钩子引用中指定preMap名称,关联到不同资源。function - 抛出异常会导致整个分页失败。在批量钩子(preSavePage、preMap、postMap、postSubmit)中,未处理的异常会导致该分页所有记录失败,而非单条记录。使用错误返回模式()处理单条记录错误。
{ errors: [...] } - 属于流程而非资源。该钩子配置在流程/API/工具的
postResponseMap条目上,尽管它处理的是导出或导入的响应数据。pageProcessors[] - filter/transform脚本会替代基于表达式的方案。关联脚本过滤器会替换任何现有的表达式过滤器。它们无法在同一资源上共存。
- 输出会写入脚本日志而非stdout。使用
console.log()查看输出。调试级消息需要启用调试模式才能记录。celigo scripts debug-logs - 仅需要调试窗口。
console.debug()/error/warn/info始终会被捕获;log输出仅在限时调试窗口开启时(debug)才会被持久化。窗口关闭后,celigo scripts enable-debug输出会被静默丢弃。console.debug() - 共享脚本的日志会在多个钩子点交错显示。一个脚本可包含多个函数并用于多个导出/导入步骤,因此其日志流会混合所有使用该脚本的条目。读取时按流程、级别和时间过滤;每条条目的和
functionType可标识其来源。_resourceId - 清除脚本模式的filter/transform会将插槽恢复为声明式模式。四个可切换模式的插槽(、
filter、input_filter、transform)只能容纳规则树或脚本,不能同时存在——移除脚本会将插槽恢复为规则模式,关联脚本会替换规则。branching
Common Errors
常见错误
| Error / Symptom | Cause | Fix |
|---|---|---|
| "The number of elements in the return value must match the input" | Batch hook return array length differs from input | Ensure return array has exactly |
| All records on a page fail with no per-record detail | Unhandled exception thrown in batch hook | Wrap logic in try/catch; return |
| Script content is empty after update | PUT omitted the | Always GET first, modify, then PUT the complete object (or use |
| | This is expected behavior; use error returns or filter to skip individual records |
| Script not executing / no logs | Script not wired to any resource, or debug mode not enabled | Verify |
| "Function not found" or similar | | Check the function name matches exactly (case-sensitive) between the hook config and the script's |
| Filter always returns all/no records | Filter function returns truthy/falsy value instead of strict boolean | Return explicit |
| Hook wired on the import/export instead of the flow's | Move the hook config to the |
| No debug window was open while the script ran | Open a window first ( |
| Log stream is a confusing mix of unrelated entries | Script is shared across many hooks/flows and the query is unfiltered | Filter by |
| 错误/症状 | 原因 | 修复方案 |
|---|---|---|
| "返回值中的元素数量必须与输入匹配" | 批量钩子返回的数组长度与输入不同 | 确保返回数组的长度恰好等于 |
| 分页中所有记录失败且无单条记录详情 | 批量钩子中抛出未处理的异常 | 将逻辑包裹在try/catch中;使用 |
| 更新后脚本内容为空 | PUT请求省略了 | 始终先GET、修改,再PUT完整对象(或使用 |
设置 | | 这是预期行为;使用错误返回或过滤器跳过单条记录 |
| 脚本未执行/无日志 | 脚本未关联到任何资源,或未启用调试模式 | 验证导出/导入/流程上的 |
| "未找到函数"或类似错误 | 钩子引用中的 | 检查钩子配置与脚本 |
| 过滤器始终返回所有/无记录 | 过滤器函数返回真值/假值而非严格布尔值 | 返回明确的 |
| 钩子关联到了导入/导出而非流程的 | 将钩子配置移至流程的 |
| 脚本运行时未开启调试窗口 | 先开启窗口( |
| 日志流混杂无关条目 | 脚本在多个钩子/流程中共享且查询未过滤 | 按 |