@aloma.io/integration-sdk 3.3.64 → 3.3.66

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.
@@ -16,7 +16,7 @@ export default class RuntimeContext {
16
16
  let icon;
17
17
  try {
18
18
  if (data.icon) {
19
- icon = fs.readFileSync(data.icon).toString('base64');
19
+ icon = fs.readFileSync(data.icon).toString("base64");
20
20
  }
21
21
  }
22
22
  catch (e) {
@@ -26,7 +26,7 @@ export default class RuntimeContext {
26
26
  id: data.id,
27
27
  version: data.version,
28
28
  name: `${data.id}/${data.version}`,
29
- icon
29
+ icon,
30
30
  });
31
31
  const configuration = connector.configure().config(data.config || {});
32
32
  const resolvers = {};
@@ -29,11 +29,10 @@ const transform = (meta) => {
29
29
  let eg;
30
30
  if (example) {
31
31
  const parts = example.split(/```/);
32
- const backticks = '```';
33
- eg = `@example ${parts[0] || 'usage'}\n${backticks}${parts[1]}${backticks}`;
32
+ const backticks = "```";
33
+ eg = `@example ${parts[0] || "usage"}\n${backticks}${parts[1]}${backticks}`;
34
34
  }
35
- const paramDocs = docs
36
- .filter((what) => what.kind === "param");
35
+ const paramDocs = docs.filter((what) => what.kind === "param");
37
36
  const params = sig
38
37
  .getParameters()
39
38
  .filter((param) => param.isNamed())
@@ -46,12 +45,10 @@ const transform = (meta) => {
46
45
  return `${p.getName()}${defaultVal}`;
47
46
  })
48
47
  .join("; ");
49
- const suffix = serialized
50
- .type
51
- .properties
48
+ const suffix = serialized.type.properties
52
49
  .map((p) => {
53
50
  const comment = paramDocs.find((what) => what.value.name === p.name);
54
- const desc = (comment?.value.description || '').replace(/\\@/gi, '@');
51
+ const desc = (comment?.value.description || "").replace(/\\@/gi, "@");
55
52
  return `\n/**\n${desc}\n */\n ${p.name}: ${p.type.text}`;
56
53
  })
57
54
  .join("; ");
@@ -66,7 +63,7 @@ const transform = (meta) => {
66
63
  /**
67
64
  * ${desc || ""}
68
65
  *
69
- * ${eg || ''}
66
+ * ${eg || ""}
70
67
  **/
71
68
  declare function ${member.getName()}(${params}): ${retVal};
72
69
  `;
@@ -79,6 +76,6 @@ declare function ${member.getName()}(${params}): ${retVal};
79
76
  export default async (path) => {
80
77
  const parsed = await parseFromFiles([path]);
81
78
  if (parsed.errors?.length)
82
- throw new Error(path + ' ' + JSON.stringify(parsed.errors));
79
+ throw new Error(path + " " + JSON.stringify(parsed.errors));
83
80
  return transform(parsed.project?.getModules() || []);
84
81
  };
@@ -7,7 +7,7 @@ export declare abstract class AbstractController {
7
7
  protected fallback(arg: any): Promise<any>;
8
8
  protected endpoint(arg: any): Promise<any>;
9
9
  protected newTask(name: string, data: any): Promise<string>;
10
- protected getClient({ baseUrl, onResponse }: {
10
+ protected getClient({ baseUrl, onResponse, }: {
11
11
  baseUrl: string;
12
12
  onResponse?: (response: any) => void;
13
13
  }): Promise<any>;
@@ -15,7 +15,7 @@ export class AbstractController {
15
15
  async newTask(name, data) {
16
16
  throw new Error("not implemented");
17
17
  }
18
- getClient({ baseUrl, onResponse }) {
18
+ getClient({ baseUrl, onResponse, }) {
19
19
  throw new Error("not implemented");
20
20
  }
21
21
  async updateTask(name, data) {
@@ -44,7 +44,7 @@ class Dispatcher {
44
44
  placeholder: "e.g. 1234",
45
45
  type: "line",
46
46
  optional: !!arg.configurableClientOptional,
47
- plain: true
47
+ plain: true,
48
48
  },
49
49
  clientSecret: {
50
50
  name: "OAuth Client Secret",
@@ -67,8 +67,8 @@ class Dispatcher {
67
67
  ${arg.configurableClientScope}
68
68
  `,
69
69
  optional: true,
70
- plain: true
71
- }
70
+ plain: true,
71
+ },
72
72
  },
