@celigo/api-specs 0.2.138 → 0.2.140

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/dist/tool.yml CHANGED
@@ -1224,8 +1224,9 @@ paths:
1224
1224
  $ref: '#/components/responses/404-not-found'
1225
1225
  '422':
1226
1226
  description: |-
1227
- The Tool ran but a step failed. Includes `invocationId` when logging is active, so
1228
- the failed run can be opened in the run history.
1227
+ A step failed, or the Tool was refused before any step ran because its branches
1228
+ don't all merge back (`tool_dangling_branch`). Either way the response includes
1229
+ `invocationId` when logging is active, so the run can be opened in the run history.
1229
1230
  content:
1230
1231
  application/json:
1231
1232
  schema:
@@ -2398,6 +2399,11 @@ paths:
2398
2399
  `GET /v1/tools/{_id}/test/run/{runId}/{_stepId}` to inspect stage-by-stage
2399
2400
  results. The run id for follow-up calls is the `flowJob._id` value.
2400
2401
 
2402
+ A test run is not free of outside calls: lookups call their sources live. Imports never
2403
+ send; each returns its saved `mockResponse`, or a placeholder response when none is saved
2404
+ (see `mockResponse` on imports). A second test run started while one is still running is
2405
+ refused with `test_run_not_allowed`.
2406
+
2401
2407
  Test runs are a separate, short-lived history from normal runs — capture
2402
2408
  any follow-up step or log details soon after the run completes.
2403
2409
  operationId: testRunTool
@@ -2520,7 +2526,14 @@ paths:
2520
2526
  status: completed
2521
2527
  numError: 1
2522
2528
  '400':
2523
- $ref: '#/components/responses/400-bad-request'
2529
+ description: |-
2530
+ The run was refused before any step ran. A Tool with no steps fails with
2531
+ `tool_empty_router`, and one whose branches don't all merge back with
2532
+ `tool_dangling_branch`; re-running the same document fails the same way.
2533
+ content:
2534
+ application/json:
2535
+ schema:
2536
+ $ref: '#/components/schemas/Error'
2524
2537
  '401':
2525
2538
  $ref: '#/components/responses/401-unauthorized'
2526
2539
  '404':
@@ -3546,14 +3559,15 @@ components:
3546
3559
  - `objectarray`: Array of objects (most common array type)
3547
3560
  - `arrayarray`: Array of arrays (for matrix/table structures)
3548
3561
 
3549
- Array dataTypes can be populated two ways: pass a source array through
3550
- unchanged via `extract` alone (when the source is already an array of
3551
- the right shape), or construct/iterate via `buildArrayHelper`.
3562
+ Array dataTypes can be populated three ways: pass a source array
3563
+ through unchanged via a JSONPath `extract` alone (when the source is
3564
+ already an array of the right shape), construct/iterate via
3565
+ `buildArrayHelper`, or set a constant with `hardCodedValue`.
3552
3566
 
3553
3567
  IMPORTANT: The dataType controls which additional fields are relevant:
3554
3568
  - For date-like string fields: extractDateFormat, generateDateFormat, etc. become relevant
3555
3569
  - For object types: 'mappings' array becomes relevant
3556
- - For array types: `buildArrayHelper` is one option (see above)
3570
+ - For array types: a JSONPath `extract` alone, `buildArrayHelper`, or `hardCodedValue` (see above)
3557
3571
 
3558
3572
  When analyzing existing mappings or generating new ones, always check dataType first
3559
3573
  to understand what additional fields should be present.
@@ -3616,9 +3630,12 @@ components:
3616
3630
  - Access input record fields with {{record.fieldName}} notation; a grouped
