@velocitycareerlabs/server-webwallet 1.27.0-dev-build.163831870 → 1.27.0-dev-build.17b8f41df

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.
Files changed (28) hide show
  1. package/package.json +18 -18
  2. package/src/controllers/linkedin/controller.js +9 -6
  3. package/src/fetchers/career-wallet/create-account-fetcher.js +4 -2
  4. package/src/fetchers/career-wallet/create-did-fetcher.js +12 -9
  5. package/src/fetchers/career-wallet/get-app-config.js +6 -6
  6. package/src/fetchers/career-wallet/get-consents.js +8 -5
  7. package/src/fetchers/career-wallet/get-credential-categories.js +6 -2
  8. package/src/fetchers/career-wallet/get-personas.js +4 -2
  9. package/src/fetchers/career-wallet/post-consent.js +7 -4
  10. package/src/fetchers/career-wallet/send-feedback.js +8 -9
  11. package/src/fetchers/career-wallet/sign-fetcher.js +8 -9
  12. package/src/fetchers/career-wallet/verify-id-credential-confirm-code.js +9 -7
  13. package/src/fetchers/career-wallet/verify-id-credential-request-code.js +9 -7
  14. package/src/fetchers/credverify/remove-credentials.js +9 -6
  15. package/src/fetchers/lib-api/get-credential-display-schema.js +6 -7
  16. package/src/fetchers/linkedin/create-linkedin-post.js +35 -32
  17. package/src/fetchers/linkedin/get-access-token.js +18 -15
  18. package/src/fetchers/linkedin/get-linkedin-user-email.js +8 -5
  19. package/src/fetchers/linkedin/get-linkedin-user-id.js +11 -11
  20. package/src/fetchers/linkedin/register-image-to-upload.js +20 -17
  21. package/src/fetchers/linkedin/revoke-linkedin-access.js +18 -12
  22. package/src/fetchers/linkedin/upload-image-to-linkedin.js +10 -10
  23. package/src/init-server.js +44 -64
  24. package/src/plugins/crypto-services/jwt-sign-service-impl.js +7 -1
  25. package/src/plugins/crypto-services/key-service-impl.js +7 -1
  26. package/src/plugins/fetch-errors-handler-plugin.js +22 -9
  27. package/test/fetch-errors-handler-plugin.test.js +34 -11
  28. package/test/linkedin-controller.test.js +1 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velocitycareerlabs/server-webwallet",
3
- "version": "1.27.0-dev-build.163831870",
3
+ "version": "1.27.0-dev-build.17b8f41df",
4
4
  "description": "Web Wallet application",
5
5
  "repository": "https://github.com/velocitycareerlabs/packages",
6
6
  "engines": {
@@ -34,31 +34,31 @@
34
34
  "@fastify/swagger": "^9.0.0",
35
35
  "@fastify/swagger-ui": "^5.0.0",
36
36
  "@spencejs/spence-mongo-repos": "^0.10.2",
37
- "@velocitycareerlabs/migrations": "1.27.0-dev-build.163831870",
38
- "@verii/auth": "1.0.7",
39
- "@verii/common-functions": "1.0.7",
40
- "@verii/common-schemas": "1.0.7",
41
- "@verii/config": "1.0.7",
42
- "@verii/fastify-plugins": "1.0.7",
43
- "@verii/jwt": "1.0.7",
44
- "@verii/request": "1.0.7",
45
- "@verii/server-provider": "1.0.7",
46
- "@verii/vc-checks": "1.0.7",
47
- "@verii/vnf-nodejs-wallet-sdk": "1.0.7",
37
+ "@velocitycareerlabs/migrations": "1.27.0-dev-build.17b8f41df",
38
+ "@verii/auth": "1.1.0-pre.1763452964",
39
+ "@verii/common-functions": "1.1.0-pre.1763452964",
40
+ "@verii/common-schemas": "1.1.0-pre.1763452964",
41
+ "@verii/config": "1.1.0-pre.1763452964",
42
+ "@verii/fastify-plugins": "1.1.0-pre.1763452964",
43
+ "@verii/http-client": "1.1.0-pre.1763452964",
44
+ "@verii/jwt": "1.1.0-pre.1763452964",
45
+ "@verii/server-provider": "1.1.0-pre.1763452964",
46
+ "@verii/vc-checks": "1.1.0-pre.1763452964",
47
+ "@verii/vnf-nodejs-wallet-sdk": "1.1.0-pre.1763452964",
48
48
  "blueimp-md5": "2.19.0",
49
49
  "env-var": "^7.0.0",
50
50
  "fastify": "^5.0.0",
51
51
  "fastify-plugin": "^5.0.0",
52
- "got": "11.8.6",
53
52
  "http-errors": "2.0.0",
54
53
  "lodash": "^4.17.21",
55
54
  "migrate-mongo": "~11.0.0",
56
- "mongodb": "~6.19.0"
55
+ "mongodb": "~6.19.0",
56
+ "undici": "^7.0.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@spencejs/spence-factories": "0.10.2",
60
- "@verii/crypto": "1.0.7",
61
- "@verii/tests-helpers": "1.0.7",
60
+ "@verii/crypto": "1.1.0-pre.1763452964",
61
+ "@verii/tests-helpers": "1.1.0-pre.1763452964",
62
62
  "dotenv": "16.6.1",
63
63
  "eslint": "8.57.1",
64
64
  "eslint-config-airbnb-base": "14.2.1",
@@ -70,9 +70,9 @@
70
70
  "eslint-plugin-prettier": "4.2.5",
71
71
  "eslint-watch": "7.0.0",
72
72
  "expect": "30.2.0",
73
- "nock": "14.0.9",
73
+ "nock": "v15.0.0-beta.6",
74
74
  "nodemon": "3.1.10",
75
75
  "prettier": "2.8.8"
76
76
  },
