@foxtware/mineral 0.1.8 → 0.1.10

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 (186) hide show
  1. package/.creds.yml.sample +43 -1
  2. package/AGENTS.md +6 -1
  3. package/README.md +1 -1
  4. package/api/bleckmann/.gitkeep +0 -0
  5. package/api/bleckmann/bleckmann.constants.js +8 -0
  6. package/api/bleckmann/bleckmann.utils.js +32 -0
  7. package/api/bleckmann/bleckmannAsnGet.js +52 -0
  8. package/api/bleckmann/bleckmannAsnsGet.js +65 -0
  9. package/api/constants.js +2 -1
  10. package/api/github/github.constants.js +11 -0
  11. package/api/github/github.utils.js +65 -0
  12. package/api/github/githubGet.js +144 -0
  13. package/api/github/githubIssueCreate.js +71 -0
  14. package/api/github/githubIssueGet.js +65 -0
  15. package/api/github/githubIssueUpdate.js +71 -0
  16. package/api/github/githubIssuesGet.js +74 -0
  17. package/api/github/githubPullRequestCreate.js +74 -0
  18. package/api/github/githubPullRequestGet.js +65 -0
  19. package/api/github/githubPullRequestMerge.js +77 -0
  20. package/api/github/githubPullRequestUpdate.js +72 -0
  21. package/api/github/githubPullRequestsGet.js +74 -0
  22. package/api/github/githubRepoCreate.js +80 -0
  23. package/api/github/githubRepoDelete.js +60 -0
  24. package/api/github/githubRepoGet.js +61 -0
  25. package/api/github/githubRepoUpdate.js +68 -0
  26. package/api/github/githubReposGet.js +69 -0
  27. package/api/github/githubUserGet.js +64 -0
  28. package/api/linear/linear.utils.js +9 -14
  29. package/api/linear/linearIssuesGet.js +9 -9
  30. package/api/logiwa/logiwa.utils.js +27 -25
  31. package/api/logiwa/logiwaInventoriesGet.js +5 -3
  32. package/api/logiwa/logiwaOrderGet.js +4 -2
  33. package/api/logiwa/logiwaOrdersGet.js +5 -3
  34. package/api/logiwa/logiwaProductGet.js +4 -2
  35. package/api/logiwa/logiwaProductsGet.js +5 -3
  36. package/api/logiwa/logiwaReportGetAvailableToPromise.js +5 -3
  37. package/api/logiwa/logiwaReportGetInventoryCalculation.js +5 -3
  38. package/api/logiwa/logiwaReportGetInventorySnapshot.js +5 -3
  39. package/api/logiwa/logiwaReportGetTotalInventory.js +5 -3
  40. package/api/logiwa/logiwaWebhookStatusGet.js +4 -2
  41. package/api/logiwa/logiwaWebhookSubscribe.js +8 -6
  42. package/api/logiwa/logiwaWebhookUnsubscribe.js +4 -2
  43. package/api/logiwa/logiwaWebhooksGet.js +4 -2
  44. package/api/loop/loop.constants.js +7 -0
  45. package/api/loop/loop.utils.js +37 -0
  46. package/api/loop/loopAllowlistItemsGet.js +42 -0
  47. package/api/loop/loopBlocklistItemsGet.js +46 -0
  48. package/api/loop/loopDestinationsGet.js +42 -0
  49. package/api/loop/loopGet.js +139 -0
  50. package/api/loop/loopReturnGet.js +73 -0
  51. package/api/loop/loopReturnsGet.js +46 -0
  52. package/api/peoplevox/peoplevox.constants.js +1 -1
  53. package/api/peoplevox/peoplevox.sessions.js +54 -0
  54. package/api/peoplevox/peoplevox.utils.js +67 -31
  55. package/api/peoplevox/peoplevoxGetSingle.js +7 -5
  56. package/api/peoplevox/peoplevoxOrderEdit.js +7 -5
  57. package/api/peoplevox/peoplevoxReportGet.js +11 -9
  58. package/api/pipelineSteps.js +49 -0
  59. package/api/shopify/shopify.utils.js +18 -24
  60. package/api/shopify/shopifyBulkMutationDo.js +211 -0
  61. package/api/shopify/shopifyBulkOperationGet.js +86 -0
  62. package/api/shopify/shopifyBulkOperationRunMutation.js +83 -0
  63. package/api/shopify/shopifyCheckoutAndAccountsConfigurationUpdate.js +79 -0
  64. package/api/shopify/shopifyCollectionGet.js +7 -7
  65. package/api/shopify/shopifyCustomerGet.js +6 -6
  66. package/api/shopify/shopifyGet.js +18 -13
  67. package/api/shopify/shopifyGetSingle.js +9 -9
  68. package/api/shopify/shopifyMutationDo.js +6 -6
  69. package/api/shopify/shopifyOrdersGet.js +11 -11
  70. package/api/shopify/shopifyStagedUploadCreate.js +96 -0
  71. package/api/shopify/shopifyTagsAdd.js +1 -1
  72. package/api/shopify/shopifyTagsAddBulk.js +90 -0
  73. package/api/shopify/shopifyTagsRemove.js +1 -1
  74. package/api/slack/slack.utils.js +10 -19
  75. package/api/slack/slackMessagePost.js +11 -11
  76. package/api/starshipit/starshipit.constants.js +8 -0
  77. package/api/starshipit/starshipit.utils.js +71 -0
  78. package/api/starshipit/starshipitAddressCreate.js +77 -0
  79. package/api/starshipit/starshipitAddressDelete.js +55 -0
  80. package/api/starshipit/starshipitAddressUpdate.js +69 -0
  81. package/api/starshipit/starshipitAddressesGet.js +52 -0
  82. package/api/starshipit/starshipitGet.js +146 -0
  83. package/api/starshipit/starshipitOrderDelete.js +102 -0
  84. package/api/starshipit/starshipitOrderGet.js +74 -0
  85. package/api/starshipit/starshipitOrderUpdate.js +109 -0
  86. package/api/starshipit/starshipitOrdersListShipped.js +64 -0
  87. package/api/starshipit/starshipitProductAdd.js +100 -0
  88. package/api/starshipit/starshipitProductsDelete.js +57 -0
  89. package/api/starshipit/starshipitProductsGet.js +49 -0
  90. package/api/starshipit/starshipitTrackingGet.js +69 -0
  91. package/api/stripe/_example.js +48 -0
  92. package/api/stripe/stripe.constants.js +5 -0
  93. package/api/stripe/stripe.utils.js +42 -0
  94. package/api/stripe/stripeCardCharge.js +98 -0
  95. package/api/stripe/stripeCardTokenCreate.js +70 -0
  96. package/api/stripe/stripeChargeCapture.js +63 -0
  97. package/api/stripe/stripeChargeCreate.js +70 -0
  98. package/api/stripe/stripeChargeGet.js +51 -0
  99. package/api/stripe/stripeChargesGet.js +52 -0
  100. package/api/stripe/stripeRefundCreate.js +64 -0
  101. package/api/stripe/stripeRefundGet.js +51 -0
  102. package/api/stripe/stripeRefundsGet.js +52 -0
  103. package/api/stripe/stripeTokenGet.js +51 -0
  104. package/api/stylearcade/stylearcade.constants.js +5 -0
  105. package/api/stylearcade/stylearcade.utils.js +40 -0
  106. package/api/stylearcade/stylearcadeDataGet.js +62 -0
  107. package/api/stylearcade/stylearcadeGet.js +133 -0
  108. package/api/stylearcade/stylearcadeMetadataGet.js +47 -0
  109. package/api/supabase/supabase.utils.js +52 -0
  110. package/api/supabase/supabaseRowDelete.js +95 -0
  111. package/api/supabase/supabaseRowGet.js +58 -0
  112. package/api/supabase/supabaseRowInsert.js +56 -0
  113. package/api/supabase/supabaseRowUpdate.js +58 -0
  114. package/api/supabase/supabaseRpc.js +61 -0
  115. package/api/supabase/supabaseTableGet.js +44 -0
  116. package/api/supabase/supabaseTableGetAll.js +86 -0
  117. package/api/threeclicks/threeclicks.constants.js +8 -0
  118. package/api/threeclicks/threeclicks.utils.js +119 -0
  119. package/api/threeclicks/threeclicksCollectionsGet.js +40 -0
  120. package/api/threeclicks/threeclicksGet.js +138 -0
  121. package/api/threeclicks/threeclicksKeycodeCreate.js +55 -0
  122. package/api/threeclicks/threeclicksKeycodeGet.js +47 -0
  123. package/api/threeclicks/threeclicksPurchaseOrderCreate.js +34 -0
  124. package/api/threeclicks/threeclicksPurchaseOrderCreateBulk.js +34 -0
  125. package/api/threeclicks/threeclicksPurchaseOrderGet.js +33 -0
  126. package/api/threeclicks/threeclicksPurchaseOrderQuantitiesGet.js +33 -0
  127. package/api/threeclicks/threeclicksPurchaseOrderQuantityCreate.js +34 -0
  128. package/api/threeclicks/threeclicksPurchaseOrderQuantityCreateBulk.js +34 -0
  129. package/api/threeclicks/threeclicksPurchaseOrderQuantityUpdate.js +46 -0
  130. package/api/threeclicks/threeclicksPurchaseOrderQuantityUpdateBulk.js +46 -0
  131. package/api/threeclicks/threeclicksPurchaseOrderUpdate.js +35 -0
  132. package/api/threeclicks/threeclicksPurchaseOrdersGet.js +30 -0
  133. package/api/threeclicks/threeclicksShipmentCreate.js +34 -0
  134. package/api/threeclicks/threeclicksShipmentGet.js +33 -0
  135. package/api/threeclicks/threeclicksShipmentOrderAdd.js +38 -0
  136. package/api/threeclicks/threeclicksShipmentOrderQuantityCreate.js +35 -0
  137. package/api/threeclicks/threeclicksShipmentQuantityUpdate.js +35 -0
  138. package/api/threeclicks/threeclicksShipmentStatusUpdate.js +45 -0
  139. package/api/threeclicks/threeclicksShipmentsGet.js +52 -0
  140. package/api/threeclicks/threeclicksSignatureCalculate.js +73 -0
  141. package/api/threeclicks/threeclicksStyleCodesGet.js +46 -0
  142. package/api/threeclicks/threeclicksStyleColourCreate.js +47 -0
  143. package/api/threeclicks/threeclicksStyleColourDelete.js +34 -0
  144. package/api/threeclicks/threeclicksStyleCreate.js +44 -0
  145. package/api/threeclicks/threeclicksStyleDelete.js +33 -0
  146. package/api/threeclicks/threeclicksStyleGet.js +43 -0
  147. package/api/threeclicks/threeclicksStylePriceUpdate.js +70 -0
  148. package/api/threeclicks/threeclicksStyleUpdate.js +47 -0
  149. package/api/threeclicks/threeclicksStylesGet.js +45 -0
  150. package/api/upstash/upstash.utils.js +36 -0
  151. package/api/upstash/upstashDel.js +46 -0
  152. package/api/upstash/upstashExists.js +46 -0
  153. package/api/upstash/upstashGet.js +46 -0
  154. package/api/upstash/upstashSet.js +64 -0
  155. package/api/utils.js +90 -76
  156. package/api/validators.js +1 -1
  157. package/api/workable/workable.constants.js +3 -0
  158. package/api/workable/workable.utils.js +41 -0
  159. package/api/workable/workableGet.js +151 -0
  160. package/api/workable/workableJobCandidateCreate.js +87 -0
  161. package/api/workable/workableJobGet.js +52 -0
  162. package/api/workable/workableJobMembersGet.js +52 -0
  163. package/api/workable/workableJobStagesGet.js +52 -0
  164. package/api/workable/workableJobsGet.js +78 -0
  165. package/api/yotpo/yotpo.utils.js +17 -22
  166. package/api/yotpo/yotpoCampaignsGet.js +6 -6
  167. package/api/yotpo/yotpoCustomerActionRecord.js +7 -7
  168. package/api/yotpo/yotpoCustomerAnniversaryGet.js +7 -7
  169. package/api/yotpo/yotpoCustomerAnniversarySet.js +7 -7
  170. package/api/yotpo/yotpoCustomerBirthdaySet.js +7 -7
  171. package/api/yotpo/yotpoCustomerGet.js +6 -6
  172. package/api/yotpo/yotpoCustomerPointsAdjust.js +7 -7
  173. package/api/yotpo/yotpoCustomerUpsert.js +7 -7
  174. package/api/yotpo/yotpoCustomersRecentGet.js +6 -6
  175. package/api/yotpo/yotpoRedemptionCreate.js +7 -7
  176. package/api/yotpo/yotpoRedemptionOptionsGet.js +6 -6
  177. package/api/yotpo/yotpoVipTiersGet.js +5 -5
  178. package/api/youtube/youtube.constants.js +5 -0
  179. package/api/youtube/youtube.utils.js +77 -0
  180. package/api/youtube/youtubeChannelVideosGet.js +25 -70
  181. package/hosting/.hosting.yml.sample +9 -11
  182. package/hosting/copyCredsToEnv.js +58 -2
  183. package/hosting/deployFromHostingYml.js +9 -2
  184. package/hosting/hosting.utils.js +3 -2
  185. package/package.json +3 -1
  186. package/server.utils.js +1 -0
