@lowdefy/operators-js 5.0.0 → 5.2.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.
@@ -19,12 +19,13 @@ function _api({ params, apiResponses }) {
19
19
  }
20
20
  const splitKey = params.split('.');
21
21
  const [endpoint, ...keyParts] = splitKey;
22
- if (endpoint in apiResponses && !apiResponses[endpoint][0].loading) {
22
+ const entry = apiResponses[endpoint]?.[0];
23
+ if (entry && (!entry.loading || entry.holdValue)) {
23
24
  if (splitKey.length === 1) {
24
- return apiResponses[endpoint][0];
25
+ return entry;
25
26
  }
26
27
  const key = keyParts.join('.');
27
- return get(apiResponses[endpoint][0], key, {
28
+ return get(entry, key, {
28
29
  copy: true,
29
30
  default: null
30
31
  });
@@ -12,17 +12,21 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ function js(operatorContext) {
15
+ */ import { type } from '@lowdefy/helpers';
16
+ function js(operatorContext) {
16
17
  const { jsMap, operators, params } = operatorContext;
17
- if (!jsMap[params]) {
18
- throw new Error(`_js function not found. The function may not have been built yet. Received hash: ${params}`);
18
+ const hash = type.isString(params) ? params : params?.fn;
19
+ const args = type.isObject(params) ? params.args : undefined;
20
+ if (!jsMap[hash]) {
21
+ throw new Error(`_js function not found. The function may not have been built yet. Received hash: ${hash}`);
19
22
  }
20
23
  try {
21
- return jsMap[params]({
24
+ return jsMap[hash]({
22
25
  actions: (p)=>operators._actions({
23
26
  ...operatorContext,
24
27
  params: p
25
28
  }),
29
+ args,
26
30
  event: (p)=>operators._event({
27
31
  ...operatorContext,
28
32
  params: p
@@ -57,7 +61,7 @@
57
61
  })
58
62
  });
59
63
  } catch (error) {
60
- throw new Error(`_js function execution error. Function: ${jsMap[params].toString()}`, {
64
+ throw new Error(`_js function execution error. Function: ${jsMap[hash].toString()}`, {
61
65
  cause: error
62
66
  });
63
67
  }
@@ -15,7 +15,27 @@
15
15
  */ export default {
16
16
  type: 'object',
17
17
  params: {
18
- type: 'string',
19
- description: 'Hash identifier of the pre-built JavaScript function to execute.'
18
+ oneOf: [
19
+ {
20
+ type: 'string',
21
+ description: 'Hash identifier of the pre-built JavaScript function to execute.'
22
+ },
23
+ {
24
+ type: 'object',
25
+ required: [
26
+ 'fn'
27
+ ],
28
+ additionalProperties: false,
29
+ properties: {
30
+ fn: {
31
+ type: 'string',
32
+ description: 'Hash identifier of the pre-built JavaScript function to execute.'
33
+ },
34
+ args: {
35
+ description: 'Pre-resolved values injected into the JavaScript function as `args`.'
36
+ }
37
+ }
38
+ }
39
+ ]
20
40
  }
21
41
  };
@@ -19,12 +19,13 @@ function _request({ arrayIndices, params, requests }) {
19
19
  }
20
20
  const splitKey = params.split('.');
21
21
  const [requestId, ...keyParts] = splitKey;
22
- if (requestId in requests && !requests[requestId][0].loading) {
22
+ const entry = requests[requestId]?.[0];
23
+ if (entry && (!entry.loading || entry.holdValue)) {
23
24
  if (splitKey.length === 1) {
24
- return serializer.copy(requests[requestId][0].response);
25
+ return serializer.copy(entry.response);
25
26
  }
26
27
  const key = keyParts.reduce((acc, value)=>acc === '' ? value : acc.concat('.', value), '');
27
- return get(requests[requestId][0].response, applyArrayIndices(arrayIndices, key), {
28
+ return get(entry.response, applyArrayIndices(arrayIndices, key), {
28
29
  copy: true,
29
30
  default: null
30
31
  });
@@ -12,13 +12,17 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ function js(operatorContext) {
15
+ */ import { type } from '@lowdefy/helpers';
16
+ function js(operatorContext) {
16
17
  const { jsMap, operators, location, params } = operatorContext;
17
- if (!jsMap[params]) {
18
- throw new Error(`_js function not found. The function may not have been built yet. Received hash: ${params}`);
18
+ const hash = type.isString(params) ? params : params?.fn;
19
+ const args = type.isObject(params) ? params.args : undefined;
20
+ if (!jsMap[hash]) {
21
+ throw new Error(`_js function not found. The function may not have been built yet. Received hash: ${hash}`);
19
22
  }
20
23
  try {
21
- return jsMap[params]({
24
+ return jsMap[hash]({
25
+ args,
22
26
  payload: (p)=>operators._payload({
23
27
  ...operatorContext,
24
28
  params: p
@@ -45,7 +49,7 @@
45
49
  })
46
50
  });
47
51
  } catch (error) {
48
- throw new Error(`_js function execution error. Function: ${jsMap[params].toString()}`, {
52
+ throw new Error(`_js function execution error. Function: ${jsMap[hash].toString()}`, {
49
53
  cause: error
50
54
  });
51
55
  }
@@ -15,7 +15,27 @@
15
15
  */ export default {
16
16
  type: 'object',
17
17
  params: {
18
- type: 'string',
19
- description: 'Hash identifier of the pre-built JavaScript function to execute.'
18
+ oneOf: [
19
+ {
20
+ type: 'string',
21
+ description: 'Hash identifier of the pre-built JavaScript function to execute.'
22
+ },
23
+ {
24
+ type: 'object',
25
+ required: [
26
+ 'fn'
27
+ ],
28
+ additionalProperties: false,
29
+ properties: {
30
+ fn: {
31
+ type: 'string',
32
+ description: 'Hash identifier of the pre-built JavaScript function to execute.'
33
+ },
34
+ args: {
35
+ description: 'Pre-resolved values injected into the JavaScript function as `args`.'
36
+ }
37
+ }
38
+ }
39
+ ]
20
40
  }
21
41
  };
@@ -13,7 +13,7 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import { serializer } from '@lowdefy/helpers';
16
- function _function({ actions, arrayIndices, event, location, operatorPrefix, params, parser }) {
16
+ function _function({ actions, arrayIndices, event, location, operatorPrefix, params, parser, payload, steps }) {
17
17
  return (...args)=>{
18
18
  const { output, errors } = parser.parse({
19
19
  actions,
@@ -22,7 +22,9 @@ function _function({ actions, arrayIndices, event, location, operatorPrefix, par
22
22
  event,
23
23
  input: serializer.copy(params),
24
24
  location,
25
- operatorPrefix: `_${operatorPrefix}`
25
+ operatorPrefix: `_${operatorPrefix}`,
26
+ payload,
27
+ steps
26
28
  });
27
29
  if (errors.length > 0) {
28
30
  throw errors[0];
@@ -279,7 +279,38 @@ const meta = {
279
279
  prep
280
280
  }
281
281
  };
282
+ function runFormat({ params, location }) {
283
+ let template;
284
+ let lookup;
285
+ if (type.isArray(params)) {
286
+ if (!type.isString(params[0])) {
287
+ throw new Error(`Operator Error: _string.format - first array element must be the template string at ${location}.`);
288
+ }
289
+ template = params[0];
290
+ const values = params.slice(1);
291
+ lookup = (key)=>values[Number(key)];
292
+ } else if (type.isObject(params)) {
293
+ if (!type.isString(params.template)) {
294
+ throw new Error(`Operator Error: _string.format - "template" must be a string at ${location}.`);
295
+ }
296
+ template = params.template;
297
+ const on = params.on ?? {};
298
+ lookup = (key)=>on[key];
299
+ } else {
300
+ throw new Error(`Operator Error: _string.format accepts an array or object at ${location}.`);
301
+ }
302
+ return template.replace(/\{\{|\}\}|\{(\w+)\}/g, (match, key)=>{
303
+ if (match === '{{') return '{';
304
+ if (match === '}}') return '}';
305
+ const v = lookup(key);
306
+ return type.isNone(v) ? '' : String(v);
307
+ });
308
+ }
282
309
  function _string({ params, location, methodName }) {
310
+ if (methodName === 'format') return runFormat({
311
+ params,
312
+ location
313
+ });
283
314
  return runInstance({
284
315
  location,
285
316
  meta,
@@ -15,6 +15,6 @@
15
15
  */ export default {
16
16
  type: 'object',
17
17
  params: {
18
- description: 'String method params. Accepts array positional args or object with named args depending on method.'
18
+ description: 'String method params. Accepts array positional args or object with named args depending on method. The "format" method takes a template string with {0}/{1} positional placeholders (array form) or {name} placeholders (object form: { template, on }).'
19
19
  }
20
20
  };
@@ -12,8 +12,70 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ import { getFromObject } from '@lowdefy/operators';
16
- function _user({ arrayIndices, location, params, user }) {
15
+ */ import { type } from '@lowdefy/helpers';
16
+ import { getFromObject } from '@lowdefy/operators';
17
+ const roleMethods = [
18
+ 'hasRole',
19
+ 'hasSomeRoles',
20
+ 'hasAllRoles'
21
+ ];
22
+ function getUserRoles({ user, methodName }) {
23
+ const roles = user?.roles;
24
+ if (type.isNone(roles)) return [];
25
+ if (!type.isArray(roles)) {
26
+ throw new Error(`_user.${methodName} expects "user.roles" to be an array of strings. Received ${JSON.stringify(roles)}.`);
27
+ }
28
+ return roles;
29
+ }
30
+ function validateRoleString({ params, methodName }) {
31
+ if (!type.isString(params)) {
32
+ throw new Error(`_user.${methodName} accepts a string. Received ${JSON.stringify(params)}.`);
33
+ }
34
+ return params;
35
+ }
36
+ function validateRoleArray({ params, methodName }) {
37
+ if (!type.isArray(params) || !params.every((role)=>type.isString(role))) {
38
+ throw new Error(`_user.${methodName} accepts an array of strings. Received ${JSON.stringify(params)}.`);
39
+ }
40
+ return params;
41
+ }
42
+ function _user({ arrayIndices, location, methodName, params, user }) {
43
+ if (methodName === 'hasRole') {
44
+ const role = validateRoleString({
45
+ params,
46
+ methodName
47
+ });
48
+ const userRoles = getUserRoles({
49
+ user,
50
+ methodName
51
+ });
52
+ return userRoles.includes(role);
53
+ }
54
+ if (methodName === 'hasSomeRoles') {
55
+ const required = validateRoleArray({
56
+ params,
57
+ methodName
58
+ });
59
+ const userRoles = getUserRoles({
60
+ user,
61
+ methodName
62
+ });
63
+ return required.some((role)=>userRoles.includes(role));
64
+ }
65
+ if (methodName === 'hasAllRoles') {
66
+ const required = validateRoleArray({
67
+ params,
68
+ methodName
69
+ });
70
+ const userRoles = getUserRoles({
71
+ user,
72
+ methodName
73
+ });
74
+ return required.every((role)=>userRoles.includes(role));
75
+ }
76
+ if (!type.isUndefined(methodName)) {
77
+ throw new Error(`_user.${methodName} is not supported, use one of the following: ${roleMethods.join(', ')}.`);
78
+ }
17
79
  return getFromObject({
18
80
  arrayIndices,
19
81
  location,
@@ -18,7 +18,7 @@
18
18
  oneOf: [
19
19
  {
20
20
  type: 'string',
21
- description: 'Dot-notation path to value in user object.'
21
+ description: 'Dot-notation path to value in user object, or a role name when used with a role method.'
22
22
  },
23
23
  {
24
24
  type: 'integer',
@@ -31,6 +31,13 @@
31
31
  ],
32
32
  description: 'Return all user data.'
33
33
  },
34
+ {
35
+ type: 'array',
36
+ items: {
37
+ type: 'string'
38
+ },
39
+ description: 'Array of role names when used with a role method.'
40
+ },
34
41
  {
35
42
  type: 'object',
36
43
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/operators-js",
3
- "version": "5.0.0",
3
+ "version": "5.2.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -43,12 +43,12 @@
43
43
  "dist/*"
44
44
  ],
45
45
  "dependencies": {
46
- "@lowdefy/helpers": "5.0.0",
47
- "@lowdefy/operators": "5.0.0"
46
+ "@lowdefy/helpers": "5.2.0",
47
+ "@lowdefy/operators": "5.2.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@jest/globals": "28.1.3",
51
- "@lowdefy/node-utils": "5.0.0",
51
+ "@lowdefy/node-utils": "5.2.0",
52
52
  "@swc/cli": "0.8.0",
53
53
  "@swc/core": "1.15.18",
54
54
  "@swc/jest": "0.2.39",