@withone/cli 1.20.1 → 1.20.3
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/index.js +37 -3
- package/package.json +1 -1
- package/skills/one/references/flows.md +61 -3
package/dist/index.js
CHANGED
|
@@ -2455,6 +2455,16 @@ ${JSON.stringify(st.example, null, 2)}
|
|
|
2455
2455
|
- **Interpolation** (\`{{$.input.x}}\`): Use inside string values where the selector is embedded in text \u2014 e.g., \`"Hello {{$.steps.getUser.response.name}}"\`. The resolved value is always stringified. Use this in \`data\`, \`pathVars\`, and \`queryParams\` when mixing selectors with literal text.
|
|
2456
2456
|
- **Rule of thumb**: If the value is purely a selector, use bare. If it's a string containing a selector, use \`{{...}}\`.
|
|
2457
2457
|
|
|
2458
|
+
### Selectors vs expressions
|
|
2459
|
+
|
|
2460
|
+
Selectors in data fields (\`data\`, \`queryParams\`, \`pathVars\`, \`connectionKey\`) are **dot-path lookups only** \u2014 they do not support JavaScript operators like \`||\` or \`&&\`. For default values, use the \`default\` field on the input definition:
|
|
2461
|
+
|
|
2462
|
+
\`\`\`json
|
|
2463
|
+
{ "inputs": { "maxResults": { "type": "number", "default": 10 } } }
|
|
2464
|
+
\`\`\`
|
|
2465
|
+
|
|
2466
|
+
The \`if\`, \`unless\`, \`condition.expression\`, \`while.condition\`, \`transform.expression\`, and \`code.source\` fields **do** support full JavaScript expressions (e.g., \`$.input.email && $.input.email.length > 0\`).
|
|
2467
|
+
|
|
2458
2468
|
### \`output\` vs \`response\` on step results
|
|
2459
2469
|
|
|
2460
2470
|
Every completed step produces both \`output\` and \`response\`:
|
|
@@ -2745,11 +2755,12 @@ function validateSelectorReferences(flow2) {
|
|
|
2745
2755
|
return ids;
|
|
2746
2756
|
}
|
|
2747
2757
|
const allStepIds = getAllStepIds(flow2.steps);
|
|
2758
|
+
const SELECTOR_TOKEN_RE = /\$\.[a-zA-Z_][\w.\[\]*]*/g;
|
|
2748
2759
|
function extractSelectors(value) {
|
|
2749
2760
|
const selectors = [];
|
|
2750
2761
|
if (typeof value === "string") {
|
|
2751
|
-
|
|
2752
|
-
selectors.push(
|
|
2762
|
+
for (const match of value.matchAll(SELECTOR_TOKEN_RE)) {
|
|
2763
|
+
selectors.push(match[0]);
|
|
2753
2764
|
}
|
|
2754
2765
|
const interpolated = value.matchAll(/\{\{(\$\.[^}]+)\}\}/g);
|
|
2755
2766
|
for (const match of interpolated) {
|
|
@@ -2784,6 +2795,24 @@ function validateSelectorReferences(flow2) {
|
|
|
2784
2795
|
}
|
|
2785
2796
|
}
|
|
2786
2797
|
}
|
|
2798
|
+
const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
|
|
2799
|
+
function checkOperatorsInSelectorField(value, path5) {
|
|
2800
|
+
if (typeof value === "string" && value.startsWith("$.")) {
|
|
2801
|
+
if (value.includes("||")) {
|
|
2802
|
+
errors.push({ path: path5, message: `Selector "${value}" contains unsupported operator "||". Selectors in data fields use dot-path resolution, not JS evaluation. Use the "default" field on the input definition instead, or use a "code" step for complex expressions.` });
|
|
2803
|
+
} else if (value.includes("&&")) {
|
|
2804
|
+
errors.push({ path: path5, message: `Selector "${value}" contains unsupported operator "&&". Selectors in data fields use dot-path resolution, not JS evaluation. Use a "condition" step or "code" step for complex expressions.` });
|
|
2805
|
+
}
|
|
2806
|
+
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2807
|
+
for (const [k, v] of Object.entries(value)) {
|
|
2808
|
+
checkOperatorsInSelectorField(v, `${path5}.${k}`);
|
|
2809
|
+
}
|
|
2810
|
+
} else if (Array.isArray(value)) {
|
|
2811
|
+
for (let i = 0; i < value.length; i++) {
|
|
2812
|
+
checkOperatorsInSelectorField(value[i], `${path5}[${i}]`);
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2787
2816
|
function checkStep(step, pathPrefix) {
|
|
2788
2817
|
if (step.if) checkSelectors(extractSelectors(step.if), `${pathPrefix}.if`);
|
|
2789
2818
|
if (step.unless) checkSelectors(extractSelectors(step.unless), `${pathPrefix}.unless`);
|
|
@@ -2796,7 +2825,12 @@ function validateSelectorReferences(flow2) {
|
|
|
2796
2825
|
if (fd.stepsArray) continue;
|
|
2797
2826
|
const value = config[fieldName];
|
|
2798
2827
|
if (value !== void 0) {
|
|
2799
|
-
|
|
2828
|
+
const fieldKey = `${descriptor.configKey}.${fieldName}`;
|
|
2829
|
+
const fieldPath = `${pathPrefix}.${fieldKey}`;
|
|
2830
|
+
checkSelectors(extractSelectors(value), fieldPath);
|
|
2831
|
+
if (!EXPRESSION_FIELDS.has(fieldKey)) {
|
|
2832
|
+
checkOperatorsInSelectorField(value, fieldPath);
|
|
2833
|
+
}
|
|
2800
2834
|
}
|
|
2801
2835
|
}
|
|
2802
2836
|
}
|
package/package.json
CHANGED
|
@@ -102,6 +102,20 @@ Connection inputs with a `connection` field auto-resolve if the user has exactly
|
|
|
102
102
|
|
|
103
103
|
A pure `$.xxx` value resolves to the raw type. A string containing `{{$.xxx}}` does string interpolation.
|
|
104
104
|
|
|
105
|
+
### Selectors vs expressions
|
|
106
|
+
|
|
107
|
+
Selectors in data fields (`data`, `queryParams`, `pathVars`, `connectionKey`) are **dot-path lookups only** — they do not support JavaScript operators like `||` or `&&`. For default values, use the `default` field on the input definition:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"inputs": {
|
|
112
|
+
"maxResults": { "type": "number", "default": 10 }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The `if`, `unless`, `condition.expression`, `while.condition`, `transform.expression`, and `code.source` fields **do** support full JavaScript expressions (e.g., `$.input.email && $.input.email.length > 0`).
|
|
118
|
+
|
|
105
119
|
## Step Types
|
|
106
120
|
|
|
107
121
|
### `action` — Execute a One API action
|
|
@@ -172,14 +186,47 @@ A pure `$.xxx` value resolves to the raw type. A string containing `{{$.xxx}}` d
|
|
|
172
186
|
|
|
173
187
|
### `parallel` — Run steps concurrently
|
|
174
188
|
|
|
189
|
+
Use when fetching from 2+ independent data sources before combining results. Each substep must have the full step schema (`id`, `name`, `type`, and type-specific config).
|
|
190
|
+
|
|
175
191
|
```json
|
|
176
192
|
{
|
|
177
|
-
"id": "
|
|
193
|
+
"id": "fetchAll",
|
|
194
|
+
"name": "Fetch email and calendar data in parallel",
|
|
178
195
|
"type": "parallel",
|
|
179
|
-
"parallel": {
|
|
196
|
+
"parallel": {
|
|
197
|
+
"maxConcurrency": 5,
|
|
198
|
+
"steps": [
|
|
199
|
+
{
|
|
200
|
+
"id": "fetchEmails",
|
|
201
|
+
"name": "Fetch recent emails",
|
|
202
|
+
"type": "action",
|
|
203
|
+
"action": {
|
|
204
|
+
"platform": "gmail",
|
|
205
|
+
"actionId": "conn_mod_def::GmailListMessages::xxx",
|
|
206
|
+
"connectionKey": "$.input.gmailKey",
|
|
207
|
+
"pathVars": { "userId": "me" },
|
|
208
|
+
"queryParams": { "maxResults": 10 }
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "fetchEvents",
|
|
213
|
+
"name": "Fetch today's calendar events",
|
|
214
|
+
"type": "action",
|
|
215
|
+
"action": {
|
|
216
|
+
"platform": "google-calendar",
|
|
217
|
+
"actionId": "conn_mod_def::CalendarListEvents::xxx",
|
|
218
|
+
"connectionKey": "$.input.calendarKey",
|
|
219
|
+
"pathVars": { "calendarId": "primary" },
|
|
220
|
+
"queryParams": { "maxResults": 10 }
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
180
225
|
}
|
|
181
226
|
```
|
|
182
227
|
|
|
228
|
+
After a parallel step, access each substep's output by its `id`: `$.steps.fetchEmails.response`, `$.steps.fetchEvents.response`.
|
|
229
|
+
|
|
183
230
|
### `file-read` / `file-write` — Filesystem access
|
|
184
231
|
|
|
185
232
|
```json
|
|
@@ -247,7 +294,18 @@ Strategies: `fail` (default), `continue`, `retry`, `fallback`.
|
|
|
247
294
|
|
|
248
295
|
Conditional execution: `"if": "$.steps.find.response.data.length > 0"`
|
|
249
296
|
|
|
250
|
-
## AI-Augmented
|
|
297
|
+
## AI-Augmented Patterns
|
|
298
|
+
|
|
299
|
+
### When to use parallel steps
|
|
300
|
+
|
|
301
|
+
Use `parallel` when your workflow fetches from 2+ independent data sources before combining them. Common patterns:
|
|
302
|
+
- Fetch Gmail + Calendar + Sheets → compile into daily briefing
|
|
303
|
+
- Search Exa + scrape with Firecrawl → merge research data
|
|
304
|
+
- Query BigQuery + list Google Drive files → combine for analysis
|
|
305
|
+
|
|
306
|
+
Each substep inside `parallel.steps` must have the full step schema: `id`, `name`, `type`, and the type-specific config (`action`, `code`, etc.). Follow a parallel step with a `code` or `transform` step to combine the results.
|
|
307
|
+
|
|
308
|
+
### file-write -> bash -> code
|
|
251
309
|
|
|
252
310
|
When raw data needs analysis, use this pattern:
|
|
253
311
|
1. `file-write` — save data to temp file (API responses are too large to inline)
|