@syncmatters/connector-sdk 1.0.17 → 1.0.18

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.
@@ -128,7 +128,7 @@ always stored, they were simply never written down here:
128
128
  | `mandatory: true` | the form blocks save until the setting has a value |
129
129
  | `display_if` / `display_if_setting` / `display_if_values` | conditional rendering (`displayIfHasValue` is the deprecated spelling, still accepted) |
130
130
  | `prerequisite: true` | two-phase connectors only — see below |
131
- | `affectsMeta: true` | `meta()` reads this setting (a scope, a checkpoint column, an API version), so changing its value marks the connection's cached metadata stale until the next full refresh. Independent of `discovery`; implied by `prerequisite`; no effect on a `metaRefreshDisabled` connector |
131
+ | `affects_meta: true` | `meta()` reads this setting (a scope, a checkpoint column, an API version), so changing its value marks the connection's cached metadata stale until the next full refresh. Independent of `discovery`; implied by `prerequisite`; no effect on a `metaRefreshDisabled` connector |
132
132
 
133
133
  Use `control: "timezone"` for IANA time zone pickers (e.g. fleet `time_zone` setting). The stored
134
134
  value is a plain string (`"America/New_York"`, `"UTC"`, …); the UI renders a searchable list of
@@ -159,7 +159,7 @@ objects THIS account has — set `"discovery": true` and implement `discover()`
159
159
  "password": { "order": "02", "name": "Password", "type": "string", "control": "singlelinetext", "secret": true, "mandatory": true, "prerequisite": true },
160
160
  "database": { "order": "03", "name": "Database", "type": "string", "control": "singlelinetext", "mandatory": true, "prerequisite": true,
161
161
  "description": "The catalogue lists this database's tables and views." },
162
- "schema": { "order": "04", "name": "Schema", "type": "string", "control": "select", "affectsMeta": true,
162
+ "schema": { "order": "04", "name": "Schema", "type": "string", "control": "select", "affects_meta": true,
163
163
  "description": "Restrict the catalogue to one schema; the options come from discovery." },
164
164
  "timeZone": { "order": "05", "name": "Time Zone", "type": "string", "control": "timezone" }
165
165
  }
@@ -169,14 +169,44 @@ objects THIS account has — set `"discovery": true` and implement `discover()`
169
169
  Rules worth knowing before you mark anything:
170
170
 
171
171
  - `defines_version: true` implies `prerequisite: true` (the version core has to be chosen before
172
- anything can be discovered); `prerequisite: true` in turn implies `affectsMeta: true`.
172
+ anything can be discovered); `prerequisite: true` in turn implies `affects_meta: true`.
173
173
  - Changing a `prerequisite` setting on a live connection marks the stored catalogue stale — the
174
174
  previous result is kept and the user is offered a re-collect. Nothing is queued automatically.
175
175
  - A setting with no `options`, in the sidecar or in the overrides, renders as free text. The
176
176
  overrides may also supply `default`, `mandatory`, `readonly`, `hidden` and `description`.
177
177
  - `prerequisite` is ignored when `discovery` is absent, and `sm validate` rejects
178
- `"discovery": true` with no `prerequisite` setting (or with no `discover()` on the entry class,
179
- and vice versa).
178
+ `"discovery": true` with no `prerequisite` setting. It warns when it finds no `discover()` on
179
+ the entry class (and vice versa): the flag is what the platform reads, so a flagged class
180
+ without the method fails loudly in the wizard with `NotImplimented` rather than being treated
181
+ as single-phase.
182
+
183
+ #### A version that cannot discover: `"discovery": false` on its option
184
+
185
+ `discovery` is connector-wide, but on a multi-version connector one version core may be unable to
186
+ produce a catalogue (a superseded API). Mark that version's option instead of throwing:
187
+
188
+ ```json
189
+ "version": {
190
+ "order": "01", "name": "Version", "type": "string", "control": "select", "defines_version": true,
191
+ "default": { "type": "string", "expression": "3b" },
192
+ "options": [
193
+ { "id": "1", "name": "Superseded - legacy API (v1)", "order": "00", "discovery": false },
194
+ { "id": "3b", "name": "3b (Recommended)", "order": "03" }
195
+ ]
196
+ }
197
+ ```
198
+
199
+ A connection is two-phase when `connector_metadata.discovery` is `true` **and** no `prerequisite`
200
+ (or `defines_version`) select setting has its selected option marked `"discovery": false`. An
201
+ option without the field inherits the connector's flag, so a new version is two-phase with
202
+ nothing written; the only thing you ever write is the exception, next to the "Superseded" label.
203
+ A connection on a marked version gets the single-phase form, `discover()` is never called, and
204
+ its metadata is collected on first use like a connector without discovery. The platform reads the
205
+ connection's selected value, not the setting's `default`. Changing a live connection's version
206
+ across the line keeps its cached objects either way: moving to a two-phase version turns them
207
+ into the selection; moving to a marked version clears the selection, so the next refresh collects
208
+ everything. `sm validate` rejects the field on a setting that is not a prerequisite, and on the
209
+ setting's default option.
180
210
 
