@vouchfor/sdk 1.1.33 → 1.1.34

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.
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(grep -l \"Router\\\\\\(\\\\\\)\" /home/david/dev/vouch-new/amplify/backend/function/restapi/lib/controllers/*.ts | xargs grep -L \"@openapi\")",
5
+ "Bash(for f:*)",
6
+ "Bash(cd /home/david/dev/vouch-new/amplify/backend/function/restapi/openapi && node -e \"const s = require\\('./components/schemas'\\); console.log\\(Object.keys\\(s\\).join\\(', '\\)\\)\" 2>&1)",
7
+ "Bash(cd /home/david/dev/vouch-new/amplify/backend/function/restapi/openapi && node -e \"const r = require\\('./components/responses'\\); console.log\\(Object.keys\\(r\\).join\\(', '\\)\\)\" 2>&1)"
8
+ ]
9
+ }
10
+ }
@@ -1,4 +1,5 @@
1
1
  const utils = require('../shared/utils');
2
+ const tasks = require('../shared/tasks');
2
3
 
3
4
  // set up env for local development
4
5
  // set env SDK_LOCAL_DEV to use default local development endpoints
@@ -25,6 +26,7 @@ class BaseService {
25
26
  this._client = client;
26
27
  this._apiKey = config.apiKey || '';
27
28
  this._integrationKey = config.integrationKey || '';
29
+ this._callbackUrl = config.callbackUrl || '';
28
30
  this._baseUrl = `${config.baseUrl}${basePath}`;
29
31
  this._logger = logger;
30
32
  this._utils = utils;
@@ -49,13 +51,74 @@ class BaseService {
49
51
  apiHeaders['x-integration-key'] = integrationKey;
50
52
  }
51
53
 
52
- return this._utils.request({
53
- body,
54
- headers: apiHeaders,
55
- method,
56
- url,
57
- logger: this._logger
58
- });
54
+ const elapsedTimeInSeconds = (start) => {
55
+ return ((Date.now() - start) / 1000).toFixed(3) + 's';
56
+ }
57
+
58
+ const logAsyncSuccess = ({ id, status, json, start }) => {
59
+ const elapsed = elapsedTimeInSeconds(start);
60
+ const response = JSON.stringify(json);
61
+ this._logger.info(
62
+ `async success for task: ${task.id} ++ ${elapsed}\n`
63
+ + `========================================\n`
64
+ + `Content-Type: application/json\n`
65
+ + `Content-Length: ${response.length}\n`
66
+ + '\n' + response + '\n'
67
+ + `========================================`);
68
+ }
69
+
70
+ const logAsyncFailure = ({ id, status, json, start }) => {
71
+ const elapsed = elapsedTimeInSeconds(start);
72
+ const response = JSON.stringify(json);
73
+ this._logger.info(
74
+ `async failure for task: ${task.id} ++ ${elapsed}\n`
75
+ + `========================================\n`
76
+ + `Content-Type: application/json\n`
77
+ + `Content-Length: ${response.length}\n`
78
+ + '\n' + response + '\n'
79
+ + `========================================`);
80
+ }
81
+
82
+ const registerAsyncResponse = () => {
83
+ if (this._callbackUrl) {
84
+ const start = Date.now();
85
+ const task = tasks.create();
86
+ apiHeaders['x-callback-url'] = this._callbackUrl + utils.queryString({ id: task.id });
87
+ const promise = task.promise
88
+ .then(({ status, json }) => {
89
+ logAsyncSuccess({ id: task.id, status, json, start });
90
+ return { json };
91
+ })
92
+ .catch(({ status, json }) => {
93
+ logAsyncFailure({ id: task.id, status, json, start });
94
+ throw json.error;
95
+ });
96
+ promise.catch(() => {});
97
+ return { id: task.id, promise };
98
+ }
99
+ return {};
100
+ }
101
+
102
+ const task = registerAsyncResponse();
103
+
104
+ let [res, cb]= await Promise.all([
105
+ this._utils.request({
106
+ body,
107
+ headers: apiHeaders,
108
+ method,
109
+ url,
110
+ logger: this._logger
111
+ }),
112
+ task.promise || {}
113
+ ]);
114
+
115
+ if (res.task === task.id && task.id) {
116
+ res = cb.json; // we got the async response we expected
117
+ } else {
118
+ tasks.cancel(task.id); // our callback url was ignored
119
+ }
120
+
121
+ return res;
59
122
  }
60
123
  }
61
124
 