@@ -0,0 +1,42 @@
1
+ const { ArgsWarden } = require('../utils');
2
+ const { credsValidator } = require('../validators');
3
+ const { loopGet } = require('../loop/loopGet');
4
+
5
+ const argsWarden = new ArgsWarden([
6
+ ['credsPayload', credsValidator],
7
+ ]);
8
+
9
+ const loopDestinationsGet = async (
10
+ credsPayload,
11
+ {
12
+ ...getterOptions
13
+ } = {},
14
+ ) => {
15
+
16
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload });
17
+ if (rejectResponse) {
18
+ return rejectResponse;
19
+ }
20
+
21
+ return loopGet(credsPayload, '/destinations', {
22
+ resultsKey: 'destinations',
23
+ ...getterOptions,
24
+ });
25
+ };
26
+
27
+ const funcApiConfig = {
28
+ argsWarden,
29
+ };
30
+
31
+ module.exports = {
32
+ loopDestinationsGet,
33
+ funcApiConfig,
34
+ };
35
+
36
+ /*
37
+ curl -X POST "http://localhost:8000/loopDestinationsGet" \
38
+ -H "Content-Type: application/json" \
39
+ -d '{
40
+ "credsPayload": { "credsPath": "loop.au" }
41
+ }'
42
+ */
@@ -0,0 +1,139 @@
1
+ const { ArgsWarden, Getter } = require('../utils');
2
+ const { credsValidator } = require('../validators');
3
+ const { loopClient } = require('../loop/loop.utils');
4
+ const { MAX_PER_PAGE } = require('../loop/loop.constants');
5
+
6
+ const argsWarden = new ArgsWarden([
7
+ ['credsPayload', credsValidator],
8
+ ['url'],
9
+ ]);
10
+
11
+ const loopGetPacket = async (
12
+ credsPayload,
13
+ url,
14
+ {
15
+ params,
16
+ perPage = MAX_PER_PAGE,
17
+ paginate = true,
18
+ } = {},
19
+ ) => {
20
+ return loopClient.fetch({
21
+ requestPayload: {
22
+ url,
23
+ ...(paginate && {
24
+ params: {
25
+ paginate: true,
26
+ pageSize: perPage,
27
+ ...params,
28
+ },
29
+ }),
30
+ },
31
+ context: {
32
+ credsPayload,
33
+ },
34
+ });
35
+ };
36
+
37
+ const loopGetPaginator = async (currentParams, response) => {
38
+ const { args } = currentParams;
39
+
40
+ if (!response?.ok) {
41
+ return [true];
42
+ }
43
+
44
+ const nextPageUrl = response?.data?.nextPageUrl;
45
+ if (!nextPageUrl) {
46
+ return [true];
47
+ }
48
+
49
+ const [credsPayload] = args;
50
+
51
+ return [false, {
52
+ args: [credsPayload, nextPageUrl],
53
+ options: {
54
+ paginate: false,
55
+ },
56
+ }];
57
+ };
58
+
59
+ const loopGet = async (
60
+ returnGetter,
61
+
62
+ credsPayload,
63
+ url,
64
+ {
65
+ params,
66
+ perPage = MAX_PER_PAGE,
67
+ resultsKey,
68
+ ...getterOptions
69
+ } = {},
70
+ ) => {
71
+
72
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
73
+ credsPayload,
74
+ url,
75
+ });
76
+ if (rejectResponse) {
77
+ return rejectResponse;
78
+ }
79
+
80
+ const getter = new Getter(
81
+ {
82
+ args: [credsPayload, url],
83
+ options: {
84
+ params,
85
+ perPage,
86
+ },
87
+ },
88
+ {
89
+ func: loopGetPacket,
90
+ digester: (response) => {
91
+ if (!response?.ok) {
92
+ return [];
93
+ }
94
+
95
+ if (resultsKey) {
96
+ return response?.data?.[resultsKey] ?? [];
97
+ }
98
+
99
+ return [];
100
+ },
101
+ paginator: loopGetPaginator,
102
+ ...getterOptions,
103
+ },
104
+ );
105
+
106
+ if (returnGetter) {
107
+ return getter;
108
+ }
109
+
110
+ const data = await getter.run({ returnAll: true });
111
+
112
+ return {
113
+ ok: true,
114
+ data,
115
+ };
116
+ };
117
+
118
+ const funcApiConfig = {
119
+ argsWarden,
120
+ };
121
+
122
+ module.exports = {
123
+ loopGet: (...args) => loopGet(false, ...args),
124
+ loopGetter: (...args) => loopGet(true, ...args),
125
+ funcApiConfig,
126
+ };
127
+
128
+ /*
129
+ curl -X POST "http://localhost:8000/loopGet" \
130
+ -H "Content-Type: application/json" \
131
+ -d '{
132
+ "credsPayload": { "credsPath": "loop.au" },
133
+ "url": "/warehouse/return/list",
134
+ "options": {
135
+ "resultsKey": "returns",
136
+ "limit": 10
137
+ }
138
+ }'
139
+ */
@@ -0,0 +1,73 @@
1
+ // https://docs.loopreturns.com/api-reference/latest/return-data/get-return-details
2
+
3
+ const { objHasAny, ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { loopClient } = require('../loop/loop.utils');
6
+
7
+ const returnIdentifierValidator = (returnIdentifier) => {
8
+ return objHasAny(returnIdentifier, [
9
+ 'returnId',
10
+ 'orderId',
11
+ 'orderName',
12
+ ]);
13
+ };
14
+
15
+ const argsWarden = new ArgsWarden([
16
+ ['credsPayload', credsValidator],
17
+ ['returnIdentifier', returnIdentifierValidator],
18
+ ]);
19
+
20
+ const loopReturnGet = async (
21
+ credsPayload,
22
+ returnIdentifier,
23
+ options = {},
24
+ ) => {
25
+
26
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
27
+ credsPayload,
28
+ returnIdentifier,
29
+ });
30
+ if (rejectResponse) {
31
+ return rejectResponse;
32
+ }
33
+
34
+ const {
35
+ returnId,
36
+ orderId,
37
+ orderName,
38
+ } = returnIdentifier;
39
+
40
+ const params = {
41
+ ...returnId && { return_id: returnId },
42
+ ...orderId && { order_id: orderId },
43
+ ...orderName && { order_name: orderName },
44
+ };
45
+
46
+ return loopClient.fetch({
47
+ requestPayload: {
48
+ url: '/warehouse/return/details',
49
+ params,
50
+ },
51
+ context: {
52
+ credsPayload,
53
+ },
54
+ });
55
+ };
56
+
57
+ const funcApiConfig = {
58
+ argsWarden,
59
+ };
60
+
61
+ module.exports = {
62
+ loopReturnGet,
63
+ funcApiConfig,
64
+ };
65
+
66
+ /*
67
+ curl -X POST "http://localhost:8000/loopReturnGet" \
68
+ -H "Content-Type: application/json" \
69
+ -d '{
70
+ "credsPayload": { "credsPath": "loop.au" },
71
+ "returnIdentifier": { "returnId": "85747906" }
72
+ }'
73
+ */
@@ -0,0 +1,46 @@
1
+ const { ArgsWarden } = require('../utils');
2
+ const { credsValidator } = require('../validators');
3
+ const { loopGet } = require('../loop/loopGet');
4
+
5
+ const argsWarden = new ArgsWarden([
6
+ ['credsPayload', credsValidator],
7
+ ]);
8
+
9
+ const loopReturnsGet = async (
10
+ credsPayload,
11
+ {
12
+ ...getterOptions
13
+ } = {},
14
+ ) => {
15
+
16
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload });
17
+ if (rejectResponse) {
18
+ return rejectResponse;
19
+ }
20
+
21
+ return loopGet(credsPayload, '/warehouse/return/list', {
22
+ resultsKey: 'returns',
23
+ ...getterOptions,
24
+ });
25
+ };
26
+
27
+ const funcApiConfig = {
28
+ argsWarden,
29
+ };
30
+
31
+ module.exports = {
32
+ loopReturnsGet,
33
+ funcApiConfig,
34
+ };
35
+
36
+ /*
37
+ curl -X POST "http://localhost:8000/loopReturnsGet" \
38
+ -H "Content-Type: application/json" \
39
+ -d '{
40
+ "credsPayload": { "credsPath": "loop.au" },
41
+ "options": {
42
+ "limit": 20,
43
+ "perPage": 7
44
+ }
45
+ }'
46
+ */
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
2
  MAX_REQUEST_ITEMS: 100,