77
- "gitHead": "06c1711138b1159662859238bf0b2b57c834d5a6"
77
+ "gitHead": "c9d4aa06c8f27df3ed4c9f54437a6f65c2726035"
78
78
  }
@@ -119,7 +119,7 @@ const linkedinController = async (fastify) => {
119
119
  userEmail: elements[0]['handle~'].emailAddress,
120
120
  };
121
121
  } catch (error) {
122
- if (error?.response.statusCode === 401) {
122
+ if (error?.statusCode === 401) {
123
123
  await accounts.updateUsingFilter(
124
124
  {
125
125
  filter: { userId: user.sub },
@@ -244,11 +244,14 @@ const linkedinController = async (fastify) => {
244
244
  asset: uploadLinkData.value.asset,
245
245
  };
246
246
 
247
- await uploadImageToLinkedin({
248
- accessToken: linkedinAccessToken,
249
- file: params.logo,
250
- uploadUrl: imageData.uploadUrl,
251
- });
247
+ await uploadImageToLinkedin(
248
+ {
249
+ accessToken: linkedinAccessToken,
250
+ file: params.logo,
251
+ uploadUrl: imageData.uploadUrl,
252
+ },
253
+ req
254
+ );
252
255
  }
253
256
  return createLinkedinPost(
254
257
  {
@@ -1,5 +1,7 @@
1
- const createCareerWalletAccount = (payload, { careerWalletFetch }) => {
2
- return careerWalletFetch.post('api/v0.6/accounts', { json: payload }).json();
1
+ const createCareerWalletAccount = async (payload, { careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.post('api/v0.6/accounts', payload);
3
+
4
+ return response.json();
3
5
  };
4
6
 
5
7
  module.exports = {
@@ -1,15 +1,18 @@
1
- const createDidForAccount = (crv, accessToken, { careerWalletFetch }) => {
2
- return careerWalletFetch
3
- .post('api/v0.6/create_did_key', {
4
- json: {
5
- crv: `${crv}`,
6
- didMethod: 'did:jwk',
7
- },
1
+ const createDidForAccount = async (crv, accessToken, { careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.post(
3
+ 'api/v0.6/create_did_key',
4
+ {
5
+ crv: `${crv}`,
6
+ didMethod: 'did:jwk',
7
+ },
8
+ {
8
9
  headers: {
9
10
  Authorization: `Bearer ${accessToken}`,
10
11
  },
11
- })
12
- .json();
12
+ }
13
+ );
14
+
15
+ return response.json();
13
16
  };
14
17
 
15
18
  module.exports = {
@@ -1,9 +1,9 @@
1
- const getAppConfig = async ({ careerWalletFetch, cache }) => {
2
- return careerWalletFetch
3
- .get('api/v0.6/careerwallet/appconfig', {
4
- cache,
5
- })
6
- .json();
1
+ const getAppConfig = async ({ careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.get(
3
+ 'api/v0.6/careerwallet/appconfig'
4
+ );
5
+
6
+ return response.json();
7
7
  };
8
8
 
9
9
  module.exports = {
@@ -1,11 +1,14 @@
1
- const getConsentLatest = (accountId, { careerWalletFetch, config }) => {
2
- return careerWalletFetch
3
- .get(`api/v0.6/careerwallet/consents/latest?accountId=${accountId}`, {
1
+ const getConsentLatest = async (accountId, { careerWalletFetch, config }) => {
2
+ const response = await careerWalletFetch.get(
3
+ `api/v0.6/careerwallet/consents/latest?accountId=${accountId}`,
4
+ {
4
5
  headers: {
5
6
  Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
6
7
  },
7
- })
8
- .json();
8
+ }
9
+ );
10
+
11
+ return response.json();
9
12
  };
10
13
 
11
14
  module.exports = {
@@ -1,5 +1,9 @@
1
- const getCredentialCategories = ({ careerWalletFetch }) => {
2
- return careerWalletFetch.get('api/v0.6/credential-categories').json();
1
+ const getCredentialCategories = async ({ careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.get(
3
+ 'api/v0.6/credential-categories'
4
+ );
5
+
6
+ return response.json();
3
7
  };
4
8
 
5
9
  module.exports = {
@@ -1,5 +1,7 @@
1
- const getPersonas = ({ careerWalletFetch, cache }) => {
2
- return careerWalletFetch.get('reference/personas', { cache }).json();
1
+ const getPersonas = async ({ careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.get('reference/personas');
3
+
4
+ return response.json();
3
5
  };
4
6
 
5
7
  module.exports = {
@@ -1,7 +1,10 @@
1
- const postConsent = (payload, authorization, { careerWalletFetch }) => {
2
- return careerWalletFetch
3
- .post('api/v0.6/careerwallet/consents/add', { json: payload })
4
- .json();
1
+ const postConsent = async (payload, authorization, { careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.post(
3
+ 'api/v0.6/careerwallet/consents/add',
4
+ payload
5
+ );
6
+
7
+ return response.json();
5
8
  };
6
9
 
7
10
  module.exports = {
@@ -1,12 +1,11 @@
1
- const sendFeedback = (payload, { careerWalletFetch, config }) => {
2
- return careerWalletFetch
3
- .post('api/v0.6/feedback', {
4
- json: payload,
5
- headers: {
6
- Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
7
- },
8
- })
9
- .json();
1
+ const sendFeedback = async (payload, { careerWalletFetch, config }) => {
2
+ const response = await careerWalletFetch.post('api/v0.6/feedback', payload, {
3
+ headers: {
4
+ Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
5
+ },
6
+ });
7
+
8
+ return response.json();
10
9
  };
11
10
 
12
11
  module.exports = {
@@ -1,12 +1,11 @@
1
- const signFetcher = (payload, accessToken, { careerWalletFetch }) => {
2
- return careerWalletFetch
3
- .post('api/v0.6/jwt/sign', {
4
- json: { ...payload },
5
- headers: {
6
- Authorization: `Bearer ${accessToken}`,
7
- },
8
- })
9
- .json();
1
+ const signFetcher = async (payload, accessToken, { careerWalletFetch }) => {
2
+ const response = await careerWalletFetch.post('api/v0.6/jwt/sign', payload, {
3
+ headers: {
4
+ Authorization: `Bearer ${accessToken}`,
5
+ },
6
+ });
7
+
8
+ return response.json();
10
9
  };
11
10
 
12
11
  module.exports = {
@@ -1,17 +1,19 @@
1
1
  const verifyIdCredentialConfirmCode = async (
2
2
  verificationCode,
3
- { careerWalletFetch, cache, config }
3
+ { careerWalletFetch, config }
4
4
  ) => {
5
- return careerWalletFetch
6
- .post('api/v0.6/verify/confirm', {
7
- json: { verificationCode },
5
+ const response = await careerWalletFetch.post(
6
+ 'api/v0.6/verify/confirm',
7
+ { verificationCode },
8
+ {
8
9
  headers: {
9
10
  'x-vcl-verif-version': config.vclVerificationVersion,
10
11
  Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
11
12
  },
12
- cache,
13
- })
14
- .json();
13
+ }
14
+ );
15
+
16
+ return response.json();
15
17
  };
16
18
 
17
19
  module.exports = {
@@ -1,18 +1,20 @@
1
1
  const verifyIdCredentialRequestCode = async (
2
2
  credentialType,
3
3
  value,
4
- { careerWalletFetch, cache, config }
4
+ { careerWalletFetch, config }
5
5
  ) => {
6
- return careerWalletFetch
7
- .post(`api/v0.6/verify/${credentialType}/request-code`, {
8
- json: { value },
6
+ const response = await careerWalletFetch.post(
7
+ `api/v0.6/verify/${credentialType}/request-code`,
8
+ { value },
9
+ {
9
10
  headers: {
10
11
  'x-vcl-verif-version': config.vclVerificationVersion,
11
12
  Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
12
13
  },
13
- cache,
14
- })
15
- .json();
14
+ }
15
+ );
16
+
17
+ return response.json();
16
18
  };
17
19
 
18
20
  module.exports = {
@@ -1,15 +1,18 @@
1
- const removeCredentials = (
1
+ const removeCredentials = async (
2
2
  payload,
3
3
  { verificationServiceActionFetch, config }
4
4
  ) => {
5
- return verificationServiceActionFetch
6
- .post('remove-credentials', {
7
- json: payload,
5
+ const response = await verificationServiceActionFetch.post(
6
+ 'remove-credentials',
7
+ payload,
8
+ {
8
9
  headers: {
9
10
  Authorization: `Bearer ${config.careerWalletAdminAccessToken}`,
10
11
  },
11
- })
12
- .json();
12
+ }
13
+ );
14
+
15
+ return response.json();
13
16
  };
14
17
 
15
18
  module.exports = {
@@ -1,10 +1,9 @@
1
- const getCredentialDisplaySchema = async (
2
- credentialType,
3
- { libFetch, cache }
4
- ) => {
5
- return libFetch
6
- .get(`display-descriptors/${credentialType}.descriptor.json`, { cache })
7
- .json();
1
+ const getCredentialDisplaySchema = async (credentialType, { libFetch }) => {
2
+ const response = await libFetch.get(
3
+ `display-descriptors/${credentialType}.descriptor.json`
4
+ );
5
+
6
+ return response.json();
8
7
  };
9
8
 
10
9
  module.exports = {
@@ -1,43 +1,46 @@
1
- const createLinkedinPost = (
1
+ const createLinkedinPost = async (
2
2
  { accessToken, linkedinUserId, text, asset },
3
3
  { linkedInFetch }
4
4
  ) => {
5
- return linkedInFetch
6
- .post('ugcPosts', {
5
+ const response = await linkedInFetch.post(
6
+ 'ugcPosts',
7
+ {
8
+ author: `urn:li:person:${linkedinUserId}`,
9
+ lifecycleState: 'PUBLISHED',
10
+ specificContent: {
11
+ 'com.linkedin.ugc.ShareContent': {
12
+ shareCommentary: {
13
+ text,
14
+ },
15
+ ...(asset
16
+ ? {
17
+ shareMediaCategory: 'IMAGE',
18
+ media: [
19
+ {
20
+ status: 'READY',
21
+ media: asset,
22
+ },
23
+ ],
24
+ }
25
+ : {
26
+ shareMediaCategory: 'NONE',
27
+ }),
28
+ },
29
+ },
30
+ visibility: {
31
+ 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
32
+ },
33
+ },
34
+ {
7
35
  headers: {
8
36
  'Content-Type': 'application/json',
9
37
  'X-Restli-Protocol-Version': '2.0.0',
10
38
  Authorization: `Bearer ${accessToken}`,
11
39
  },
12
- json: {
13
- author: `urn:li:person:${linkedinUserId}`,
14
- lifecycleState: 'PUBLISHED',
15
- specificContent: {
16
- 'com.linkedin.ugc.ShareContent': {
17
- shareCommentary: {
18
- text,
19
- },
20
- ...(asset
21
- ? {
22
- shareMediaCategory: 'IMAGE',
23
- media: [
24
- {
25
- status: 'READY',
26
- media: asset,
27
- },
28
- ],
29
- }
30
- : {
31
- shareMediaCategory: 'NONE',
32
- }),
33
- },
34
- },
35
- visibility: {
36
- 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
37
- },
38
- },
39
- })
40
- .json();
40
+ }
41
+ );
42
+
43
+ return response.json();
41
44
  };
42
45
 
43
46
  module.exports = {
@@ -1,24 +1,27 @@
1
- const getLinkedInAccessToken = (
1
+ const getLinkedInAccessToken = async (
2
2
  { code, redirectUri },
3
3
  { config, linkedInAuthFetch }
4
4
  ) => {
5
- return linkedInAuthFetch
6
- .post('accessToken', {
5
+ const response = await linkedInAuthFetch.post(
6
+ 'accessToken',
7
+ String(
8
+ new URLSearchParams({
9
+ code,
10
+ redirect_uri:
11
+ redirectUri || `${config.webWalletBaseUrl}/share-to-linkedin`,
12
+ client_id: config.linkedIn.clientId,
13
+ client_secret: config.linkedIn.clientSecret,
14
+ grant_type: 'authorization_code',
15
+ })
16
+ ),
17
+ {
7
18
  headers: {
8
19
  'Content-Type': ' application/x-www-form-urlencoded',
9
20
  },
10
- body: String(
11
- new URLSearchParams({
12
- code,
13
- redirect_uri:
14
- redirectUri || `${config.webWalletBaseUrl}/share-to-linkedin`,
15
- client_id: config.linkedIn.clientId,
16
- client_secret: config.linkedIn.clientSecret,
17
- grant_type: 'authorization_code',
18
- })
19
- ),
20
- })
21
- .json();
21
+ }
22
+ );
23
+
24
+ return response.json();
22
25
  };
23
26
 
24
27
  module.exports = {
@@ -1,11 +1,14 @@
1
- const getLinkedInUserEmail = (accessToken, { linkedInFetch }) => {
2
- return linkedInFetch
3
- .get('emailAddress?q=members&projection=(elements*(handle~))', {
1
+ const getLinkedInUserEmail = async (accessToken, { linkedInFetch }) => {
2
+ const response = await linkedInFetch.get(
3
+ 'emailAddress?q=members&projection=(elements*(handle~))',
4
+ {
4
5
  headers: {
5
6
  Authorization: `Bearer ${accessToken}`,
6
7
  },
7
- })
8
- .json();
8
+ }
9
+ );
10
+
11
+ return response.json();
9
12
  };
10
13
 
11
14
  module.exports = {
@@ -1,14 +1,14 @@
1
- const getLinkedInUserId = (accessToken, { linkedInFetch }) => {
2
- return linkedInFetch
3
- .get(
4
- 'me?projection=(id,localizedFirstName,localizedLastName,profilePicture(displayImage~digitalmediaAsset:playableStreams))',
5
- {
6
- headers: {
7
- Authorization: `Bearer ${accessToken}`,
8
- },
9
- }
10
- )
11
- .json();
1
+ const getLinkedInUserId = async (accessToken, { linkedInFetch }) => {
2
+ const response = await linkedInFetch.get(
3
+ 'me?projection=(id,localizedFirstName,localizedLastName,profilePicture(displayImage~digitalmediaAsset:playableStreams))',
4
+ {
5
+ headers: {
6
+ Authorization: `Bearer ${accessToken}`,
7
+ },
8
+ }
9
+ );
10
+
11
+ return response.json();
12
12
  };
13
13
 
14
14
  module.exports = {
@@ -1,28 +1,31 @@
1
- const registerImageToUpload = (
1
+ const registerImageToUpload = async (
2
2
  { linkedinUserId, accessToken },
3
3
  { linkedInFetch }
4
4
  ) => {
5
- return linkedInFetch
6
- .post('assets?action=registerUpload', {
5
+ const response = await linkedInFetch.post(
6
+ 'assets?action=registerUpload',
7
+ {
8
+ registerUploadRequest: {
9
+ recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
10
+ owner: `urn:li:person:${linkedinUserId}`,
11
+ serviceRelationships: [
12
+ {
13
+ relationshipType: 'OWNER',
14
+ identifier: 'urn:li:userGeneratedContent',
15
+ },
16
+ ],
17
+ },
18
+ },
19
+ {
7
20
  headers: {
8
21
  'Content-Type': 'application/json',
9
22
  'X-Restli-Protocol-Version': '2.0.0',
10
23
  Authorization: `Bearer ${accessToken}`,
11
24
  },
12
- json: {
13
- registerUploadRequest: {
14
- recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
15
- owner: `urn:li:person:${linkedinUserId}`,
16
- serviceRelationships: [
17
- {
18
- relationshipType: 'OWNER',
19
- identifier: 'urn:li:userGeneratedContent',
20
- },
21
- ],
22
- },
23
- },
24
- })
25
- .json();
25
+ }
26
+ );
27
+
28
+ return response.json();
26
29
  };
27
30
 
28
31
  module.exports = {
@@ -1,18 +1,24 @@
1
- const revokeLinkedinAccess = (accessToken, { config, linkedInAuthFetch }) => {
2
- return linkedInAuthFetch
3
- .post('revoke', {
1
+ const revokeLinkedinAccess = async (
2
+ accessToken,
3
+ { config, linkedInAuthFetch }
4
+ ) => {
5
+ const response = await linkedInAuthFetch.post(
6
+ 'revoke',
7
+ String(
8
+ new URLSearchParams({
9
+ client_id: config.linkedIn.clientId,
10
+ client_secret: config.linkedIn.clientSecret,
11
+ token: accessToken,
12
+ })
13
+ ),
14
+ {
4
15
  headers: {
5
16
  'Content-Type': ' application/x-www-form-urlencoded',
6
17
  },
7
- body: String(
8
- new URLSearchParams({
9
- client_id: config.linkedIn.clientId,
10
- client_secret: config.linkedIn.clientSecret,
11
- token: accessToken,
12
- })
13
- ),
14
- })
15
- .json();
18
+ }
19
+ );
20
+
21
+ return response.json();
16
22
  };
17
23
 
18
24
  module.exports = {
@@ -1,14 +1,14 @@
1
- const { default: got } = require('got');
1
+ const uploadImageToLinkedin = async (
2
+ { accessToken, uploadUrl, file },
3
+ { fetch }
4
+ ) => {
5
+ const response = await fetch.post(uploadUrl, file, {
6
+ headers: {
7
+ Authorization: `Bearer ${accessToken}`,
8
+ },
9
+ });
2
10
 
3
- const uploadImageToLinkedin = ({ accessToken, uploadUrl, file }) => {
4
- return got
5
- .post(uploadUrl, {
6
- headers: {
7
- Authorization: `Bearer ${accessToken}`,
8
- },
9
- body: file,
10
- })
11
- .json();
11
+ return response.json();
12
12
  };
13
13
 
14
14
  module.exports = {
@@ -1,5 +1,5 @@
1
1
  const { corsPlugin } = require('@verii/fastify-plugins');
2
- const initRequest = require('@verii/request');
2
+ const { httpClientPlugin } = require('@verii/fastify-plugins');
3
3
  const AutoLoad = require('@fastify/autoload');
4
4
  const path = require('path');
5
5
  const { pick } = require('lodash/fp');
@@ -27,87 +27,67 @@ const initServer = (server) => {
27
27
  autoHooks: true,
28
28
  cascadeHooks: true,
29
29
  })
30
- .decorate(
31
- 'baseAgentFetch',
32
- initRequest({
30
+ .register(httpClientPlugin, {
31
+ name: 'fetch',
32
+ options: pick(
33
+ ['nodeEnv', 'requestTimeout', 'traceIdHeader', 'isTest'],
34
+ server.config
35
+ ),
36
+ })
37
+ .register(httpClientPlugin, {
38
+ name: 'agentFetch',
39
+ options: {
33
40
  ...server.config,
34
41
  prefixUrl: server.config.agentUrl,
35
- })
36
- )
37
- .decorateRequest('agentFetch', null)
38
- .addHook('preValidation', async (req) => {
39
- req.agentFetch = server.baseAgentFetch(req);
42
+ },
40
43
  })
41
- .decorate(
42
- 'baseRegistrarFetch',
43
- initRequest({
44
+ .register(httpClientPlugin, {
45
+ name: 'registrarFetch',
46
+ options: {
44
47
  ...server.config,
45
48
  prefixUrl: server.config.registrarUrl,
46
- })
47
- )
48
- .decorateRequest('registrarFetch', null)
49
- .addHook('preValidation', async (req) => {
50
- req.registrarFetch = server.baseRegistrarFetch(req);
49
+ },
51
50
  })
52
- .decorate(
53
- 'baseLibFetch',
54
- initRequest({
55
- ...pick(['nodeEnv', 'requestTimeout', 'traceIdHeader'], server.config),
51
+ .register(httpClientPlugin, {
52
+ name: 'libFetch',
53
+ options: {
54
+ ...pick(
55
+ ['nodeEnv', 'requestTimeout', 'traceIdHeader', 'isTest'],
56
+ server.config
57
+ ),
56
58
  prefixUrl: server.config.libUrl,
57
- })
58
- )
59
- .decorateRequest('libFetch', null)
60
- .addHook('preValidation', async (req) => {
61
- req.libFetch = server.baseLibFetch(req);
59
+ },
62
60
  })
63
- .decorate(
64
- 'baseVerificationServiceActionFetch',
65
- initRequest({
66
- ...pick(['nodeEnv', 'requestTimeout', 'traceIdHeader'], server.config),
61
+ .register(httpClientPlugin, {
62
+ name: 'verificationServiceActionFetch',
63
+ options: {
64
+ ...pick(
65
+ ['nodeEnv', 'requestTimeout', 'traceIdHeader', 'isTest'],
66
+ server.config
67
+ ),
67
68
  prefixUrl: server.config.verificationServiceActionBaseUrl,
68
- })
69
- )
70
- .decorateRequest('verificationServiceActionFetch', null)
71
- .addHook('preValidation', async (req) => {
72
- req.verificationServiceActionFetch =
73
- server.baseVerificationServiceActionFetch(req);
69
+ },
74
70
  })
75
- .decorate(
76
- 'baseCareerWalletFetch',
77
- initRequest({
71
+ .register(httpClientPlugin, {
72
+ name: 'careerWalletFetch',
73
+ options: {
78
74
  ...server.config,
79
75
  prefixUrl: server.config.careerWalletUrl,
80
- })
81
- )
82
- .decorate(
83
- 'globalCareerWalletFetch',
84
- server.baseCareerWalletFetch({ log: server.log })
85
- )
86
- .decorateRequest('careerWalletFetch', null)
87
- .addHook('preValidation', async (req) => {
88
- req.careerWalletFetch = server.baseCareerWalletFetch(req);
76
+ },
89
77
  })
90
- .decorate(
91
- 'baseLinkedInFetch',
92
- initRequest({
78
+ .register(httpClientPlugin, {
79
+ name: 'linkedInFetch',
80
+ options: {
93
81
  ...server.config,
94
82
  prefixUrl: server.config.linkedIn.apiUrl,
95
- })
96
- )
97
- .decorateRequest('linkedInFetch', null)
98
- .addHook('preValidation', async (req) => {
99
- req.linkedInFetch = server.baseLinkedInFetch(req);
83
+ },
100
84
  })
101
- .decorate(
102
- 'baseLinkedInAuthFetch',
103
- initRequest({
85
+ .register(httpClientPlugin, {
86
+ name: 'linkedInAuthFetch',
87
+ options: {
104
88
  ...server.config,
105
89
  prefixUrl: server.config.linkedIn.authUrl,
106
- })
107
- )
108
- .decorateRequest('linkedInAuthFetch', null)
109
- .addHook('preValidation', async (req) => {
110
- req.linkedInAuthFetch = server.baseLinkedInAuthFetch(req);
90
+ },
111
91
  })
112
92
  .register(vnfSdkPlugin)
113
93
  .addHook('preValidation', async (req) => {
@@ -13,7 +13,13 @@ const JwtSignServiceImpl = (context) => {
13
13
  const signedJwtRes = await signFetcher(
14
14
  payload,
15
15
  remoteCryptoServicesToken,
16
- { ...context, careerWalletFetch: context.globalCareerWalletFetch }
16
+ {
17
+ ...context,
18
+ careerWalletFetch: context.baseCareerWalletFetch()(
19
+ context.config.careerWalletUrl,
20
+ context
21
+ ),
22
+ }
17
23
  );
18
24
  const signedJwt = signedJwtRes.compactJwt;
19
25
  return new Promise((resolve) => {
@@ -9,7 +9,13 @@ const KeyServiceImpl = (context) => {
9
9
  const didJwkJson = await createDidForAccount(
10
10
  didJwkDescriptor.signatureAlgorithm,
11
11
  didJwkDescriptor.remoteCryptoServicesToken,
12
- { ...context, careerWalletFetch: context.globalCareerWalletFetch }
12
+ {
13
+ ...context,
14
+ careerWalletFetch: context.baseCareerWalletFetch()(
15
+ context.config.careerWalletUrl,
16
+ context
17
+ ),
18
+ }
13
19
  );
14
20
  return new Promise((resolve) => {
15
21
  resolve(VCLDidJwk.fromJSON(didJwkJson));
@@ -1,6 +1,6 @@
1
1
  const fp = require('fastify-plugin');
2
2
  const newError = require('http-errors');
3
- const { HTTPError } = require('got');
3
+ const { errors } = require('undici');
4
4
  const { isObject } = require('lodash/fp');
5
5
  const { WebWalletServerError } = require('../errors/error-codes');
6
6
 
@@ -20,7 +20,7 @@ const fetchErrorsHandlerPlugin = (fastify, options, next) => {
20
20
  };
21
21
 
22
22
  const handleHttpErrors = (error) => {
23
- if (error instanceof HTTPError) {
23
+ if (error instanceof errors.ResponseError) {
24
24
  handleHTTPError(error);
25
25
  } else {
26
26
  handleGenericError(error);
@@ -28,16 +28,29 @@ const handleHttpErrors = (error) => {
28
28
  };
29
29
 
30
30
  const handleHTTPError = (error) => {
31
- const errorBody = parseErrorBody(error.response.body);
32
- throw newError(
33
- error.response.statusCode,
34
- errorBody?.message || errorBody || error.response.statusMessage,
35
- {
31
+ if (!error.errorCode) {
32
+ const errorBody = getErrorBody(error);
33
+ throw newError(getStatusCode(error), getErrorMesssage(error, errorBody), {
36
34
  ...(isObject(errorBody) ? errorBody : {}),
37
- }
38
- );
35
+ });
36
+ } else {
37
+ throw error;
38
+ }
39
39
  };
40
40
 
41
+ const getErrorBody = (error) =>
42
+ parseErrorBody(error?.response?.body || error?.body);
43
+
44
+ const getStatusCode = (error) =>
45
+ error?.response?.statusCode || error?.statusCode;
46
+
47
+ const getErrorMesssage = (error, errorBody) =>
48
+ errorBody?.message ||
49
+ errorBody ||
50
+ error?.statusMessage ||
51
+ error?.code ||
52
+ 'HTTP Error';
53
+
41
54
  const handleGenericError = (error) => {
42
55
  if (!error.errorCode) {
43
56
  throw newError(error.statusCode || 500, error.message, {
@@ -4,9 +4,21 @@ const { expect } = require('expect');
4
4
 
5
5
  const buildFastify = require('fastify');
6
6
  const nock = require('nock');
7
- const got = require('got');
7
+ const { request, errors } = require('undici');
8
8
  const { fetchErrorsHandlerPlugin } = require('../src/plugins');
9
9
 
10
+ const handleResponse = async (response, isText = false) => {
11
+ if (response.statusCode >= 300) {
12
+ const body = isText
13
+ ? await response.body.text()
14
+ : await response.body.json();
15
+ throw new errors.ResponseError(body.message, response.statusCode, {
16
+ code: body.code,
17
+ body,
18
+ });
19
+ }
20
+ };
21
+
10
22
  describe('Test fetchErrorsHandlerPlugin', () => {
11
23
  let fastify;
12
24
 
@@ -16,9 +28,13 @@ describe('Test fetchErrorsHandlerPlugin', () => {
16
28
  });
17
29
 
18
30
  it('Should return the same HTTPError as the nested fetch request', async () => {
19
- fastify.get('/test', () =>
20
- got.get('https://test/endpoint_that_returns_error')
21
- );
31
+ fastify.get('/test', async () => {
32
+ const response = await request(
33
+ 'https://test/endpoint_that_returns_error'
34
+ );
35
+
36
+ await handleResponse(response);
37
+ });
22
38
 
23
39
  const nockedRequest = nock('https://test')
24
40
  .get('/endpoint_that_returns_error')
@@ -49,9 +65,13 @@ describe('Test fetchErrorsHandlerPlugin', () => {
49
65
  });
50
66
 
51
67
  it('Should return correct error when nested fetch request returns fatal error', async () => {
52
- fastify.get('/test', () =>
53
- got.get('https://test/endpoint_that_throws_fatal_error')
54
- );
68
+ fastify.get('/test', async () => {
69
+ const response = await request(
70
+ 'https://test/endpoint_that_throws_fatal_error'
71
+ );
72
+
73
+ await handleResponse(response);
74
+ });
55
75
 
56
76
  const nockedRequest = nock('https://test')
57
77
  .get('/endpoint_that_throws_fatal_error')
@@ -65,7 +85,6 @@ describe('Test fetchErrorsHandlerPlugin', () => {
65
85
  expect(response.statusCode).toBe(500);
66
86
 
67
87
  expect(response.json()).toEqual({
68
- code: 'ERR_GOT_REQUEST_ERROR',
69
88
  error: 'Internal Server Error',
70
89
  message: 'Unknown fatal error',
71
90
  statusCode: 500,
@@ -75,9 +94,13 @@ describe('Test fetchErrorsHandlerPlugin', () => {
75
94
  });
76
95
 
77
96
  it('Should return correct error when nested fetch request returns string error', async () => {
78
- fastify.get('/test', () =>
79
- got.get('https://test/endpoint_that_returns_error')
80
- );
97
+ fastify.get('/test', async () => {
98
+ const response = await request(
99
+ 'https://test/endpoint_that_returns_error'
100
+ );
101
+
102
+ await handleResponse(response, true);
103
+ });
81
104
 
82
105
  const nockedRequest = nock('https://test')
83
106
  .get('/endpoint_that_returns_error')
@@ -401,9 +401,7 @@ describe('linkedin-controller', () => {
401
401
  });
402
402
 
403
403
  expect(response.statusCode).toBe(400);
404
- expect(JSON.parse(response.payload).error).toBe(
405
- 'Response code 400 (Bad Request)'
406
- );
404
+ expect(JSON.parse(response.payload).error).toBe('Response Error');
407
405
  });
408
406
  });
409
407
  });