@foxtware/mineral 0.1.36 → 0.1.38

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 (38) hide show
  1. package/.creds.yml.sample +9 -0
  2. package/api/marketingcloud/docs.md +6 -0
  3. package/api/marketingcloud/marketingcloud.constants.js +5 -0
  4. package/api/marketingcloud/marketingcloud.utils.js +67 -0
  5. package/api/marketingcloud/marketingcloudAttributesSearch.js +87 -0
  6. package/api/marketingcloud/marketingcloudAuthGet.js +111 -0
  7. package/api/marketingcloud/marketingcloudContactGet.js +79 -0
  8. package/api/marketingcloud/marketingcloudContactSearch.js +87 -0
  9. package/api/marketingcloud/marketingcloudSmsSubscriptionsGet.js +79 -0
  10. package/api/peoplevox/peoplevoxItemEdit.js +59 -22
  11. package/api/peoplevox/peoplevoxOrderEdit.js +49 -25
  12. package/api/shopify/shopifyInventoryItemUpdate.js +22 -16
  13. package/api/shopify/shopifyInventoryItemsUpdateBulk.js +79 -0
  14. package/api/shopify/shopifyMetafieldsSetBulk.js +87 -0
  15. package/api/shopify/shopifyProductGet.js +1 -0
  16. package/api/shopify/shopifyProductUpdate.js +136 -0
  17. package/api/shopify/shopifyProductUpdateTrigger.js +96 -0
  18. package/api/snowflake/docs.md +8 -2
  19. package/api/snowflake/snowflake.constants.js +19 -0
  20. package/api/snowflake/snowflake.utils.js +326 -0
  21. package/api/snowflake/snowflakeAuthGet.js +73 -0
  22. package/api/snowflake/snowflakeDatabasesGet.js +62 -0
  23. package/api/snowflake/snowflakeDynamicTablesGet.js +72 -0
  24. package/api/snowflake/snowflakeEventTablesGet.js +72 -0
  25. package/api/snowflake/snowflakeGet.js +153 -0
  26. package/api/snowflake/snowflakeIntegrationsGet.js +59 -0
  27. package/api/snowflake/snowflakeQuery.js +227 -0
  28. package/api/snowflake/snowflakeSchemasGet.js +69 -0
  29. package/api/snowflake/snowflakeStatementCancel.js +75 -0
  30. package/api/snowflake/snowflakeStatementExecute.js +105 -0
  31. package/api/snowflake/snowflakeStatementGet.js +80 -0
  32. package/api/snowflake/snowflakeTablesGet.js +72 -0
  33. package/api/snowflake/snowflakeUsersGet.js +60 -0
  34. package/api/snowflake/snowflakeWarehousesGet.js +43 -0
  35. package/api/starshipit/starshipitProductUpdate.js +1 -1
  36. package/api/starshipit/starshipitProductsGet.js +13 -6
  37. package/api/utils.js +62 -3
  38. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ // https://docs.snowflake.com/en/developer-guide/sql-api/handling-responses