3
- };
3
+ };
@@ -0,0 +1,54 @@
1
+ const { HOSTED } = require('../constants');
2
+ const { credsFromPayload } = require('../utils');
3
+ const { peoplevoxAuthGet } = require('./peoplevoxAuthGet');
4
+
5
+ // TODO: Track where auth comes from in order to facilitate retrying
6
+ // TODO: Consider only storing auth when successful request goes through
7
+
8
+ const SESSION_IDS = new Map();
9
+
10
+ const getSessionId = async (credsPayload) => {
11
+ const { CLIENT_ID } = await credsFromPayload(credsPayload);
12
+
13
+ let sessionId = SESSION_IDS.get(CLIENT_ID);
14
+
15
+ if (sessionId) {
16
+ !HOSTED && console.log('Peoplevox auth: from memory');
17
+ return {
18
+ ok: true,
19
+ data: sessionId,
20
+ meta: {
21
+ source: 'memory',
22
+ },
23
+ };
24
+ }
25
+
26
+ const authResponse = await peoplevoxAuthGet(credsPayload);
27
+
28
+ if (!authResponse.ok) {
29
+ return authResponse;
30
+ }
31
+
32
+ const { Detail } = authResponse?.data?.['soap:Envelope']?.['soap:Body']?.['AuthenticateResponse']?.['AuthenticateResult'];
33
+ const [, responseSessionId] = Detail.split(',');
34
+
35
+ SESSION_IDS.set(CLIENT_ID, responseSessionId);
36
+ !HOSTED && console.log('Peoplevox auth: from API');
37
+ return {
38
+ ok: true,
39
+ data: responseSessionId,
40
+ meta: {
41
+ source: 'api',
42
+ },
43
+ };
44
+ };
45
+
46
+ const setSessionId = async (credsPayload, sessionId) => {
47
+ const { CLIENT_ID } = await credsFromPayload(credsPayload);
48
+ SESSION_IDS.set(CLIENT_ID, sessionId);
49
+ };
50
+
51
+ module.exports = {
52
+ getSessionId,
53
+ setSessionId,
54
+ };
@@ -1,7 +1,12 @@
1
1
  const csvtojson = require('csvtojson');
