({
config,
dependencies,
jobIndex,
logger,
watches: _watches,
}: {
config: Config;
dependencies: Record<string, string>;
jobIndex: number;
logger: Logger;
/**
* Always undefined on the first run, defined on subsequent runs.
*/
watches?: ReadonlyArray<WatchValues>;
})
| 24 | import { PythonRenderer } from './py-dsl'; |
| 25 | |
| 26 | export async function createClient({ |
| 27 | config, |
| 28 | dependencies, |
| 29 | jobIndex, |
| 30 | logger, |
| 31 | watches: _watches, |
| 32 | }: { |
| 33 | config: Config; |
| 34 | dependencies: Record<string, string>; |
| 35 | jobIndex: number; |
| 36 | logger: Logger; |
| 37 | /** |
| 38 | * Always undefined on the first run, defined on subsequent runs. |
| 39 | */ |
| 40 | watches?: ReadonlyArray<WatchValues>; |
| 41 | }): Promise<Context | undefined> { |
| 42 | const watches: ReadonlyArray<WatchValues> = |
| 43 | _watches || |
| 44 | Array.from({ length: config.input.length }, () => ({ |
| 45 | headers: new Headers(), |
| 46 | })); |
| 47 | |
| 48 | const jobStart = Date.now(); |
| 49 | const inputPaths = config.input.map((input) => compileInputPath(input)); |
| 50 | |
| 51 | // on first run, print the message as soon as possible |
| 52 | if (!_watches) { |
| 53 | logInputPaths(inputPaths, jobIndex, config.logs.level); |
| 54 | } |
| 55 | |
| 56 | const getSpecData = async (input: Input, index: number) => { |
| 57 | const eventSpec = logger.timeEvent('spec'); |
| 58 | const { arrayBuffer, error, resolvedInput, response } = await getSpec({ |
| 59 | fetchOptions: input.fetch, |
| 60 | inputPath: inputPaths[index]!.path, |
| 61 | timeout: input.watch.timeout, |
| 62 | watch: watches[index]!, |
| 63 | }); |
| 64 | eventSpec.timeEnd(); |
| 65 | |
| 66 | // throw on first run if there's an error to preserve user experience |
| 67 | // if in watch mode, subsequent errors won't throw to gracefully handle |
| 68 | // cases where server might be reloading |
| 69 | if (error && !_watches) { |
| 70 | const text = await response.text().catch((): string => ''); |
| 71 | const message = `Request failed with status ${response.status}: ${text || response.statusText}`; |
| 72 | // Handle 4xx client errors as input errors (bad URL, bad API key, etc.) |
| 73 | if (response.status >= 400 && response.status < 500) { |
| 74 | const statusText = response.statusText || 'Unknown'; |
| 75 | const originalError = new Error(message) as Error & { source?: string }; |
| 76 | originalError.source = String(inputPaths[index]!.path); |
| 77 | throw new InputError( |
| 78 | `Input request failed: ${response.status} ${statusText}`, |
| 79 | originalError, |
| 80 | ); |
| 81 | } |
| 82 | // For 5xx server errors, keep the generic error (could be a bug) |
| 83 | throw new Error(message); |
nothing calls this directly
no test coverage detected