qranswers 1.0.2 → 1.0.4

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/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # qranswers_module
2
+ QR-Answers API module
3
+
4
+ This module allows you to use nodejs to access the QR-Answers API.
5
+
6
+ ## Webhooks
7
+
8
+ To use a webhook, create an endpoint (e.g. https://mydomain.com/qrhook)
9
+ In the app, go to Home -> Manage Plan -> Developer to retrieve your API key and Secret Key as well as input your endpoint.
10
+ For the webhook, you need to select which events you would like to receive from the Events to send section. Choose events from
11
+ the dropdown and you will see them appear in a list below. You may remove any events you no longer want to receive by
12
+ clicking the trash can next to the event and choosing Update Webhook.
13
+
14
+ To use this module:
15
+
16
+ ```
17
+ npm install qranswers
18
+ ```
19
+
20
+ Your webhook will need to collect the raw Body (a Buffer) of the request received. If you use express, you may add this to your file:
21
+
22
+ ```
23
+ npm install body-parser
24
+ ```
25
+
26
+ Then, in your nodejs app:
27
+
28
+ ```
29
+ const bodyParser = require('body-parser')
30
+
31
+ app.use(
32
+ bodyParser.json({
33
+ verify: function(req, res, buf) {
34
+ req.rawBody = buf;
35
+ }
36
+ })
37
+ );
38
+ ```
39
+
40
+ Then when you receive the event via a post, you will need to retrieve the ```x-qr-signature``` header and verify the event with the ```qranswers.webhook.constructEvent()``` method.
41
+ The method will throw an error if the signature does not match or if the period between the request and the decoding is too long.
42
+ You should return a json response to the QR-Answers server like below.
43
+
44
+ ```
45
+ app.post('/qrhook', function(req, res) {
46
+ const sig = req.headers['x-qr-signature'];
47
+ let event
48
+ try {
49
+ event = qranswers.webhooks.constructEvent(req.rawBody, sig, endpointSecret)
50
+ } catch (err) {
51
+ console.log('Error', err);
52
+ res.json({error: `Webhook Error: ${err.message}`});
53
+ return;
54
+ }
55
+
56
+ switch (event.type) {
57
+ case 'vote.evResponseVote':
58
+ const data = event.data.object;
59
+ console.log('Received event:', event);
60
+ break;
61
+ }
62
+
63
+ res.json({success: 'post call succeed!', url: req.url, body: req.body})
64
+ });
65
+ ```
66
+
67
+ The QR-Answers server(s) will only try 3 times with backoff to deliver your event. The server determines whether to retry sending the event by examining the
68
+ {success: "xxx"} field in the returned JSON.
69
+
70
+
71
+ ## API
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+ const {Amplify, API} = require('aws-amplify');
3
+
4
+ Amplify.configure({
5
+ 'aws_appsync_graphqlEndpoint': "https://sy35eokcbzcrvjomxqrx3xgawy.appsync-api.us-east-1.amazonaws.com/graphql",
6
+ 'aws_appsync_region': "us-east-1",
7
+ 'aws_appsync_authenticationType': "AWS_LAMBDA",
8
+ })
9
+
10
+ const onResponseByClientId = /* GraphQL */ `
11
+ subscription OnResponseByClientId($clientId: String!) {
12
+ onResponseByClientId(clientId: $clientId) {
13
+ clientId
14
+ projectId
15
+ baseId
16
+ answerId
17
+ count
18
+ }
19
+ }
20
+ `;
21
+ const getClientIdFromApiKey = /* GraphQL */ `
22
+ query GetClientIdFromApiKey($apiKey: String!) {
23
+ getClientIdFromApiKey(apiKey: $apiKey) {
24
+ clientID
25
+ }
26
+ }
27
+ `;
28
+
29
+ const QRSubscription = {
30
+ setKey(key) {
31
+ this._apiKey = key;
32
+ },
33
+ async initialize() {
34
+ const apiKey = this._apiKey;
35
+ if (apiKey === undefined) {
36
+ throw new Error("You must provide your API key when establishing the module. const qranswers = require('qranswers')(apiKey); ");
37
+ }
38
+ if (this.clientId !== undefined) {
39
+ return true;
40
+ }
41
+ // We need to get our clientId from the server
42
+ try {
43
+ const qlResp = await API.graphql({
44
+ query: getClientIdFromApiKey,
45
+ variables: { apiKey: apiKey },
46
+ authToken: this._apiKey
47
+ });
48
+ this._clientId = qlResp.data.getClientIdFromApiKey.clientID;
49
+ return true;
50
+ } catch (err) {
51
+ console.warn(err);
52
+ return false;
53
+ }
54
+ },
55
+ subscribeToResponse(callBack, errCallBack) {
56
+ if (this._clientId === undefined) {
57
+ throw new Error('You must first call qranswers.subscriptions.initialize() before calling any subscription');
58
+ }
59
+
60
+ const subscription = API.graphql({
61
+ query: onResponseByClientId,
62
+ variables: { clientId: this._clientId },
63
+ authToken: this._apiKey
64
+ }
65
+ ).subscribe({
66
+ next: ({ provider, value }) => {
67
+ const response = value.data.onResponseByClientId;
68
+ callBack(response);
69
+ },
70
+ error: (error) => {
71
+ console.warn(error)
72
+ if (errCallBack) {
73
+ errCallBack(error);
74
+ }
75
+ },
76
+ });
77
+ return subscription;
78
+ },
79
+ unsubscribeToResponse(subscription) {
80
+ subscription.unsubscribe();
81
+ }
82
+ }
83
+
84
+ module.exports = QRSubscription;
85
+ //export default QRSubscription;
package/lib/Webhooks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
- const crypto = require('crypto');
2
+ //const crypto = require('crypto');
3
3
 
4
4
  const Webhook = {
5
5
  DEFAULT_TOLERANCE: 300000, // in ms
@@ -89,6 +89,7 @@ function parseHeader(header, scheme) {
89
89
  signatures: [],
90
90
  }
91
91
  );
92
- }
92
+ };
93
+
93
94
  module.exports = Webhook;