73
73
  });
74
74
  }
@@ -38,7 +38,7 @@ const unwrap = async (ret, options) => {
38
38
  return JSON.parse(text);
39
39
  }
40
40
  catch (e) {
41
- throw (e + ' ' + text);
41
+ throw e + " " + text;
42
42
  }
43
43
  };
44
44
  class Fetcher {
@@ -48,7 +48,7 @@ class Fetcher {
48
48
  this.onResponse = onResponse;
49
49
  }
50
50
  async customize(options, args = {}) { }
51
- async onError(e, url, options, retries, args) {
51
+ async onError(e, url, options, retries, args, rateLimit) {
52
52
  var local = this;
53
53
  return new Promise((resolve, reject) => {
54
54
  setTimeout(async () => {
@@ -58,7 +58,7 @@ class Fetcher {
58
58
  catch (e) {
59
59
  reject(e);
60
60
  }
61
- }, 500);
61
+ }, rateLimit ? 10000 : 500);
62
62
  });
63
63
  }
64
64
  async fetch(url, options = {}, retries, args = {}) {
@@ -125,15 +125,22 @@ class OAuthFetcher extends Fetcher {
125
125
  if (!force && oauth.accessToken())
126
126
  return oauth.accessToken();
127
127
  const refreshToken = oauth.refreshToken();
128
- if (!refreshToken)
129
- throw new Error("have no access_token and no refresh_token");
130
- const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
131
- if (ret.access_token) {
132
- oauth.update(ret.access_token, ret.refresh_token);
133
- return ret.access_token;
128
+ try {
129
+ if (!refreshToken) {
130
+ throw new Error("have no access_token and no refresh_token");
131
+ }
132
+ const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
133
+ if (ret.access_token) {
134
+ oauth.update(ret.access_token, ret.refresh_token);
135
+ return ret.access_token;
136
+ }
137
+ else {
138
+ throw new Error("could not obtain access token via refresh token");
139
+ }
134
140
  }
135
- else {
136
- throw new Error("could not obtain access token via refresh token");
141
+ catch (e) {
142
+ oauth.invalidate(e);
143
+ throw (e);
137
144
  }
138
145
  }
139
146
  async onError(e, url, options, retries, args, rateLimit) {
@@ -192,12 +199,16 @@ class OAuth {
192
199
  }
193
200
  async periodicRefresh() {
194
201
  const clients = this.clients;
195
- console.log('refreshing oauth clients', clients.length);
202
+ console.log("refreshing oauth clients", clients.length);
196
203
  for (let i = 0; i < clients.length; ++i) {
197
204
  const client = clients[0];
198
205
  await client.periodicRefresh();
199
206
  }
200
207
  }
208
+ async invalidate(err) {
209
+ console.log('could not obtain access token, marking connector as disconnected', err);
210
+ await this.upate(null, null);
211
+ }
201
212
  getClient(arg = {}) {
202
213
  const client = new OAuthFetcher({ ...arg, oauth: this });
203
214
  this.clients.push(client);
@@ -251,7 +262,7 @@ class Connector {
251
262
  publicKey: process.env.PUBLIC_KEY,
252
263
  introspect,
253
264
  configSchema,
254
- icon: this.icon
265
+ icon: this.icon,
255
266
  });
256
267
  if (Object.keys(configSchema().fields).length) {
257
268
  try {
@@ -293,7 +304,7 @@ ${text}
293
304
  const value = secrets[key];
294
305
  if (!value)
295
306
  continue;
296
- if (fields[key]?.plain || ['endpointUrl'].includes(key)) {
307
+ if (fields[key]?.plain || ["endpointUrl"].includes(key)) {
297
308
  decrypted[key] = value;
298
309
  }
299
310
  else {
@@ -338,7 +349,6 @@ ${text}
338
349
  const clientId = process.env.OAUTH_CLIENT_ID ||
339
350
  decrypted.clientId ||
340
351
  that._oauth.clientId;
341
- ;
342
352
  if (!clientId)
343
353
  throw new Error("clientId not configured");
344
354
  const clientSecret = process.env.OAUTH_CLIENT_SECRET ||
@@ -411,11 +421,16 @@ ${text}
411
421
  return { value: await jwe.encrypt(data, "none", config.id()) };
412
422
  };
413
423
  const saveOAuthResult = async (what) => {
414
- const jwe = await config.validateKeys("RSA-OAEP-256");
424
+ let value = null;
425
+ if (what) {
426
+ const jwe = await config.validateKeys("RSA-OAEP-256");
427
+ value = await jwe.encrypt(what, "none", config.id());
428
+ }
429
+ ;
415
430
  const packet = transport.newPacket({});
416
431
  packet.method("connector.config-update");
417
432
  packet.args({
418
- value: await jwe.encrypt(what, "none", config.id()),
433
+ value
419
434
  });
420
435
  transport.send(packet);
421
436
  };
@@ -473,7 +488,7 @@ ${text}
473
488
  await theOAuth.periodicRefresh();
474
489
  }
475
490
  catch (e) {
476
- console.log('periodic refresh', e);
491
+ console.log("periodic refresh", e);
477
492
  }
478
493
  }, 4 * 60 * 60 * 15000);
479
494
  }
@@ -1,5 +1,5 @@
1
1
  export class Config {
2
- constructor({ registrationToken, version, name, id, endpoint, wsEndpoint, privateKey, publicKey, introspect, configSchema, icon }: {
2
+ constructor({ registrationToken, version, name, id, endpoint, wsEndpoint, privateKey, publicKey, introspect, configSchema, icon, }: {
3
3
  registrationToken: any;
4
4
  version: any;
5
5
  name: any;
@@ -1,7 +1,7 @@
1
1
  import C from "./connection/constants.mjs";
2
2
  import JWE from "../util/jwe/index.mjs";
3
3
  class Config {
4
- constructor({ registrationToken, version, name, id, endpoint, wsEndpoint, privateKey, publicKey, introspect, configSchema, icon }) {
4
+ constructor({ registrationToken, version, name, id, endpoint, wsEndpoint, privateKey, publicKey, introspect, configSchema, icon, }) {
5
5
  this._token = null;
6
6
  this._registrationToken = registrationToken;
7
7
  this._version = version;
@@ -19,7 +19,7 @@ class Registration {
19
19
  id: config.id(),
20
20
  publicKey: config.publicKey(),
21
21
  schema: { configSchema, introspect: intro },
22
- icon
22
+ icon,
23
23
  }),
24
24
  headers: { "Content-Type": "application/json" },
25
25
  }, config));
@@ -47,15 +47,25 @@ class Transport {
47
47
  local.close();
48
48
  this.running = true;
49
49
  const ws = (local.ws = new WebSocket(config.wsUrl(), ["connector"], C.augmentRequest({ headers: {} }, config)));
50
+ ws.onPing = function () {
51
+ clearTimeout(this.pingTimeout);
52
+ this.pingTimeout = setTimeout(() => {
53
+ console.log("terminating ws");
54
+ if (local.running)
55
+ this.terminate();
56
+ }, 30000 + 15000);
57
+ };
50
58
  ws.on("open", () => {
51
59
  console.log("websocket connected");
52
60
  local.connected = true;
61
+ ws.onPing();
53
62
  local.pinger = setInterval(() => ws.ping(() => null), pingInterval);
54
63
  local.onConnect(local);
55
64
  });
56
65
  ws.on("message", (message) => {
57
66
  setTimeout(() => local.onMessages(JSON.parse(message)), 0);
58
67
  });
68
+ ws.on("ping", () => ws.onPing());
59
69
  ws.on("error", (message) => {
60
70
  console.log("error:", message);
61
71
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aloma.io/integration-sdk",
3
- "version": "3.3.64",
3
+ "version": "3.3.66",
4
4
  "description": "",
5
5
  "author": "aloma.io",
6
6
  "license": "Apache-2.0",
@@ -38,7 +38,7 @@ export class Builder {
38
38
  await this.parsePackageJson();
39
39
  await this.discoverTypes();
40
40
  await this.checkIcon();
41
-
41
+
42
42
  // @ts-ignore
43
43
  const Controller = (
44
44
  await import(__dirname + "/../../../../../build/controller/index.mjs")
@@ -46,11 +46,11 @@ export class Builder {
46
46
 
47
47
  return new RuntimeContext(new Controller(), this.data);
48
48
  }
49
-
49
+
50
50
  private async checkIcon() {
51
51
  const data = this.data;
52
- const root = __dirname + "/../../../../../"
53
-
52
+ const root = __dirname + "/../../../../../";
53
+
54
54
  data.icon = `${root}/logo.png`;
55
55
  }
56
56
 
@@ -1,7 +1,7 @@
1
1
  import { AbstractController } from "../controller/index.mjs";
2
2
  import { Connector } from "../internal/index.mjs";
3
3
  import fs from "node:fs";
4
-
4
+
5
5
  export default class RuntimeContext {
6
6
  constructor(
7
7
  private controller: AbstractController,
@@ -14,25 +14,22 @@ export default class RuntimeContext {
14
14
  if (!(controller instanceof AbstractController))
15
15
  throw new Error("the controller needs to extend AbstractController");
16
16
  const data: any = this.data;
17
-
17
+
18
18
  let icon;
19
-
20
- try
21
- {
22
- if (data.icon)
23
- {
24
- icon = fs.readFileSync(data.icon).toString('base64');
19
+
20
+ try {
21
+ if (data.icon) {
22
+ icon = fs.readFileSync(data.icon).toString("base64");
25
23
  }
26
- } catch(e) {
24
+ } catch (e) {
27
25
  // blank
28
26
  }
29
-
30
27
 
31
28
  const connector = new Connector({
32
29
  id: data.id,
33
30
  version: data.version,
34
31
  name: `${data.id}/${data.version}`,
35
- icon
32
+ icon,
36
33
  });
37
34
 
38
35
  const configuration = connector.configure().config(data.config || {});
@@ -56,7 +53,10 @@ export default class RuntimeContext {
56
53
  configuration.types(data.types).resolvers(resolvers);
57
54
 
58
55
  if (data.options?.endpoint?.enabled) {
59
- configuration.endpoint((arg) => controller.__endpoint(arg), data.options?.endpoint?.required);
56
+ configuration.endpoint(
57
+ (arg) => controller.__endpoint(arg),
58
+ data.options?.endpoint?.required,
59
+ );
60
60
  }
61
61
 
62
62
  if (data.auth?.oauth) {
@@ -81,7 +81,7 @@ export default class RuntimeContext {
81
81
  );
82
82
 
83
83
  connector.run();
84
-
84
+
85
85
  const term = async () => {
86
86
  await controller._doStop(true);
87
87
 
@@ -31,21 +31,20 @@ const transform = (meta: any) => {
31
31
  const docs = sig.getJSDoc().serialize() || [];
32
32
  const desc = docs.find((what: any) => what.kind === "description")
33
33
  ?.value;
34
-
34
+
35
35
  const example = docs.find((what: any) => what.kind === "example")
36
36
  ?.value;
37
37
 
38
38
  let eg;
39
- if (example)
40
- {
39
+ if (example) {
41
40
  const parts = example.split(/```/);
42
- const backticks = '```';
43
- eg = `@example ${parts[0] || 'usage'}\n${backticks}${parts[1]}${backticks}`;
41
+ const backticks = "```";
42
+ eg = `@example ${parts[0] || "usage"}\n${backticks}${
43
+ parts[1]
44
+ }${backticks}`;
44
45
  }
45
-
46
- const paramDocs =
47
- docs
48
- .filter((what: any) => what.kind === "param")
46
+
47
+ const paramDocs = docs.filter((what: any) => what.kind === "param");
49
48
 
50
49
  const params = sig
51
50
  .getParameters()
@@ -62,22 +61,25 @@ const transform = (meta: any) => {
62
61
  return `${p.getName()}${defaultVal}`;
63
62
  })
64
63
  .join("; ");
65
-
66
- const suffix = serialized
67
- .type
68
- .properties
64
+
65
+ const suffix = serialized.type.properties
69
66
  .map((p) => {
70
- const comment = paramDocs.find((what) => what.value.name === p.name);
71
- const desc = (comment?.value.description || '').replace(/\\@/gi, '@');
72
-
67
+ const comment = paramDocs.find(
68
+ (what) => what.value.name === p.name,
69
+ );
70
+ const desc = (comment?.value.description || "").replace(
71
+ /\\@/gi,
72
+ "@",
73
+ );
74
+
73
75
  return `\n/**\n${desc}\n */\n ${p.name}: ${p.type.text}`;
74
76
  })
75
77
  .join("; ");
76
-
78
+
77
79
  return `{${prefix}}: {${suffix}}`;
78
80
  })
79
81
  .join(", ");
80
-
82
+
81
83
  const retVal = sig
82
84
  .serialize()
83
85
  .return.type.text.replace(/^Promise</, "")
@@ -87,7 +89,7 @@ const transform = (meta: any) => {
87
89
  /**
88
90
  * ${desc || ""}
89
91
  *
90
- * ${eg || ''}
92
+ * ${eg || ""}
91
93
  **/
92
94
  declare function ${member.getName()}(${params}): ${retVal};
93
95
  `;
@@ -101,6 +103,7 @@ declare function ${member.getName()}(${params}): ${retVal};
101
103
 
102
104
  export default async (path: string) => {
103
105
  const parsed = await parseFromFiles([path]);
104
- if (parsed.errors?.length) throw new Error(path + ' ' + JSON.stringify(parsed.errors));
106
+ if (parsed.errors?.length)
107
+ throw new Error(path + " " + JSON.stringify(parsed.errors));
105
108
  return transform(parsed.project?.getModules() || []);
106
109
  };
@@ -22,7 +22,13 @@ export abstract class AbstractController {
22
22
  throw new Error("not implemented");
23
23
  }
24
24
 
25
- protected getClient({ baseUrl, onResponse }: { baseUrl: string, onResponse?: (response: any) => void }): Promise<any> {
25
+ protected getClient({
26
+ baseUrl,
27
+ onResponse,
28
+ }: {
29
+ baseUrl: string;
30
+ onResponse?: (response: any) => void;
31
+ }): Promise<any> {
26
32
  throw new Error("not implemented");
27
33
  }
28
34
 
@@ -51,7 +51,7 @@ class Dispatcher {
51
51
  placeholder: "e.g. 1234",
52
52
  type: "line",
53
53
  optional: !!arg.configurableClientOptional,
54
- plain: true
54
+ plain: true,
55
55
  },
56
56
  clientSecret: {
57
57
  name: "OAuth Client Secret",
@@ -62,7 +62,7 @@ class Dispatcher {
62
62
  },
63
63
  });
64
64
  }
65
-
65
+
66
66
  if (arg.configurableClientScope) {
67
67
  this.config({
68
68
  fields: {
@@ -75,8 +75,8 @@ class Dispatcher {
75
75
  ${arg.configurableClientScope}
76
76
  `,
77
77
  optional: true,
78
- plain: true
79
- }
78
+ plain: true,
79
+ },
80
80
  },
81
81
  });
82
82
  }
@@ -111,7 +111,7 @@ ${arg.configurableClientScope}
111
111
  _endpointToken: {
112
112
  name: "Endpoint Token",
113
113
  placeholder: "e.g. 1234",
114
- type: !!notOptional?"managed":"line",
114
+ type: !!notOptional ? "managed" : "line",
115
115
  plain: true,
116
116
  optional: !notOptional,
117
117
  },
@@ -40,14 +40,13 @@ const reply = (arg, packet, transport) => {
40
40
  const unwrap = async (ret, options) => {
41
41
  if (options?.text) return await ret.text();
42
42
  if (options?.base64) return (await ret.buffer()).toString("base64");
43
-
43
+
44
44
  const text = await ret.text();
45
-
46
- try
47
- {
45
+
46
+ try {
48
47
  return JSON.parse(text);
49
- } catch(e) {
50
- throw (e + ' ' + text)
48
+ } catch (e) {
49
+ throw e + " " + text;
51
50
  }
52
51
  };
53
52
 
@@ -60,7 +59,7 @@ class Fetcher {
60
59
 
61
60
  async customize(options, args = {}) {}
62
61
 
63
- async onError(e, url, options, retries, args) {
62
+ async onError(e, url, options, retries, args, rateLimit) {
64
63
  var local = this;
65
64
 
66
65
  return new Promise((resolve, reject) => {
@@ -70,7 +69,7 @@ class Fetcher {
70
69
  } catch (e) {
71
70
  reject(e);
72
71
  }
73
- }, 500);
72
+ }, rateLimit?10000:500);
74
73
  });
75
74
  }
76
75
 
@@ -120,9 +119,8 @@ class Fetcher {
120
119
  e.status = status;
121
120
  throw e;
122
121
  }
123
-
124
- if (local.onResponse)
125
- {
122
+
123
+ if (local.onResponse) {
126
124
  await local.onResponse(ret);
127
125
  }
128
126
 
@@ -130,9 +128,9 @@ class Fetcher {
130
128
  } catch (e) {
131
129
  // too many requests
132
130
  if (e.status === 429) {
133
- return local.onError(e, url, options, retries, args, true);
131
+ return local.onError(e, url, options, retries, args, true);
134
132
  }
135
-
133
+
136
134
  --retries;
137
135
 
138
136
  console.log(theURL, e);
@@ -161,17 +159,26 @@ class OAuthFetcher extends Fetcher {
161
159
  if (!force && oauth.accessToken()) return oauth.accessToken();
162
160
 
163
161
  const refreshToken = oauth.refreshToken();
164
- if (!refreshToken)
165
- throw new Error("have no access_token and no refresh_token");
162
+
163
+ try
164
+ {
165
+ if (!refreshToken) {
166
+ throw new Error("have no access_token and no refresh_token");
167
+ }
166
168
 
167
- const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
169
+ const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
168
170
 
169
- if (ret.access_token) {
170
- oauth.update(ret.access_token, ret.refresh_token);
171
+ if (ret.access_token) {
172
+ oauth.update(ret.access_token, ret.refresh_token);
171
173
 
172
- return ret.access_token;
173
- } else {
174
- throw new Error("could not obtain access token via refresh token");
174
+ return ret.access_token;
175
+ } else {
176
+ throw new Error("could not obtain access token via refresh token");
177
+ }
178
+ } catch(e) {
179
+ oauth.invalidate(e);
180
+
181
+ throw(e);
175
182
  }
176
183
  }
177
184
 
@@ -179,24 +186,29 @@ class OAuthFetcher extends Fetcher {
179
186
  var local = this;
180
187
 
181
188
  return new Promise((resolve, reject) => {
182
- setTimeout(async () => {
183
- try {
184
- resolve(
185
- await local.fetch(url, options, retries, {
186
- forceTokenRefresh: e.status === 401,
187
- }),
188
- );
189
- } catch (e) {
190
- reject(e);
191
- }
192
- }, rateLimit?10000:500);
189
+ setTimeout(
190
+ async () => {
191
+ try {
192
+ resolve(
193
+ await local.fetch(url, options, retries, {
194
+ forceTokenRefresh: e.status === 401,
195
+ }),
196
+ );
197
+ } catch (e) {
198
+ reject(e);
199
+ }
200
+ },
201
+ rateLimit ? 10000 : 500,
202
+ );
193
203
  });
194
204
  }
195
205
 
196
206
  async periodicRefresh() {
197
- const local = this, oauth = local.oauth;
207
+ const local = this,
208
+ oauth = local.oauth;
209
+
198
210
  if (!oauth.refreshToken()) return;
199
-
211
+
200
212
  await local.getToken(true);
201
213
  }
202
214
 
@@ -244,15 +256,21 @@ class OAuth {
244
256
 
245
257
  async periodicRefresh() {
246
258
  const clients = this.clients;
247
-
248
- console.log('refreshing oauth clients', clients.length)
249
-
259
+
260
+ console.log("refreshing oauth clients", clients.length);
261
+
250
262
  for (let i = 0; i < clients.length; ++i) {
251
263
  const client = clients[0];
252
-
264
+
253
265
  await client.periodicRefresh();
254
266
  }
255
267
  }
268
+
269
+ async invalidate(err) {
270
+ console.log('could not obtain access token, marking connector as disconnected', err);
271
+
272
+ await this.upate(null, null);
273
+ }
256
274
 
257
275
  getClient(arg = {}) {
258
276
  const client = new OAuthFetcher({ ...arg, oauth: this });
@@ -321,7 +339,7 @@ class Connector {
321
339
  publicKey: process.env.PUBLIC_KEY,
322
340
  introspect,
323
341
  configSchema,
324
- icon: this.icon
342
+ icon: this.icon,
325
343
  });
326
344
 
327
345
  if (Object.keys(configSchema().fields).length) {
@@ -369,7 +387,7 @@ ${text}
369
387
  const value = secrets[key];
370
388
  if (!value) continue;
371
389
 
372
- if (fields[key]?.plain || ['endpointUrl'].includes(key)) {
390
+ if (fields[key]?.plain || ["endpointUrl"].includes(key)) {
373
391
  decrypted[key] = value;
374
392
  } else {
375
393
  try {
@@ -383,16 +401,17 @@ ${text}
383
401
  this.startOAuth = async function (args) {
384
402
  if (!this._oauth) throw new Error("oauth not configured");
385
403
 
386
- const clientId = process.env.OAUTH_CLIENT_ID ||
404
+ const clientId =
405
+ process.env.OAUTH_CLIENT_ID ||
387
406
  decrypted.clientId ||
388
- this._oauth.clientId;
389
-
407
+ this._oauth.clientId;
408
+
390
409
  if (!clientId) throw new Error("clientId not configured");
391
410
 
392
411
  const scopes =
393
412
  process.env.OAUTH_SCOPE ||
394
413
  decrypted.scope ||
395
- this._oauth.scope ||
414
+ this._oauth.scope ||
396
415
  "";
397
416
  const useCodeChallenge = !!that._oauth.useCodeChallenge;
398
417
 
@@ -417,18 +436,17 @@ ${text}
417
436
  if (!arg.code || !arg.redirectURI)
418
437
  throw new Error("need code and redirectUri");
419
438
 
420
- const clientId = process.env.OAUTH_CLIENT_ID ||
421
- decrypted.clientId ||
422
-
423
- that._oauth.clientId;
439
+ const clientId =
440
+ process.env.OAUTH_CLIENT_ID ||
441
+ decrypted.clientId ||
442
+ that._oauth.clientId;
424
443
 
425
- ;
426
444
  if (!clientId) throw new Error("clientId not configured");
427
445
 
428
446
  const clientSecret =
429
447
  process.env.OAUTH_CLIENT_SECRET ||
430
448
  decrypted.clientSecret ||
431
- that._oauth.clientSecret;
449
+ that._oauth.clientSecret;
432
450
  if (!clientSecret) throw new Error("clientSecret not configured");
433
451
 
434
452
  const additionalTokenArgs = that._oauth.additionalTokenArgs || {};
@@ -507,12 +525,18 @@ ${text}
507
525
  };
508
526
 
509
527
  const saveOAuthResult = async (what) => {
510
- const jwe = await config.validateKeys("RSA-OAEP-256");
528
+ let value = null;
529
+
530
+ if (what) {
531
+ const jwe = await config.validateKeys("RSA-OAEP-256");
532
+ value = await jwe.encrypt(what, "none", config.id())
533
+ };
534
+
511
535
  const packet = transport.newPacket({});
512
536
 
513
537
  packet.method("connector.config-update");
514
538
  packet.args({
515
- value: await jwe.encrypt(what, "none", config.id()),
539
+ value
516
540
  });
517
541
 
518
542
  transport.send(packet);
@@ -522,17 +546,15 @@ ${text}
522
546
 
523
547
  const getRefreshToken = async (refreshToken) => {
524
548
  const clientId =
525
-
526
549
  process.env.OAUTH_CLIENT_ID ||
527
- decrypted.clientId ||
528
- that._oauth.clientId;
550
+ decrypted.clientId ||
551
+ that._oauth.clientId;
529
552
  if (!clientId) throw new Error("clientId not configured");
530
553
 
531
554
  const clientSecret =
532
-
533
555
  process.env.OAUTH_CLIENT_SECRET ||
534
556
  decrypted.clientSecret ||
535
- that._oauth.clientSecret;
557
+ that._oauth.clientSecret;
536
558
  if (!clientSecret) throw new Error("clientSecret not configured");
537
559
 
538
560
  const useAuthHeader = !!that._oauth.useAuthHeader;
@@ -580,21 +602,21 @@ ${text}
580
602
 
581
603
  if (theOAuth) {
582
604
  clearInterval(this._refreshOAuthToken);
583
-
605
+
584
606
  if (!(this._oauth.noPeriodicTokenRefresh === false)) {
585
- this._refreshOAuthToken = setInterval(async () => {
586
-
587
- try
588
- {
589
- await theOAuth.periodicRefresh();
590
- } catch(e) {
591
- console.log('periodic refresh', e);
592
- }
593
- }, 4 * 60 * 60 * 15000);
607
+ this._refreshOAuthToken = setInterval(
608
+ async () => {
609
+ try {
610
+ await theOAuth.periodicRefresh();
611
+ } catch (e) {
612
+ console.log("periodic refresh", e);
613
+ }
614
+ },
615
+ 4 * 60 * 60 * 15000,
616
+ );
594
617
  }
595
-
596
618
  }
597
-
619
+
598
620
  start({
599
621
  config: decrypted,
600
622
  oauth: theOAuth,
@@ -13,7 +13,7 @@ class Config {
13
13
  publicKey,
14
14
  introspect,
15
15
  configSchema,
16
- icon
16
+ icon,
17
17
  }) {
18
18
  this._token = null;
19
19
  this._registrationToken = registrationToken;
@@ -100,7 +100,7 @@ class Config {
100
100
  token() {
101
101
  return this._token;
102
102
  }
103
-
103
+
104
104
  icon() {
105
105
  return this._icon;
106
106
  }
@@ -12,7 +12,7 @@ class Registration {
12
12
  const configSchema = config.configSchema();
13
13
  const intro = await config.introspect();
14
14
  const icon = config.icon();
15
-
15
+
16
16
  const response = await fetch(
17
17
  config.url() + "register",
18
18
  C.augmentRegistration(
@@ -25,7 +25,7 @@ class Registration {
25
25
  id: config.id(),
26
26
  publicKey: config.publicKey(),
27
27
  schema: { configSchema, introspect: intro },
28
- icon
28
+ icon,
29
29
  }),
30
30
  headers: { "Content-Type": "application/json" },
31
31
  },
@@ -68,9 +68,18 @@ class Transport {
68
68
  C.augmentRequest({ headers: {} }, config),
69
69
  ));
70
70
 
71
+ ws.onPing = function () {
72
+ clearTimeout(this.pingTimeout);
73
+ this.pingTimeout = setTimeout(() => {
74
+ console.log("terminating ws");
75
+ if (local.running) this.terminate();
76
+ }, 30000 + 15000);
77
+ };
78
+
71
79
  ws.on("open", () => {
72
80
  console.log("websocket connected");
73
81
  local.connected = true;
82
+ ws.onPing();
74
83
  local.pinger = setInterval(() => ws.ping(() => null), pingInterval);
75
84
 
76
85
  local.onConnect(local);
@@ -80,6 +89,8 @@ class Transport {
80
89
  setTimeout(() => local.onMessages(JSON.parse(message)), 0);
81
90
  });
82
91
 
92
+ ws.on("ping", () => ws.onPing());
93
+
83
94
  ws.on("error", (message) => {
84
95
  console.log("error:", message);
85
96
  });