181
211
  ### `oauth2_provider`
182
212
 
@@ -171,4 +171,8 @@ implementation into per-version core modules. The entry class reads the setting
171
171
  delegates every SDK method to the selected core (`this.#core.query(options)` etc.), loading the
172
172
  core with a dynamic `await import("./acme-v3")` so unselected versions never load. `discover()`
173
173
  delegates like the rest: a `defines_version` setting is implicitly `prerequisite`, so the version
174
- is chosen before discovery runs and each core can discover its own way.
174
+ is chosen before discovery runs and each core can discover its own way. A core that cannot
175
+ discover at all (a superseded API) is marked on its option with `"discovery": false`
176
+ ([01](./01-workspace-and-meta-json.md#a-version-that-cannot-discover-discovery-false-on-its-option)):
177
+ connections on that version stay single-phase and `discover()` is never called for them. Keep a
178
+ `NotImplimented` throw in that core's `discover()` as the backstop.
@@ -99,6 +99,20 @@
99
99
  the first `init()` of a connection's life runs with only the prerequisite settings entered,
100
100
  so a connector that demands the rest up front fails discovery before the user can be shown
101
101
  the values ([02](./02-lifecycle-and-shape.md)). Validate them where they are used.
102
+ 20. **An unmarked version whose core cannot discover fails loudly in the wizard.** That is the
103
+ design: with `"discovery": true` every version is two-phase unless its option says
104
+ `"discovery": false`, so a new connection on an unmarked legacy version hits the core's
105
+ `NotImplimented` throw on Continue (shown inline, with Retry) instead of being silently
106
+ downgraded. Mark the option
107
+ ([01](./01-workspace-and-meta-json.md#a-version-that-cannot-discover-discovery-false-on-its-option)).
108
+ Marking the setting's default option is a `sm validate` error: every new connection would
109
+ be single-phase.
110
+ 21. **Reading another object's metadata through `objectMeta()` works on legacy connections and
111
+ fails on selected ones.** Keep an object self-contained: put what its own query/upsert needs
112
+ on its `data`; treat any other object's metadata as optional and fail with a clear
113
+ `ConnectorError` when it is absent. A two-phase connection caches only the objects the user
114
+ selected, so a companion object the parent reads its association ids or aliases from may
115
+ simply not be there.
102
116
 
103
117
  ## Useful utilities you might otherwise reimplement
104
118
 
@@ -590,7 +590,7 @@ Three deltas, nothing else changes.
590
590
  "discovery": true,
591
591
  "settings": {
592
592
  "api_key": { "order": "00", "name": "API Key", "type": "string", "control": "singlelinetext", "secret": true, "mandatory": true, "prerequisite": true },
593
- "businessUnit": { "order": "01", "name": "Business Unit", "type": "string", "control": "select", "affectsMeta": true,
593
+ "businessUnit": { "order": "01", "name": "Business Unit", "type": "string", "control": "select", "affects_meta": true,
594
594
  "description": "Sales orders are scoped to this unit; the options come from your account." },
595
595
  "debug": { "order": "02", "name": "Debug", "advanced": true, "type": "boolean", "control": "singlelinetext" }
596
596
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncmatters/connector-sdk",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "TypeScript type definitions for the SyncMatters connector SDK (types only - connectors execute on the SyncMatters platform)",
5
5
  "types": "./index.d.ts",
6
6
  "exports": {
@@ -12,9 +12,9 @@
12
12
  "license": "MIT",
13
13
  "author": "SyncMatters",
14
14
  "homepage": "https://syncmatters.com",
15
- "typesContentHash": "314515b24178a1bb092c58fdf12782eb777f8ad583d83c9837536be02c751490",
15
+ "typesContentHash": "2d30d816e8bb71a9fe2d9390945f4aa62c8eff1f4f86e69ec8f965e8a42cd6c8",
16
16
  "dependencies": {
17
17
  "@types/node": "*",
18
- "@syncmatters/script-api": "^1.0.17"
18
+ "@syncmatters/script-api": "^1.0.19"
19
19
  }
20
20
  }