94
95
 
package/lib/qranswers.js CHANGED
@@ -24,10 +24,10 @@ function QRAnswers(key, config = {}) {
24
24
  if (
25
25
  props.protocol &&
26
26
  props.protocol !== 'https' &&
27
- (!props.host || /\.stripe\.com$/.test(props.host))
27
+ (!props.host || /\.qr-answers\.com$/.test(props.host))
28
28
  ) {
29
29
  throw new Error(
30
- 'The `https` protocol must be used when sending requests to `*.stripe.com`'
30
+ 'The `https` protocol must be used when sending requests to `*.qr-answers.com`'
31
31
  );
32
32
  }
33
33
  const agent = props.httpAgent || null;
@@ -40,16 +40,22 @@ function QRAnswers(key, config = {}) {
40
40
  version: props.apiVersion || DEFAULT_API_VERSION,
41
41
  timeout: utils.validateInteger('timeout', props.timeout, DEFAULT_TIMEOUT),
42
42
  };
43
+ this._setApiKey(key);
44
+
45
+ this.webhooks = require('./Webhooks');
46
+ this.subscriptions = require('./Subscriptions');
47
+ this.subscriptions.setKey(key);
43
48
 
44
49
  }
45
50
  QRAnswers.webhooks = require("./Webhooks");
51
+ QRAnswers.subscriptions = require("./Subscriptions");
46
52
  QRAnswers.prototype = {
47
53
  VERSION: null,
48
54
  webhooks: null,
49
55
  _api: null,
50
56
  _setApiKey(key) {
51
57
  if (key) {
52
- this._setApiField('auth', `Bearer ${key}`);
58
+ this._setApiField('key', key);
53
59
  }
54
60
  },
55
61
  _setApiField(key, value) {
@@ -91,7 +97,7 @@ QRAnswers.prototype = {
91
97
  };
92
98
  module.exports = QRAnswers;
93
99
  // expose constructor as a named property to enable mocking with Sinon.JS
94
- module.exports.Stripe = QRAnswers;
100
+ module.exports.QRAnswers = QRAnswers;
95
101
  // Allow use with the TypeScript compiler without `esModuleInterop`.
96
102
  // We may also want to add `Object.defineProperty(exports, "__esModule", {value: true});` in the future, so that Babel users will use the `default` version.
97
103
  module.exports.default = QRAnswers;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qranswers",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Helper module to access QR-Answers API",
5
5
  "main": "lib/qranswers.js",
6
6
  "scripts": {
@@ -23,6 +23,7 @@
23
23
  },
24
24
  "homepage": "https://github.com/ggcespia/qranswers_module#readme",
25
25
  "dependencies": {
26
+ "aws-amplify": "^5.3.11",
26
27
  "crypto": "^1.0.1"
27
28
  }
28
29
  }