@lowdefy/operators 5.5.1 → 6.0.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/dist/evaluateOperators.js +30 -5
- package/dist/getFromObject.js +14 -8
- package/dist/webParser.js +2 -1
- package/package.json +5 -5
|
@@ -45,7 +45,14 @@ function hasDynamicMarker(value) {
|
|
|
45
45
|
if ((type.isArray(value) || type.isObject(value)) && value['~dyn'] === true) return true;
|
|
46
46
|
return hasDynChild(value);
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
// Build-time prefixes are '_build.' and its escaped forms ('__build.', '___build.', …)
|
|
49
|
+
// produced when _function re-parses its body with `_${operatorPrefix}`. Runtime
|
|
50
|
+
// prefixes ('_', '__', '___', …) never match. Escape depth does not change the
|
|
51
|
+
// evaluation mode: any build prefix means the author asked for build-time evaluation.
|
|
52
|
+
function isBuildPrefix(operatorPrefix) {
|
|
53
|
+
return /^_+build\.$/.test(operatorPrefix);
|
|
54
|
+
}
|
|
55
|
+
function evaluateOperators({ input, operators, operatorPrefix = '_', env, lowdefyApp, dynamicIdentifiers, typeNames, args }) {
|
|
49
56
|
if (type.isUndefined(input)) {
|
|
50
57
|
return {
|
|
51
58
|
output: input,
|
|
@@ -57,6 +64,7 @@ function evaluateOperators({ input, operators, operatorPrefix = '_', env, dynami
|
|
|
57
64
|
}
|
|
58
65
|
const resolvedDynamicIdentifiers = dynamicIdentifiers ?? new Set();
|
|
59
66
|
const resolvedTypeNames = typeNames ?? new Set();
|
|
67
|
+
const isBuildTimePrefix = isBuildPrefix(operatorPrefix);
|
|
60
68
|
const errors = [];
|
|
61
69
|
const parser = {
|
|
62
70
|
parse: ({ args: callArgs, input: callInput, operatorPrefix: callPrefix })=>evaluateOperators({
|
|
@@ -64,6 +72,7 @@ function evaluateOperators({ input, operators, operatorPrefix = '_', env, dynami
|
|
|
64
72
|
operators,
|
|
65
73
|
operatorPrefix: callPrefix ?? operatorPrefix,
|
|
66
74
|
env,
|
|
75
|
+
lowdefyApp,
|
|
67
76
|
dynamicIdentifiers: resolvedDynamicIdentifiers,
|
|
68
77
|
typeNames: resolvedTypeNames,
|
|
69
78
|
args: callArgs
|
|
@@ -100,7 +109,7 @@ function evaluateOperators({ input, operators, operatorPrefix = '_', env, dynami
|
|
|
100
109
|
}
|
|
101
110
|
// Bubble up ~dyn from children (but not at type boundaries).
|
|
102
111
|
// _build.* operators always evaluate even with dynamic params, so skip bubble-up for them.
|
|
103
|
-
const isBuildOperator = isOperatorObject &&
|
|
112
|
+
const isBuildOperator = isOperatorObject && isBuildTimePrefix;
|
|
104
113
|
if (!isTypeBoundary && !isBuildOperator && hasDynamicMarker(node)) {
|
|
105
114
|
return setDynamicMarker(node);
|
|
106
115
|
}
|
|
@@ -111,17 +120,32 @@ function evaluateOperators({ input, operators, operatorPrefix = '_', env, dynami
|
|
|
111
120
|
const [op, methodName] = `_${key.substring(operatorPrefix.length)}`.split('.');
|
|
112
121
|
// Dynamic identifier check — skip for _build.* operators
|
|
113
122
|
const fullIdentifier = methodName ? `${op}.${methodName}` : op;
|
|
114
|
-
if (
|
|
123
|
+
if (!isBuildTimePrefix) {
|
|
115
124
|
if (resolvedDynamicIdentifiers.has(fullIdentifier) || resolvedDynamicIdentifiers.has(op)) {
|
|
116
125
|
return setDynamicMarker(node);
|
|
117
126
|
}
|
|
118
127
|
}
|
|
119
|
-
// Unknown operator
|
|
128
|
+
// Unknown operator. Under a runtime prefix an operator may be runtime-only,
|
|
129
|
+
// so it is deferred by marking it dynamic. Under a build prefix (at any escape
|
|
130
|
+
// depth) the author asked for build-time evaluation, so an unknown operator
|
|
131
|
+
// (typo, or a runtime-only operator misused at build time) is a config error.
|
|
120
132
|
if (type.isUndefined(operators[op])) {
|
|
133
|
+
if (isBuildTimePrefix) {
|
|
134
|
+
const error = new ConfigError(`Operator "${key}" is not a valid _build operator.`, {
|
|
135
|
+
configKey: node['~k'],
|
|
136
|
+
received: {
|
|
137
|
+
[key]: node[key]
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
error.lineNumber = node['~l'];
|
|
141
|
+
error.refId = node['~r'];
|
|
142
|
+
errors.push(error);
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
121
145
|
return setDynamicMarker(node);
|
|
122
146
|
}
|
|
123
147
|
// Dynamic params check — skip for _build.* operators (they always evaluate)
|
|
124
|
-
if (
|
|
148
|
+
if (!isBuildTimePrefix) {
|
|
125
149
|
if (hasDynamicMarker(node[key])) {
|
|
126
150
|
return setDynamicMarker(node);
|
|
127
151
|
}
|
|
@@ -135,6 +159,7 @@ function evaluateOperators({ input, operators, operatorPrefix = '_', env, dynami
|
|
|
135
159
|
args,
|
|
136
160
|
arrayIndices: [],
|
|
137
161
|
env,
|
|
162
|
+
lowdefyApp,
|
|
138
163
|
methodName,
|
|
139
164
|
operators,
|
|
140
165
|
params,
|
package/dist/getFromObject.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
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 { applyArrayIndices, get, serializer, type } from '@lowdefy/helpers';
|
|
15
|
+
*/ import { ReservedKeyError, applyArrayIndices, get, serializer, type } from '@lowdefy/helpers';
|
|
16
16
|
function getFromObject({ params, object, arrayIndices, operator, location }) {
|
|
17
17
|
if (params === true) params = {
|
|
18
18
|
all: true
|
|
@@ -23,20 +23,26 @@ function getFromObject({ params, object, arrayIndices, operator, location }) {
|
|
|
23
23
|
if (!type.isObject(params)) {
|
|
24
24
|
throw new Error(`${operator} params must be of type string, integer, boolean or object.`);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
const defaultValue = get(params, 'default', {
|
|
27
27
|
default: null,
|
|
28
28
|
copy: true
|
|
29
29
|
});
|
|
30
|
+
if (params.key === null) return defaultValue;
|
|
30
31
|
if (params.all === true) return serializer.copy(object);
|
|
31
32
|
if (!type.isString(params.key) && !type.isInt(params.key)) {
|
|
32
33
|
throw new Error(`${operator}.key must be of type string or integer.`);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
default:
|
|
35
|
+
try {
|
|
36
|
+
return get(object, applyArrayIndices(arrayIndices, params.key), {
|
|
37
|
+
default: defaultValue,
|
|
37
38
|
copy: true
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
});
|
|
40
|
+
} catch (error) {
|
|
41
|
+
// Tier 2: a runtime read of an app-developer keypath. There is no loud failure that helps here —
|
|
42
|
+
// a thrown error in the browser is worse than the default, and the reserved rule's job (refusing
|
|
43
|
+
// the read) is already done. Author-written identifiers fail loudly at build instead.
|
|
44
|
+
if (error instanceof ReservedKeyError) return defaultValue;
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
export default getFromObject;
|
package/dist/webParser.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/operators",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"dist/*"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@lowdefy/errors": "
|
|
38
|
-
"@lowdefy/helpers": "
|
|
37
|
+
"@lowdefy/errors": "6.0.0",
|
|
38
|
+
"@lowdefy/helpers": "6.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@jest/globals": "28.1.3",
|
|
42
|
-
"@swc/cli": "0.8.
|
|
43
|
-
"@swc/core": "1.15.
|
|
42
|
+
"@swc/cli": "0.8.1",
|
|
43
|
+
"@swc/core": "1.15.32",
|
|
44
44
|
"@swc/jest": "0.2.39",
|
|
45
45
|
"jest": "28.1.3",
|
|
46
46
|
"jest-environment-jsdom": "28.1.3"
|