@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.
- package/.claude/settings.local.json +10 -0
- package/lib/services/baseService.js +70 -7
- package/lib/services/callbackService.js +17 -0
- package/lib/services/index.js +2 -1
- package/lib/services/rest/base.js +1 -0
- package/lib/shared/tasks.js +72 -0
- package/lib/vouch.js +1 -0
- package/package.json +1 -1
- package/test-callback.js +21 -0
|
@@ -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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
|
package/lib/services/index.js
CHANGED
|
@@ -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
|
-
|
|
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
package/package.json
CHANGED
package/test-callback.js
ADDED
|
@@ -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
|
+
|