@syncmatters/script-api 1.0.7 → 1.0.8
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/README.md +29 -3
- package/docs/01-workspace-layout.md +41 -0
- package/docs/02-script-api-imports.md +57 -0
- package/docs/03-sync-logic-modules.md +58 -0
- package/docs/04-module-wiring-and-sidecars.md +59 -0
- package/docs/05-reading-sync-snapshots.md +45 -0
- package/docs/06-cli-workflow-and-tokens.md +56 -0
- package/docs/07-style-and-pitfalls.md +37 -0
- package/docs/script-sync-authoring.md +71 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,10 +3,23 @@
|
|
|
3
3
|
TypeScript type definitions for the **SyncMatters script API**.
|
|
4
4
|
|
|
5
5
|
This is a **types-only** package: it provides IntelliSense and type checking when developing
|
|
6
|
-
SyncMatters integration scripts locally (for example in VS Code or Cursor).
|
|
7
|
-
the SyncMatters platform, which provides the runtime implementation of
|
|
6
|
+
SyncMatters integration scripts and sync logic modules locally (for example in VS Code or Cursor).
|
|
7
|
+
Script code executes on the SyncMatters platform, which provides the runtime implementation of
|
|
8
|
+
this API.
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## Authoring guide (humans and AI assistants)
|
|
11
|
+
|
|
12
|
+
The complete guide to integration scripts and sync custom logic ships inside this package,
|
|
13
|
+
version-locked to the types:
|
|
14
|
+
|
|
15
|
+
- [`docs/script-sync-authoring.md`](./docs/script-sync-authoring.md) — start here (cheat sheet +
|
|
16
|
+
index); focused topic files sit alongside it.
|
|
17
|
+
|
|
18
|
+
If you are an AI assistant working in a CLI-pulled workspace: **read that file before writing
|
|
19
|
+
script or sync logic code.** Workspaces created by the `sm` CLI also contain an `AGENTS.md`
|
|
20
|
+
pointing here and at the connector guide in `@syncmatters/connector-sdk`.
|
|
21
|
+
|
|
22
|
+
## Usage — integration script
|
|
10
23
|
|
|
11
24
|
```js
|
|
12
25
|
import API from "@syncmatters/script-api";
|
|
@@ -17,6 +30,19 @@ export async function main(ctx) {
|
|
|
17
30
|
}
|
|
18
31
|
```
|
|
19
32
|
|
|
33
|
+
## Usage — sync logic module
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import API from "@syncmatters/script-api";
|
|
37
|
+
|
|
38
|
+
export default class MySyncLogic {
|
|
39
|
+
/** @param {API.SyncLogicFilterFastContext} ctx @returns {Promise<boolean>} */
|
|
40
|
+
async filterFast(ctx) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
20
46
|
Connector test harnesses additionally use the `sdk-test` entry point:
|
|
21
47
|
|
|
22
48
|
```js
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Workspace layout (CLI-pulled tree)
|
|
2
|
+
|
|
3
|
+
A workspace pulled by `sm` mirrors platform script files locally and adds editor tooling.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
files/ # script source (.mjs, .json, …) — EDIT and push via sm push
|
|
7
|
+
meta/ # one *.meta.json sidecar per file under files/ — EDIT and push
|
|
8
|
+
syncs/<sync_uid>/ # sync.config.json — GENERATED read-only snapshots (sm pull sync)
|
|
9
|
+
groups/<group_uid>/ # group.config.json — GENERATED read-only snapshots
|
|
10
|
+
types/ # typed-connection .d.ts — GENERATED (sm types)
|
|
11
|
+
.sm/state.json # pull pins for conflict detection — do not edit
|
|
12
|
+
package.json # CLI-generated IntelliSense overlay — do not edit
|
|
13
|
+
jsconfig.json # CLI-generated — do not edit
|
|
14
|
+
AGENTS.md # CLI-generated agent guide (managed block + your notes below)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Push boundary
|
|
18
|
+
|
|
19
|
+
| Path | Agent may edit? | `sm push`? |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `files/**` | Yes (when tasked) | Yes (with sidecar) |
|
|
22
|
+
| `meta/**` | Yes | Yes (meta fields) |
|
|
23
|
+
| `syncs/**/sync.config.json` | **No** | **No** |
|
|
24
|
+
| `groups/**/group.config.json` | **No** | **No** |
|
|
25
|
+
| `types/**`, `.sm/`, `package.json`, `jsconfig.json` | **No** | **No** |
|
|
26
|
+
|
|
27
|
+
Sync and sync-group **configuration** (mappings, schedules, which module is attached) is changed
|
|
28
|
+
in the **web UI** today. The CLI exports snapshots for **read-only context** so agents know what
|
|
29
|
+
is deployed; a future `sm sync …` push workflow is not available yet.
|
|
30
|
+
|
|
31
|
+
Generated sync/group files include a marker:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"$sm": { "generated_by": "sm pull", "kind": "sync.config" },
|
|
36
|
+
...
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Refresh snapshots with `sm pull sync` or `sm pull --force` (overwrites dirty generated files
|
|
41
|
+
only). See [05-reading-sync-snapshots.md](./05-reading-sync-snapshots.md).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Script API imports and integration scripts
|
|
2
|
+
|
|
3
|
+
## Import style
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import API from "@syncmatters/script-api";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The legacy `@ihq/script-api` npm alias resolves to the same package — match whichever the file
|
|
10
|
+
you are editing already uses; do not mix scopes within one file.
|
|
11
|
+
|
|
12
|
+
Connector test harnesses additionally use:
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import SDKTest from "@syncmatters/script-api/sdk-test";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
(See `@syncmatters/connector-sdk` testing docs — not used for sync logic modules.)
|
|
19
|
+
|
|
20
|
+
## Integration script entrypoint
|
|
21
|
+
|
|
22
|
+
Integration scripts export **`main`** receiving **`API.Context`**:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import API from "@syncmatters/script-api";
|
|
26
|
+
|
|
27
|
+
/** @param {API.Context} ctx */
|
|
28
|
+
export async function main(ctx) {
|
|
29
|
+
ctx.log.info("Hello");
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Context highlights (`API.Context`)
|
|
34
|
+
|
|
35
|
+
| Member | Purpose |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `ctx.log` | Platform logger (`info`, `warn`, `error`, …) |
|
|
38
|
+
| `ctx.parameters` | Script parameters configured on the platform |
|
|
39
|
+
| `ctx.connections` | Named connections → async factories returning `API.Connection` |
|
|
40
|
+
| `ctx.syncGroups` | Named sync groups → async factories |
|
|
41
|
+
| `ctx.state` | Persistent key/value (`get` / `set`) across runs |
|
|
42
|
+
| `ctx.feedback` | Progress reporting for long jobs |
|
|
43
|
+
| `ctx.sendEmail` | Platform email helper |
|
|
44
|
+
| `ctx.account.executions.list` | Query past executions |
|
|
45
|
+
| `ctx.environment.engineUid` | Runtime engine identifier |
|
|
46
|
+
|
|
47
|
+
Use JSDoc (`/** @param {API.Context} ctx */`) so `checkJs` in the workspace validates calls.
|
|
48
|
+
|
|
49
|
+
## Sync logic modules use the same import
|
|
50
|
+
|
|
51
|
+
Sync custom logic lives in separate `.mjs` module files and uses `import API from "@syncmatters/script-api"` for hook context types — see [03-sync-logic-modules.md](./03-sync-logic-modules.md).
|
|
52
|
+
|
|
53
|
+
## Types-only package
|
|
54
|
+
|
|
55
|
+
`@syncmatters/script-api` is **types-only** locally. At runtime the platform provides the real
|
|
56
|
+
implementations. Do not expect `main()` or sync hooks to run when executing Node locally against
|
|
57
|
+
the pulled tree.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Sync logic modules (`API.SyncLogic`)
|
|
2
|
+
|
|
3
|
+
Sync **custom logic** is optional JavaScript attached to a sync configuration. The platform
|
|
4
|
+
loads your module, instantiates the **default-exported class** (`new YourClass()`), binds
|
|
5
|
+
methods, and invokes hooks during the sync pipeline.
|
|
6
|
+
|
|
7
|
+
## Export shape
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import API from "@syncmatters/script-api";
|
|
11
|
+
|
|
12
|
+
export default class MySyncLogic {
|
|
13
|
+
/** @param {API.SyncLogicFilterFastContext} ctx @returns {Promise<boolean>} */
|
|
14
|
+
async filterFast(ctx) {
|
|
15
|
+
return true; // true = include row, false = exclude
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use a **class** with async methods (not a plain object). Only implement hooks you need; omitted
|
|
21
|
+
hooks are skipped.
|
|
22
|
+
|
|
23
|
+
## Hooks (`API.SyncLogic`)
|
|
24
|
+
|
|
25
|
+
| Hook | When it runs | Return |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `beforeRun(ctx)` | Once before the sync processes rows | `Promise<void>` |
|
|
28
|
+
| `filterFast(ctx)` | Early filter on source row (+ optional prior match) | `Promise<boolean>` — keep? |
|
|
29
|
+
| `filterRelated(ctx)` | After related rows are loaded | `Promise<boolean>` |
|
|
30
|
+
| `reviewMatches(ctx)` | When multiple destination matches exist | `Promise<Array<unknown>>` — ordered candidates |
|
|
31
|
+
| `filterMatched(ctx)` | After match + lookups | `Promise<boolean>` |
|
|
32
|
+
| `calculate(ctx)` | Before field mapping | `Promise<void>` — write `ctx.calculated` |
|
|
33
|
+
|
|
34
|
+
Context types: `SyncLogicBeforeRunContext`, `SyncLogicFilterFastContext`,
|
|
35
|
+
`SyncLogicFilterRelatedContext`, `SyncLogicSelectMatchContext`, `SyncLogicFilterMatchedContext`,
|
|
36
|
+
`SyncLogicCalcContext` (all under `API.*`).
|
|
37
|
+
|
|
38
|
+
### `beforeRun` state
|
|
39
|
+
|
|
40
|
+
`SyncLogicBeforeRunContext.state` provides `get()` / `set()` for logic that must persist across
|
|
41
|
+
rows in one group run (use sparingly; prefer stateless filters when possible).
|
|
42
|
+
|
|
43
|
+
### `calculate`
|
|
44
|
+
|
|
45
|
+
Populate calculated fields on `ctx.calculated` (map of field id → value) for the mapping phase
|
|
46
|
+
to consume.
|
|
47
|
+
|
|
48
|
+
## Relationship to connectors
|
|
49
|
+
|
|
50
|
+
Connectors supply endpoint rows (`query`, `upsert`, …). Sync logic **filters and transforms**
|
|
51
|
+
rows inside a configured sync — it does not replace connector code. Connector authoring:
|
|
52
|
+
`@syncmatters/connector-sdk/docs/connector-authoring.md`.
|
|
53
|
+
|
|
54
|
+
## Wiring
|
|
55
|
+
|
|
56
|
+
The module file must be staged on the platform and referenced from sync configuration
|
|
57
|
+
(`script_file_id`). Sidecars and paths: [04-module-wiring-and-sidecars.md](./04-module-wiring-and-sidecars.md).
|
|
58
|
+
Which file is attached: see pulled `sync.config.json` — [05-reading-sync-snapshots.md](./05-reading-sync-snapshots.md).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Module wiring and sidecars
|
|
2
|
+
|
|
3
|
+
Script files on the platform always have a parallel **`meta/<same-path>.meta.json`** sidecar.
|
|
4
|
+
The platform stages exactly the files listed in sidecars — an import that is not wired will fail
|
|
5
|
+
at runtime.
|
|
6
|
+
|
|
7
|
+
This mirrors connector module wiring; see also
|
|
8
|
+
`@syncmatters/connector-sdk/docs/01-workspace-and-meta-json.md` for the full sidecar field
|
|
9
|
+
reference.
|
|
10
|
+
|
|
11
|
+
## Module files
|
|
12
|
+
|
|
13
|
+
| Sidecar `type` | Typical use |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| `"module"` | Shared logic, sync logic classes, helper modules |
|
|
16
|
+
| `"javascript"` / others | Depends on how the file was created on the platform |
|
|
17
|
+
|
|
18
|
+
Minimum sidecar for a new module pushed from the CLI:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{ "type": "module", "name": "my-sync-logic.mjs" }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## `module_script_file_paths`
|
|
25
|
+
|
|
26
|
+
The **entry** script's sidecar lists every file the platform must stage for that tree
|
|
27
|
+
(transitively). Each module's sidecar lists only its **direct** imports.
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
"module_script_file_paths": [
|
|
31
|
+
"Services/AcmeSync/acme-filter.mjs",
|
|
32
|
+
"Services/AcmeSync/acme-utils.mjs"
|
|
33
|
+
]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`sm push` maps paths to platform file ids from workspace state. Every referenced path must exist
|
|
37
|
+
and be tracked — unresolved references block the wiring change for that file.
|
|
38
|
+
|
|
39
|
+
## Linking sync logic to a sync
|
|
40
|
+
|
|
41
|
+
1. Push the module file(s) under `files/` with correct sidecars.
|
|
42
|
+
2. In the **web UI**, open the sync configuration and attach the script file as custom logic
|
|
43
|
+
(sets `script_file_id` on the platform).
|
|
44
|
+
3. Locally, run `sm pull sync` and read `syncs/<sync_uid>/sync.config.json`:
|
|
45
|
+
- `script_file_id` — platform id of the attached logic file
|
|
46
|
+
- `sync_uid` — stable uid used in the snapshot path
|
|
47
|
+
- field maps, filters, source/destination — full config context
|
|
48
|
+
|
|
49
|
+
Do **not** edit `sync.config.json` to change wiring or mappings — it is a generated snapshot,
|
|
50
|
+
not a push payload.
|
|
51
|
+
|
|
52
|
+
## New local files
|
|
53
|
+
|
|
54
|
+
A new file under `files/` is created on the platform only when:
|
|
55
|
+
|
|
56
|
+
1. It has a `meta/` sidecar, and
|
|
57
|
+
2. You `sm push` it.
|
|
58
|
+
|
|
59
|
+
No sidecar → no push.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Reading sync and group snapshots
|
|
2
|
+
|
|
3
|
+
After `sm pull sync` (or default `sm pull` when the token has `syncs:read`), the workspace
|
|
4
|
+
contains read-only JSON snapshots:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
syncs/<sync_uid>/sync.config.json # full ScriptSync configuration + version
|
|
8
|
+
groups/<sync_group_uid>/group.config.json # ScriptSyncGroup incl. schedule
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Each file starts with:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
"$sm": { "generated_by": "sm pull", "kind": "sync.config" }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
(or `"kind": "group.config"` for groups).
|
|
18
|
+
|
|
19
|
+
## What agents should use them for
|
|
20
|
+
|
|
21
|
+
- **Context:** sync name, uid, source/destination endpoints, field mappings, filters, attached
|
|
22
|
+
`script_file_id`, group membership, schedule.
|
|
23
|
+
- **Locate code:** map `script_file_id` to a path via `.sm/state.json` `files` entries (match
|
|
24
|
+
`fileId`) or search `files/` / platform tree — then edit the **module under `files/`**, not
|
|
25
|
+
the snapshot.
|
|
26
|
+
- **Drift awareness:** `version` (sync) or `modified` (group) plus `.sm/state.json` pins tell
|
|
27
|
+
you if the platform changed since pull (`sm diff` / re-pull).
|
|
28
|
+
|
|
29
|
+
## What not to do
|
|
30
|
+
|
|
31
|
+
- Do **not** hand-edit snapshots to change mappings, schedules, or wiring.
|
|
32
|
+
- Do **not** `sm push` snapshot paths — there is no push route for them today.
|
|
33
|
+
- Do **not** treat snapshots as the source of truth for writes — the web UI (or future CLI sync
|
|
34
|
+
commands) owns configuration changes.
|
|
35
|
+
|
|
36
|
+
## Refresh
|
|
37
|
+
|
|
38
|
+
| Command | Effect |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `sm pull sync` | Refresh sync/group snapshots only |
|
|
41
|
+
| `sm pull` | Scripts + snapshots (unless `--no-syncs`) |
|
|
42
|
+
| `sm pull sync --force` | Overwrite locally modified **generated** snapshots |
|
|
43
|
+
|
|
44
|
+
Missing `syncs:read` on the developer token: default pull warns and skips; `sm pull sync` exits
|
|
45
|
+
2 with mint-token guidance.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# CLI workflow and developer tokens
|
|
2
|
+
|
|
3
|
+
## Services / sync module workflow
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
sm pull # scripts + meta pins (+ syncs/groups when scoped)
|
|
7
|
+
sm pull sync # optional: refresh sync/group snapshots only
|
|
8
|
+
→ edit files/ and meta/ only
|
|
9
|
+
→ sm validate
|
|
10
|
+
→ sm status / sm diff
|
|
11
|
+
→ sm push -m "describe change" --yes
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- **Scripts only:** `sm push` uploads changed files under `files/` (and meta sidecars). It does
|
|
15
|
+
**not** upload `syncs/` or `groups/`.
|
|
16
|
+
- **Sync config changes:** web UI (future CLI sync push out of scope).
|
|
17
|
+
- **Reading snapshots:** use `syncs/` and `groups/` for context before editing the wired module
|
|
18
|
+
in `files/`.
|
|
19
|
+
|
|
20
|
+
## Connector workflow (when also in the workspace)
|
|
21
|
+
|
|
22
|
+
Connector work adds `sm test`, `sm connector features`, etc. See
|
|
23
|
+
`@syncmatters/connector-sdk/docs/connector-authoring.md` and workspace `AGENTS.md`.
|
|
24
|
+
|
|
25
|
+
## Developer token scopes (agents / IDE)
|
|
26
|
+
|
|
27
|
+
Prefer tokens **without execute scopes** for day-to-day edit/push work:
|
|
28
|
+
|
|
29
|
+
| Scope | Typical agent use |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `scripts:read` | pull, diff incoming |
|
|
32
|
+
| `scripts:write` | push script files |
|
|
33
|
+
| `syncs:read` | `sm pull sync`, sync snapshots |
|
|
34
|
+
| `connections:read` | `sm types`, connection resolution |
|
|
35
|
+
| `scripts:execute` | **Only when running** `sm test` / connector features |
|
|
36
|
+
| `syncs:execute` | Reserved; not needed for authoring |
|
|
37
|
+
|
|
38
|
+
Default token UI omits `syncs:execute`; keep execute scopes off unless the user explicitly wants
|
|
39
|
+
platform test runs from the agent.
|
|
40
|
+
|
|
41
|
+
## 403 handling
|
|
42
|
+
|
|
43
|
+
If the CLI reports **403** with missing scope or "not available to developer token sessions":
|
|
44
|
+
|
|
45
|
+
1. **Stop** — do not retry other commands hoping one will work.
|
|
46
|
+
2. Tell the user to mint a new token with the required scope (User settings → Developer tokens)
|
|
47
|
+
and run `sm auth` again.
|
|
48
|
+
|
|
49
|
+
Examples:
|
|
50
|
+
|
|
51
|
+
- Missing `syncs:read` → cannot pull sync snapshots (`sm pull sync`).
|
|
52
|
+
- Missing `scripts:execute` → cannot run `sm test` (expected if using a read/write-only token).
|
|
53
|
+
|
|
54
|
+
## Non-interactive runs
|
|
55
|
+
|
|
56
|
+
Never answer `[y/N]` prompts in the terminal. Use `--yes` on `sm push`, `sm rm`, etc.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Style and pitfalls
|
|
2
|
+
|
|
3
|
+
## Style (match the fleet)
|
|
4
|
+
|
|
5
|
+
- **Double quotes** for strings in `.mjs` files.
|
|
6
|
+
- **JSDoc** all parameters and return types; workspace `checkJs` is active.
|
|
7
|
+
- Prefix unused callback parameters with `_`.
|
|
8
|
+
- **Private state** in `#private` fields on classes (sync logic modules and connectors).
|
|
9
|
+
- **Import alias:** use `@syncmatters/script-api` or `@ihq/script-api` consistently within a
|
|
10
|
+
file — never mix.
|
|
11
|
+
|
|
12
|
+
## Pitfalls
|
|
13
|
+
|
|
14
|
+
| Trap | Correct approach |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| Editing `sync.config.json` to fix mappings | Change sync in web UI; re-pull snapshots |
|
|
17
|
+
| Pushing `syncs/` or `groups/` | Not supported — push only `files/` + `meta/` |
|
|
18
|
+
| Plain object default export for sync logic | **Class** default export; platform uses `new` |
|
|
19
|
+
| Missing meta sidecar on new file | Add `meta/.../*.meta.json` before push |
|
|
20
|
+
| Unwired `import` | Add path to `module_script_file_paths` in sidecar |
|
|
21
|
+
| Running sync logic locally | Types check locally; execution is platform-only |
|
|
22
|
+
| Retrying after 403 | Stop; user must fix token scopes |
|
|
23
|
+
| Using `scripts:execute` on every agent token | Reserve execute for explicit test runs |
|
|
24
|
+
|
|
25
|
+
## Connector vs sync logic
|
|
26
|
+
|
|
27
|
+
- **Connector** (`@syncmatters/connector-sdk`): talks to an external API — `meta()`, `query()`,
|
|
28
|
+
`upsert()`, …
|
|
29
|
+
- **Sync logic** (`API.SyncLogic`): filters/calculates rows **inside** a configured sync.
|
|
30
|
+
|
|
31
|
+
Both can exist in one workspace; edit only the files your task names.
|
|
32
|
+
|
|
33
|
+
## Further reading
|
|
34
|
+
|
|
35
|
+
- Connectors: `node_modules/@syncmatters/connector-sdk/docs/connector-authoring.md`
|
|
36
|
+
- Sync pipeline vs connector capabilities:
|
|
37
|
+
`@syncmatters/connector-sdk/docs/16-the-end-game-syncs.md`
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Integration scripts and sync logic — the authoring guide
|
|
2
|
+
|
|
3
|
+
This is the canonical guide to writing **integration scripts** and **sync custom-logic modules** for
|
|
4
|
+
the SyncMatters platform. It ships inside `@syncmatters/script-api` and is version-locked to the
|
|
5
|
+
type definitions next to it. Read this file first, then open only the topic files your task
|
|
6
|
+
touches.
|
|
7
|
+
|
|
8
|
+
**Integration scripts** are scheduled or triggered `.mjs` files that orchestrate work using
|
|
9
|
+
`API.Context` (connections, sync groups, logging, state). **Sync logic modules** are `.mjs`
|
|
10
|
+
classes wired to a sync configuration; the platform instantiates your class and calls optional
|
|
11
|
+
hooks (`filterFast`, `calculate`, …) as rows move through the sync pipeline.
|
|
12
|
+
|
|
13
|
+
Your code **executes on the SyncMatters platform**, not locally — the workspace pulled by the
|
|
14
|
+
`sm` CLI is for editing, type-checking and pushing script files only.
|
|
15
|
+
|
|
16
|
+
For **connectors** (external system adapters), use the separate guide in
|
|
17
|
+
`@syncmatters/connector-sdk/docs/connector-authoring.md`.
|
|
18
|
+
|
|
19
|
+
## Topic files (read what your task touches)
|
|
20
|
+
|
|
21
|
+
| File | Read when you are… |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| [01-workspace-layout.md](./01-workspace-layout.md) | understanding `files/`, `meta/`, `syncs/`, `groups/`, `types/`, `.sm/` and what is pushable |
|
|
24
|
+
| [02-script-api-imports.md](./02-script-api-imports.md) | starting an integration script; `import API`, `main(ctx)`, `API.Context` |
|
|
25
|
+
| [03-sync-logic-modules.md](./03-sync-logic-modules.md) | implementing sync custom logic — `API.SyncLogic` hooks and context shapes |
|
|
26
|
+
| [04-module-wiring-and-sidecars.md](./04-module-wiring-and-sidecars.md) | wiring modules via `*.meta.json`, `module_script_file_paths`, linking logic to a sync |
|
|
27
|
+
| [05-reading-sync-snapshots.md](./05-reading-sync-snapshots.md) | using pulled `sync.config.json` / `group.config.json` for context (read-only) |
|
|
28
|
+
| [06-cli-workflow-and-tokens.md](./06-cli-workflow-and-tokens.md) | `sm pull`, `sm pull sync`, validate/status/diff/push; developer token scopes |
|
|
29
|
+
| [07-style-and-pitfalls.md](./07-style-and-pitfalls.md) | JSDoc, quotes, import aliases, common traps |
|
|
30
|
+
|
|
31
|
+
## The 60-second version — sync logic module
|
|
32
|
+
|
|
33
|
+
A minimal sync logic class (only `filterFast`; add other hooks as needed):
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import API from "@syncmatters/script-api";
|
|
37
|
+
|
|
38
|
+
export default class AcmeContactFilter {
|
|
39
|
+
/**
|
|
40
|
+
* @param {API.SyncLogicFilterFastContext} ctx
|
|
41
|
+
* @returns {Promise<boolean>} true = keep row, false = exclude
|
|
42
|
+
*/
|
|
43
|
+
async filterFast(ctx) {
|
|
44
|
+
const row = /** @type {{ email?: string }} */ (ctx.src);
|
|
45
|
+
return typeof row.email === "string" && row.email.endsWith("@example.com");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Sidecar: `"type": "module"`. Wire the module in the entry sidecar's `module_script_file_paths`.
|
|
51
|
+
The platform links this file to a sync via **sync configuration** (`script_file_id` in the web
|
|
52
|
+
UI) — see [04-module-wiring-and-sidecars.md](./04-module-wiring-and-sidecars.md). Use the pulled
|
|
53
|
+
`syncs/<sync_uid>/sync.config.json` snapshot to see which script file is attached; do **not**
|
|
54
|
+
edit that JSON locally.
|
|
55
|
+
|
|
56
|
+
## The 60-second version — integration script
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import API from "@syncmatters/script-api";
|
|
60
|
+
|
|
61
|
+
/** @param {API.Context} ctx */
|
|
62
|
+
export async function main(ctx) {
|
|
63
|
+
ctx.log.info("Starting integration script");
|
|
64
|
+
const conn = await ctx.connections["My Connection"]();
|
|
65
|
+
await conn.test();
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Sidecar `"type"` matches the script kind configured on the platform (often `"javascript"` or
|
|
70
|
+
`"integration"` depending on how the file was created). New files need a `meta/` sidecar before
|
|
71
|
+
`sm push` creates them on the platform.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncmatters/script-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "TypeScript type definitions for the SyncMatters script API (types only - scripts execute on the SyncMatters platform)",
|
|
5
5
|
"types": "./index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"author": "SyncMatters",
|
|
22
22
|
"homepage": "https://syncmatters.com",
|
|
23
|
-
"typesContentHash": "
|
|
23
|
+
"typesContentHash": "06c0e7d73e478f9b36cfd586c79b5d57c001924d7f7f1b7868771537b4176e27",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@types/node": "*"
|
|
26
26
|
}
|