2
2
  const xml2js = require('xml2js');
3
- const { FetchClient, credsFromPayload, appendUrlToBase, logDeep, Chain } = require('../utils');
4
- const { peoplevoxAuthGet } = require('../peoplevox/peoplevoxAuthGet');
3
+ const { resolveCreds } = require('../pipelineSteps');
4
+ const {
5
+ FetchClient,
6
+ appendUrlToBase,
7
+ logDeep,
8
+ } = require('../utils');
9
+ const { getSessionId, setSessionId } = require('../peoplevox/peoplevox.sessions');
5
10
 
6
11
  const xml2jsBuilder = new xml2js.Builder({
7
12
  headless: true,
@@ -45,46 +50,38 @@ const buildSoapEnvelope = ({
45
50
  return xml2jsBuilder.buildObject(envelopeObject);
46
51
  };
47
52
 
48
- // TODO: Split into multiple steps, allow mutating context
49
- const peoplevoxRequestPreparer = async (requestPayload, context) => {
50
- const { headers, body } = requestPayload;
51
- const { credsPayload, action } = context;
52
- let { sessionId: localSessionId } = context;
53
- const { CLIENT_ID } = await credsFromPayload(credsPayload);
54
-
55
- if (!localSessionId) {
56
- const authResponse = await peoplevoxAuthGet(credsPayload);
57
-
58
- if (!authResponse.ok) {
59
- return { ...authResponse, breakChain: true };
60
- }
61
-
62
- const { Detail } = authResponse?.data?.['soap:Envelope']?.['soap:Body']?.['AuthenticateResponse']?.['AuthenticateResult'];
63
- const [, responseSessionId] = Detail.split(',');
53
+ const useSoapEnvelope = async (state) => {
54
+ const { requestPayload, context } = state;
55
+ const { creds, action, sessionId } = context;
56
+ const { CLIENT_ID } = creds;
64
57
 
65
- localSessionId = responseSessionId;
58
+ if (!sessionId) {
59
+ throw new Error('PeopleVox sessionId is required');
66
60
  }
67
61
 
68
62
  const baseUrl = `https://ap.peoplevox.net/${ CLIENT_ID }/Resources/IntegrationServicev4.asmx`;
63
+ const { headers, body } = requestPayload;
69
64
 
70
65
  const envelopeXml = buildSoapEnvelope({
71
66
  action,
72
67
  body,
73
68
  clientId: CLIENT_ID,
74
- sessionId: localSessionId,
69
+ sessionId,
75
70
  });
76
71
 
77
72
  logDeep({ envelopeXml });
78
73
 
79
74
  return {
80
- ...requestPayload,
81
- url: appendUrlToBase(baseUrl, requestPayload.url),
82
- headers: {
83
- ...headers,
84
- 'Content-Type': 'text/xml; charset=utf-8',
85
- 'SOAPAction': `http://www.peoplevox.net/${ action }`,
75
+ requestPayload: {
76
+ ...requestPayload,
77
+ url: appendUrlToBase(baseUrl, requestPayload.url),
78
+ headers: {
79
+ ...headers,
80
+ 'Content-Type': 'text/xml; charset=utf-8',
81
+ 'SOAPAction': `http://www.peoplevox.net/${ action }`,
82
+ },
83
+ body: envelopeXml,
86
84
  },
87
- body: envelopeXml,
88
85
  };
89
86
  };
90
87
 
@@ -177,15 +174,54 @@ const hoistDetail = (state) => {
177
174
  };
178
175
 
179
176
  const peoplevoxClient = new FetchClient({
180
- requestPreparer: peoplevoxRequestPreparer,
181
- responseInterpreter: new Chain([
177
+ pipeline: [
178
+ resolveCreds,
179
+ useSoapEnvelope,
180
+ 'fetch',
182
181
  stripEnvelope,
183
182
  tryToParseDetailAsCsv,
184
183
  unwrapSingleDetail,
185
184
  hoistDetail,
186
- ]),
185
+ ],
187
186
  });
188
187
 
188
+ const fetchWithoutAuth = peoplevoxClient.fetch.bind(peoplevoxClient);
189
+
190
+ peoplevoxClient.fetch = async ({
191
+ requestPayload,
192
+ context = {},
193
+ inspect = false,
194
+ }) => {
195
+ const { credsPayload } = context;
196
+
197
+ const sessionIdResponse = await getSessionId(credsPayload);
198
+
199
+ const {
200
+ ok: sessionIdOk,
201
+ data: sessionId,
202
+ } = sessionIdResponse;
203
+
204
+ if (!sessionIdOk) {
205
+ return sessionIdResponse;
206
+ }
207
+
208
+ const response = await fetchWithoutAuth({
209
+ requestPayload,
210
+ context: {
211
+ ...context,
212
+ sessionId,
213
+ },
214
+ inspect,
215
+ });
216
+
217
+ if (response.ok) {
218
+ await setSessionId(credsPayload, sessionId);
219
+ }
220
+
221
+ // TODO: Check if it was an auth error, and try another auth method if so
222
+ return response;
223
+ };
224
+
189
225
  module.exports = {
190
226
  peoplevoxClient,
191
- };
227
+ };
@@ -32,11 +32,13 @@ const peoplevoxGetSingle = async (
32
32
  const resolvedSearchClause = searchClause || `${ idName }.Equals("${ id }")`;
33
33
 
34
34
  const response = await peoplevoxClient.fetch({
35
- method: 'post',
36
- body: {
37
- getRequest: {
38
- TemplateName: templateName,
39
- SearchClause: resolvedSearchClause,
35
+ requestPayload: {
36
+ method: 'post',
37
+ body: {
38
+ getRequest: {
39
+ TemplateName: templateName,
40
+ SearchClause: resolvedSearchClause,
41
+ },
40
42
  },
41
43
  },
42
44
  context: {
@@ -37,11 +37,13 @@ const peoplevoxOrderEdit = async (
37
37
  }
38
38
 
39
39
  return peoplevoxClient.fetch({
40
- method: 'post',
41
- body: {
42
- saveRequest: {
43
- TemplateName: 'Sales orders',
44
- CsvData: csvData,
40
+ requestPayload: {
41
+ method: 'post',
42
+ body: {
43
+ saveRequest: {
44
+ TemplateName: 'Sales orders',
45
+ CsvData: csvData,
46
+ },
45
47
  },
46
48
  },
47
49
  context: {
@@ -25,15 +25,17 @@ const peoplevoxReportGet = async (
25
25
  }
26
26
 
27
27
  const reportGetResponse = await peoplevoxClient.fetch({
28
- method: 'post',
29
- body: {
30
- getReportRequest: {
31
- TemplateName: reportName,
32
- ...(searchClause ? { SearchClause: searchClause } : {}),
33
- ...(perPage ? { ItemsPerPage: perPage } : {}),
34
- ...(filter ? { FilterClause: filter } : {}),
35
- ...(orderBy ? { OrderBy: orderBy } : {}),
36
- ...(columns ? { Columns: columns.join(',') } : {}),
28
+ requestPayload: {
29
+ method: 'post',
30
+ body: {
31
+ getReportRequest: {
32
+ TemplateName: reportName,
33
+ ...(searchClause ? { SearchClause: searchClause } : {}),
34
+ ...(perPage ? { ItemsPerPage: perPage } : {}),
35
+ ...(filter ? { FilterClause: filter } : {}),
36
+ ...(orderBy ? { OrderBy: orderBy } : {}),
37
+ ...(columns ? { Columns: columns.join(',') } : {}),
38
+ },
37
39
  },
38
40
  },
39
41
  context: {
@@ -0,0 +1,49 @@
1
+ const { appendUrlToBase, credsFromPayload } = require('./utils');
2
+
3
+ const resolveCreds = async (state) => {
4
+ const { context } = state;
5
+ const { creds, credsPayload } = context;
6
+
7
+ if (creds || !credsPayload) {
8
+ return {};
9
+ }
10
+
11
+ const resolvedCreds = await credsFromPayload(credsPayload);
12
+
13
+ return {
14
+ context: {
15
+ ...context,
16
+ creds: resolvedCreds,
17
+ },
18
+ };
19
+ };
20
+
21
+ const useBaseUrl = (baseUrl) => async (state) => {
22
+ const { requestPayload, context } = state;
23
+ const resolvedBaseUrl = baseUrl ?? context.baseUrl;
24
+
25
+ if (!resolvedBaseUrl) {
26
+ return {
27
+ breakChain: true,
28
+ response: {
29
+ ok: false,
30
+ error: {
31
+ code: 'NO_BASE_URL',
32
+ message: 'No base URL provided',
33
+ },
34
+ },
35
+ };
36
+ }
37
+
38
+ return {
39
+ requestPayload: {
40
+ ...requestPayload,
41
+ url: appendUrlToBase(resolvedBaseUrl, requestPayload.url),
42
+ },
43
+ };
44
+ };
45
+
46
+ module.exports = {
47
+ resolveCreds,
48
+ useBaseUrl,
49
+ };
@@ -1,7 +1,7 @@
1
1
  const { DEFAULT_API_VERSION } = require('../shopify/shopify.constants');
2
+ const { resolveCreds } = require('../pipelineSteps');
2
3
  const {
3
4
  FetchClient,
4
- Chain,
5
5
  appendUrlToBase,
6
6
  fetchClientCommonSteps,
7
7
  pathAsArray,
@@ -49,11 +49,11 @@ const handleMutationUserErrors = async (state) => {
49
49
  };
50
50
  };
51
51
 
52
- const addUrlAndAuthHeaders = async (state) => {
52
+ const useUrlAndAuthHeaders = async (state) => {
53
53
  const { requestPayload, context } = state;
54
54
  const {
55
- creds,
56
55
  apiVersion = DEFAULT_API_VERSION,
56
+ creds,
57
57
  } = context;
58
58
  const {
59
59
  STORE_HANDLE,
@@ -61,15 +61,13 @@ const addUrlAndAuthHeaders = async (state) => {
61
61
  } = creds;
62
62
 
63
63
  const baseUrl = `https://${ STORE_HANDLE }.myshopify.com/admin/api/${ apiVersion }/graphql.json`;
64
- const baseHeaders = {
65
- 'X-Shopify-Access-Token': API_KEY,
66
- };
67
64
 
68
65
  return {
69
66
  requestPayload: {
67
+ ...requestPayload,
70
68
  url: appendUrlToBase(baseUrl, requestPayload.url),
71
69
  headers: {
72
- ...baseHeaders,
70
+ 'X-Shopify-Access-Token': API_KEY,
73
71
  ...requestPayload.headers,
74
72
  },
75
73
  },
@@ -99,25 +97,21 @@ const movePageInfoToMeta = async (state) => {
99
97
  };
100
98
  };
101
99
 
102
- const shopifyClientRequestPreparer = new Chain([
103
- addUrlAndAuthHeaders,
104
- ]);
105
-
106
- const shopifyClientResponseInterpreter = new Chain([
107
- movePageInfoToMeta,
108
- fetchClientCommonSteps.stripEdgesAndNodes,
109
- fetchClientCommonSteps.collapseDataWithOneValue,
110
- fetchClientCommonSteps.exitEarlyOnNotOk,
111
- fetchClientCommonSteps.exitEarlyOnGraphqlErrors,
112
- fetchClientCommonSteps.digToPath,
113
- handleMutationUserErrors,
114
- ]);
115
-
116
100
  const shopifyClient = new FetchClient({
117
- requestPreparer: shopifyClientRequestPreparer,
118
- responseInterpreter: shopifyClientResponseInterpreter,
101
+ pipeline: [
102
+ resolveCreds,
103
+ useUrlAndAuthHeaders,
104
+ 'fetch',
105
+ movePageInfoToMeta,
106
+ fetchClientCommonSteps.stripEdgesAndNodes,
107
+ fetchClientCommonSteps.collapseDataWithOneValue,
108
+ fetchClientCommonSteps.exitEarlyOnNotOk,
109
+ fetchClientCommonSteps.exitEarlyOnGraphqlErrors,
110
+ fetchClientCommonSteps.digToPath,
111
+ handleMutationUserErrors,
112
+ ],
119
113
  });
120
114
 
121
115
  module.exports = {
122
116
  shopifyClient,
123
- };
117
+ };