2
+
3
+ const { ArgsWarden, actionSingleOrMultiple, logDeep } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { snowflakeClient } = require('../snowflake/snowflake.utils');
6
+ const { SQL_API_PATH } = require('../snowflake/snowflake.constants');
7
+
8
+ const argsWarden = new ArgsWarden([
9
+ ['credsPayload', credsValidator],
10
+ ['statementHandle'],
11
+ ]);
12
+
13
+ const snowflakeStatementGetSingle = async (
14
+ credsPayload,
15
+ statementHandle,
16
+ {
17
+ partition,
18
+ fetchClient = snowflakeClient,
19
+ } = {},
20
+ ) => {
21
+ const response = await fetchClient.fetch({
22
+ context: { credsPayload },
23
+ requestPayload: {
24
+ method: 'get',
25
+ url: `${ SQL_API_PATH }/${ statementHandle }`,
26
+ params: {
27
+ ...(partition !== undefined && { partition }),
28
+ },
29
+ },
30
+ });
31
+
32
+ const { ok, data, error } = response;
33
+ if (!ok) {
34
+ logDeep({ error });
35
+ return { ok: false, error };
36
+ }
37
+
38
+ return {
39
+ ok: true,
40
+ data,
41
+ };
42
+ };
43
+
44
+ const snowflakeStatementGet = async (
45
+ credsPayload,
46
+ statementHandle,
47
+ {
48
+ partition,
49
+ queueRunOptions,
50
+ fetchClient,
51
+ } = {},
52
+ ) => {
53
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
54
+ credsPayload,
55
+ statementHandle,
56
+ });
57
+ if (rejectResponse) {
58
+ return rejectResponse;
59
+ }
60
+
61
+ return actionSingleOrMultiple(
62
+ statementHandle,
63
+ snowflakeStatementGetSingle,
64
+ (handleItem) => ({
65
+ args: [credsPayload, handleItem, { partition, fetchClient }],
66
+ }),
67
+ {
68
+ ...(queueRunOptions ? { queueRunOptions } : {}),
69
+ },
70
+ );
71
+ };
72
+
73
+ const funcApiConfig = {
74
+ argsWarden,
75
+ };
76
+
77
+ module.exports = {
78
+ snowflakeStatementGet,
79
+ funcApiConfig,
80
+ };
@@ -0,0 +1,72 @@
1
+ // https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/reference/table
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const {
6
+ snowflakeGet,
7
+ snowflakeGetter,
8
+ } = require('../snowflake/snowflakeGet');
9
+ const {
10
+ REST_API_VERSION,
11
+ DEFAULT_SHOW_LIMIT,
12
+ } = require('../snowflake/snowflake.constants');
13
+
14
+ const argsWarden = new ArgsWarden([
15
+ ['credsPayload', credsValidator],
16
+ ['databaseName'],
17
+ ['schemaName'],
18
+ ]);
19
+
20
+ const snowflakeTablesGetImpl = async (
21
+ returnGetter,
22
+ credsPayload,
23
+ databaseName,
24
+ schemaName,
25
+ {
26
+ like,
27
+ startsWith,
28
+ history,
29
+ showLimit = DEFAULT_SHOW_LIMIT,
30
+ fromName,
31
+ apiVersion = REST_API_VERSION,
32
+ fetchClient,
33
+ ...getterOptions
34
+ } = {},
35
+ ) => {
36
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
37
+ credsPayload,
38
+ databaseName,
39
+ schemaName,
40
+ });
41
+ if (rejectResponse) {
42
+ return rejectResponse;
43
+ }
44
+
45
+ const method = returnGetter ? snowflakeGetter : snowflakeGet;
46
+
47
+ return method(
48
+ credsPayload,
49
+ `/api/${ apiVersion }/databases/${ databaseName }/schemas/${ schemaName }/tables`,
50
+ {
51
+ params: {
52
+ ...(like !== undefined && { like }),
53
+ ...(startsWith !== undefined && { startsWith }),
54
+ ...(history !== undefined && { history }),
55
+ ...(fromName !== undefined && { fromName }),
56
+ },
57
+ showLimit,
58
+ fetchClient,
59
+ ...getterOptions,
60
+ },
61
+ );
62
+ };
63
+
64
+ const funcApiConfig = {
65
+ argsWarden,
66
+ };
67
+
68
+ module.exports = {
69
+ snowflakeTablesGet: (...args) => snowflakeTablesGetImpl(false, ...args),
70
+ snowflakeTablesGetter: (...args) => snowflakeTablesGetImpl(true, ...args),
71
+ funcApiConfig,
72
+ };
@@ -0,0 +1,60 @@
1
+ // https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/user
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const {
6
+ snowflakeGet,
7
+ snowflakeGetter,
8
+ } = require('../snowflake/snowflakeGet');
9
+ const {
10
+ REST_API_VERSION,
11
+ DEFAULT_SHOW_LIMIT,
12
+ } = require('../snowflake/snowflake.constants');
13
+
14
+ const argsWarden = new ArgsWarden([
15
+ ['credsPayload', credsValidator],
16
+ ]);
17
+
18
+ const snowflakeUsersGetImpl = async (
19
+ returnGetter,
20
+ credsPayload,
21
+ {
22
+ like,
23
+ startsWith,
24
+ showLimit = DEFAULT_SHOW_LIMIT,
25
+ fromName,
26
+ apiVersion = REST_API_VERSION,
27
+ fetchClient,
28
+ ...getterOptions
29
+ } = {},
30
+ ) => {
31
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
32
+ credsPayload,
33
+ });
34
+ if (rejectResponse) {
35
+ return rejectResponse;
36
+ }
37
+
38
+ const method = returnGetter ? snowflakeGetter : snowflakeGet;
39
+
40
+ return method(credsPayload, `/api/${ apiVersion }/users`, {
41
+ params: {
42
+ ...(like !== undefined && { like }),
43
+ ...(startsWith !== undefined && { startsWith }),
44
+ ...(fromName !== undefined && { fromName }),
45
+ },
46
+ showLimit,
47
+ fetchClient,
48
+ ...getterOptions,
49
+ });
50
+ };
51
+
52
+ const funcApiConfig = {
53
+ argsWarden,
54
+ };
55
+
56
+ module.exports = {
57
+ snowflakeUsersGet: (...args) => snowflakeUsersGetImpl(false, ...args),
58
+ snowflakeUsersGetter: (...args) => snowflakeUsersGetImpl(true, ...args),
59
+ funcApiConfig,
60
+ };
@@ -0,0 +1,43 @@
1
+ // https://docs.snowflake.com/en/sql-reference/sql/show-warehouses
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { snowflakeQuery } = require('../snowflake/snowflakeQuery');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ]);
10
+
11
+ const snowflakeWarehousesGet = async (
12
+ credsPayload,
13
+ {
14
+ like,
15
+ fetchClient,
16
+ ...queryOptions
17
+ } = {},
18
+ ) => {
19
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
20
+ credsPayload,
21
+ });
22
+ if (rejectResponse) {
23
+ return rejectResponse;
24
+ }
25
+
26
+ const statement = like
27
+ ? `show warehouses like '${ String(like).replace(/'/g, "''") }'`
28
+ : 'show warehouses';
29
+
30
+ return snowflakeQuery(credsPayload, statement, {
31
+ fetchClient,
32
+ ...queryOptions,
33
+ });
34
+ };
35
+
36
+ const funcApiConfig = {
37
+ argsWarden,
38
+ };
39
+
40
+ module.exports = {
41
+ snowflakeWarehousesGet,
42
+ funcApiConfig,
43
+ };
@@ -76,7 +76,7 @@ const starshipitProductUpdate = async (
76
76
  },
