@syncmatters/script-api 1.0.18 → 1.0.20

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.
@@ -452,6 +452,12 @@ export interface ObjectSettingMetaOption {
452
452
  id: string;
453
453
  name?: string;
454
454
  order?: string;
455
+ /**
456
+ * on an option of a prerequisite (or defines_version) connection setting: `false` makes a connection
457
+ * with this option selected single-phase - discover() is never called and its metadata is collected on
458
+ * first use, as for a connector without discovery. Absent inherits the connector's `discovery` flag.
459
+ */
460
+ discovery?: boolean;
455
461
  }
456
462
  export interface ObjectRowFilter {
457
463
  /** unique identifier for the filter */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncmatters/script-api",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
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": {
@@ -28,7 +28,7 @@
28
28
  "license": "MIT",
29
29
  "author": "SyncMatters",
30
30
  "homepage": "https://syncmatters.com",
31
- "typesContentHash": "880590dffe9b93eb5e71e130baabce5cc64b79f2376389a7e1f09d5663e5420e",
31
+ "typesContentHash": "6f0e7724c2cff15e666109cc05b76419887b64ffa0310e9ec23fe2b585a323e5",
32
32
  "dependencies": {
33
33
  "@types/node": "*"
34
34
  }
@@ -130,6 +130,17 @@ export interface ObjectFeatures {
130
130
  relationshipsToSameAsObjectId?: string;
131
131
  /** This option is as-per the object level cannotTestReason, however applied to all relationship operations */
132
132
  relationshipsToCannotTestReason?: string;
133
+ /**
134
+ * The query field whose value becomes row.meta.key (generated like upsert.key). When declared, the fieldMetadata
135
+ * feature checks that the field is tagged isKey (isUserKey when expectUserKey) and that no other query field is, and
136
+ * the list and idsFilter features check that every returned row's meta.key equals the string form of its value.
137
+ */
138
+ key?: {
139
+ /** Path to the key in query fields */
140
+ path?: API.JsonValuePath;
141
+ /** Is the key field tagged isUserKey (a user supplied key) rather than isKey? */
142
+ expectUserKey?: boolean;
143
+ };
133
144
  };
134
145
  upsert?: {
135
146
  /** This option is as-per the object level sameAsObjectId, however applied at the upsert operation */
@@ -219,15 +230,15 @@ export interface ObjectTestResult {
219
230
  fatalError?: CaughtError;
220
231
  notTestedSameAsObjectId?: string;
221
232
  notTestedReason?: string;
222
- list?: "Passed" | "Passed: Limited test data, pagination not tested" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports list, test spec does not" | "Failed: Test spec supports list, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data";
233
+ list?: "Passed" | "Passed: Limited test data, pagination not tested" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports list, test spec does not" | "Failed: Test spec supports list, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Expected values did not match" | "Failed: Expected error did not occur";
223
234
  listNotTestedSameAsObjectId?: string;
224
235
  listNotTestedReason?: string;
225
236
  listFatalError?: CaughtError;
226
- idsFilter?: "Passed" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports idsFilter, test spec does not" | "Failed: Test spec supports idsFilter, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Returned unexpected row" | "Failed: Row not returned" | "Failed: More rows returned than expected";
237
+ idsFilter?: "Passed" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports idsFilter, test spec does not" | "Failed: Test spec supports idsFilter, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Returned unexpected row" | "Failed: Row not returned" | "Failed: More rows returned than expected" | "Failed: Expected values did not match" | "Failed: Expected error did not occur";
227
238
  idsFilterNotTestedSameAsObjectId?: string;
228
239
  idsFilterNotTestedReason?: string;
229
240
  idsFilterFatalError?: CaughtError;
230
- checkpointFilter?: "Passed" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports checkpointFilter, test spec does not" | "Failed: Test spec supports checkpointFilter, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data for step 1" | "Failed: No test data for step 2" | "Failed: Returned unexpected row for step 1" | "Failed: Returned unexpected row for step 2" | "Failed: Row not returned for step 1" | "Failed: Row not returned for step 2" | "Failed: Next checkpoint not returned";
241
+ checkpointFilter?: "Passed" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Object metadata supports checkpointFilter, test spec does not" | "Failed: Test spec supports checkpointFilter, object metadata does not" | "Failed: Fatal error during testing" | "Failed: No test data for step 1" | "Failed: No test data for step 2" | "Failed: Returned unexpected row for step 1" | "Failed: Returned unexpected row for step 2" | "Failed: Row not returned for step 1" | "Failed: Row not returned for step 2" | "Failed: Next checkpoint not returned" | "Failed: Expected values did not match" | "Failed: Expected error did not occur";
231
242
  checkpointFilterNotTestedSameAsObjectId?: string;
232
243
  checkpointFilterNotTestedReason?: string;
233
244
  checkpointFilterFatalError?: CaughtError;
@@ -240,7 +251,7 @@ export interface ObjectTestResult {
240
251
  matchFilterNotTestedReason?: string;
241
252
  matchFieldCount?: number;
242
253
  matchFilterResults?: MatchRuleTestResult[];
243
- upsert?: "Passed" | "Passed (insert only)" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Feature has no test spec" | "Failed: Fatal error during testing" | "Failed: Test spec does not define key field" | "Failed: No test data for insert" | "Failed: No test data for update" | "Failed: No verifyField included with test data" | "Failed: query after insert did not return expected rows" | "Failed: No key path to test update" | "Failed: update returned unexpected row" | "Failed: verifyField value on the upsert row was blank" | "Failed: verifyField value on the queried row does not match the upsert value";
254
+ upsert?: "Passed" | "Passed (insert only)" | "Not tested" | "Not supported" | "Failed: 'Same as object' not tested" | "Failed: Feature has no test spec" | "Failed: Fatal error during testing" | "Failed: Test spec does not define key field" | "Failed: No test data for insert" | "Failed: No test data for update" | "Failed: No verifyField included with test data" | "Failed: query after insert did not return expected rows" | "Failed: No key path to test update" | "Failed: update returned unexpected row" | "Failed: verifyField value on the upsert row was blank" | "Failed: verifyField value on the queried row does not match the upsert value" | "Failed: Expected values did not match";
244
255
  upsertNotTestedSameAsObjectId?: string;
245
256
  upsertNotTestedReason?: string;
246
257
  upsertFatalError?: CaughtError;
@@ -263,11 +274,11 @@ export interface ObjectTestResult {
263
274
  export interface FieldMetadataIssue {
264
275
  operation: "query" | "upsert" | "delete";
265
276
  path?: string;
266
- issue: "Missing canMatch" | "No test spec for key field" | "Key field from test spec not found on object" | "Key field not tagged with isKey" | "Key field not tagged with isUserKey" | "Key field user key structure incorrect {value: string, operation: string}";
277
+ issue: "Missing canMatch" | "No test spec for key field" | "Key field from test spec not found on object" | "Key field not tagged with isKey" | "Key field not tagged with isUserKey" | "Key field user key structure incorrect {value: string, operation: string}" | "More than one query field tagged with isKey or isUserKey";
267
278
  }
268
279
  export interface MatchRuleTestResult {
269
280
  rule: API.RowMatchRuleType;
270
- status?: "Passed" | "Not tested" | "Failed: Rule has no test spec" | "Failed: Rule not present on object" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Expected match not returned" | "Failed: Wrong match returned" | "Failed: Test data invalid, no expected row ids";
281
+ status?: "Passed" | "Not tested" | "Failed: Rule has no test spec" | "Failed: Rule not present on object" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Expected match not returned" | "Failed: Wrong match returned" | "Failed: Test data invalid, no expected row ids" | "Failed: Expected values did not match" | "Failed: Expected error did not occur";
271
282
  notTestedSameAsObjectId?: string;
272
283
  notTestedReason?: string;
273
284
  errorRowId?: string;
@@ -277,7 +288,7 @@ export interface MatchRuleTestResult {
277
288
  }
278
289
  export interface RelatedFilterTestResult {
279
290
  relationshipId: string;
280
- status?: "Passed" | "Not tested" | "Failed: Relationship has no test spec" | "Failed: Relationship not present on object" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Did not find expected related row" | "Failed: Found unexpected row" | "Failed: Test data invalid, no expected row ids" | "Failed: Test data invalid, 'from' row not returned via idsFilter";
291
+ status?: "Passed" | "Not tested" | "Failed: Relationship has no test spec" | "Failed: Relationship not present on object" | "Failed: Fatal error during testing" | "Failed: No test data" | "Failed: Did not find expected related row" | "Failed: Found unexpected row" | "Failed: Test data invalid, no expected row ids" | "Failed: Test data invalid, 'from' row not returned via idsFilter" | "Failed: Expected values did not match" | "Failed: Expected error did not occur";
281
292
  notTestedSameAsObjectId?: string;
282
293
  notTestedReason?: string;
283
294
  errorRowId?: string;
@@ -328,6 +339,11 @@ export interface UpsertData {
328
339
  verifyFields?: Array<API.JsonValuePath>;
329
340
  /** optionally specify other fields to include when querying the data back for validation */
330
341
  fields?: Array<API.JsonValuePath>;
342
+ /**
343
+ * Assertions on the query-back of this data's row, for values the test did not write (identity and computed columns,
344
+ * defaults, server timestamps, rowversions). Not evaluated by the delete test, which reuses upsertPrepare.
345
+ */
346
+ expect?: UpsertExpect;
331
347
  }
332
348
  /** Expresses how to simulate an upsertClean issue, and defines the expected response. */
333
349
  export interface UpsertIssueSimulator {
@@ -360,6 +376,8 @@ export interface MatchData {
360
376
  expectedMatchRowIds: string[];
361
377
  /** optionally specify the fields to include in the match query */
362
378
  fields?: Array<API.JsonValuePath>;
379
+ /** the match query must fail (error), or its matched rows must hold these values (rows) */
380
+ expect?: Expect;
363
381
  }
364
382
  /** Options passed when requesting data that will be used for a relationship test. */
365
383
  export interface RelationshipOptions {
@@ -384,6 +402,8 @@ export interface RelationshipData {
384
402
  srcFields?: Array<API.JsonValuePath>;
385
403
  /** optionally specify the fields from the 'other' row that should be returned in the response */
386
404
  relatedFields?: Array<API.JsonValuePath>;
405
+ /** the related query must fail (error), or the related rows it returns must hold these values (rows) */
406
+ expect?: Expect;
387
407
  }
388
408
  /** Options passed when requesting data that will be used for a checkpoint test. */
389
409
  export interface CheckpointStep1Options {
@@ -411,12 +431,16 @@ export interface CheckpointStep1Data {
411
431
  expectedRowIds: string[];
412
432
  /** optionally specify the fields to include in the checkpoint query */
413
433
  fields?: Array<API.JsonValuePath>;
434
+ /** the step 1 query must fail (error; step 2 is then skipped), or its rows must hold these values (rows) */
435
+ expect?: Expect;
414
436
  }
415
437
  export interface CheckpointStep2Data {
416
438
  /** id of rows we should receive back in response to the second checkpoint query */
417
439
  expectedRowIds: string[];
418
440
  /** optionally specify the fields to include in the checkpoint query */
419
441
  fields?: Array<API.JsonValuePath>;
442
+ /** the step 2 query must fail (error), or its rows must hold these values (rows) */
443
+ expect?: Expect;
420
444
  }
421
445
  /** Options passed when requesting data that will be used for an list test. */
422
446
  export interface ListOptions {
@@ -435,6 +459,11 @@ export interface ListData {
435
459
  fields?: Array<API.JsonValuePath>;
436
460
  /** if the test harness created test data, place the ids of the rows created here */
437
461
  rowIds?: string[];
462
+ /**
463
+ * The list query must fail (error), or the rows it returns must hold these values (rows). The list reads one page plus
464
+ * one row (pageSize + 1), so a row named by its key must be within that read; use "*" for assertions on every row.
465
+ */
466
+ expect?: Expect;
438
467
  }
439
468
  /** Options passed when requesting data that will be used for an idsFilter test. */
440
469
  export interface IdsFilterOptions {
@@ -451,6 +480,11 @@ export interface IdsFilterData {
451
480
  id2: string;
452
481
  /** optionally specify the fields to include in the idsFilter query */
453
482
  fields?: Array<API.JsonValuePath>;
483
+ /**
484
+ * With error, the connector must reject the ids: the harness runs one query for [id1, id2] and passes only when it
485
+ * fails as described. With rows, the rows that query returns must hold these values.
486
+ */
487
+ expect?: Expect;
454
488
  }
455
489
  /** Options passed when requesting data that will be used for a rowFilters test. */
456
490
  export interface RowFiltersOptions {
@@ -469,7 +503,64 @@ export interface RowFilterData {
469
503
  expectedRowIds: string[];
470
504
  /** optionally specify the fields to include in the rowFilter query */
471
505
  fields?: Array<API.JsonValuePath>;
506
+ /** declared for uniformity with the other features; the harness does not run row filters yet, so it is not evaluated */
507
+ expect?: Expect;
508
+ }
509
+ /**
510
+ * Expected outcome of a feature's query, beyond which rows come back. The module computes these at prepare time from
511
+ * data it seeded; nothing here should be read from the connector under test.
512
+ */
513
+ export interface Expect {
514
+ /** the operation must fail, and fail like this; a success is a failure of the test */
515
+ error?: ExpectedError;
516
+ /**
517
+ * Assertions on returned rows' values by path, keyed by row meta.key; "*" applies to every returned row, and an
518
+ * assertion under a row's own key overrides a "*" assertion on the same path.
519
+ */
520
+ rows?: Record<string, Assertion[]>;
521
+ }
522
+ /** How an expected failure must look. With neither member set, any error passes. */
523
+ export interface ExpectedError {
524
+ /** must equal the thrown error's `code` (e.g. a ScriptError code) */
525
+ code?: string;
526
+ /** regex source that must match the thrown error's message */
527
+ messagePattern?: string;
528
+ }
529
+ /** Assertions on the query-back of an upsert test row, which cannot be keyed: the insert assigns its key. */
530
+ export interface UpsertExpect {
531
+ /** assertions on the row queried back after the insert */
532
+ insert?: Assertion[];
533
+ /** assertions on the row queried back after the update (not run for insertOnly objects) */
534
+ update?: Assertion[];
472
535
  }
536
+ /**
537
+ * One assertion on a value in row.data:
538
+ * - equals: compared per the field's declared type (strings exactly, numbers numerically, booleans, dates as instants at
539
+ * the precision the field's date format implies, objects and arrays structurally; undeclared paths structurally)
540
+ * - matches: regex source the value (as a string) must match, for hex, GUIDs and formats
541
+ * - approx: numeric value within tolerance
542
+ * - present: the value is there and not null
543
+ * - absent: the path is not in the row at all (a column the connector must not echo)
544
+ */
545
+ export type Assertion = {
546
+ path: API.JsonValuePath;
547
+ equals: unknown;
548
+ } | {
549
+ path: API.JsonValuePath;
550
+ matches: string;
551
+ } | {
552
+ path: API.JsonValuePath;
553
+ approx: {
554
+ value: number;
555
+ tolerance: number;
556
+ };
557
+ } | {
558
+ path: API.JsonValuePath;
559
+ present: true;
560
+ } | {
561
+ path: API.JsonValuePath;
562
+ absent: true;
563
+ };
473
564
  /**
474
565
  * Find object field metadata by path.
475
566
  * @param {API.ObjectField[]} fields