@@ -0,0 +1,17 @@
1
+ const tasks = require('../shared/tasks');
2
+
3
+ class CallbackService {
4
+ response(id, body) {
5
+ const { status, json } = body || {};
6
+ if (!(id && status)) {
7
+ // invalid - do nothing
8
+ } else if (status < 400) {
9
+ tasks.respond(id, body);
10
+ } else {
11
+ tasks.fail(id, body);
12
+ }
13
+ }
14
+ }
15
+
16
+ module.exports = CallbackService;
17
+
@@ -11,9 +11,10 @@ module.exports = Object.freeze({
11
11
  compositions: require('./rest/compositionService'),
12
12
  files: require('./rest/fileService'),
13
13
  images: require('./rest/imageService'),
14
- audios: require('./rest/audioService'),
14
+ audio: require('./rest/audioService'),
15
15
  documents: require('./rest/documentService'),
16
16
  links: require('./rest/linkService'),
17
17
  advocacy: require('./rest/advocacyService'),
18
18
  utilities: require('./rest/utilityService'),
19
+ callback: require('./callbackService'),
19
20
  });
@@ -6,6 +6,7 @@ class BaseRestService extends BaseService {
6
6
  super(client, {
7
7
  apiKey: config.apiKey,
8
8
  integrationKey: config.integrationKey,
9
+ callbackUrl: config.callbackUrl,
9
10
  baseUrl: process.env.SDK_LOCAL_REST || `https://api${utils.getApiSuffix(config.env)}.vouchfor.com/v1`,
10
11
  basePath,
11
12
  env: config.env,
@@ -0,0 +1,72 @@
1
+ const crypto = require('node:crypto')
2
+
3
+ function generateId() {
4
+ const id = crypto.randomBytes(40)
5
+ .toString('base64url')
6
+ .replace(/[^a-zA-Z0-9]/g, '')
7
+ .slice(0, 10);
8
+ return id;
9
+ }
10
+
11
+ class TaskBroker {
12
+ constructor() {
13
+ this.pending = new Map();
14
+ }
15
+
16
+ create(timeoutMs = 120000) {
17
+ const id = generateId();
18
+
19
+ let resolveFn;
20
+ let rejectFn;
21
+
22
+ const promise = new Promise((resolve, reject) => {
23
+ resolveFn = resolve;
24
+ rejectFn = reject;
25
+ })
26
+
27
+ const timeout = setTimeout(() => {
28
+ if (!this.pending.has(id)) return;
29
+ this.pending.delete(id);
30
+ rejectFn(new Error(`Timed out waiting for ${id}`));
31
+ }, timeoutMs);
32
+
33
+ this.pending.set(id, {
34
+ resolve: value => {
35
+ clearTimeout(timeout);
36
+ this.pending.delete(id);
37
+ resolveFn(value);
38
+ },
39
+ reject: err => {
40
+ clearTimeout(timeout);
41
+ this.pending.delete(id);
42
+ rejectFn(err);
43
+ }
44
+ })
45
+
46
+ return { id, promise };
47
+ }
48
+
49
+ cancel(id) {
50
+ const entry = this.pending.get(id);
51
+ if (!entry) return false;
52
+ entry.reject({ status: 0, json: 'cancelled' });
53
+ return true;
54
+ }
55
+
56
+ respond(id, value) {
57
+ const entry = this.pending.get(id);
58
+ if (!entry) return false;
59
+ entry.resolve(value);
60
+ return true;
61
+ }
62
+
63
+ fail(id, value) {
64
+ const entry = this.pending.get(id);
65
+ if (!entry) return false;
66
+ entry.reject(value);
67
+ return true;
68
+ }
69
+ }
70
+
71
+ const broker = new TaskBroker()
72
+ module.exports = broker
package/lib/vouch.js CHANGED
@@ -3,6 +3,7 @@ class Vouch {
3
3
  this.config = Object.freeze({
4
4
  apiKey: config.apiKey,
5
5
  integrationKey: config.integrationKey,
6
+ callbackUrl: config.callbackUrl,
6
7
  env: config.env || 'prod',
7
8
  });
8
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vouchfor/sdk",
3
- "version": "1.1.33",
3
+ "version": "1.1.34",
4
4
  "description": "Vouch API SDK",
5
5
  "main": "lib/index.js",
6
6
  "repository": {
@@ -0,0 +1,21 @@
1
+ const Vouch = require("./lib/vouch");
2
+
3
+ const vouchClient = new Vouch({
4
+ env: 'dev',
5
+ integrationKey: 'b0883f06-84af-4108-8543-31874c335c36-kkr3Wy4CLY8C2g65UT79sgUfOIR2ZzkA9uQam3bTs4ZNdlSs7M',
6
+ callbackUrl: 'https://extrajudicial-melanie-unadministratively.ngrok-free.dev/callback'
7
+ }, console);
8
+
9
+ console.log(vouchClient);
10
+
11
+ const apiKey = 'kTYGShoaeg-QvraTZk9LmHNsxP4dWcye82uJB6Rf0XtIsgq7UaEcYpVhMDl3z';
12
+
13
+ (async () => {
14
+ const params = {
15
+ query: 'why',
16
+ limit: 2
17
+ };
18
+ const data = await vouchClient.campaigns.search(params, apiKey).catch(() => undefined);
19
+ console.log(data);
20
+ })();
21
+