Skip to content

Commit f82984f

Browse files
committed
fixes
1 parent 4079f5a commit f82984f

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

botasaurus-controls/src/index.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ const affirmativeValues = new Set(["true", "yes", "y", "1", "yeah", "yep", "sure
248248
* @returns The trimmed searchMethod if provided, or undefined
249249
*/
250250
function validateOptionsOrSearchMethod(id: string, controlType: string, props: ControlInput<any, WithOptions>) {
251-
const hasOptions = props.options && props.options.length > 0;
251+
const hasOptions = !!props.options
252252
let trimmedSearchMethod: string | undefined = undefined;
253253

254254
// Trim searchMethod if it's a string
@@ -269,10 +269,42 @@ function validateOptionsOrSearchMethod(id: string, controlType: string, props: C
269269
)
270270
}
271271

272+
if (hasOptions) {
273+
validateOptions(props.options as any, controlType, id)
274+
}
275+
272276
return trimmedSearchMethod;
273277
}
274278

275279

280+
281+
function validateOptions(options:any[], controlType: string, id: string) {
282+
if (!Array.isArray(options)) {
283+
throw new Error(
284+
`${controlType} control with id '${id}' requires an array of options`
285+
)
286+
}
287+
if (!options.length) {
288+
throw new Error(
289+
`${controlType} control with id '${id}' requires at least one option`
290+
)
291+
}
292+
293+
options.forEach(option => {
294+
if (!isValidSelectOptionObject(option)) {
295+
296+
if (options.every(option => !isValidSelectOptionObject(option))) {
297+
throw new Error(
298+
`The Option of ${controlType} control with id "${id}" must be an object with 'value' and 'label' properties. Received: ${JSON.stringify(options)}`
299+
)
300+
}
301+
302+
throw new Error(
303+
`Each Option of ${controlType} control with id "${id}" must be an object with 'value' and 'label' properties. Received: ${JSON.stringify(option)}`
304+
)
305+
}
306+
})
307+
}
276308
/**
277309
* Validates that an item is a valid select option object with only value and label properties
278310
* @param item - The item to validate
@@ -592,11 +624,8 @@ class Controls {
592624
return this
593625
}
594626
choose(id: string, props: ControlInput<string, WithChooseOptions> = {}) {
595-
if (!props.options || !props.options.length) {
596-
throw new Error(
597-
`Choose control with id '${id}' requires at least one option`
598-
)
599-
}
627+
628+
validateOptions(props.options as any, 'Choose', id)
600629

601630
return this.add<string>(id, "choose", {
602631
...props,

docs/docs/botasaurus-desktop/enhancing-scrapers/input-controls.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,16 @@ A single-select dropdown menu. It requires either an `options` array or a `searc
133133

134134
To use `searchMethod`, you need to define async handler functions and add them using `Server.addSearchOptionsEndpoints()`.
135135

136-
**Backend Implementation:**
136+
**Input JS Implementation:**
137+
```ts
138+
.select("city", {
139+
searchMethod: "getCityOptions", // Backend method that fetches options
140+
canCreateOptions: true, // Allow users to create custom options
141+
defaultValue: {value: 'US__CA__SF', label: "San Francisco"},
142+
})
143+
```
144+
145+
**`server.ts` Implementation:**
137146
```ts
138147
import { Server } from 'botasaurus-server/server';
139148
import axios from 'axios';

0 commit comments

Comments
 (0)