@foxtware/mineral 0.1.0
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/.creds.yml.sample +21 -0
- package/AGENTS.md +13 -0
- package/README.md +52 -0
- package/_build_scripts/copyCredsToEnv.js +45 -0
- package/_build_scripts/createNewFunction.js +361 -0
- package/_docs/standard_response_examples.md +67 -0
- package/api/_example.js +45 -0
- package/api/constants.js +3 -0
- package/api/linear/linear.constants.js +5 -0
- package/api/linear/linear.utils.js +43 -0
- package/api/linear/linearIssuesGet.js +106 -0
- package/api/peoplevox/.gitkeep +0 -0
- package/api/peoplevox/_example.js +49 -0
- package/api/peoplevox/peoplevox.constants.js +3 -0
- package/api/peoplevox/peoplevox.utils.js +191 -0
- package/api/peoplevox/peoplevoxAuthGet.js +99 -0
- package/api/peoplevox/peoplevoxGetSingle.js +119 -0
- package/api/peoplevox/peoplevoxOrderEdit.js +82 -0
- package/api/peoplevox/peoplevoxOrderGet.js +60 -0
- package/api/peoplevox/peoplevoxReportGet.js +76 -0
- package/api/shopify/.gitkeep +0 -0
- package/api/shopify/_example.create.js +69 -0
- package/api/shopify/_example.getsingle.js +55 -0
- package/api/shopify/_example.js +45 -0
- package/api/shopify/_example.mutation.js +58 -0
- package/api/shopify/shopify.constants.js +7 -0
- package/api/shopify/shopify.utils.js +123 -0
- package/api/shopify/shopifyCollectionGet.js +109 -0
- package/api/shopify/shopifyCustomerCreate.js +71 -0
- package/api/shopify/shopifyCustomerGet.js +112 -0
- package/api/shopify/shopifyCustomerMarketingConsentUpdateEmail.js +84 -0
- package/api/shopify/shopifyCustomerUpdate.js +75 -0
- package/api/shopify/shopifyCustomersGet.js +50 -0
- package/api/shopify/shopifyGet.js +309 -0
- package/api/shopify/shopifyGetSingle.js +106 -0
- package/api/shopify/shopifyGiftCardCreate.js +95 -0
- package/api/shopify/shopifyGiftCardDeactivate.js +58 -0
- package/api/shopify/shopifyMetafieldsSet.js +100 -0
- package/api/shopify/shopifyMutationDo.js +95 -0
- package/api/shopify/shopifyOrderGet.js +123 -0
- package/api/shopify/shopifyOrdersGet.js +80 -0
- package/api/shopify/shopifyPageDelete.js +59 -0
- package/api/shopify/shopifyPageGet.js +57 -0
- package/api/shopify/shopifyPageUpdate.js +79 -0
- package/api/shopify/shopifyTagsAdd.js +94 -0
- package/api/shopify/shopifyTagsRemove.js +94 -0
- package/api/shopify/shopifyThemeDelete.js +87 -0
- package/api/shopify/shopifyThemeDuplicate.js +70 -0
- package/api/shopify/shopifyThemeGet.js +59 -0
- package/api/shopify/shopifyThemeUpdate.js +71 -0
- package/api/shopify/shopifyThemesGet.js +63 -0
- package/api/utils.js +1166 -0
- package/api/validators.js +12 -0
- package/api/yotpo/yotpo.constants.js +7 -0
- package/api/yotpo/yotpo.utils.js +47 -0
- package/api/yotpo/yotpoCampaignsGet.js +75 -0
- package/api/yotpo/yotpoCustomerActionRecord.js +95 -0
- package/api/yotpo/yotpoCustomerAnniversaryGet.js +60 -0
- package/api/yotpo/yotpoCustomerAnniversarySet.js +78 -0
- package/api/yotpo/yotpoCustomerBirthdaySet.js +91 -0
- package/api/yotpo/yotpoCustomerGet.js +104 -0
- package/api/yotpo/yotpoCustomerPointsAdjust.js +89 -0
- package/api/yotpo/yotpoCustomerUpsert.js +91 -0
- package/api/yotpo/yotpoCustomersRecentGet.js +62 -0
- package/api/yotpo/yotpoRedemptionCreate.js +96 -0
- package/api/yotpo/yotpoRedemptionOptionsGet.js +78 -0
- package/api/yotpo/yotpoVipTiersGet.js +51 -0
- package/api/youtube/youtubeChannelVideosGet.js +249 -0
- package/bin/mineral.js +5 -0
- package/package.json +24 -0
- package/server.js +196 -0
- package/server.utils.js +228 -0
- package/test.js +19 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// https://linear.app/developers/graphql
|
|
2
|
+
|
|
3
|
+
const { credsFromPayload, ArgsWarden } = require('../utils');
|
|
4
|
+
const { credsValidator } = require('../validators');
|
|
5
|
+
const { linearClient } = require('../linear/linear.utils');
|
|
6
|
+
|
|
7
|
+
const argsWarden = new ArgsWarden([
|
|
8
|
+
['credsPayload', credsValidator],
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
const linearIssuesGet = async (
|
|
12
|
+
credsPayload,
|
|
13
|
+
{
|
|
14
|
+
first = 50,
|
|
15
|
+
teamId,
|
|
16
|
+
inspect = false,
|
|
17
|
+
} = {},
|
|
18
|
+
) => {
|
|
19
|
+
|
|
20
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({
|
|
21
|
+
credsPayload,
|
|
22
|
+
});
|
|
23
|
+
if (rejectResponse) {
|
|
24
|
+
return rejectResponse;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const creds = await credsFromPayload(credsPayload);
|
|
28
|
+
|
|
29
|
+
const filter = teamId
|
|
30
|
+
? { team: { id: { eq: teamId } } }
|
|
31
|
+
: undefined;
|
|
32
|
+
|
|
33
|
+
const response = await linearClient.fetch({
|
|
34
|
+
body: {
|
|
35
|
+
query: `
|
|
36
|
+
query IssuesGet($first: Int!, $filter: IssueFilter) {
|
|
37
|
+
issues(first: $first, filter: $filter) {
|
|
38
|
+
nodes {
|
|
39
|
+
id
|
|
40
|
+
identifier
|
|
41
|
+
title
|
|
42
|
+
priority
|
|
43
|
+
createdAt
|
|
44
|
+
updatedAt
|
|
45
|
+
state {
|
|
46
|
+
id
|
|
47
|
+
name
|
|
48
|
+
}
|
|
49
|
+
team {
|
|
50
|
+
id
|
|
51
|
+
name
|
|
52
|
+
}
|
|
53
|
+
assignee {
|
|
54
|
+
id
|
|
55
|
+
name
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`,
|
|
61
|
+
variables: {
|
|
62
|
+
first,
|
|
63
|
+
...(filter && { filter }),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
context: { creds },
|
|
67
|
+
inspect,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const issues = response.data?.data?.issues?.nodes ?? [];
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
data: issues,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const funcApiConfig = {
|
|
83
|
+
argsWarden,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
linearIssuesGet,
|
|
88
|
+
funcApiConfig,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
curl -X POST "http://localhost:8000/linearIssuesGet" \
|
|
93
|
+
-H "Content-Type: application/json" \
|
|
94
|
+
-d '{
|
|
95
|
+
"credsPayload": { "credsPath": "linear" }
|
|
96
|
+
}'
|
|
97
|
+
|
|
98
|
+
curl -X POST "http://localhost:8000/linearIssuesGet" \
|
|
99
|
+
-H "Content-Type: application/json" \
|
|
100
|
+
-d '{
|
|
101
|
+
"credsPayload": { "credsPath": "linear" },
|
|
102
|
+
"options": {
|
|
103
|
+
"first": 5
|
|
104
|
+
}
|
|
105
|
+
}'
|
|
106
|
+
*/
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const { credsValidator } = require('../validators');
|
|
2
|
+
const { logDeep, ArgsWarden } = require('../utils');
|
|
3
|
+
const { peoplevoxGetSingle } = require('../peoplevox/peoplevoxGetSingle');
|
|
4
|
+
|
|
5
|
+
const argsWarden = new ArgsWarden([
|
|
6
|
+
['credsPayload', credsValidator],
|
|
7
|
+
['salesOrderNumber'],
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
const FUNC = async (
|
|
11
|
+
credsPayload,
|
|
12
|
+
salesOrderNumber,
|
|
13
|
+
) => {
|
|
14
|
+
|
|
15
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload, salesOrderNumber });
|
|
16
|
+
if (rejectResponse) {
|
|
17
|
+
return rejectResponse;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const response = await peoplevoxGetSingle(
|
|
21
|
+
credsPayload,
|
|
22
|
+
'Sales orders',
|
|
23
|
+
{
|
|
24
|
+
id: salesOrderNumber,
|
|
25
|
+
idName: 'SalesOrderNumber',
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
logDeep('response', response);
|
|
30
|
+
return response;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const funcApiConfig = {
|
|
34
|
+
argsWarden,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
FUNC,
|
|
39
|
+
funcApiConfig,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
curl -X POST "http://localhost:8000/FUNC" \
|
|
44
|
+
-H "Content-Type: application/json" \
|
|
45
|
+
-d '{
|
|
46
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
47
|
+
"salesOrderNumber": "5977690603592"
|
|
48
|
+
}'
|
|
49
|
+
*/
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const csvtojson = require('csvtojson');
|
|
2
|
+
const xml2js = require('xml2js');
|
|
3
|
+
const { FetchClient, credsFromPayload, appendUrlToBase, logDeep, Chain } = require('../utils');
|
|
4
|
+
const { peoplevoxAuthGet } = require('../peoplevox/peoplevoxAuthGet');
|
|
5
|
+
|
|
6
|
+
const xml2jsBuilder = new xml2js.Builder({
|
|
7
|
+
headless: true,
|
|
8
|
+
renderOpts: {
|
|
9
|
+
pretty: false,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const buildSoapEnvelope = ({
|
|
14
|
+
action,
|
|
15
|
+
body,
|
|
16
|
+
clientId,
|
|
17
|
+
sessionId,
|
|
18
|
+
}) => {
|
|
19
|
+
const envelopeObject = {
|
|
20
|
+
'soap:Envelope': {
|
|
21
|
+
'$': {
|
|
22
|
+
'xmlns:soap': 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
23
|
+
},
|
|
24
|
+
'soap:Header': {
|
|
25
|
+
'UserSessionCredentials': {
|
|
26
|
+
'$': {
|
|
27
|
+
'xmlns': 'http://www.peoplevox.net/',
|
|
28
|
+
},
|
|
29
|
+
'UserId': 1,
|
|
30
|
+
'ClientId': clientId,
|
|
31
|
+
'SessionId': sessionId,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
'soap:Body': {
|
|
35
|
+
[action]: {
|
|
36
|
+
'$': {
|
|
37
|
+
'xmlns': 'http://www.peoplevox.net/',
|
|
38
|
+
},
|
|
39
|
+
...body,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return xml2jsBuilder.buildObject(envelopeObject);
|
|
46
|
+
};
|
|
47
|
+
|
|
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(',');
|
|
64
|
+
|
|
65
|
+
localSessionId = responseSessionId;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const baseUrl = `https://ap.peoplevox.net/${ CLIENT_ID }/Resources/IntegrationServicev4.asmx`;
|
|
69
|
+
|
|
70
|
+
const envelopeXml = buildSoapEnvelope({
|
|
71
|
+
action,
|
|
72
|
+
body,
|
|
73
|
+
clientId: CLIENT_ID,
|
|
74
|
+
sessionId: localSessionId,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
logDeep({ envelopeXml });
|
|
78
|
+
|
|
79
|
+
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 }`,
|
|
86
|
+
},
|
|
87
|
+
body: envelopeXml,
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const stripEnvelope = (state) => {
|
|
92
|
+
const { response, context } = state;
|
|
93
|
+
const { action } = context;
|
|
94
|
+
|
|
95
|
+
if (!response?.data) {
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
response: {
|
|
101
|
+
data: response.data?.['soap:Envelope']?.['soap:Body']?.[`${ action }Response`]?.[`${ action }Result`],
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const tryToParseDetailAsCsv = async (state) => {
|
|
107
|
+
const { response } = state;
|
|
108
|
+
|
|
109
|
+
if (!response?.ok || !response?.data?.Detail) {
|
|
110
|
+
return {};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const { Detail } = response.data;
|
|
114
|
+
|
|
115
|
+
if (typeof Detail !== 'string') {
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let parsedDetail = Detail;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const parsed = await csvtojson().fromString(Detail);
|
|
123
|
+
|
|
124
|
+
if (parsed.length || !Detail.trim()) {
|
|
125
|
+
parsedDetail = parsed;
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.warn('error parsing Detail', error, Detail);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
response: {
|
|
133
|
+
data: {
|
|
134
|
+
Detail: parsedDetail,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const unwrapSingleDetail = (state) => {
|
|
141
|
+
const { response } = state;
|
|
142
|
+
|
|
143
|
+
if (!response?.ok || !Array.isArray(response?.data?.Detail)) {
|
|
144
|
+
return {};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const { Detail } = response.data;
|
|
148
|
+
|
|
149
|
+
if (Detail.length !== 1) {
|
|
150
|
+
return {};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
response: {
|
|
155
|
+
data: {
|
|
156
|
+
Detail: Detail[0],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const hoistDetail = (state) => {
|
|
163
|
+
const { response } = state;
|
|
164
|
+
|
|
165
|
+
if (!response?.ok || !response?.data || response.data.Detail === undefined) {
|
|
166
|
+
return {};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const { Detail, ...metaFromData } = response.data;
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
response: {
|
|
173
|
+
data: Detail,
|
|
174
|
+
meta: metaFromData,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const peoplevoxClient = new FetchClient({
|
|
180
|
+
requestPreparer: peoplevoxRequestPreparer,
|
|
181
|
+
responseInterpreter: new Chain([
|
|
182
|
+
stripEnvelope,
|
|
183
|
+
tryToParseDetailAsCsv,
|
|
184
|
+
unwrapSingleDetail,
|
|
185
|
+
hoistDetail,
|
|
186
|
+
]),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
module.exports = {
|
|
190
|
+
peoplevoxClient,
|
|
191
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const { credsFromPayload, customFetch, ArgsWarden } = require('../utils');
|
|
2
|
+
const { credsValidator } = require('../validators');
|
|
3
|
+
|
|
4
|
+
const argsWarden = new ArgsWarden([
|
|
5
|
+
['credsPayload', credsValidator],
|
|
6
|
+
]);
|
|
7
|
+
|
|
8
|
+
const peoplevoxAuthGet = async (
|
|
9
|
+
credsPayload,
|
|
10
|
+
) => {
|
|
11
|
+
|
|
12
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload });
|
|
13
|
+
if (rejectResponse) {
|
|
14
|
+
return rejectResponse;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
CLIENT_ID,
|
|
19
|
+
USERNAME,
|
|
20
|
+
PASSWORD,
|
|
21
|
+
} = await credsFromPayload(credsPayload);
|
|
22
|
+
|
|
23
|
+
const url = `https://ap.peoplevox.net/${ CLIENT_ID }/Resources/IntegrationServicev4.asmx`;
|
|
24
|
+
|
|
25
|
+
const headers = {
|
|
26
|
+
'Content-Type': 'text/xml; charset=utf-8',
|
|
27
|
+
'SOAPAction': 'http://www.peoplevox.net/Authenticate',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const envelope = `
|
|
31
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
|
32
|
+
<soap:Body>
|
|
33
|
+
<Authenticate xmlns="http://www.peoplevox.net/">
|
|
34
|
+
<clientId>${ CLIENT_ID }</clientId>
|
|
35
|
+
<username>${ USERNAME }</username>
|
|
36
|
+
<password>${ btoa(PASSWORD) }</password>
|
|
37
|
+
</Authenticate>
|
|
38
|
+
</soap:Body>
|
|
39
|
+
</soap:Envelope>
|
|
40
|
+
`.trim();
|
|
41
|
+
|
|
42
|
+
const response = await customFetch(
|
|
43
|
+
url,
|
|
44
|
+
{
|
|
45
|
+
headers,
|
|
46
|
+
method: 'post',
|
|
47
|
+
body: envelope,
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/* e.g.
|
|
52
|
+
'soap:Envelope': {
|
|
53
|
+
'soap:Body': {
|
|
54
|
+
AuthenticateResponse: {
|
|
55
|
+
AuthenticateResult: {
|
|
56
|
+
ResponseId: '0',
|
|
57
|
+
TotalCount: '1',
|
|
58
|
+
Detail: 'abc123,9999999-3e02-46a3-bb7c-9dca6b9db243',
|
|
59
|
+
Statuses: '',
|
|
60
|
+
ImportingQueueId: '0',
|
|
61
|
+
SalesOrdersToDespatchIds: '',
|
|
62
|
+
ErrorCode: ''
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
return response;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const funcApiConfig = {
|
|
73
|
+
argsWarden,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
peoplevoxAuthGet,
|
|
78
|
+
funcApiConfig,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
curl -X POST "http://localhost:8000/peoplevoxAuthGet" \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d '{
|
|
85
|
+
"credsPayload": {
|
|
86
|
+
"credsObject": {
|
|
87
|
+
"CLIENT_ID": "aveng1963",
|
|
88
|
+
"USERNAME": "bannerb",
|
|
89
|
+
"PASSWORD": "$MASh123!"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}'
|
|
93
|
+
|
|
94
|
+
curl -X POST "http://localhost:8000/peoplevoxAuthGet" \
|
|
95
|
+
-H "Content-Type: application/json" \
|
|
96
|
+
-d '{
|
|
97
|
+
"credsPayload": { "credsPath": "peoplevox" }
|
|
98
|
+
}'
|
|
99
|
+
*/
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const { peoplevoxClient } = require('../peoplevox/peoplevox.utils');
|
|
2
|
+
const { credsValidator } = require('../validators');
|
|
3
|
+
const { ArgsWarden } = require('../utils');
|
|
4
|
+
|
|
5
|
+
const searchParametersValidator = ({ searchClause, id, idName }) => {
|
|
6
|
+
return searchClause || (id && idName);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const argsWarden = new ArgsWarden([
|
|
10
|
+
['credsPayload', credsValidator],
|
|
11
|
+
['templateName'],
|
|
12
|
+
['searchParameters', searchParametersValidator],
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const peoplevoxGetSingle = async (
|
|
16
|
+
credsPayload,
|
|
17
|
+
templateName,
|
|
18
|
+
searchParameters = {},
|
|
19
|
+
options = {},
|
|
20
|
+
) => {
|
|
21
|
+
|
|
22
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({
|
|
23
|
+
credsPayload,
|
|
24
|
+
templateName,
|
|
25
|
+
searchParameters,
|
|
26
|
+
});
|
|
27
|
+
if (rejectResponse) {
|
|
28
|
+
return rejectResponse;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { searchClause, id, idName } = searchParameters;
|
|
32
|
+
const resolvedSearchClause = searchClause || `${ idName }.Equals("${ id }")`;
|
|
33
|
+
|
|
34
|
+
const response = await peoplevoxClient.fetch({
|
|
35
|
+
method: 'post',
|
|
36
|
+
body: {
|
|
37
|
+
getRequest: {
|
|
38
|
+
TemplateName: templateName,
|
|
39
|
+
SearchClause: resolvedSearchClause,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
context: {
|
|
43
|
+
credsPayload,
|
|
44
|
+
action: 'GetData',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
return response;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { data } = response;
|
|
53
|
+
|
|
54
|
+
const multipleResults = Array.isArray(data) && data.length > 1;
|
|
55
|
+
|
|
56
|
+
if (!multipleResults) {
|
|
57
|
+
return response;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (id && idName) {
|
|
61
|
+
const targetResults = data.filter(result => result[idName] === id);
|
|
62
|
+
|
|
63
|
+
const stillMultipleResults = Array.isArray(targetResults) && targetResults.length > 1;
|
|
64
|
+
if (stillMultipleResults) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
error: {
|
|
68
|
+
code: 'MULTIPLE_RESULTS',
|
|
69
|
+
message: 'Multiple results found',
|
|
70
|
+
details: targetResults,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (targetResults.length === 0) {
|
|
76
|
+
return {
|
|
77
|
+
ok: false,
|
|
78
|
+
error: {
|
|
79
|
+
code: 'NOT_FOUND',
|
|
80
|
+
message: 'No results found',
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
...response,
|
|
87
|
+
data: targetResults[0],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return response;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const funcApiConfig = {
|
|
95
|
+
argsWarden,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
module.exports = {
|
|
99
|
+
peoplevoxGetSingle,
|
|
100
|
+
funcApiConfig,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
curl -X POST "http://localhost:8000/peoplevoxGetSingle" \
|
|
105
|
+
-H "Content-Type: application/json" \
|
|
106
|
+
-d '{
|
|
107
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
108
|
+
"templateName": "Sales orders",
|
|
109
|
+
"searchParameters": { "id": "7680864157768", "idName": "SalesOrderNumber" }
|
|
110
|
+
}'
|
|
111
|
+
|
|
112
|
+
curl -X POST "http://localhost:8000/peoplevoxGetSingle" \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-d '{
|
|
115
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
116
|
+
"templateName": "Sales orders",
|
|
117
|
+
"searchParameters": { "searchClause": "SalesOrderNumber.Equals(\"7680864157768\")" }
|
|
118
|
+
}'
|
|
119
|
+
*/
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const { json2csv } = require('json-2-csv');
|
|
2
|
+
const { credsValidator } = require('../validators');
|
|
3
|
+
const { ensureArray, everyIfArray, ArgsWarden } = require('../utils');
|
|
4
|
+
const { peoplevoxClient } = require('../peoplevox/peoplevox.utils');
|
|
5
|
+
const { MAX_REQUEST_ITEMS } = require('../peoplevox/peoplevox.constants');
|
|
6
|
+
|
|
7
|
+
const orderPayloadValidator = (orderPayload) => orderPayload?.SalesOrderNumber;
|
|
8
|
+
|
|
9
|
+
const argsWarden = new ArgsWarden([
|
|
10
|
+
['credsPayload', credsValidator],
|
|
11
|
+
['orderPayload', (i) => everyIfArray(orderPayloadValidator, i)],
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
const peoplevoxOrderEdit = async (
|
|
15
|
+
credsPayload,
|
|
16
|
+
orderPayload,
|
|
17
|
+
) => {
|
|
18
|
+
|
|
19
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload, orderPayload });
|
|
20
|
+
if (rejectResponse) {
|
|
21
|
+
return rejectResponse;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// TODO: Consider making CSV transformation a request preparer step
|
|
25
|
+
const csvData = await json2csv(ensureArray(orderPayload));
|
|
26
|
+
|
|
27
|
+
// TODO: Handle by chunking
|
|
28
|
+
// TODO: Chunk objects by common fields so that each call has a consistent schema - bedrock groupObjectsByFields
|
|
29
|
+
if (csvData.length > MAX_REQUEST_ITEMS) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
error: {
|
|
33
|
+
code: 'MAX_REQUEST_ITEMS_EXCEEDED',
|
|
34
|
+
message: `Max request items exceeded. Max is ${ MAX_REQUEST_ITEMS }.`,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return peoplevoxClient.fetch({
|
|
40
|
+
method: 'post',
|
|
41
|
+
body: {
|
|
42
|
+
saveRequest: {
|
|
43
|
+
TemplateName: 'Sales orders',
|
|
44
|
+
CsvData: csvData,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
context: {
|
|
48
|
+
credsPayload,
|
|
49
|
+
action: 'SaveData',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const funcApiConfig = {
|
|
55
|
+
argsWarden,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
peoplevoxOrderEdit,
|
|
60
|
+
funcApiConfig,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
curl -X POST "http://localhost:8000/peoplevoxOrderEdit" \
|
|
65
|
+
-H "Content-Type: application/json" \
|
|
66
|
+
-d '{
|
|
67
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
68
|
+
"orderPayload": { "SalesOrderNumber": "7696610951240", "Attribute1": "Whatever" }
|
|
69
|
+
}'
|
|
70
|
+
|
|
71
|
+
Take order off hold:
|
|
72
|
+
curl -X POST "http://localhost:8000/peoplevoxOrderEdit" \
|
|
73
|
+
-H "Content-Type: application/json" \
|
|
74
|
+
-d '{
|
|
75
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
76
|
+
"orderPayload": {
|
|
77
|
+
"SalesOrderNumber": "7696610951240",
|
|
78
|
+
"OnHold": false,
|
|
79
|
+
"StopShip": false
|
|
80
|
+
}
|
|
81
|
+
}'
|
|
82
|
+
*/
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const { credsValidator } = require('../validators');
|
|
2
|
+
const { ArgsWarden } = require('../utils');
|
|
3
|
+
const { peoplevoxGetSingle } = require('../peoplevox/peoplevoxGetSingle');
|
|
4
|
+
|
|
5
|
+
const argsWarden = new ArgsWarden([
|
|
6
|
+
['credsPayload', credsValidator],
|
|
7
|
+
['salesOrderNumber'],
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
const peoplevoxOrderGet = async (
|
|
11
|
+
credsPayload,
|
|
12
|
+
salesOrderNumber,
|
|
13
|
+
) => {
|
|
14
|
+
|
|
15
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({ credsPayload, salesOrderNumber });
|
|
16
|
+
if (rejectResponse) {
|
|
17
|
+
return rejectResponse;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return peoplevoxGetSingle(
|
|
21
|
+
credsPayload,
|
|
22
|
+
'Sales orders',
|
|
23
|
+
{
|
|
24
|
+
id: salesOrderNumber,
|
|
25
|
+
idName: 'SalesOrderNumber',
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const funcApiConfig = {
|
|
31
|
+
argsWarden,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
peoplevoxOrderGet,
|
|
36
|
+
funcApiConfig,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
curl localhost:8000/peoplevoxOrderGet \
|
|
41
|
+
-X POST \
|
|
42
|
+
-H "Content-Type: application/json" \
|
|
43
|
+
-d '{
|
|
44
|
+
"credsPayload": {
|
|
45
|
+
"credsObject": {
|
|
46
|
+
"CLIENT_ID": "kaibacorp",
|
|
47
|
+
"USERNAME": "Seto",
|
|
48
|
+
"PASSWORD": "8lu33y3z8e$t"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"salesOrderNumber": "7680864157768"
|
|
52
|
+
}'
|
|
53
|
+
|
|
54
|
+
curl -X POST "http://localhost:8000/peoplevoxOrderGet" \
|
|
55
|
+
-H "Content-Type: application/json" \
|
|
56
|
+
-d '{
|
|
57
|
+
"credsPayload": { "credsPath": "peoplevox" },
|
|
58
|
+
"salesOrderNumber": "7680864157768"
|
|
59
|
+
}'
|
|
60
|
+
*/
|