77
77
  context: {
78
78
  credsPayload,
79
- resultPath: 'result.product',
79
+ resultPath: 'product',
80
80
  },
81
81
  });
82
82
  };
@@ -42,10 +42,17 @@ module.exports = {
42
42
  };
43
43
 
44
44
  /*
45
- curl -X POST "http://localhost:8000/starshipitProductsGet" \
46
- -H "Content-Type: application/json" \
47
- -d '{
48
- "credsPayload": { "credsPath": "starshipit.wf" },
49
- "options": { "limit": 20 }
50
- }'
45
+ curl -X POST "http://localhost:8000/starshipitProductsGet" \
46
+ -H "Content-Type: application/json" \
47
+ -d '{
48
+ "credsPayload": { "credsPath": "starshipit.acc" },
49
+ "options": { "searchTerm": "WFAL48-1-S" }
50
+ }'
51
+
52
+ curl -X POST "http://localhost:8000/starshipitProductsGet" \
53
+ -H "Content-Type: application/json" \
54
+ -d '{
55
+ "credsPayload": { "credsPath": "starshipit.wf" },
56
+ "options": { "limit": 20 }
57
+ }'
51
58
  */
package/api/utils.js CHANGED
@@ -40,7 +40,7 @@ const getWithLocalCachedFile = async (
40
40
  return getFunction();
41
41
  }
42
42
 
43
- const directory = `${ getWorkspace() }/api/_temp`;
43
+ const directory = `${ getWorkspace() }/_temp`;
44
44
  const filepath = `${ directory }/${ filename }`;
45
45
 
46
46
  let cachedFile;
@@ -967,6 +967,32 @@ const arrayToChunks = (array, chunkSize, { chunkBy } = {}) => {
967
967
  return chunks;
968
968
  };
969
969
 
