@syncmatters/connector-sdk 1.0.0
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/LICENSE +21 -0
- package/README.md +39 -0
- package/index.d.ts +3 -0
- package/index.js +1 -0
- package/lib/connector-error.d.ts +38 -0
- package/lib/connector.d.ts +470 -0
- package/lib/environment.d.ts +45 -0
- package/lib/file-provider-buffer.d.ts +11 -0
- package/lib/file-provider-disk.d.ts +11 -0
- package/lib/file-provider-string.d.ts +11 -0
- package/lib/http-client.d.ts +10 -0
- package/lib/kv-store.d.ts +7 -0
- package/lib/open-api-3.d.ts +30 -0
- package/lib/path-utils.d.ts +18 -0
- package/lib/rate-limiter.d.ts +14 -0
- package/lib/serve-api.d.ts +4 -0
- package/lib/utilities.d.ts +9 -0
- package/module.d.ts +19 -0
- package/package.json +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SyncMatters
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @syncmatters/connector-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript type definitions for the **SyncMatters Connector SDK**.
|
|
4
|
+
|
|
5
|
+
This is a **types-only** package: it provides IntelliSense and type checking when developing
|
|
6
|
+
SyncMatters connectors locally (for example in VS Code or Cursor). Connector code executes on the
|
|
7
|
+
SyncMatters platform, which provides the runtime implementation of this SDK.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import SDK from "@syncmatters/connector-sdk";
|
|
13
|
+
|
|
14
|
+
export default class MyConnector {
|
|
15
|
+
/** @param {SDK.InitArgs} args @returns {Promise<void>} */
|
|
16
|
+
async init(args) {
|
|
17
|
+
SDK.verifyType(this);
|
|
18
|
+
// ...
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @returns {Promise<SDK.TestResult>} */
|
|
22
|
+
async test() {
|
|
23
|
+
// ...
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Add `"checkJs": true` to your `jsconfig.json` to activate the JSDoc type annotations used in
|
|
29
|
+
connector `.mjs` files.
|
|
30
|
+
|
|
31
|
+
## Legacy package name
|
|
32
|
+
|
|
33
|
+
`@ihq/connector-sdk` is the legacy name of this package (IntegrateHQ is now SyncMatters).
|
|
34
|
+
Existing connectors importing the legacy name continue to work on-platform.
|
|
35
|
+
|
|
36
|
+
## Support
|
|
37
|
+
|
|
38
|
+
- <https://syncmatters.com>
|
|
39
|
+
- <support@syncmatters.com>
|
package/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw new Error("This package contains type definitions only - connector and script code executes on the SyncMatters platform. See https://syncmatters.com");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CodedError } from "@syncmatters/script-api";
|
|
2
|
+
/** ErrorCode values are common to all connectors. */
|
|
3
|
+
export declare enum ErrorCode {
|
|
4
|
+
None = "CONN_NONE" /** default */,
|
|
5
|
+
ApiReportedError = "CONN_API_REPORTED_ERROR",
|
|
6
|
+
ApiTokenGenerationTerminated = "CONN_API_TOKEN_GENERATION_TERMINATED",
|
|
7
|
+
ApiUrlNotSupported = "CONN_API_URL_NOT_SUPPORTED",
|
|
8
|
+
InvalidApiKey = "CONN_INVALID_API_KEY",
|
|
9
|
+
InvalidFieldId = "CONN_INVALID_FIELD_ID",
|
|
10
|
+
InvalidFieldMeta = "CONN_INVALID_FIELD_METADATA",
|
|
11
|
+
InvalidCacheFileId = "CONN_INVALID_CACHE_FILE_ID",
|
|
12
|
+
InvalidCacheFilter = "CONN_INVALID_CACHE_FILTER",
|
|
13
|
+
InvalidCachePageFormat = "CONN_INVALID_CACHE_PAGE_FORMAT",
|
|
14
|
+
InvalidCacheRowKey = "CONN_INVALID_CACHE_ROW_KEY",
|
|
15
|
+
InvalidFilePath = "CONN_INVALID_FILE_PATH",
|
|
16
|
+
InvalidFilterParameter = "CONN_INVALID_FILTER_PARAMETER",
|
|
17
|
+
InvalidObjectId = "CONN_INVALID_OBJECT_ID",
|
|
18
|
+
InvalidEventId = "CONN_INVALID_EVENT_ID",
|
|
19
|
+
InvalidOperation = "CONN_INVALID_OPERATION",
|
|
20
|
+
InvalidOptionValue = "CONN_INVALID_OPTION_VALUE",
|
|
21
|
+
InvalidPassword = "CONN_INVALID_PASSWORD",
|
|
22
|
+
InvalidRecordId = "CONN_INVALID_RECORD_ID",
|
|
23
|
+
InvalidQueryResponse = "CONN_INVALID_QUERY_RESPONSE",
|
|
24
|
+
InvalidRelationshipMeta = "CONN_INVALID_RELATIONSHIP_METADATA",
|
|
25
|
+
InvalidUserName = "CONN_INVALID_USERNAME",
|
|
26
|
+
NotImplimented = "CONN_NOT_IMPLEMENTED",
|
|
27
|
+
ResourceAlreadyClosed = "CONN_RESOURCE_CLOSED"
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* ConnectorError extends error to expose a meaningful error code & optionally type-specific
|
|
31
|
+
* useful data for handling the error e.g.const err = new SDK.ConnectorError(SDK.ErrorCode.InvalidOptionValue,
|
|
32
|
+
* "supplied option not valid", {issues: [{objectId: "Deals", fieldId: "sales_rep", option: "Bob Smith"}]});
|
|
33
|
+
*/
|
|
34
|
+
export declare class ConnectorError extends Error implements CodedError {
|
|
35
|
+
readonly code: string;
|
|
36
|
+
readonly data: unknown;
|
|
37
|
+
constructor(code: ErrorCode, message?: string, data?: unknown);
|
|
38
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import { EventTypeMeta, Logger, ObjectField, UpsertIssue, ObjectIndex, ObjectMeta, ObjectMetaUpsert, Row, TestResult, ScriptType, UpsertFieldOptionMeta, QueryMatchFilter, QueryCheckpointFilter, JsonValuePathPart, SyncSession, ObjectFieldOption, RowMatchRuleType, SyncOptimalBatchSizeOperation, SyncOptimalBatchSizeBatchType } from "@syncmatters/script-api";
|
|
2
|
+
import SDK from "../index.js";
|
|
3
|
+
/**
|
|
4
|
+
* InitArgs are passed as the only argument to the connector init() function.
|
|
5
|
+
*/
|
|
6
|
+
export interface InitArgs {
|
|
7
|
+
/** id uniquely identifies the connection instance within the scripting environment */
|
|
8
|
+
readonly id: string;
|
|
9
|
+
/** display name of the connection */
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/** identity is optionally returned by the meta() call and may supply a useful, system
|
|
12
|
+
* specific, identifier of the identity of the connection (e.g. email address used to
|
|
13
|
+
* connect) */
|
|
14
|
+
readonly identity?: string;
|
|
15
|
+
/** mode holds the reason for which the connection is being created */
|
|
16
|
+
readonly mode: ScriptType;
|
|
17
|
+
/** log can write messages to the platform log */
|
|
18
|
+
readonly log: Logger;
|
|
19
|
+
/** sourcePath is the directory holding the main connector file */
|
|
20
|
+
readonly sourcePath: string;
|
|
21
|
+
/** webhookUrl is connection specific webhook url */
|
|
22
|
+
readonly webhookUrl?: string;
|
|
23
|
+
/** webhookUid is a globally unique string used within the connection specific webhook url */
|
|
24
|
+
readonly webhookUid?: string;
|
|
25
|
+
/** settings holds the configured connection instance settings */
|
|
26
|
+
readonly settings: Map<string, any>;
|
|
27
|
+
/** if the connection has a managet OAuth2 token this provider will grant access to the access token */
|
|
28
|
+
oauth2Provider?: OAuth2TokenProvider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Connector represents a connection to a system, exposing meta data and data.
|
|
32
|
+
*/
|
|
33
|
+
export interface Connector {
|
|
34
|
+
/** init is called exactly once for each instance of a connector reference by a script. */
|
|
35
|
+
init?(args: InitArgs): Promise<void>;
|
|
36
|
+
/** test attempts to connect to the system, so validating credentials and basic settings. */
|
|
37
|
+
test(): Promise<TestResult>;
|
|
38
|
+
/** meta connects to the system to retrieve system, object and field definitions (metadata). */
|
|
39
|
+
meta(): Promise<ConnectorMeta>;
|
|
40
|
+
/**
|
|
41
|
+
* query connects to the system to retrieve data from the object with the given id. The connector manages
|
|
42
|
+
* state needed for multi-page quesies using parameter 'queryState'. On the first call to query() 'queryState'
|
|
43
|
+
* will be undefined; on subseqent calls the 'queryState' will be supplied, holding the value of the 'queryState'
|
|
44
|
+
* returned by the prior call to query().
|
|
45
|
+
*/
|
|
46
|
+
query?(options: QueryOptions): Promise<QueryPage>;
|
|
47
|
+
/** @deprecated cacheRefreshSpec generates the queryFilter etc ... needed to initate a refresh of the objects cached data. */
|
|
48
|
+
cacheRefreshOptions?(options: RefreshSpecOptions): Promise<RefreshSpec>;
|
|
49
|
+
/** upsert adds/updates records in the target system, returning rows in "query" result format. */
|
|
50
|
+
upsert?(options: UpsertOptions): Promise<Row[]>;
|
|
51
|
+
/** upsertClean may test whether the upsert request is well formed and repair/remove invalid field values. */
|
|
52
|
+
upsertClean?(options: UpsertCleanOptions): Promise<UpsertCleanResponse>;
|
|
53
|
+
/** upsertFieldOptions adds/updates field option values to picklist style fields. */
|
|
54
|
+
upsertFieldOptions?(options: UpsertOptionsOptions): Promise<UpsertOptionsResponse>;
|
|
55
|
+
/** delete records from the target system, returning the key's of deleted rows. */
|
|
56
|
+
delete?(options: DeleteOptions): Promise<Row[]>;
|
|
57
|
+
/** the endpoint can recommend batch sizes to used when querying/updating/deleting data */
|
|
58
|
+
optimalBatchSize?(options: OptimalBatchSizeOptions): Promise<OptimalBatchSizeResponse>;
|
|
59
|
+
/** parseEvents receives raw event payloads from webhooks and transforms it to ParsedEvent format. */
|
|
60
|
+
parseEvents?(optons: ParseEventsOptions): Promise<ParsedEvents>;
|
|
61
|
+
/**
|
|
62
|
+
* handleParsedEvent processes events emitted by the parseEvents(...) produces changed records that may be used
|
|
63
|
+
* to keep the cache up to date - e.g. some systems emit record deleted events, this handler can notify the cache
|
|
64
|
+
* that records have been deleted. This method is optional.
|
|
65
|
+
*/
|
|
66
|
+
handleParsedEvent?(options: HandleParsedEventOptions): Promise<void>;
|
|
67
|
+
/** [optional] inpliment sync session begin/end if the connector needs to bootstrap internal caching for a sync group run */
|
|
68
|
+
syncSessionBegin?(session: SyncSession): Promise<void>;
|
|
69
|
+
syncSessionEnd?(session: SyncSession): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* [optional] implement this method if unmanaged resources must be destroyed when the process exits. Note that this
|
|
72
|
+
* function is run on a best-effort basis - i.e. it is possible for the process to exit abnormally without calling
|
|
73
|
+
* this method. */
|
|
74
|
+
dispose?(options: DisposeOptions): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* base may be implimented by a connector to return an underlying object that can be used to interact directly
|
|
77
|
+
* with a source system.
|
|
78
|
+
* <p>
|
|
79
|
+
* Note: connectors are often developed on top of 3rd party libraries. In such cases, for diagnostic reasons, it
|
|
80
|
+
* is appropriate to allow direct access to the instantiated instance of the base library via this method.
|
|
81
|
+
* </p>
|
|
82
|
+
*/
|
|
83
|
+
base?(): Promise<any>;
|
|
84
|
+
}
|
|
85
|
+
/** verifyType may be used to check whether the connector class correctly impliments Connector */
|
|
86
|
+
export declare function verifyType(_connector: Connector): void;
|
|
87
|
+
/** QueryOptions are passed to the query function. */
|
|
88
|
+
export interface QueryOptions {
|
|
89
|
+
/** log can record to the platform event store */
|
|
90
|
+
log: Logger;
|
|
91
|
+
/** id of the object being queried */
|
|
92
|
+
id: string;
|
|
93
|
+
/** metadata from the object being queried */
|
|
94
|
+
meta: ObjectMeta;
|
|
95
|
+
/** request cached metadata from any object on the connection */
|
|
96
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
97
|
+
/** request checkpoint data from a previous saved checkpointFilter */
|
|
98
|
+
checkpointData(checkpoint: string): Promise<SDK.FileProvider>;
|
|
99
|
+
/** options to apply to the query */
|
|
100
|
+
queryOptions?: {
|
|
101
|
+
/** max rows to return */
|
|
102
|
+
limit?: number;
|
|
103
|
+
/** should the reponse include a file for each row? */
|
|
104
|
+
file?: boolean;
|
|
105
|
+
/** fields the caller expects in the response */
|
|
106
|
+
fields?: Array<Array<JsonValuePathPart>>;
|
|
107
|
+
/** include fields needed to collect rows from selected relationships */
|
|
108
|
+
relationshipFields?: Array<string>;
|
|
109
|
+
/** retrieve a random sample of up to 'limit' records */
|
|
110
|
+
randomFilter?: boolean;
|
|
111
|
+
/** filter for rows by row id (key) */
|
|
112
|
+
idsFilter?: Array<string>;
|
|
113
|
+
/** filter for rows related to other rows */
|
|
114
|
+
relatedFilter?: QueryRelatedFilter;
|
|
115
|
+
/** filter for rows that meet a specific matching rule */
|
|
116
|
+
matchFilter?: QueryMatchFilter;
|
|
117
|
+
/** collect records changed since a particular checkpoint */
|
|
118
|
+
checkpointFilter?: QueryCheckpointFilter;
|
|
119
|
+
/** system specific row filters */
|
|
120
|
+
rowFilter?: any;
|
|
121
|
+
/** system specific property filters */
|
|
122
|
+
propertyFilter?: any;
|
|
123
|
+
};
|
|
124
|
+
queryState?: any;
|
|
125
|
+
}
|
|
126
|
+
/** QueryRelatedFilter holds filters to apply when querying rows from this object that relate to rows from another object. */
|
|
127
|
+
export interface QueryRelatedFilter {
|
|
128
|
+
/** id of the other object for which related rows from this object are sought */
|
|
129
|
+
otherObjectId: string;
|
|
130
|
+
/** unique id of the relationship defined on the other object that describes how other object rows relate to rows on
|
|
131
|
+
* this object */
|
|
132
|
+
otherRelationshipId: string;
|
|
133
|
+
/** rows from the other object for which related rows from this object are sought */
|
|
134
|
+
otherRows: Array<Row>;
|
|
135
|
+
}
|
|
136
|
+
/** ParseEventsOptions are passed to the connector parseEvents(...) function. */
|
|
137
|
+
export interface ParseEventsOptions {
|
|
138
|
+
/** request cached metadata from any object on the connection */
|
|
139
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
140
|
+
/** verify the hash of the payload using a server side managed key */
|
|
141
|
+
verifyHash: (options: {
|
|
142
|
+
strategy: "OAuth2.Sha256.Hex" | "OAuth2.Md5.Hex";
|
|
143
|
+
expression: string;
|
|
144
|
+
expected: string;
|
|
145
|
+
}) => Promise<{
|
|
146
|
+
success: boolean;
|
|
147
|
+
}>;
|
|
148
|
+
/** the raw event payload */
|
|
149
|
+
payload: {
|
|
150
|
+
webhookUid: string;
|
|
151
|
+
uri: string;
|
|
152
|
+
headers: {
|
|
153
|
+
[name: string]: string[];
|
|
154
|
+
};
|
|
155
|
+
method: string;
|
|
156
|
+
body: Buffer;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/** ParsedEvents are returned from the parseEvents(...) function. */
|
|
160
|
+
export interface ParsedEvents {
|
|
161
|
+
events: ParsedEvent[];
|
|
162
|
+
}
|
|
163
|
+
/** ParsedEvent holds the details of an event as parsed by connector parseEvents(...) */
|
|
164
|
+
export interface ParsedEvent {
|
|
165
|
+
eventIdentity: string;
|
|
166
|
+
uniqueId?: string;
|
|
167
|
+
typeId: string;
|
|
168
|
+
timestamp: number;
|
|
169
|
+
object?: {
|
|
170
|
+
id: string;
|
|
171
|
+
key: string;
|
|
172
|
+
};
|
|
173
|
+
data?: any;
|
|
174
|
+
}
|
|
175
|
+
/** HandleParsedEventOptions are passed to the handleParsedEvent function. */
|
|
176
|
+
export interface HandleParsedEventOptions {
|
|
177
|
+
id: string;
|
|
178
|
+
meta: ObjectMeta;
|
|
179
|
+
event: {
|
|
180
|
+
id: string;
|
|
181
|
+
timestamp: number;
|
|
182
|
+
key?: string;
|
|
183
|
+
data?: any;
|
|
184
|
+
};
|
|
185
|
+
reportChanges: (changes: {
|
|
186
|
+
id: string;
|
|
187
|
+
page: QueryPage;
|
|
188
|
+
}) => Promise<void>;
|
|
189
|
+
}
|
|
190
|
+
/** QueryPage is a page of data returned in response to a query. */
|
|
191
|
+
export interface QueryPage {
|
|
192
|
+
/** rows of data from the page. */
|
|
193
|
+
rows: Row[];
|
|
194
|
+
/** Connector should store query specific details to the queryState, with subsequent calls passing the state back to
|
|
195
|
+
* the query(...) call.
|
|
196
|
+
* Typically holds pointers such as 'offset' and 'pageSize'. Only the first call to query(...) will have no queryState. */
|
|
197
|
+
queryState?: any;
|
|
198
|
+
/** Only applicable to checkpointFilter queries when returning the last row.. This should hold the next checkpoint filter
|
|
199
|
+
* the caller should pass to retrieve rows that
|
|
200
|
+
* were added/updated since this checkpoint query ran. Typlically only available when finalPage=true */
|
|
201
|
+
checkpoint?: string;
|
|
202
|
+
/** Only applicable to checkpointFilter queries when returning the last row. Can attach a file holding any required state
|
|
203
|
+
* needed to respond to a future query to collect the rows from the checkpoint */
|
|
204
|
+
checkpointData?: SDK.FileProvider;
|
|
205
|
+
/** @deprecated cacheState is persisted for use across multiple integration runs. It is passed to cacheRefreshOptions(...)
|
|
206
|
+
* to allow preparation of
|
|
207
|
+
* the query filter to pass to cache.refresh.ObjectId(...) in order to perform a differential refresh of the cached data. */
|
|
208
|
+
cacheState?: any;
|
|
209
|
+
/** Connector may set to true to indicate the query has no more pages of data return. Returning no QueryPage, no queryState
|
|
210
|
+
* or no rows has the same effect. */
|
|
211
|
+
finalPage?: boolean;
|
|
212
|
+
}
|
|
213
|
+
/** RefreshSpecOptions is passed to the cacheRefreshSpec function. */
|
|
214
|
+
export interface RefreshSpecOptions {
|
|
215
|
+
id: string;
|
|
216
|
+
meta: ObjectMeta;
|
|
217
|
+
cacheState: any;
|
|
218
|
+
}
|
|
219
|
+
/** RefreshSpec holds connector specific options needed to initiate a cache refresh. */
|
|
220
|
+
export interface RefreshSpec {
|
|
221
|
+
clearCache?: boolean;
|
|
222
|
+
queryOptions?: {
|
|
223
|
+
limit?: number;
|
|
224
|
+
rowFilter?: any;
|
|
225
|
+
propertyFilter?: any;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/** UpsertCleanOptions is passed to the upsertClean function. */
|
|
229
|
+
export interface UpsertCleanOptions {
|
|
230
|
+
/** log can record to the platform event store */
|
|
231
|
+
log: Logger;
|
|
232
|
+
/** the ObjectId */
|
|
233
|
+
id: string;
|
|
234
|
+
/** Object field definitions etc ... */
|
|
235
|
+
meta: ObjectMeta;
|
|
236
|
+
/** request cached metadata from any object on the connection */
|
|
237
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
238
|
+
/** the row being upserted */
|
|
239
|
+
upsert: any;
|
|
240
|
+
/** the current row to compare with the upsert to detect changes */
|
|
241
|
+
current?: SDK.Row;
|
|
242
|
+
/** reference to the upsert field the caller would like populated with details of identified issues - included
|
|
243
|
+
* to allow the connector override the default strategy used to resolve the 'currentIssues' from the 'current'
|
|
244
|
+
* row as some connectors have the Upsert row shaped differently to the Query row (default strategy: the 'currentIssues'
|
|
245
|
+
* string is expected to be found here 'current.data.{path/jsonPath}') */
|
|
246
|
+
issuesField?: {
|
|
247
|
+
path?: string[];
|
|
248
|
+
jsonPath?: string;
|
|
249
|
+
};
|
|
250
|
+
/** tests whether values in the upsert's picklist fields represent valid options, identifies issues and optionally
|
|
251
|
+
* resolves or cleanses. */
|
|
252
|
+
verifyFieldOptions: (options: {
|
|
253
|
+
cleanAction: "DeleteUpsertField" | "None";
|
|
254
|
+
meta?: (fieldPath: string[], id: any) => UpsertFieldOptionMeta;
|
|
255
|
+
matchByName?: {
|
|
256
|
+
disabled?: boolean;
|
|
257
|
+
accept?: (fieldPath: string[], id: string, matchedName: string) => boolean;
|
|
258
|
+
};
|
|
259
|
+
}) => Promise<Array<UpsertIssue>>;
|
|
260
|
+
/** tests whether values in the upsert's fields meet the field constraints, identifies issues and cleanses. */
|
|
261
|
+
verifyFieldConstraints: (options?: {
|
|
262
|
+
timeZone?: string;
|
|
263
|
+
}) => Promise<Array<UpsertIssue>>;
|
|
264
|
+
/** detects the first change in the upsert when compared to the current row */
|
|
265
|
+
detectFirstChange: (options?: DetectFirstChangeOptions) => UpsertCleanResponse["change"] | undefined;
|
|
266
|
+
}
|
|
267
|
+
/** DetectFirstChangeOptions are passed to the detectFirstChange function. */
|
|
268
|
+
export interface DetectFirstChangeOptions {
|
|
269
|
+
/** confirmChange is an optional handler that can confirm the change is real/reportable */
|
|
270
|
+
confirmChange?: (options: ConfirmChangeOptions) => boolean;
|
|
271
|
+
/** optionally override the default behavior of the detectFirstChange function */
|
|
272
|
+
overrides?: {
|
|
273
|
+
/** treat null as not equal to an empty array */
|
|
274
|
+
nullDoesNotEqualEmptyArray?: boolean;
|
|
275
|
+
/** treat null as not equal to an empty string */
|
|
276
|
+
nullDoesNotEqualEmptyString?: boolean;
|
|
277
|
+
/** treat null as not equal to an empty object */
|
|
278
|
+
nullDoesNotEqualEmptyObject?: boolean;
|
|
279
|
+
/** do not treat array element removal as a change */
|
|
280
|
+
doNotTreatArrayElementRemovalAsChange?: boolean;
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** ConfirmChangeOptions are passed to the optional confirmChange handler function */
|
|
284
|
+
export interface ConfirmChangeOptions {
|
|
285
|
+
/** id of the object being upserted */
|
|
286
|
+
objectId: string;
|
|
287
|
+
/** path to the field that is being upserted */
|
|
288
|
+
fieldPath: string[];
|
|
289
|
+
/** metadata for the field that is being upserted */
|
|
290
|
+
fieldMeta?: ObjectField;
|
|
291
|
+
/** the value of the field before the upsert */
|
|
292
|
+
oldValue?: any;
|
|
293
|
+
/** the value of the field after the upsert */
|
|
294
|
+
newValue?: any;
|
|
295
|
+
}
|
|
296
|
+
/** UpsertCleanResponse is returned from the upsertClean function. */
|
|
297
|
+
export interface UpsertCleanResponse {
|
|
298
|
+
/** indicates that changes were detected (ie. the row needed to be upserted) */
|
|
299
|
+
hasChanges: boolean;
|
|
300
|
+
/** details of the first change found */
|
|
301
|
+
change?: {
|
|
302
|
+
field: string;
|
|
303
|
+
oldValue?: string;
|
|
304
|
+
newValue?: string;
|
|
305
|
+
};
|
|
306
|
+
/** details of issues (includes any issues that were 'cleansed' to resolve) */
|
|
307
|
+
issues: UpsertIssue[];
|
|
308
|
+
/** if the default strategy to resolve 'currentIssues' from the 'current' row is overridden by the connector then
|
|
309
|
+
* 'currentIssues' should be extracted from 'current' row & returned here as a resolved/blank string (null/undefined
|
|
310
|
+
* indicates the detault strategy should be used) */
|
|
311
|
+
currentIssues?: string;
|
|
312
|
+
}
|
|
313
|
+
/** UpsertOptions is passed to the upsert function. */
|
|
314
|
+
export interface UpsertOptions {
|
|
315
|
+
/** log can record to the platform event store */
|
|
316
|
+
log: Logger;
|
|
317
|
+
/** id of the object being updated */
|
|
318
|
+
id: string;
|
|
319
|
+
/** metadata from the object being updated */
|
|
320
|
+
meta: ObjectMeta;
|
|
321
|
+
/** request cached metadata from any object on the connection */
|
|
322
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
323
|
+
/** rows to be written */
|
|
324
|
+
rows: any[];
|
|
325
|
+
}
|
|
326
|
+
/** UpsertOptionsOptions is passed to the upsertFieldOptions function. */
|
|
327
|
+
export interface UpsertOptionsOptions {
|
|
328
|
+
/** log can record to the platform event store */
|
|
329
|
+
log: Logger;
|
|
330
|
+
/** id of the object being updated */
|
|
331
|
+
id: string;
|
|
332
|
+
/** metadata from the object being updated */
|
|
333
|
+
meta: ObjectMeta;
|
|
334
|
+
/** request cached metadata from any object on the connection */
|
|
335
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
336
|
+
/** path to the field that is to have options updated */
|
|
337
|
+
fieldPath: string[];
|
|
338
|
+
/** picklist options to be added / updated */
|
|
339
|
+
options: Array<{
|
|
340
|
+
id: string;
|
|
341
|
+
meta?: {
|
|
342
|
+
name?: string;
|
|
343
|
+
order?: string;
|
|
344
|
+
pipeline?: string;
|
|
345
|
+
probability?: string;
|
|
346
|
+
};
|
|
347
|
+
}>;
|
|
348
|
+
}
|
|
349
|
+
/** UpsertOptionsResponse is returned from the upsertFieldOptions function. */
|
|
350
|
+
export interface UpsertOptionsResponse {
|
|
351
|
+
/** holds details of option id's that were created/found in the system (e.g. system may
|
|
352
|
+
* generate its own unique option id's) */
|
|
353
|
+
resolvedIds: Array<{
|
|
354
|
+
id: string;
|
|
355
|
+
resolvedId: string;
|
|
356
|
+
}>;
|
|
357
|
+
/** count of new options added */
|
|
358
|
+
added: number;
|
|
359
|
+
/** count of existing options updated */
|
|
360
|
+
updated: number;
|
|
361
|
+
/** count of existing options that need not be changed */
|
|
362
|
+
unchanged: number;
|
|
363
|
+
/** count of options that could not be added/updated */
|
|
364
|
+
unresolved: number;
|
|
365
|
+
/** optionally return changed object metadata to avoid meta refresh */
|
|
366
|
+
metaUpdate?: {
|
|
367
|
+
/** changed options to be applied to the object, will apply to both query & upsert fields (use if the options are the only change) */
|
|
368
|
+
objectFieldOptions?: ObjectFieldOption[];
|
|
369
|
+
/** updated upsert field to be applied to the object (use if other field metadata changes are required) */
|
|
370
|
+
upsertField?: ObjectField;
|
|
371
|
+
/** updated query field to be applied to the object, same path as upsert field (use if other field metadata changes are required) */
|
|
372
|
+
queryField?: ObjectField;
|
|
373
|
+
/** updated objects to be applied to the connection (use if other object metadata changes are required) */
|
|
374
|
+
objects?: ObjectMetaUpsert[];
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
/** DeleteOptions is passed to the delete function. */
|
|
378
|
+
export interface DeleteOptions {
|
|
379
|
+
/** log can record to the platform event store */
|
|
380
|
+
log: Logger;
|
|
381
|
+
/** id of the object that will have rows deleted */
|
|
382
|
+
id: string;
|
|
383
|
+
/** metadata from the object that will have rows deleted */
|
|
384
|
+
meta: ObjectMeta;
|
|
385
|
+
/** request cached metadata from any object on the connection */
|
|
386
|
+
objectMeta(id: string): Promise<ObjectMeta>;
|
|
387
|
+
/** connector specific details of rows to delete */
|
|
388
|
+
rows: any[];
|
|
389
|
+
}
|
|
390
|
+
/** OptimalBatchSizeOptions is passed to the optimalBatchSize function. */
|
|
391
|
+
export interface OptimalBatchSizeOptions {
|
|
392
|
+
/** id of the object for which batch size info is sought */
|
|
393
|
+
id: string;
|
|
394
|
+
/** metadata from the object */
|
|
395
|
+
meta: ObjectMeta;
|
|
396
|
+
/** operation to determine the optimal batch size for */
|
|
397
|
+
operation: SyncOptimalBatchSizeOperation;
|
|
398
|
+
/** for relatedFilter operation, the other object id and relationship id may refine the response */
|
|
399
|
+
relatedFilter?: {
|
|
400
|
+
otherObjectId: string;
|
|
401
|
+
otherRelationshipId: string;
|
|
402
|
+
};
|
|
403
|
+
/** for matchFilter operation, the rule may refine the response */
|
|
404
|
+
matchFilter?: RowMatchRuleType;
|
|
405
|
+
}
|
|
406
|
+
/** OptimalBatchSizeResponse is returned from the optimalBatchSize function. */
|
|
407
|
+
export interface OptimalBatchSizeResponse {
|
|
408
|
+
/** ideal batch size for the operation */
|
|
409
|
+
size: number;
|
|
410
|
+
/** for upsert & delete operations, optionally describe how batching behaves */
|
|
411
|
+
batchType?: SyncOptimalBatchSizeBatchType;
|
|
412
|
+
}
|
|
413
|
+
/** DisposeOptions is passed to the dispose function. */
|
|
414
|
+
export interface DisposeOptions {
|
|
415
|
+
/** log can record to the platform event store */
|
|
416
|
+
log: Logger;
|
|
417
|
+
}
|
|
418
|
+
/** ConnectorMeta provides access to connector metadata. */
|
|
419
|
+
export interface ConnectorMeta {
|
|
420
|
+
identity?: string;
|
|
421
|
+
objects: ObjectMetaUpsert[] | ObjectMetaSummary[];
|
|
422
|
+
events?: {
|
|
423
|
+
/** event identity should only be provided if the connector has a webhook mode of "per connector" */
|
|
424
|
+
identity?: string;
|
|
425
|
+
/** event types describe the events presented by this connecion */
|
|
426
|
+
types: EventTypeMeta[];
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
/** @deprecated ObjectMetaSummary provides access to a summary info for a single object. */
|
|
430
|
+
export interface ObjectMetaSummary {
|
|
431
|
+
id: string;
|
|
432
|
+
name?: string;
|
|
433
|
+
order?: string;
|
|
434
|
+
detail: () => Promise<ObjectMetaDetail>;
|
|
435
|
+
}
|
|
436
|
+
/** @deprecated ObjectMetaDetail provides detailed info for a single object. */
|
|
437
|
+
export interface ObjectMetaDetail {
|
|
438
|
+
queryFields?: ObjectField[];
|
|
439
|
+
queryFilter?: {
|
|
440
|
+
rowFilter?: ObjectField[];
|
|
441
|
+
propertyFilter?: ObjectField[];
|
|
442
|
+
};
|
|
443
|
+
queryFile?: boolean;
|
|
444
|
+
upsertFields?: ObjectField[];
|
|
445
|
+
deleteFields?: ObjectField[];
|
|
446
|
+
canUpsertClean?: boolean;
|
|
447
|
+
canUpsertFieldOptions?: boolean;
|
|
448
|
+
canAddCustomRelationships?: boolean;
|
|
449
|
+
systemIndexes?: ObjectIndex[];
|
|
450
|
+
data?: any;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* OAuth2TokenProvider provides access to the auto-refreshing OAuth2 access token. Register a callback to the onRefresh
|
|
454
|
+
* event to e.g. auto update HTTP authentication headers.
|
|
455
|
+
*/
|
|
456
|
+
export interface OAuth2TokenProvider {
|
|
457
|
+
token: string;
|
|
458
|
+
authParams: {
|
|
459
|
+
[key: string]: string | string[];
|
|
460
|
+
};
|
|
461
|
+
/** called when the background process refreshes the token */
|
|
462
|
+
onRefresh: (cb: (token: string) => void) => void;
|
|
463
|
+
/** force an immediate refresh of the access token (only needed if token expiry is any) */
|
|
464
|
+
forceRefresh: () => Promise<void>;
|
|
465
|
+
/** introspect the current access token */
|
|
466
|
+
introspectToken?: () => Promise<unknown>;
|
|
467
|
+
scope?: string;
|
|
468
|
+
expiry?: number;
|
|
469
|
+
tokenExtras?: any;
|
|
470
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { FileProvider, KvStore } from "@syncmatters/script-api";
|
|
2
|
+
/**
|
|
3
|
+
* ApiSpec defines a temporary, dynamic API endpoint that will be hosted by the nodejs process; it will be torn down when
|
|
4
|
+
* the script
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiSpec {
|
|
7
|
+
path: string;
|
|
8
|
+
apiKey: string;
|
|
9
|
+
handler: (request: ApiRequest, response: ApiResponse) => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
/** ApiRequest holds the request received at the cusom endpoint */
|
|
12
|
+
export interface ApiRequest {
|
|
13
|
+
params: {
|
|
14
|
+
[name: string]: string;
|
|
15
|
+
};
|
|
16
|
+
body: any;
|
|
17
|
+
headers: {
|
|
18
|
+
[name: string]: string | string[] | undefined;
|
|
19
|
+
};
|
|
20
|
+
method: string;
|
|
21
|
+
path: string;
|
|
22
|
+
url: string;
|
|
23
|
+
}
|
|
24
|
+
/** ApiResponse is used by the custom api handler to send a response to the caller */
|
|
25
|
+
export interface ApiResponse {
|
|
26
|
+
send: (code: number, body?: any) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Environment is presented to the hosting platform. It uses dependency injection to supply production implementations
|
|
30
|
+
* of connector support classes for use within connector code, e.g. const limit = new SDK.RateLimiter();
|
|
31
|
+
*/
|
|
32
|
+
export interface Environment {
|
|
33
|
+
kvStore: () => KvStore;
|
|
34
|
+
fileProviderDisk: (path: string, deleteOnClose?: boolean) => FileProvider;
|
|
35
|
+
fileProviderBuffer: (source: Buffer) => FileProvider;
|
|
36
|
+
fileProviderString: (source: string) => FileProvider;
|
|
37
|
+
openApi3: (options: any) => any;
|
|
38
|
+
serveApi: (options: ApiSpec) => string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* envSet is called by the hosting platform to supply the runtime environment components.
|
|
42
|
+
* @param env
|
|
43
|
+
*/
|
|
44
|
+
export declare function envSet(env: Environment): void;
|
|
45
|
+
export declare function envGet(): Environment;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FileProvider } from "@syncmatters/script-api";
|
|
2
|
+
export declare class FileProviderBuffer implements FileProvider {
|
|
3
|
+
constructor(source: Buffer);
|
|
4
|
+
length(): Promise<number>;
|
|
5
|
+
stream(): Promise<NodeJS.ReadableStream>;
|
|
6
|
+
formDataValue(encoding?: "utf8" | "utf16le" | "ucs2"): Promise<unknown>;
|
|
7
|
+
blob(fileName?: string): Promise<Blob>;
|
|
8
|
+
save(path?: string): Promise<string>;
|
|
9
|
+
close(): Promise<void>;
|
|
10
|
+
toJSON(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FileProvider } from "@syncmatters/script-api";
|
|
2
|
+
export declare class FileProviderDisk implements FileProvider {
|
|
3
|
+
constructor(path: string, deleteOnClose?: boolean);
|
|
4
|
+
length(): Promise<number>;
|
|
5
|
+
stream(): Promise<NodeJS.ReadableStream>;
|
|
6
|
+
formDataValue(encoding?: "utf8" | "utf16le" | "ucs2"): Promise<unknown>;
|
|
7
|
+
blob(fileName?: string): Promise<Blob>;
|
|
8
|
+
save(path?: string): Promise<string>;
|
|
9
|
+
close(): Promise<void>;
|
|
10
|
+
toJSON(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FileProvider } from "@syncmatters/script-api";
|
|
2
|
+
export declare class FileProviderString implements FileProvider {
|
|
3
|
+
constructor(source: string);
|
|
4
|
+
length(): Promise<number>;
|
|
5
|
+
stream(): Promise<NodeJS.ReadableStream>;
|
|
6
|
+
formDataValue(encoding?: "utf8" | "utf16le" | "ucs2"): Promise<unknown>;
|
|
7
|
+
blob(fileName?: string): Promise<Blob>;
|
|
8
|
+
save(path?: string): Promise<string>;
|
|
9
|
+
close(): Promise<void>;
|
|
10
|
+
toJSON(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import API from "@syncmatters/script-api";
|
|
2
|
+
/**
|
|
3
|
+
* This class exists as Connector SDK 1.0 exposed HttpClient as a helper class. Later this was moved to follow the API.utilities.helperFunc(...)
|
|
4
|
+
* paradigm to provide better consistency between the SDK and API.
|
|
5
|
+
*/
|
|
6
|
+
export declare class HttpClient {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(options?: API.HttpClientOptions);
|
|
9
|
+
execute(r: API.HttpRequest): Promise<any>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as API from "@syncmatters/script-api";
|
|
2
|
+
import { Logger, HttpClientOptions, RateLimiter, RateLimiterOptions } from "@syncmatters/script-api";
|
|
3
|
+
import { OAuth2TokenProvider } from "./connector.js";
|
|
4
|
+
export interface OpenApi3Options {
|
|
5
|
+
specPathYaml: string;
|
|
6
|
+
oauth2?: {
|
|
7
|
+
oauth2Provider: OAuth2TokenProvider;
|
|
8
|
+
securityName: string;
|
|
9
|
+
};
|
|
10
|
+
apiKey?: {
|
|
11
|
+
key: string;
|
|
12
|
+
securityName: string;
|
|
13
|
+
};
|
|
14
|
+
basicAuth?: {
|
|
15
|
+
username: string;
|
|
16
|
+
password: string;
|
|
17
|
+
securityName: string;
|
|
18
|
+
};
|
|
19
|
+
rateLimiterOptions?: RateLimiterOptions;
|
|
20
|
+
httpClientOverrides?: HttpClientOptions;
|
|
21
|
+
serverOverride?: string;
|
|
22
|
+
errLog?: Logger;
|
|
23
|
+
}
|
|
24
|
+
export declare class OpenApi3 {
|
|
25
|
+
static createAsync(options: OpenApi3Options): Promise<OpenApi3>;
|
|
26
|
+
private constructor();
|
|
27
|
+
get rateLimiter(): RateLimiter | undefined;
|
|
28
|
+
get httpClient(): typeof API.utilities.httpClient | undefined;
|
|
29
|
+
get apis(): any;
|
|
30
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const PathUtils: {
|
|
2
|
+
pathify: typeof pathify;
|
|
3
|
+
unpathify: typeof unpathify;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* converts an array of strings into a fully-qualified JSONPath path string, escaping
|
|
7
|
+
* part names as required (i.e. "\" becomes "\\" and "." becomes "\.").
|
|
8
|
+
* @param array The array to be converted
|
|
9
|
+
* @returns the converted string
|
|
10
|
+
*/
|
|
11
|
+
declare function pathify(array: string[]): string;
|
|
12
|
+
/**
|
|
13
|
+
* converts a pathified string into an un-escaped array of path parts.
|
|
14
|
+
* @param pathStr the string to be un-pathified
|
|
15
|
+
* @returns the converted array, or undefined if no string is passed
|
|
16
|
+
*/
|
|
17
|
+
declare function unpathify(pathStr: string): string[];
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import API from "@syncmatters/script-api";
|
|
2
|
+
/**
|
|
3
|
+
* This class exists as Connector SDK 1.0 exposed RateLimiter as a helper class. Later this was moved to follow the API.utilities.helperFunc(...)
|
|
4
|
+
* paradigm to provide better consistency between the SDK and API.
|
|
5
|
+
*/
|
|
6
|
+
export declare class RateLimiter implements API.RateLimiter {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(options: API.RateLimiterOptions);
|
|
9
|
+
take(cost?: number): Promise<void>;
|
|
10
|
+
execute<T>(options: {
|
|
11
|
+
cost?: number;
|
|
12
|
+
exec: () => Promise<T>;
|
|
13
|
+
}): Promise<T>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import API, { ObjectField } from "@syncmatters/script-api";
|
|
2
|
+
import { ServeApi } from "./serve-api.js";
|
|
3
|
+
type ConnectorUtilities = typeof API.utilities & {
|
|
4
|
+
fieldsFromJSON: typeof fieldsFromJSON;
|
|
5
|
+
serveApi: typeof ServeApi.serveApi;
|
|
6
|
+
};
|
|
7
|
+
export declare const utilities: ConnectorUtilities;
|
|
8
|
+
declare function fieldsFromJSON(json: any): ObjectField[];
|
|
9
|
+
export {};
|
package/module.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector SDK (SDK) is a fusion of elements from the script API and
|
|
3
|
+
* SDK specific elements that would be of no interest to users of the API.
|
|
4
|
+
*/
|
|
5
|
+
export { EventScriptComplete } from "@syncmatters/script-api";
|
|
6
|
+
export type { Cache, FileProvider, HttpRequest, HttpClientOptions, KvCollection, KvIterator, Logger, EventContext, TestResult, Row, ObjectMeta, ObjectField, ObjectFieldOption, RateLimiterOptions, ScriptType, } from "@syncmatters/script-api";
|
|
7
|
+
export * from "./lib/connector.js";
|
|
8
|
+
export * from "./lib/connector-error.js";
|
|
9
|
+
export { envSet } from "./lib/environment.js";
|
|
10
|
+
export type { Environment, ApiRequest, ApiResponse, ApiSpec } from "./lib/environment.js";
|
|
11
|
+
export { FileProviderBuffer } from "./lib/file-provider-buffer.js";
|
|
12
|
+
export { FileProviderDisk } from "./lib/file-provider-disk.js";
|
|
13
|
+
export { FileProviderString } from "./lib/file-provider-string.js";
|
|
14
|
+
export { OpenApi3 } from "./lib/open-api-3.js";
|
|
15
|
+
export type { OpenApi3Options } from "./lib/open-api-3.js";
|
|
16
|
+
export * from "./lib/kv-store.js";
|
|
17
|
+
export { utilities } from "./lib/utilities.js";
|
|
18
|
+
export { RateLimiter } from "./lib/rate-limiter.js";
|
|
19
|
+
export { HttpClient } from "./lib/http-client.js";
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@syncmatters/connector-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript type definitions for the SyncMatters connector SDK (types only - connectors execute on the SyncMatters platform)",
|
|
5
|
+
"types": "./index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"default": "./index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "SyncMatters",
|
|
14
|
+
"homepage": "https://syncmatters.com",
|
|
15
|
+
"typesContentHash": "39bdb6461d3d6962e0d284c2f4b6c71f1d08a6cd6a4b422754b3c731414fe6da",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@types/node": "*",
|
|
18
|
+
"@syncmatters/script-api": "^1.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|