@foxtware/mineral 0.1.16 → 0.1.17
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.
|
@@ -5,8 +5,8 @@ const { credsValidator } = require('../validators');
|
|
|
5
5
|
const { etsyClient } = require('./etsy.utils');
|
|
6
6
|
|
|
7
7
|
const updatePayloadWithListingIdValidator = (updatePayloadWithListingId) => {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const { listingId, ...updatePayload } = updatePayloadWithListingId;
|
|
9
|
+
return valueProvided(listingId) && Object.keys(updatePayload).length > 0;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
const argsWarden = new ArgsWarden([
|
|
@@ -14,7 +14,7 @@ const argsWarden = new ArgsWarden([
|
|
|
14
14
|
['updatePayloadWithListingId', (updatePayloadWithListingId) => everyIfArray(updatePayloadWithListingIdValidator, updatePayloadWithListingId)],
|
|
15
15
|
]);
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const etsyListingInventoryUpdateSingle = async (
|
|
18
18
|
credsPayload,
|
|
19
19
|
updatePayloadWithListingId,
|
|
20
20
|
{
|
|
@@ -24,9 +24,9 @@ const etsyListingupdatePayloadWithListingIdSingle = async (
|
|
|
24
24
|
} = {},
|
|
25
25
|
) => {
|
|
26
26
|
|
|
27
|
-
const {
|
|
28
|
-
listingId,
|
|
29
|
-
...updatePayload
|
|
27
|
+
const {
|
|
28
|
+
listingId,
|
|
29
|
+
...updatePayload
|
|
30
30
|
} = updatePayloadWithListingId;
|
|
31
31
|
|
|
32
32
|
return fetchClient.fetch({
|
|
@@ -44,7 +44,7 @@ const etsyListingupdatePayloadWithListingIdSingle = async (
|
|
|
44
44
|
});
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
const
|
|
47
|
+
const etsyListingInventoryUpdate = async (
|
|
48
48
|
credsPayload,
|
|
49
49
|
updatePayloadWithListingId,
|
|
50
50
|
{
|
|
@@ -65,7 +65,7 @@ const etsyListingupdatePayloadWithListingId = async (
|
|
|
65
65
|
|
|
66
66
|
return actionSingleOrMultiple(
|
|
67
67
|
updatePayloadWithListingId,
|
|
68
|
-
|
|
68
|
+
etsyListingInventoryUpdateSingle,
|
|
69
69
|
(updatePayloadWithListingIdItem) => ({
|
|
70
70
|
args: [credsPayload, updatePayloadWithListingIdItem, { params, inspect, fetchClient }],
|
|
71
71
|
}),
|
|
@@ -80,12 +80,12 @@ const funcApiConfig = {
|
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
module.exports = {
|
|
83
|
-
|
|
83
|
+
etsyListingInventoryUpdate,
|
|
84
84
|
funcApiConfig,
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
/*
|
|
88
|
-
curl -X POST "http://localhost:8000/
|
|
88
|
+
curl -X POST "http://localhost:8000/etsyListingInventoryUpdate" \
|
|
89
89
|
-H "Content-Type: application/json" \
|
|
90
90
|
-d '{
|
|
91
91
|
"credsPayload": {
|
|
@@ -93,7 +93,7 @@ curl -X POST "http://localhost:8000/etsyListingupdatePayloadWithListingId" \
|
|
|
93
93
|
},
|
|
94
94
|
"updatePayloadWithListingId": {
|
|
95
95
|
"listingId": "1234567890",
|
|
96
|
-
"
|
|
96
|
+
"products": []
|
|
97
97
|
}
|
|
98
98
|
}'
|
|
99
99
|
*/
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// https://shopify.dev/docs/api/admin-graphql/latest/mutations/metafieldDefinitionCreate
|
|
2
|
+
// https://shopify.dev/docs/api/admin-graphql/latest/queries/metafieldDefinition
|
|
3
|
+
|
|
4
|
+
const { credsValidator } = require('../validators');
|
|
5
|
+
const { ArgsWarden, credsFromPayload, objHasAny } = require('../utils');
|
|
6
|
+
const { shopifyClient } = require('./shopify.utils');
|
|
7
|
+
const { shopifyMutationDo } = require('./shopifyMutationDo');
|
|
8
|
+
|
|
9
|
+
const sourceMetafieldDefinitionAttrs = `
|
|
10
|
+
name
|
|
11
|
+
namespace
|
|
12
|
+
key
|
|
13
|
+
description
|
|
14
|
+
ownerType
|
|
15
|
+
pinnedPosition
|
|
16
|
+
type {
|
|
17
|
+
name
|
|
18
|
+
}
|
|
19
|
+
validations {
|
|
20
|
+
name
|
|
21
|
+
value
|
|
22
|
+
}
|
|
23
|
+
capabilities {
|
|
24
|
+
adminFilterable {
|
|
25
|
+
enabled
|
|
26
|
+
}
|
|
27
|
+
smartCollectionCondition {
|
|
28
|
+
enabled
|
|
29
|
+
}
|
|
30
|
+
uniqueValues {
|
|
31
|
+
enabled
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`.trim();
|
|
35
|
+
|
|
36
|
+
const defaultReturnCreatedDefinitionAttrs = 'id name namespace key ownerType type { name }';
|
|
37
|
+
|
|
38
|
+
const metafieldDefinitionIdentifierValidator = (metafieldDefinitionIdentifier) => {
|
|
39
|
+
return objHasAny(metafieldDefinitionIdentifier, [
|
|
40
|
+
'ownerType',
|
|
41
|
+
'namespace',
|
|
42
|
+
'key',
|
|
43
|
+
]);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const argsWarden = new ArgsWarden([
|
|
47
|
+
['fromStoreCredsPayload', credsValidator],
|
|
48
|
+
['toStoreCredsPayload', credsValidator],
|
|
49
|
+
['metafieldDefinitionIdentifier', metafieldDefinitionIdentifierValidator],
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
const metafieldDefinitionInputFromDefinition = (sourceDefinition) => {
|
|
53
|
+
const {
|
|
54
|
+
name,
|
|
55
|
+
namespace,
|
|
56
|
+
key,
|
|
57
|
+
description,
|
|
58
|
+
ownerType,
|
|
59
|
+
type,
|
|
60
|
+
validations,
|
|
61
|
+
capabilities,
|
|
62
|
+
pinnedPosition,
|
|
63
|
+
} = sourceDefinition;
|
|
64
|
+
|
|
65
|
+
const definitionInput = {
|
|
66
|
+
name,
|
|
67
|
+
namespace,
|
|
68
|
+
key,
|
|
69
|
+
ownerType,
|
|
70
|
+
type: type?.name,
|
|
71
|
+
...(description && { description }),
|
|
72
|
+
...(pinnedPosition != null && { pin: true }),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (Array.isArray(validations) && validations.length) {
|
|
76
|
+
definitionInput.validations = validations.map(({ name: validationName, value }) => ({
|
|
77
|
+
name: validationName,
|
|
78
|
+
value,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (capabilities) {
|
|
83
|
+
definitionInput.capabilities = {
|
|
84
|
+
...(capabilities.adminFilterable && {
|
|
85
|
+
adminFilterable: { enabled: capabilities.adminFilterable.enabled },
|
|
86
|
+
}),
|
|
87
|
+
...(capabilities.smartCollectionCondition && {
|
|
88
|
+
smartCollectionCondition: { enabled: capabilities.smartCollectionCondition.enabled },
|
|
89
|
+
}),
|
|
90
|
+
...(capabilities.uniqueValues && {
|
|
91
|
+
uniqueValues: { enabled: capabilities.uniqueValues.enabled },
|
|
92
|
+
}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return definitionInput;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const fetchSourceMetafieldDefinition = async (
|
|
100
|
+
fromStoreCredsPayload,
|
|
101
|
+
metafieldDefinitionIdentifier,
|
|
102
|
+
{
|
|
103
|
+
apiVersion,
|
|
104
|
+
} = {},
|
|
105
|
+
) => {
|
|
106
|
+
const creds = await credsFromPayload(fromStoreCredsPayload);
|
|
107
|
+
|
|
108
|
+
return shopifyClient.fetch({
|
|
109
|
+
method: 'post',
|
|
110
|
+
body: {
|
|
111
|
+
query: `
|
|
112
|
+
query GetMetafieldDefinition($identifier: MetafieldDefinitionIdentifierInput!) {
|
|
113
|
+
metafieldDefinition(identifier: $identifier) {
|
|
114
|
+
${ sourceMetafieldDefinitionAttrs }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
`,
|
|
118
|
+
variables: {
|
|
119
|
+
identifier: metafieldDefinitionIdentifier,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
context: {
|
|
123
|
+
creds,
|
|
124
|
+
apiVersion,
|
|
125
|
+
resultPath: 'data.metafieldDefinition',
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const shopifyMetafieldDefinitionPropagate = async (
|
|
131
|
+
fromStoreCredsPayload,
|
|
132
|
+
toStoreCredsPayload,
|
|
133
|
+
metafieldDefinitionIdentifier,
|
|
134
|
+
{
|
|
135
|
+
apiVersion,
|
|
136
|
+
returnCreatedDefinitionAttrs = defaultReturnCreatedDefinitionAttrs,
|
|
137
|
+
} = {},
|
|
138
|
+
) => {
|
|
139
|
+
|
|
140
|
+
const rejectResponse = await argsWarden.responseIfRejectingArgs({
|
|
141
|
+
fromStoreCredsPayload,
|
|
142
|
+
toStoreCredsPayload,
|
|
143
|
+
metafieldDefinitionIdentifier,
|
|
144
|
+
});
|
|
145
|
+
if (rejectResponse) {
|
|
146
|
+
return rejectResponse;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const sourceResponse = await fetchSourceMetafieldDefinition(
|
|
150
|
+
fromStoreCredsPayload,
|
|
151
|
+
metafieldDefinitionIdentifier,
|
|
152
|
+
{ apiVersion },
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
if (!sourceResponse.ok) {
|
|
156
|
+
return sourceResponse;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!sourceResponse.data) {
|
|
160
|
+
return {
|
|
161
|
+
ok: false,
|
|
162
|
+
error: {
|
|
163
|
+
code: 'NOT_FOUND',
|
|
164
|
+
message: 'Metafield definition not found on source store.',
|
|
165
|
+
details: metafieldDefinitionIdentifier,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const definitionInput = metafieldDefinitionInputFromDefinition(sourceResponse.data);
|
|
171
|
+
|
|
172
|
+
return shopifyMutationDo(
|
|
173
|
+
toStoreCredsPayload,
|
|
174
|
+
'metafieldDefinitionCreate',
|
|
175
|
+
{
|
|
176
|
+
mutationVariables: {
|
|
177
|
+
definition: {
|
|
178
|
+
type: 'MetafieldDefinitionInput!',
|
|
179
|
+
value: definitionInput,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
returnSchema: `
|
|
183
|
+
createdDefinition { ${ returnCreatedDefinitionAttrs } }
|
|
184
|
+
`.trim(),
|
|
185
|
+
apiVersion,
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const funcApiConfig = {
|
|
191
|
+
argsWarden,
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
module.exports = {
|
|
195
|
+
shopifyMetafieldDefinitionPropagate,
|
|
196
|
+
funcApiConfig,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/*
|
|
200
|
+
curl -X POST "http://localhost:8000/shopifyMetafieldDefinitionPropagate" \
|
|
201
|
+
-H "Content-Type: application/json" \
|
|
202
|
+
-d '{
|
|
203
|
+
"fromStoreCredsPayload": { "credsPath": "shopify.au" },
|
|
204
|
+
"toStoreCredsPayload": { "credsPath": "shopify.us" },
|
|
205
|
+
"metafieldDefinitionIdentifier": {
|
|
206
|
+
"ownerType": "PRODUCT",
|
|
207
|
+
"namespace": "custom",
|
|
208
|
+
"key": "outfit_builder_image"
|
|
209
|
+
}
|
|
210
|
+
}'
|
|
211
|
+
*/
|
|
@@ -141,7 +141,7 @@ const deployFunction = async ({
|
|
|
141
141
|
console.log(deployCommand);
|
|
142
142
|
|
|
143
143
|
try {
|
|
144
|
-
await execCommand(deployCommand);
|
|
144
|
+
await execCommand(deployCommand, { interactive: true });
|
|
145
145
|
} catch (error) {
|
|
146
146
|
console.error(`Error deploying function ${ functionName }:`, error);
|
|
147
147
|
return;
|
|
@@ -188,7 +188,7 @@ const deployFunction = async ({
|
|
|
188
188
|
].join(' ');
|
|
189
189
|
|
|
190
190
|
console.log(schedulerCommand);
|
|
191
|
-
await execCommand(schedulerCommand);
|
|
191
|
+
await execCommand(schedulerCommand, { interactive: true });
|
|
192
192
|
} catch (error) {
|
|
193
193
|
console.error(`Error handling scheduler job ${ jobName }:`, error);
|
|
194
194
|
}
|
package/hosting/execCommand.js
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
const { spawn } = require('child_process');
|
|
2
2
|
|
|
3
|
-
const execCommand = (command) => new Promise((resolve, reject) => {
|
|
3
|
+
const execCommand = (command, { interactive = false } = {}) => new Promise((resolve, reject) => {
|
|
4
4
|
const childProcess = spawn(command, [], {
|
|
5
|
-
stdio: 'pipe',
|
|
5
|
+
stdio: interactive ? 'inherit' : 'pipe',
|
|
6
6
|
shell: true,
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
if (interactive) {
|
|
10
|
+
childProcess.on('close', (code) => {
|
|
11
|
+
if (code === 0) {
|
|
12
|
+
resolve({ stdout: '', stderr: '', command });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
reject({ stdout: '', stderr: '', command, code });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
childProcess.on('error', (error) => {
|
|
20
|
+
reject({ error, command });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
9
26
|
let stdout = '';
|
|
10
27
|
let stderr = '';
|
|
11
28
|
|