970
+ const groupObjectsByFields = (objArr) => {
971
+ if (!Array.isArray(objArr)) {
972
+ throw new Error('groupObjectsByFields: expected an array');
973
+ }
974
+
975
+ if (objArr.some(obj => !isObject(obj))) {
976
+ throw new Error('groupObjectsByFields: expected array of objects');
977
+ }
978
+
979
+ const bucketsMap = new Map();
980
+
981
+ for (const obj of objArr) {
982
+ // Get sorted keys as a string identifier for the field set
983
+ const fieldSetKey = Object.keys(obj).sort().join(',');
984
+
985
+ if (!bucketsMap.has(fieldSetKey)) {
986
+ bucketsMap.set(fieldSetKey, []);
987
+ }
988
+
989
+ bucketsMap.get(fieldSetKey).push(obj);
990
+ }
991
+
992
+ // Return buckets as an array of arrays
993
+ return Array.from(bucketsMap.values());
994
+ };
995
+
970
996
  const arraysToCartesianProduct = (arrayOfMixed) => {
971
997
  return arrayOfMixed
972
998
  .map(ensureArray)
@@ -1092,7 +1118,10 @@ class Processor extends EventEmitter {
1092
1118
  const initialSize = this.getPileSize();
1093
1119
 
1094
1120
  const executeAction = async () => {
1095
- const actionResult = await this.action(this.pile);
1121
+ const [, actionResult] = await Promise.all([
1122
+ this.action(this.pile),
1123
+ wait(1), // TODO: consider making this optional. Forces a yield so that async processors can run in parallel.
1124
+ ]);
1096
1125
  results.push(actionResult);
1097
1126
  completedCount++;
1098
1127
 
@@ -1165,6 +1194,7 @@ class Getter extends EventEmitter {
1165
1194
  limit,
1166
1195
  // TODO: returnAllItems option or runAsFunction option
1167
1196
 
1197
+ logFlavourText,
1168
1198
  onItems,
1169
1199
  onDone,
1170
1200
  } = {},
@@ -1182,6 +1212,7 @@ class Getter extends EventEmitter {
1182
1212
  this.func = func;
1183
1213
 
1184
1214
  this.limit = limit;
1215
+ this.logFlavourText = logFlavourText;
1185
1216
 
1186
1217
  if (onItems) {
1187
1218
  this.on('items', onItems);
@@ -1246,7 +1277,7 @@ class Getter extends EventEmitter {
1246
1277
  [done, paginatedParams] = await paginator(paginatedParams, response);
1247
1278
  }
1248
1279
 
1249
- console.log('resultsCount', resultsCount);
1280
+ console.log(`${ ifTextThenSpace(this.logFlavourText) }resultsCount`, resultsCount);
1250
1281
  this.emit('done');
1251
1282
 
1252
1283
  if (returnAll) {
@@ -1515,6 +1546,31 @@ const oneTrickProcessor = (
1515
1546
  return processor;
1516
1547
  };
1517
1548
 
1549
+ const simpleHash = (str) => {
1550
+ let hash = 0;
1551
+ for (let i = 0; i < str.length; i++) {
1552
+ hash = (hash << 5) - hash + str.charCodeAt(i);
1553
+ hash |= 0; // convert to 32-bit integer
1554
+ }
1555
+ return Math.abs(hash);
1556
+ };
1557
+
1558
+ const deterministicArrayItem = (array, input) => {
1559
+ const index = simpleHash(String(input)) % array.length;
1560
+ return array[index];
1561
+ };
1562
+
1563
+ const arrayPartition = (array, partitioner) => {
1564
+ const { passed, rejected } = array.reduce(
1565
+ (acc, item) => {
1566
+ (partitioner(item) ? acc.passed : acc.rejected).push(item);
1567
+ return acc;
1568
+ },
1569
+ { passed: [], rejected: [] },
1570
+ );
1571
+ return { passed, rejected };
1572
+ };
1573
+
1518
1574
  module.exports = {
1519
1575
  wait,
1520
1576
  timeMs,
@@ -1541,6 +1597,7 @@ module.exports = {
1541
1597
  everyIfArray,
1542
1598
  simpleSort,
1543
1599
  arrayToChunks,
1600
+ groupObjectsByFields,
1544
1601
  responseArrayToResponse,
1545
1602
  responseResultsByOutcome,
1546
1603
  Operation,
@@ -1560,5 +1617,7 @@ module.exports = {
1560
1617
  diffObjects,
1561
1618
  objectPropsTranslate,
1562
1619
  randomArrayItem,
1620
+ deterministicArrayItem,
1563
1621
  oneTrickProcessor,
1622
+ arrayPartition,
1564
1623
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxtware/mineral",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
4
4
  "bin": {
5
5
  "mineral": "bin/mineral.js"
6
6
  },