3617
3631
  (array) record binds as `rows` instead — {{rows.0.fieldName}} / {{#each rows}}
3618
3632
  - Examples: "{{record.firstName}} {{record.lastName}}", "{{#if record.isActive}}Active{{else}}Inactive{{/if}}"
3619
- - Valid on `object`, `objectarray`, and primitive-array dataTypes as
3620
- well as scalars — the rendered template output must parse into the
3621
- declared shape
3633
+ - Valid on scalars and on `object` rows, where the rendered output must
3634
+ parse into an object. On an array row the template goes in a
3635
+ `buildArrayHelper` entry instead: on an `objectarray` row's own
3636
+ `extract` it is refused with 422 ("buildArrayHelper" must be present
3637
+ for object array datatype), and on a primitive-array row's own
3638
+ `extract` it renders null without an error
3622
3639
 
3623
3640
  ```json
3624
3641
  "extract": "{{record.price}} {{record.currency}}" // Combines two fields
@@ -3817,6 +3834,19 @@ components:
3817
3834
  - countryCodeToName
3818
3835
  - statusMapping
3819
3836
  - departmentCodes
3837
+ hardCodedValue:
3838
+ type: string
3839
+ description: |
3840
+ Constant written to the destination instead of an extracted value. On a primitive
3841
+ array (`stringarray`, `numberarray`, `booleanarray`) the string is split on commas,
3842
+ verbatim and untrimmed, into elements of the array's type (`"A,B"` gives `["A", "B"]`).
3843
+ On an `object` it must be a JSON object string and on an `objectarray` a JSON array
3844
+ string (an object string becomes one element); the save parses it and refuses non-JSON
3845
+ or the wrong shape with 422, and an array row with a constant needs no `buildArrayHelper`.
3846
+ examples:
3847
+ - USD
3848
+ - A,B
3849
+ - '[{"code": "A"}, {"code": "B"}]'
3820
3850
  description:
3821
3851
  type: string
3822
3852
  description: |
@@ -3952,15 +3982,25 @@ components:
3952
3982
  processor renders the entire destination array as null with no
3953
3983
  validation error. To emit a fixed number of static elements, add
3954
3984
  that many sibling constructed entries — never index the extract.
3985
+ - |-
3986
+ An entry's `extract` can be a Handlebars template. On an
3987
+ `objectarray` it must render a JSON object (one element) or a JSON
3988
+ array (one element per item). On a primitive array each entry
3989
+ renders one element, so a serialized array becomes one string
3990
+ element. A bare literal entry extract is refused with 422 ("extract
3991
+ only supports json path or handlebars expression"); set a constant
3992
+ with the row's `hardCodedValue` instead.
3955
3993
  description: |
3956
3994
  **Purpose**
3957
3995
  Configures how to construct arrays in the output record, handling various array types and inputs.
3958
3996
 
3959
3997
  **Guidance**
3960
- This is the REQUIRED mechanism for ALL array data types:
3998
+ This is the mechanism for building array data types:
3961
3999
 
3962
4000
  **When to Use**
3963
- - REQUIRED when dataType ends with "array" (stringarray, objectarray, etc.)
4001
+ - REQUIRED when dataType ends with "array" (stringarray, objectarray, etc.), unless the
4002
+ row passes a source array through with a JSONPath `extract` alone or sets
4003
+ `hardCodedValue`
3964
4004
  - Each entry in this array contributes elements to the output array
3965
4005
  - Multiple entries allow combining data from different input arrays
3966
4006
 
@@ -4585,14 +4625,15 @@ components:
4585
4625
  - `objectarray`: Array of objects (most common array type)
4586
4626
  - `arrayarray`: Array of arrays (for matrix/table structures)
4587
4627
 
4588
- Array dataTypes can be populated two ways: pass a source array through
4589
- unchanged via `extract` alone (when the source is already an array of
4590
- the right shape), or construct/iterate via `buildArrayHelper`.
4628
+ Array dataTypes can be populated three ways: pass a source array
4629
+ through unchanged via a JSONPath `extract` alone (when the source is
4630
+ already an array of the right shape), construct/iterate via
4631
+ `buildArrayHelper`, or set a constant with `hardCodedValue`.
4591
4632
 
4592
4633
  IMPORTANT: The dataType controls which additional fields are relevant:
4593
4634
  - For date-like string fields: extractDateFormat, generateDateFormat, etc. become relevant
4594
4635
  - For object types: 'mappings' array becomes relevant
4595
- - For array types: `buildArrayHelper` is one option (see above)
4636
+ - For array types: a JSONPath `extract` alone, `buildArrayHelper`, or `hardCodedValue` (see above)
4596
4637
 
4597
4638
  When analyzing existing mappings or generating new ones, always check dataType first
4598
4639
  to understand what additional fields should be present.
@@ -4655,9 +4696,12 @@ components:
4655
4696
  - Access input record fields with {{record.fieldName}} notation; a grouped
4656
4697
  (array) record binds as `rows` instead — {{rows.0.fieldName}} / {{#each rows}}
4657
4698
  - Examples: "{{record.firstName}} {{record.lastName}}", "{{#if record.isActive}}Active{{else}}Inactive{{/if}}"
4658
- - Valid on `object`, `objectarray`, and primitive-array dataTypes as
4659
- well as scalars — the rendered template output must parse into the
4660
- declared shape
4699
+ - Valid on scalars and on `object` rows, where the rendered output must
4700
+ parse into an object. On an array row the template goes in a
4701
+ `buildArrayHelper` entry instead: on an `objectarray` row's own
4702
+ `extract` it is refused with 422 ("buildArrayHelper" must be present
4703
+ for object array datatype), and on a primitive-array row's own
4704
+ `extract` it renders null without an error
4661
4705
 
4662
4706
  ```json
4663
4707
  "extract": "{{record.price}} {{record.currency}}" // Combines two fields
@@ -4856,6 +4900,19 @@ components:
4856
4900
  - countryCodeToName
4857
4901
  - statusMapping
4858
4902
  - departmentCodes
4903
+ hardCodedValue:
4904
+ type: string
4905
+ description: |
4906
+ Constant written to the destination instead of an extracted value. On a primitive
4907
+ array (`stringarray`, `numberarray`, `booleanarray`) the string is split on commas,
4908
+ verbatim and untrimmed, into elements of the array's type (`"A,B"` gives `["A", "B"]`).
4909
+ On an `object` it must be a JSON object string and on an `objectarray` a JSON array
4910
+ string (an object string becomes one element); the save parses it and refuses non-JSON
4911
+ or the wrong shape with 422, and an array row with a constant needs no `buildArrayHelper`.
4912
+ examples:
4913
+ - USD
4914
+ - A,B
4915
+ - '[{"code": "A"}, {"code": "B"}]'
4859
4916
  description:
4860
4917
  type: string
4861
4918
  description: |
@@ -4991,15 +5048,25 @@ components:
4991
5048
  processor renders the entire destination array as null with no
4992
5049
  validation error. To emit a fixed number of static elements, add
4993
5050
  that many sibling constructed entries — never index the extract.
5051
+ - |-
5052
+ An entry's `extract` can be a Handlebars template. On an
5053
+ `objectarray` it must render a JSON object (one element) or a JSON
5054
+ array (one element per item). On a primitive array each entry
5055
+ renders one element, so a serialized array becomes one string
5056
+ element. A bare literal entry extract is refused with 422 ("extract
5057
+ only supports json path or handlebars expression"); set a constant
5058
+ with the row's `hardCodedValue` instead.
4994
5059
  description: |
4995
5060
  **Purpose**
4996
5061
  Configures how to construct arrays in the output record, handling various array types and inputs.
4997
5062
 
4998
5063
  **Guidance**
4999
- This is the REQUIRED mechanism for ALL array data types:
5064
+ This is the mechanism for building array data types:
5000
5065
 
5001
5066
  **When to Use**
5002
- - REQUIRED when dataType ends with "array" (stringarray, objectarray, etc.)
5067
+ - REQUIRED when dataType ends with "array" (stringarray, objectarray, etc.), unless the
5068
+ row passes a source array through with a JSONPath `extract` alone or sets
5069
+ `hardCodedValue`
5003
5070
  - Each entry in this array contributes elements to the output array
5004
5071
  - Multiple entries allow combining data from different input arrays
5005
5072
 
@@ -6030,7 +6097,7 @@ components:
6030
6097
  - envelope
6031
6098
  x-enumDescriptions:
6032
6099
  record: The transform processor evaluates `mappings[].extract` JSONPath against the flat record itself (`$.field`, no `record.` segment) — the default when absent.
6033
- envelope: The transform processor evaluates JSONPath against the wrapped runtime envelope `{record, settings, job, …}` (file-provider steps also carry `fileMeta`) — extracts must include the `record.` segment (`$.record.field`).
6100
+ envelope: The transform processor evaluates JSONPath against the wrapped runtime envelope `{record, job, testMode, settings, headers, queryParams}` (file-provider steps also carry `fileMeta`) — record fields need the `record.` segment (`$.record.field`), while `headers` and `queryParams` sit beside `record` (`$.headers['X-Id']`, `$.queryParams.src`).
6034
6101
  description: |
6035
6102
  Controls the JSON shape the transformTwoDotZero processor
6036
6103
  evaluates `mappings[].extract` JSONPath values against at
@@ -6050,10 +6117,12 @@ components:
6050
6117
  `"$.PLACEHOLDER_<field>"`.
6051
6118
  This is the dominant Celigo idiom and the right choice for new transforms.
6052
6119
  - `envelope`: the processor sees a wrapped object
6053
- `{record: {...}, settings: ..., job: ...}` (plus
6054
- `fileMeta` on file-provider steps).
6120
+ `{record: {...}, job, testMode, settings, headers,
6121
+ queryParams}` (plus `fileMeta` on file-provider steps).
6055
6122
  `mappings[].extract` JSONPath MUST include the
6056
- `record.` segment — e.g. `"$.record.orderId"`;
6123
+ `record.` segment for record fields — e.g.
6124
+ `"$.record.orderId"` — and reads `headers` and
6125
+ `queryParams` beside it (`$.headers['X-Id']`);
6057
6126
  PLACEHOLDER extracts use `"$.record.PLACEHOLDER_<field>"`.
6058
6127
  Pick this only when the transform was authored against
6059
6128
  the envelope shape on purpose.
@@ -6062,6 +6131,11 @@ components:
6062
6131
  (`{{record.field}}`, `{{dateFormat ... record.field}}`)
6063
6132
  ALWAYS reference the `record` root regardless of
6064
6133
  `inputContext` — only JSONPath anchoring flips.
6134
+ - |-
6135
+ In `envelope` mode a `modify` transform merges its mapped
6136
+ fields into `record` and keeps the rest of the envelope
6137
+ around it; a `create` transform returns only the mapped
6138
+ fields, as a bare record.
6065
6139
  - |-
6066
6140
  Emit `inputContext` explicitly on new v2 transforms:
6067
6141
  unset is read as `record`, but stating it makes the
@@ -6082,13 +6156,17 @@ components:
6082
6156
 
6083
6157
  - ``envelope``: the transform processor sees a wrapped
6084
6158
  object of the shape
6085
- ``{record: {...}, settings: ..., job: ...}`` (plus
6086
- ``fileMeta`` on file-provider steps) — the
6159
+ ``{record: {...}, job, testMode, settings, headers,
6160
+ queryParams}`` (plus ``fileMeta`` on file-provider
6161
+ steps; ``headers`` and ``queryParams`` sit beside
6162
+ ``record``) — the
6087
6163
  same runtime-context envelope Handlebars / SQL /
6088
6164
  GraphQL templates render against. ``mappings[].extract``
6089
- JSONPath values MUST include the ``record.`` segment
6090
- — for example ``"$.record.orderId"`` or
6091
- ``"$.record.customer.email"``. PLACEHOLDER extracts
6165
+ JSONPath values for record fields MUST include the
6166
+ ``record.`` segment — for example ``"$.record.orderId"``
6167
+ or ``"$.record.customer.email"`` — while ``headers`` and
6168
+ ``queryParams`` are read beside it
6169
+ (``"$.headers['X-Id']"``). PLACEHOLDER extracts
6092
6170
  use ``"$.record.PLACEHOLDER_<field>"``. Pick this
6093
6171
  mode only when the export was authored against the
6094
6172
  envelope shape on purpose (typically because an
@@ -19798,7 +19876,7 @@ components:
19798
19876
  without the array); a mapping reshapes the message instead.
19799
19877
  - |-
19800
19878
  Publishing is not limited to flows. Verified surfaces: a flow step; an API step (the API
19801
- invoked at `POST /apis/{version}/{relativeURI}`); a Tool reached through a `ToolImport`
19879
+ invoked at `POST /apis/{version}{relativeURI}`); a Tool reached through a `ToolImport`
19802
19880
  step in a flow; and `POST /v1/imports/{_id}/invoke` with `{"data": [record, ...]}`. A flow
19803
19881
  or API test run (`/test/run`) publishes nothing — import steps are mocked there.
19804
19882
  properties:
@@ -23432,7 +23510,7 @@ components:
23432
23510
 
23433
23511
  **Common filter patterns**
23434
23512
 
23435
- 1. **Pattern matching**: Using wildcards like `*` and `?`
23513
+ 1. **Pattern matching**: Regular expressions with `matches`
23436
23514
  2. **Value range filtering**: Numbers between min and max values
23437
23515
  3. **Date range filtering**: Items created/modified within specific time ranges
23438
23516
  4. **Status checking**: Items with specific status values or properties
@@ -23482,9 +23560,12 @@ components:
23482
23560
  - `"endswith"`: String ends with specified suffix (ends with)
23483
23561
  - `"contains"`: String contains specified substring (contains)
23484
23562
  - `"doesnotcontain"`: String does not contain specified substring (does not contain)
23485
- - `"isempty"`: Field is empty or null (is empty)
23486
- - `"isnotempty"`: Field contains a value (is not empty)
23487
- - `"matches"`: Matches specified pattern (matches)
23563
+ - `"empty"`: Field is missing or empty (is empty)
23564
+ - `"notempty"`: Field contains a value (is not empty)
23565
+ - `"matches"`: Matches a regular expression (matches)
23566
+
23567
+ `isempty`, `isnotempty` and `anyof` are not operators: they are refused with 422
23568
+ "Invalid operation: <name>".
23488
23569
 
23489
23570
  **Logical Operators**
23490
23571
  - `"and"`: All conditions must be true
@@ -23504,7 +23585,11 @@ components:
23504
23585
  **Using `extract` to access record fields:**
23505
23586
  - Retrieves values from the current record being processed
23506
23587
  - Can access nested properties using dot notation (e.g., `"customer.email"`)
23507
- - Returns the raw field value which may need type conversion
23588
+ - In a record filter, must be wrapped in a type conversion (`string`, `number`,
23589
+ `boolean` or `epochtime`): a bare `["extract", ...]` operand is refused with 422
23590
+ "Field operation extract must be called by a Type Conversion Operation but was called
23591
+ by <operator>", both when an import's filter is saved and by
23592
+ `POST /v1/processors/filter`
23508
23593
 
23509
23594
  **Using `settings` to access configuration values:**
23510
23595
  - Retrieves values from the integration's configuration settings
@@ -23522,7 +23607,20 @@ components:
23522
23607
  - `"floor"`: Round number down to the nearest integer
23523
23608
  - `"abs"`: Get absolute value of a number
23524
23609
 
23525
- Type conversion operators are often necessary when comparing extracted field values against literals or when the field type doesn't match the comparison operator's expected type. For example:
23610
+ **Handlebars operands**
23611
+ - An operand can also be a string holding exactly one Handlebars expression, such as
23612
+ `"{{record.status}}"` or `"{{lowercase record.code}}"`, on either side of the
23613
+ operator. It renders against the record (`record.<field>`; an unprefixed
23614
+ `{{status}}` renders empty) before the comparison.
23615
+ - The rendered value is a string: wrap it in `["number", ...]` to compare it with a
23616
+ number, or the rule is refused with 422.
23617
+ - `epochtime` does not render Handlebars: `["epochtime", "{{timestamp}}"]` is refused
23618
+ with 422 "invalid datetime format".
23619
+ - A string with text around the expression, or with more than one expression, is
23620
+ compared as a literal.
23621
+
23622
+ Choose the type conversion that matches the comparison — `number` for numeric
23623
+ comparisons, `epochtime` for dates, `string` for text. For example:
23526
23624
 
23527
23625
  ```json
23528
23626
  [
@@ -23613,8 +23711,11 @@ components:
23613
23711
  [
23614
23712
  "notequals",
23615
23713
  [
23616
- "extract",
23617
- "status"
23714
+ "string",
23715
+ [
23716
+ "extract",
23717
+ "status"
23718
+ ]
23618
23719
  ],
23619
23720
  "cancelled"
23620
23721
  ]
@@ -23625,8 +23726,11 @@ components:
23625
23726
  [
23626
23727
  "startswith",
23627
23728
  [
23628
- "extract",
23629
- "filename"
23729
+ "string",
23730
+ [
23731
+ "extract",
23732
+ "filename"
23733
+ ]
23630
23734
  ],
23631
23735
  "HC"
23632
23736
  ]
@@ -23647,29 +23751,26 @@ components:
23647
23751
  ]
23648
23752
  ```
23649
23753
 
23650
- Example 4: Order date is after January 1, 2023
23754
+ Example 4: Order date is after January 1, 2023 (UTC). Compare dates as `epochtime`
23755
+ against epoch milliseconds: a `string` comparison of ISO timestamps orders values with
23756
+ different UTC offsets wrongly.
23651
23757
  ```json
23652
23758
  [
23653
23759
  "greaterthan",
23654
23760
  [
23655
- "extract",
23656
- "orderDate"
23657
- ],
23658
- "2023-01-01T00:00:00Z"
23659
- ]
23660
- ```
23661
-
23662
- Example 5: Category contains any of ["Urgent", "High Priority"]
23663
- ```json
23664
- [
23665
- "anyof",
23666
- [
23667
- "extract",
23668
- "category"
23761
+ "epochtime",
23762
+ [
23763
+ "extract",
23764
+ "orderDate"
23765
+ ]
23669
23766
  ],
23670
- ["Urgent", "High Priority"]
23767
+ 1672531200000
23671
23768
  ]
23672
23769
  ```
23770
+ x-celigo-ai-guidance:
23771
+ - |-
23772
+ To test whether a field has a value, use `notempty` on the wrapped extract, not a
23773
+ `matches` pattern: a record without the field matches `.*\S.*`.
23673
23774
  items:
23674
23775
  oneOf:
23675
23776
  - title: String
@@ -563,7 +563,7 @@ components:
563
563
 
564
564
  **Common filter patterns**
565
565
 
566
- 1. **Pattern matching**: Using wildcards like `*` and `?`
566
+ 1. **Pattern matching**: Regular expressions with `matches`
567
567
  2. **Value range filtering**: Numbers between min and max values
568
568
  3. **Date range filtering**: Items created/modified within specific time ranges
569
569
  4. **Status checking**: Items with specific status values or properties
@@ -613,9 +613,12 @@ components:
613
613
  - `"endswith"`: String ends with specified suffix (ends with)
614
614
  - `"contains"`: String contains specified substring (contains)
615
615
  - `"doesnotcontain"`: String does not contain specified substring (does not contain)
616
- - `"isempty"`: Field is empty or null (is empty)
617
- - `"isnotempty"`: Field contains a value (is not empty)
618
- - `"matches"`: Matches specified pattern (matches)
616
+ - `"empty"`: Field is missing or empty (is empty)
617
+ - `"notempty"`: Field contains a value (is not empty)
618
+ - `"matches"`: Matches a regular expression (matches)
619
+
620
+ `isempty`, `isnotempty` and `anyof` are not operators: they are refused with 422
621
+ "Invalid operation: <name>".
619
622
 
620
623
  **Logical Operators**
621
624
  - `"and"`: All conditions must be true
@@ -635,7 +638,11 @@ components:
635
638
  **Using `extract` to access record fields:**
636
639
  - Retrieves values from the current record being processed
637
640
  - Can access nested properties using dot notation (e.g., `"customer.email"`)
638
- - Returns the raw field value which may need type conversion
641
+ - In a record filter, must be wrapped in a type conversion (`string`, `number`,
642
+ `boolean` or `epochtime`): a bare `["extract", ...]` operand is refused with 422
643
+ "Field operation extract must be called by a Type Conversion Operation but was called
644
+ by <operator>", both when an import's filter is saved and by
645
+ `POST /v1/processors/filter`
639
646
 
640
647
  **Using `settings` to access configuration values:**
641
648
  - Retrieves values from the integration's configuration settings
@@ -653,7 +660,20 @@ components:
653
660
  - `"floor"`: Round number down to the nearest integer
654
661
  - `"abs"`: Get absolute value of a number
655
662
 
656
- Type conversion operators are often necessary when comparing extracted field values against literals or when the field type doesn't match the comparison operator's expected type. For example:
663
+ **Handlebars operands**
664
+ - An operand can also be a string holding exactly one Handlebars expression, such as
665
+ `"{{record.status}}"` or `"{{lowercase record.code}}"`, on either side of the
666
+ operator. It renders against the record (`record.<field>`; an unprefixed
667
+ `{{status}}` renders empty) before the comparison.
668
+ - The rendered value is a string: wrap it in `["number", ...]` to compare it with a
669
+ number, or the rule is refused with 422.
670
+ - `epochtime` does not render Handlebars: `["epochtime", "{{timestamp}}"]` is refused
671
+ with 422 "invalid datetime format".
672
+ - A string with text around the expression, or with more than one expression, is
673
+ compared as a literal.
674
+
675
+ Choose the type conversion that matches the comparison — `number` for numeric
676
+ comparisons, `epochtime` for dates, `string` for text. For example:
657
677
 
658
678
  ```json
659
679
  [
@@ -744,8 +764,11 @@ components:
744
764
  [
745
765
  "notequals",
746
766
  [
747
- "extract",
748
- "status"
767
+ "string",
768
+ [
769
+ "extract",
770
+ "status"
771
+ ]
749
772
  ],
750
773
  "cancelled"
751
774
  ]
@@ -756,8 +779,11 @@ components:
756
779
  [
757
780
  "startswith",
758
781
  [
759
- "extract",
760
- "filename"
782
+ "string",
783
+ [
784
+ "extract",
785
+ "filename"
786
+ ]
761
787
  ],
762
788
  "HC"
763
789
  ]
@@ -778,29 +804,26 @@ components:
778
804
  ]
779
805
  ```
780
806
 
781
- Example 4: Order date is after January 1, 2023
807
+ Example 4: Order date is after January 1, 2023 (UTC). Compare dates as `epochtime`
808
+ against epoch milliseconds: a `string` comparison of ISO timestamps orders values with
809
+ different UTC offsets wrongly.
782
810
  ```json
783
811
  [
784
812
  "greaterthan",
785
813
  [
786
- "extract",
787
- "orderDate"
788
- ],
789
- "2023-01-01T00:00:00Z"
790
- ]
791
- ```
792
-
793
- Example 5: Category contains any of ["Urgent", "High Priority"]
794
- ```json
795
- [
796
- "anyof",
797
- [
798
- "extract",
799
- "category"
814
+ "epochtime",
815
+ [
816
+ "extract",
817
+ "orderDate"
818
+ ]
800
819
  ],
801
- ["Urgent", "High Priority"]
820
+ 1672531200000
802
821
  ]
803
822
  ```
823
+ x-celigo-ai-guidance:
824
+ - |-
825
+ To test whether a field has a value, use `notempty` on the wrapped extract, not a
826
+ `matches` pattern: a record without the field matches `.*\S.*`.
804
827
  items:
805
828
  oneOf:
806
829
  - title: String
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celigo/api-specs",
3
- "version": "0.2.138",
3
+ "version": "0.2.140",
4
4
  "private": false,
5
5
  "description": "Public OpenAPI bundles (dist/) and the celigo-cli lint schema pack (schemas.json).",
6
6
  "keywords": [