@celigo/api-specs 0.2.112 → 0.2.114
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/api.yml +1 -0
- package/dist/connection.yml +1 -0
- package/dist/enduser.yml +1 -0
- package/dist/export.yml +4 -1
- package/dist/flow.yml +21 -3
- package/dist/import.yml +70 -26
- package/dist/lookupcache.yml +6 -1
- package/dist/mcp-server.yml +1 -0
- package/dist/tool.yml +75 -27
- package/package.json +1 -1
- package/schemas.json +1 -1
package/dist/api.yml
CHANGED
|
@@ -6470,6 +6470,7 @@ components:
|
|
|
6470
6470
|
but a decimal is rejected with 422 `invalid_field_value` on every write (the same rule applies to every
|
|
6471
6471
|
adaptor's `concurrencyLevel` and `targetConcurrencyLevel`, and to `ftp.multiThreadCount`).
|
|
6472
6472
|
Platform-managed while `autoRecoverRateLimitErrors` is true — a PUT ignores the value and the recovery machinery moves it toward the target; set `targetConcurrencyLevel` instead.
|
|
6473
|
+
At level 1 an import's pages run one at a time, so a record's existence lookup and write finish before the next record's start (measured on a single import); the import's `idLockTemplate` serializes only same-key records and leaves the rest parallel.
|
|
6473
6474
|
minimum: 1
|
|
6474
6475
|
maximum: 50
|
|
6475
6476
|
default: 25
|
package/dist/connection.yml
CHANGED
|
@@ -5581,6 +5581,7 @@ components:
|
|
|
5581
5581
|
but a decimal is rejected with 422 `invalid_field_value` on every write (the same rule applies to every
|
|
5582
5582
|
adaptor's `concurrencyLevel` and `targetConcurrencyLevel`, and to `ftp.multiThreadCount`).
|
|
5583
5583
|
Platform-managed while `autoRecoverRateLimitErrors` is true — a PUT ignores the value and the recovery machinery moves it toward the target; set `targetConcurrencyLevel` instead.
|
|
5584
|
+
At level 1 an import's pages run one at a time, so a record's existence lookup and write finish before the next record's start (measured on a single import); the import's `idLockTemplate` serializes only same-key records and leaves the rest parallel.
|
|
5584
5585
|
minimum: 1
|
|
5585
5586
|
maximum: 50
|
|
5586
5587
|
default: 25
|
package/dist/enduser.yml
CHANGED
|
@@ -3682,6 +3682,7 @@ components:
|
|
|
3682
3682
|
but a decimal is rejected with 422 `invalid_field_value` on every write (the same rule applies to every
|
|
3683
3683
|
adaptor's `concurrencyLevel` and `targetConcurrencyLevel`, and to `ftp.multiThreadCount`).
|
|
3684
3684
|
Platform-managed while `autoRecoverRateLimitErrors` is true — a PUT ignores the value and the recovery machinery moves it toward the target; set `targetConcurrencyLevel` instead.
|
|
3685
|
+
At level 1 an import's pages run one at a time, so a record's existence lookup and write finish before the next record's start (measured on a single import); the import's `idLockTemplate` serializes only same-key records and leaves the rest parallel.
|
|
3685
3686
|
minimum: 1
|
|
3686
3687
|
maximum: 50
|
|
3687
3688
|
default: 25
|
package/dist/export.yml
CHANGED
|
@@ -2074,6 +2074,7 @@ components:
|
|
|
2074
2074
|
x-celigo-ai-guidance:
|
|
2075
2075
|
- 'Set this only when the records sit inside an object (`{"data": {"items": [...]}}` → `data.items`). A sender that already posts a top-level array needs nothing here; a sender that posts an object with no path configured delivers exactly one record per request — the whole object — which is also the way to make one request one record on purpose.'
|
|
2076
2076
|
- 'Records are paged per request at the export''s `pageSize` (default 20) before any hook, filter, or downstream step runs: a 25-element array is a page of 20 records followed by a page of 5, and a `preSavePage` hook receives one page (up to `pageSize` records) per call. A hook that groups rows by order therefore groups only the rows on the same page — an order whose rows span two pages comes out as two grouped records, the second after the first was already processed. To keep a request''s rows together, have the sender wrap them in an object (one record, rows under `record.<path>`) or raise `pageSize` above the largest request — never `groupByFields`, which the listener applies per page after paging.'
|
|
2077
|
+
- 'Requests that arrive together, or while the listener''s current run is still collecting, become additional pages of that same run; a request that arrives after the run has stopped collecting starts a new run. Nothing on the listener de-duplicates: a sender that fires the same event twice (a retry, a button clicked twice) delivers two records, and the step that writes the effect has to be made idempotent — `ignoreExisting` or a keyed upsert under the import''s `idLockTemplate`.'
|
|
2077
2078
|
examples:
|
|
2078
2079
|
- events
|
|
2079
2080
|
- data.items
|
|
@@ -16062,7 +16063,9 @@ components:
|
|
|
16062
16063
|
`{{join "_" record.customerId record.orderId}}`). When omitted, the system picks a unique
|
|
16063
16064
|
field automatically. If a transform reshapes the data first, omit the `record.` prefix.
|
|
16064
16065
|
Trace keys are capped at 256 characters; a longer key is stored truncated from the middle,
|
|
16065
|
-
keeping the beginning and end of the value.
|
|
16066
|
+
keeping the beginning and end of the value. Downstream imports use the trace key as their
|
|
16067
|
+
default concurrency lock key (a blank key means no lock); it never de-duplicates — a record
|
|
16068
|
+
emitted twice with the same key is processed twice.
|
|
16066
16069
|
examples:
|
|
16067
16070
|
- '{{record.id}}'
|
|
16068
16071
|
- '{{join "_" record.customerId record.orderId}}'
|
package/dist/flow.yml
CHANGED
|
@@ -835,8 +835,10 @@ paths:
|
|
|
835
835
|
To trace a run end-to-end, arm debug logging before calling this, then use the returned
|
|
836
836
|
`_jobId` with the execution-log endpoints. For delta backfills, prefer passing explicit
|
|
837
837
|
`startDate`/`endDate` over editing the export's `lastExportDateTime` — the override is
|
|
838
|
-
scoped to one run. A
|
|
839
|
-
|
|
838
|
+
scoped to one run. A flow runs one instance at a time: a run requested while another
|
|
839
|
+
instance is queued or running is refused with `409 job_already_queued` ("Another instance
|
|
840
|
+
for this flow is already queued or running"), and a run-next-flow trigger that arrives in
|
|
841
|
+
that state is dropped rather than queued.
|
|
840
842
|
parameters:
|
|
841
843
|
- name: _id
|
|
842
844
|
in: path
|
|
@@ -890,6 +892,20 @@ paths:
|
|
|
890
892
|
$ref: '#/components/responses/401-unauthorized'
|
|
891
893
|
'404':
|
|
892
894
|
$ref: '#/components/responses/404-not-found'
|
|
895
|
+
'409':
|
|
896
|
+
description: |-
|
|
897
|
+
Another instance of this flow is already queued or running. Wait for it to
|
|
898
|
+
finish (poll `GET /v1/flows/{_id}/jobs/latest`) and request the run again.
|
|
899
|
+
content:
|
|
900
|
+
application/json:
|
|
901
|
+
schema:
|
|
902
|
+
$ref: '#/components/schemas/Error'
|
|
903
|
+
examples:
|
|
904
|
+
default:
|
|
905
|
+
value:
|
|
906
|
+
errors:
|
|
907
|
+
- code: job_already_queued
|
|
908
|
+
message: Another instance for this flow is already queued or running. Please try again later.
|
|
893
909
|
'422':
|
|
894
910
|
$ref: '#/components/responses/422-unprocessable-entity'
|
|
895
911
|
/v1/flows/{_flowId}/runs/stats:
|
|
@@ -5531,7 +5547,9 @@ components:
|
|
|
5531
5547
|
description: |-
|
|
5532
5548
|
Flow IDs to trigger after this flow completes successfully. Accepts null as
|
|
5533
5549
|
equivalent to an empty list (the server also serves null on documents saved
|
|
5534
|
-
that way).
|
|
5550
|
+
that way). The trigger starts the next flow from its own source steps and passes
|
|
5551
|
+
it no records; a trigger that fires while the next flow is already queued or running
|
|
5552
|
+
is dropped, not queued, so several completions in quick succession start it once.
|
|
5535
5553
|
items:
|
|
5536
5554
|
type: string
|
|
5537
5555
|
format: objectId
|
package/dist/import.yml
CHANGED
|
@@ -3802,23 +3802,25 @@ components:
|
|
|
3802
3802
|
- |-
|
|
3803
3803
|
Two ways to specify the lookup, picked per import:
|
|
3804
3804
|
|
|
3805
|
+
- **Expression form** — the default choice: set `expression` to a
|
|
3806
|
+
NetSuite search-expression literal (the canonical patterns are on
|
|
3807
|
+
the `expression` field — `["internalid","is","{{{id}}}"]` for a
|
|
3808
|
+
record that carries the internal id, `externalid` and `cust*_*`
|
|
3809
|
+
variants, `anyof` for multi-match, AND/OR compounds). When
|
|
3810
|
+
`expression` is set, `searchField` / `operator` / `extract` are
|
|
3811
|
+
ignored.
|
|
3805
3812
|
- **Simple form** — set `searchField` + `operator` (+ optional
|
|
3806
|
-
`extract`)
|
|
3807
|
-
NetSuite field
|
|
3808
|
-
expression
|
|
3809
|
-
|
|
3810
|
-
expression
|
|
3811
|
-
record-field lookups (`custbody_*` / `custrecord_*` /
|
|
3812
|
-
`custentity_*`), and the `anyof` operator that the simple form
|
|
3813
|
-
doesn't cover. When `expression` is set, `searchField` /
|
|
3814
|
-
`operator` / `extract` are ignored. The expression form is the
|
|
3815
|
-
common pattern in practice.
|
|
3813
|
+
`extract`) for a single-criterion lookup against a built-in
|
|
3814
|
+
NetSuite field; the platform builds the equivalent search
|
|
3815
|
+
expression at runtime. For the internal id itself the expression
|
|
3816
|
+
form above is the preferred path, and `anyof` is available only
|
|
3817
|
+
through `expression`.
|
|
3816
3818
|
- |-
|
|
3817
3819
|
The lookup result is what identifies the target record; on `update` a source
|
|
3818
3820
|
field mapped to `internalid` is overridden by it. When the incoming record
|
|
3819
|
-
already carries the NetSuite internal ID, point the lookup at that field
|
|
3820
|
-
|
|
3821
|
-
|
|
3821
|
+
already carries the NetSuite internal ID, point the lookup at that field with
|
|
3822
|
+
the expression form — `["internalid","is","{{{id}}}"]` — rather than removing
|
|
3823
|
+
the lookup.
|
|
3822
3824
|
properties:
|
|
3823
3825
|
extract:
|
|
3824
3826
|
type: string
|
|
@@ -3827,7 +3829,7 @@ components:
|
|
|
3827
3829
|
- |-
|
|
3828
3830
|
Path on the incoming source record (NOT the post-mapped record) whose value drives the lookup.
|
|
3829
3831
|
Used with the simple form (`searchField` + `operator`).
|
|
3830
|
-
Common values: `"
|
|
3832
|
+
Common values: `"externalId"`, `"id"`.
|
|
3831
3833
|
Ignored when `expression` is set.
|
|
3832
3834
|
examples:
|
|
3833
3835
|
- externalId
|
|
@@ -3837,8 +3839,9 @@ components:
|
|
|
3837
3839
|
x-celigo-ai-guidance:
|
|
3838
3840
|
- |-
|
|
3839
3841
|
NetSuite field the simple-form lookup queries against.
|
|
3840
|
-
Common values: `"externalId"`, `"
|
|
3841
|
-
|
|
3842
|
+
Common values: `"externalId"`, `"email"`, `"tranId"`, `"name"`.
|
|
3843
|
+
Matching on the record's internal id is the expression form —
|
|
3844
|
+
`["internalid","is","{{{id}}}"]` — not a `searchField`.
|
|
3842
3845
|
Ignored when `expression` is set.
|
|
3843
3846
|
examples:
|
|
3844
3847
|
- externalId
|
|
@@ -3848,9 +3851,9 @@ components:
|
|
|
3848
3851
|
x-celigo-ai-guidance:
|
|
3849
3852
|
- |-
|
|
3850
3853
|
Comparison operator for the simple-form lookup.
|
|
3851
|
-
Common values: `"is"` (exact match),
|
|
3852
|
-
`"
|
|
3853
|
-
`
|
|
3854
|
+
Common values: `"is"` (exact match), `"contains"`, `"startswith"`,
|
|
3855
|
+
`"equalto"`. Multi-match (`anyof`) is available only through
|
|
3856
|
+
`expression` (`["internalid","anyof","{{{id}}}"]`).
|
|
3854
3857
|
Ignored when `expression` is set.
|
|
3855
3858
|
expression:
|
|
3856
3859
|
type: string
|
|
@@ -5636,12 +5639,20 @@ components:
|
|
|
5636
5639
|
type:
|
|
5637
5640
|
- string
|
|
5638
5641
|
- 'null'
|
|
5639
|
-
description:
|
|
5642
|
+
description: |-
|
|
5643
|
+
Name of an entry in `lookups` that probes the database per record to decide whether it
|
|
5644
|
+
already exists, so `ignoreExisting` can skip it (or `ignoreMissing` can skip records with
|
|
5645
|
+
no match). Use it when existence must be read from the database; use `ignoreExtract` when
|
|
5646
|
+
the incoming record already carries the field that signals existence.
|
|
5640
5647
|
ignoreExtract:
|
|
5641
5648
|
type:
|
|
5642
5649
|
- string
|
|
5643
5650
|
- 'null'
|
|
5644
|
-
description:
|
|
5651
|
+
description: |-
|
|
5652
|
+
Path to a field on the incoming record whose presence decides the skip: with
|
|
5653
|
+
`ignoreExisting`, a populated value marks the record as existing and it is skipped; with
|
|
5654
|
+
`ignoreMissing`, an empty value marks it as missing and it is skipped. Zero per-record
|
|
5655
|
+
overhead; set exactly one of `ignoreExtract` / `ignoreLookupName`.
|
|
5645
5656
|
if:
|
|
5646
5657
|
not:
|
|
5647
5658
|
propertyNames:
|
|
@@ -15922,17 +15933,48 @@ components:
|
|
|
15922
15933
|
type: boolean
|
|
15923
15934
|
description: |-
|
|
15924
15935
|
When true, records that do not already exist in the destination system are silently
|
|
15925
|
-
skipped instead of producing errors — used for update-only operations.
|
|
15936
|
+
skipped instead of producing errors — used for update-only operations. Existing records
|
|
15937
|
+
are identified the same way as for `ignoreExisting`: the adaptor's ignore lookup
|
|
15938
|
+
(`ignoreLookupName`) or a populated `ignoreExtract` field on the incoming record.
|
|
15926
15939
|
idLockTemplate:
|
|
15927
15940
|
type:
|
|
15928
15941
|
- string
|
|
15929
15942
|
- 'null'
|
|
15930
15943
|
description: |-
|
|
15931
|
-
Handlebars template that generates a lock key for each record
|
|
15932
|
-
the same key are
|
|
15933
|
-
|
|
15944
|
+
Handlebars template that generates a concurrency lock key for each record: records that
|
|
15945
|
+
render the same key are never submitted at the same time, while records with different
|
|
15946
|
+
keys are processed in parallel. When omitted, the record's trace key is the lock key (a
|
|
15947
|
+
blank trace key means no lock); a template replaces that default rather than adding to it.
|
|
15948
|
+
The template is rendered from the record as it arrives at the import — before the import's
|
|
15949
|
+
own lookups and mapping run — so a key built from one of the import's lookup results
|
|
15950
|
+
(`{{lookup.<name>}}`) or from a mapped field renders empty, and an empty key is no lock at
|
|
15951
|
+
all; a field added upstream by a lookup step's response mapping is on the record and works.
|
|
15952
|
+
x-celigo-ai-guidance:
|
|
15953
|
+
- |-
|
|
15954
|
+
The lock is scoped to this import resource across every page and every concurrent run
|
|
15955
|
+
that submits through it — including other flows sharing the import — not to one page,
|
|
15956
|
+
and not to the connection: two different imports rendering the same key on the same
|
|
15957
|
+
connection still run in parallel. Records within a single page are
|
|
15958
|
+
sent one at a time regardless, so the lock matters when same-key records sit in different
|
|
15959
|
+
pages or runs.
|
|
15960
|
+
- |-
|
|
15961
|
+
With `ignoreExisting` and an ignore lookup, the existence lookup runs inside the lock:
|
|
15962
|
+
lookup-then-write for one key does not interleave with another record's lookup-then-write
|
|
15963
|
+
for the same key. That pairing is the duplicate-prevention pattern for destinations that
|
|
15964
|
+
can be queried but do not reject duplicates — key the lock on the business identifier the
|
|
15965
|
+
write is keyed on. With the check but no lock, concurrent same-key pages all read a miss
|
|
15966
|
+
before any write lands and all create. Connection `concurrencyLevel: 1` also closes that
|
|
15967
|
+
race for the import (measured on a single import: its pages ran one at a time and the
|
|
15968
|
+
same-key pages created once) — the lock is the per-key tool that leaves unrelated records
|
|
15969
|
+
parallel.
|
|
15970
|
+
- |-
|
|
15971
|
+
Key it on a field the record carries when it reaches this import (`{{{record.externalId}}}-GR`,
|
|
15972
|
+
or a field an upstream lookup step added through its response mapping), never on one of
|
|
15973
|
+
this import's own lookup results; the key must render non-empty for the records that
|
|
15974
|
+
matter, or those records have no lock.
|
|
15934
15975
|
examples:
|
|
15935
15976
|
- '{{record.customerId}}'
|
|
15977
|
+
- '{{{record.externalId}}}-GR'
|
|
15936
15978
|
dataURITemplate:
|
|
15937
15979
|
type:
|
|
15938
15980
|
- string
|
|
@@ -16052,7 +16094,9 @@ components:
|
|
|
16052
16094
|
Handlebars template that overrides how each record's unique trace key is generated,
|
|
16053
16095
|
used to track records through the flow and match errors to records. Trace keys are
|
|
16054
16096
|
capped at 256 characters; a longer key is stored truncated from the middle, keeping
|
|
16055
|
-
the beginning and end of the value.
|
|
16097
|
+
the beginning and end of the value. The trace key is also the import's default
|
|
16098
|
+
concurrency lock key when `idLockTemplate` is not set; it never de-duplicates — a record
|
|
16099
|
+
that arrives twice with the same key is processed twice.
|
|
16056
16100
|
x-celigo-ai-guidance:
|
|
16057
16101
|
- |-
|
|
16058
16102
|
## CRITICAL: ONLY VALID WHEN ``oneToMany: true``
|
package/dist/lookupcache.yml
CHANGED
|
@@ -410,7 +410,12 @@ paths:
|
|
|
410
410
|
summary: Upsert entries into a lookup cache
|
|
411
411
|
description: |-
|
|
412
412
|
Writes key-value entries to a lookup cache. Keys that already exist are
|
|
413
|
-
overwritten; new keys are created.
|
|
413
|
+
overwritten; new keys are created. There is no insert-only, create-if-absent or
|
|
414
|
+
compare-and-set mode — a write never fails because the key exists, so a
|
|
415
|
+
"first writer wins" claim cannot be built on this call alone: make the claim
|
|
416
|
+
on the flow's import step instead (`ignoreExisting` with a `getData` lookup on
|
|
417
|
+
the key, under `idLockTemplate` on the same key), which serializes
|
|
418
|
+
read-then-write per key. Values may be null, numbers, booleans,
|
|
414
419
|
strings, or objects — arrays at the top level are rejected (wrap them in an
|
|
415
420
|
object). One invalid entry fails the entire batch and nothing in it is written:
|
|
416
421
|
a bad value returns `400 invalid_value`, and an empty, missing, or over-length
|
package/dist/mcp-server.yml
CHANGED
|
@@ -5507,6 +5507,7 @@ components:
|
|
|
5507
5507
|
but a decimal is rejected with 422 `invalid_field_value` on every write (the same rule applies to every
|
|
5508
5508
|
adaptor's `concurrencyLevel` and `targetConcurrencyLevel`, and to `ftp.multiThreadCount`).
|
|
5509
5509
|
Platform-managed while `autoRecoverRateLimitErrors` is true — a PUT ignores the value and the recovery machinery moves it toward the target; set `targetConcurrencyLevel` instead.
|
|
5510
|
+
At level 1 an import's pages run one at a time, so a record's existence lookup and write finish before the next record's start (measured on a single import); the import's `idLockTemplate` serializes only same-key records and leaves the rest parallel.
|
|
5510
5511
|
minimum: 1
|
|
5511
5512
|
maximum: 50
|
|
5512
5513
|
default: 25
|
package/dist/tool.yml
CHANGED
|
@@ -8836,6 +8836,7 @@ components:
|
|
|
8836
8836
|
but a decimal is rejected with 422 `invalid_field_value` on every write (the same rule applies to every
|
|
8837
8837
|
adaptor's `concurrencyLevel` and `targetConcurrencyLevel`, and to `ftp.multiThreadCount`).
|
|
8838
8838
|
Platform-managed while `autoRecoverRateLimitErrors` is true — a PUT ignores the value and the recovery machinery moves it toward the target; set `targetConcurrencyLevel` instead.
|
|
8839
|
+
At level 1 an import's pages run one at a time, so a record's existence lookup and write finish before the next record's start (measured on a single import); the import's `idLockTemplate` serializes only same-key records and leaves the rest parallel.
|
|
8839
8840
|
minimum: 1
|
|
8840
8841
|
maximum: 50
|
|
8841
8842
|
default: 25
|
|
@@ -15381,23 +15382,25 @@ components:
|
|
|
15381
15382
|
- |-
|
|
15382
15383
|
Two ways to specify the lookup, picked per import:
|
|
15383
15384
|
|
|
15385
|
+
- **Expression form** — the default choice: set `expression` to a
|
|
15386
|
+
NetSuite search-expression literal (the canonical patterns are on
|
|
15387
|
+
the `expression` field — `["internalid","is","{{{id}}}"]` for a
|
|
15388
|
+
record that carries the internal id, `externalid` and `cust*_*`
|
|
15389
|
+
variants, `anyof` for multi-match, AND/OR compounds). When
|
|
15390
|
+
`expression` is set, `searchField` / `operator` / `extract` are
|
|
15391
|
+
ignored.
|
|
15384
15392
|
- **Simple form** — set `searchField` + `operator` (+ optional
|
|
15385
|
-
`extract`)
|
|
15386
|
-
NetSuite field
|
|
15387
|
-
expression
|
|
15388
|
-
|
|
15389
|
-
expression
|
|
15390
|
-
record-field lookups (`custbody_*` / `custrecord_*` /
|
|
15391
|
-
`custentity_*`), and the `anyof` operator that the simple form
|
|
15392
|
-
doesn't cover. When `expression` is set, `searchField` /
|
|
15393
|
-
`operator` / `extract` are ignored. The expression form is the
|
|
15394
|
-
common pattern in practice.
|
|
15393
|
+
`extract`) for a single-criterion lookup against a built-in
|
|
15394
|
+
NetSuite field; the platform builds the equivalent search
|
|
15395
|
+
expression at runtime. For the internal id itself the expression
|
|
15396
|
+
form above is the preferred path, and `anyof` is available only
|
|
15397
|
+
through `expression`.
|
|
15395
15398
|
- |-
|
|
15396
15399
|
The lookup result is what identifies the target record; on `update` a source
|
|
15397
15400
|
field mapped to `internalid` is overridden by it. When the incoming record
|
|
15398
|
-
already carries the NetSuite internal ID, point the lookup at that field
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
+
already carries the NetSuite internal ID, point the lookup at that field with
|
|
15402
|
+
the expression form — `["internalid","is","{{{id}}}"]` — rather than removing
|
|
15403
|
+
the lookup.
|
|
15401
15404
|
properties:
|
|
15402
15405
|
extract:
|
|
15403
15406
|
type: string
|
|
@@ -15406,7 +15409,7 @@ components:
|
|
|
15406
15409
|
- |-
|
|
15407
15410
|
Path on the incoming source record (NOT the post-mapped record) whose value drives the lookup.
|
|
15408
15411
|
Used with the simple form (`searchField` + `operator`).
|
|
15409
|
-
Common values: `"
|
|
15412
|
+
Common values: `"externalId"`, `"id"`.
|
|
15410
15413
|
Ignored when `expression` is set.
|
|
15411
15414
|
examples:
|
|
15412
15415
|
- externalId
|
|
@@ -15416,8 +15419,9 @@ components:
|
|
|
15416
15419
|
x-celigo-ai-guidance:
|
|
15417
15420
|
- |-
|
|
15418
15421
|
NetSuite field the simple-form lookup queries against.
|
|
15419
|
-
Common values: `"externalId"`, `"
|
|
15420
|
-
|
|
15422
|
+
Common values: `"externalId"`, `"email"`, `"tranId"`, `"name"`.
|
|
15423
|
+
Matching on the record's internal id is the expression form —
|
|
15424
|
+
`["internalid","is","{{{id}}}"]` — not a `searchField`.
|
|
15421
15425
|
Ignored when `expression` is set.
|
|
15422
15426
|
examples:
|
|
15423
15427
|
- externalId
|
|
@@ -15427,9 +15431,9 @@ components:
|
|
|
15427
15431
|
x-celigo-ai-guidance:
|
|
15428
15432
|
- |-
|
|
15429
15433
|
Comparison operator for the simple-form lookup.
|
|
15430
|
-
Common values: `"is"` (exact match),
|
|
15431
|
-
`"
|
|
15432
|
-
`
|
|
15434
|
+
Common values: `"is"` (exact match), `"contains"`, `"startswith"`,
|
|
15435
|
+
`"equalto"`. Multi-match (`anyof`) is available only through
|
|
15436
|
+
`expression` (`["internalid","anyof","{{{id}}}"]`).
|
|
15433
15437
|
Ignored when `expression` is set.
|
|
15434
15438
|
expression:
|
|
15435
15439
|
type: string
|
|
@@ -16946,12 +16950,20 @@ components:
|
|
|
16946
16950
|
type:
|
|
16947
16951
|
- string
|
|
16948
16952
|
- 'null'
|
|
16949
|
-
description:
|
|
16953
|
+
description: |-
|
|
16954
|
+
Name of an entry in `lookups` that probes the database per record to decide whether it
|
|
16955
|
+
already exists, so `ignoreExisting` can skip it (or `ignoreMissing` can skip records with
|
|
16956
|
+
no match). Use it when existence must be read from the database; use `ignoreExtract` when
|
|
16957
|
+
the incoming record already carries the field that signals existence.
|
|
16950
16958
|
ignoreExtract:
|
|
16951
16959
|
type:
|
|
16952
16960
|
- string
|
|
16953
16961
|
- 'null'
|
|
16954
|
-
description:
|
|
16962
|
+
description: |-
|
|
16963
|
+
Path to a field on the incoming record whose presence decides the skip: with
|
|
16964
|
+
`ignoreExisting`, a populated value marks the record as existing and it is skipped; with
|
|
16965
|
+
`ignoreMissing`, an empty value marks it as missing and it is skipped. Zero per-record
|
|
16966
|
+
overhead; set exactly one of `ignoreExtract` / `ignoreLookupName`.
|
|
16955
16967
|
if:
|
|
16956
16968
|
not:
|
|
16957
16969
|
propertyNames:
|
|
@@ -24789,17 +24801,48 @@ components:
|
|
|
24789
24801
|
type: boolean
|
|
24790
24802
|
description: |-
|
|
24791
24803
|
When true, records that do not already exist in the destination system are silently
|
|
24792
|
-
skipped instead of producing errors — used for update-only operations.
|
|
24804
|
+
skipped instead of producing errors — used for update-only operations. Existing records
|
|
24805
|
+
are identified the same way as for `ignoreExisting`: the adaptor's ignore lookup
|
|
24806
|
+
(`ignoreLookupName`) or a populated `ignoreExtract` field on the incoming record.
|
|
24793
24807
|
idLockTemplate:
|
|
24794
24808
|
type:
|
|
24795
24809
|
- string
|
|
24796
24810
|
- 'null'
|
|
24797
24811
|
description: |-
|
|
24798
|
-
Handlebars template that generates a lock key for each record
|
|
24799
|
-
the same key are
|
|
24800
|
-
|
|
24812
|
+
Handlebars template that generates a concurrency lock key for each record: records that
|
|
24813
|
+
render the same key are never submitted at the same time, while records with different
|
|
24814
|
+
keys are processed in parallel. When omitted, the record's trace key is the lock key (a
|
|
24815
|
+
blank trace key means no lock); a template replaces that default rather than adding to it.
|
|
24816
|
+
The template is rendered from the record as it arrives at the import — before the import's
|
|
24817
|
+
own lookups and mapping run — so a key built from one of the import's lookup results
|
|
24818
|
+
(`{{lookup.<name>}}`) or from a mapped field renders empty, and an empty key is no lock at
|
|
24819
|
+
all; a field added upstream by a lookup step's response mapping is on the record and works.
|
|
24820
|
+
x-celigo-ai-guidance:
|
|
24821
|
+
- |-
|
|
24822
|
+
The lock is scoped to this import resource across every page and every concurrent run
|
|
24823
|
+
that submits through it — including other flows sharing the import — not to one page,
|
|
24824
|
+
and not to the connection: two different imports rendering the same key on the same
|
|
24825
|
+
connection still run in parallel. Records within a single page are
|
|
24826
|
+
sent one at a time regardless, so the lock matters when same-key records sit in different
|
|
24827
|
+
pages or runs.
|
|
24828
|
+
- |-
|
|
24829
|
+
With `ignoreExisting` and an ignore lookup, the existence lookup runs inside the lock:
|
|
24830
|
+
lookup-then-write for one key does not interleave with another record's lookup-then-write
|
|
24831
|
+
for the same key. That pairing is the duplicate-prevention pattern for destinations that
|
|
24832
|
+
can be queried but do not reject duplicates — key the lock on the business identifier the
|
|
24833
|
+
write is keyed on. With the check but no lock, concurrent same-key pages all read a miss
|
|
24834
|
+
before any write lands and all create. Connection `concurrencyLevel: 1` also closes that
|
|
24835
|
+
race for the import (measured on a single import: its pages ran one at a time and the
|
|
24836
|
+
same-key pages created once) — the lock is the per-key tool that leaves unrelated records
|
|
24837
|
+
parallel.
|
|
24838
|
+
- |-
|
|
24839
|
+
Key it on a field the record carries when it reaches this import (`{{{record.externalId}}}-GR`,
|
|
24840
|
+
or a field an upstream lookup step added through its response mapping), never on one of
|
|
24841
|
+
this import's own lookup results; the key must render non-empty for the records that
|
|
24842
|
+
matter, or those records have no lock.
|
|
24801
24843
|
examples:
|
|
24802
24844
|
- '{{record.customerId}}'
|
|
24845
|
+
- '{{{record.externalId}}}-GR'
|
|
24803
24846
|
dataURITemplate:
|
|
24804
24847
|
type:
|
|
24805
24848
|
- string
|
|
@@ -24919,7 +24962,9 @@ components:
|
|
|
24919
24962
|
Handlebars template that overrides how each record's unique trace key is generated,
|
|
24920
24963
|
used to track records through the flow and match errors to records. Trace keys are
|
|
24921
24964
|
capped at 256 characters; a longer key is stored truncated from the middle, keeping
|
|
24922
|
-
the beginning and end of the value.
|
|
24965
|
+
the beginning and end of the value. The trace key is also the import's default
|
|
24966
|
+
concurrency lock key when `idLockTemplate` is not set; it never de-duplicates — a record
|
|
24967
|
+
that arrives twice with the same key is processed twice.
|
|
24923
24968
|
x-celigo-ai-guidance:
|
|
24924
24969
|
- |-
|
|
24925
24970
|
## CRITICAL: ONLY VALID WHEN ``oneToMany: true``
|
|
@@ -26679,6 +26724,7 @@ components:
|
|
|
26679
26724
|
x-celigo-ai-guidance:
|
|
26680
26725
|
- 'Set this only when the records sit inside an object (`{"data": {"items": [...]}}` → `data.items`). A sender that already posts a top-level array needs nothing here; a sender that posts an object with no path configured delivers exactly one record per request — the whole object — which is also the way to make one request one record on purpose.'
|
|
26681
26726
|
- 'Records are paged per request at the export''s `pageSize` (default 20) before any hook, filter, or downstream step runs: a 25-element array is a page of 20 records followed by a page of 5, and a `preSavePage` hook receives one page (up to `pageSize` records) per call. A hook that groups rows by order therefore groups only the rows on the same page — an order whose rows span two pages comes out as two grouped records, the second after the first was already processed. To keep a request''s rows together, have the sender wrap them in an object (one record, rows under `record.<path>`) or raise `pageSize` above the largest request — never `groupByFields`, which the listener applies per page after paging.'
|
|
26727
|
+
- 'Requests that arrive together, or while the listener''s current run is still collecting, become additional pages of that same run; a request that arrives after the run has stopped collecting starts a new run. Nothing on the listener de-duplicates: a sender that fires the same event twice (a retry, a button clicked twice) delivers two records, and the step that writes the effect has to be made idempotent — `ignoreExisting` or a keyed upsert under the import''s `idLockTemplate`.'
|
|
26682
26728
|
examples:
|
|
26683
26729
|
- events
|
|
26684
26730
|
- data.items
|
|
@@ -36912,7 +36958,9 @@ components:
|
|
|
36912
36958
|
`{{join "_" record.customerId record.orderId}}`). When omitted, the system picks a unique
|
|
36913
36959
|
field automatically. If a transform reshapes the data first, omit the `record.` prefix.
|
|
36914
36960
|
Trace keys are capped at 256 characters; a longer key is stored truncated from the middle,
|
|
36915
|
-
keeping the beginning and end of the value.
|
|
36961
|
+
keeping the beginning and end of the value. Downstream imports use the trace key as their
|
|
36962
|
+
default concurrency lock key (a blank key means no lock); it never de-duplicates — a record
|
|
36963
|
+
emitted twice with the same key is processed twice.
|
|
36916
36964
|
examples:
|
|
36917
36965
|
- '{{record.id}}'
|
|
36918
36966
|
- '{{join "_" record.customerId record.orderId}}'
|
package/package.json
CHANGED