(program: Command)
| 488 | } |
| 489 | |
| 490 | export function createRunAction(program: Command): (path: string | undefined, options: RunOptions) => Promise<void> { |
| 491 | return async (path, options) => { |
| 492 | try { |
| 493 | if (!path && !options.prompt) { |
| 494 | program.error(getChalk().red('Missing required argument: path (or use --prompt)'), { |
| 495 | exitCode: ExitCode.InvalidUsage, |
| 496 | }) |
| 497 | } |
| 498 | |
| 499 | debug(`Running file: ${path ?? '(prompt-only)'}`) |
| 500 | const safeOptions = { ...options, token: options.token ? '[redacted]' : undefined } |
| 501 | debug(`Options: ${JSON.stringify(safeOptions)}`) |
| 502 | |
| 503 | // Handle --list-inputs |
| 504 | if (options.listInputs) { |
| 505 | if (!path) { |
| 506 | program.error(getChalk().red('--list-inputs requires a file path'), { |
| 507 | exitCode: ExitCode.InvalidUsage, |
| 508 | }) |
| 509 | } |
| 510 | await listInputs(path, options) |
| 511 | return |
| 512 | } |
| 513 | |
| 514 | // Handle --dry-run |
| 515 | if (options.dryRun) { |
| 516 | if (!path) { |
| 517 | program.error(getChalk().red('--dry-run requires a file path'), { |
| 518 | exitCode: ExitCode.InvalidUsage, |
| 519 | }) |
| 520 | } |
| 521 | await dryRunDeepnoteProject(path, options) |
| 522 | return |
| 523 | } |
| 524 | |
| 525 | await runDeepnoteProject(path, options) |
| 526 | } catch (error) { |
| 527 | const message = error instanceof Error ? error.message : String(error) |
| 528 | // Use InvalidUsage for file/input/integration/init-resolver/API-auth errors — all user errors. |
| 529 | const isAuthApiError = error instanceof ApiError && (error.statusCode === 401 || error.statusCode === 403) |
| 530 | const exitCode = |
| 531 | error instanceof FileResolutionError || |
| 532 | error instanceof MissingInputError || |
| 533 | error instanceof MissingIntegrationError || |
| 534 | error instanceof InitNotebookResolutionError || |
| 535 | isAuthApiError |
| 536 | ? ExitCode.InvalidUsage |
| 537 | : ExitCode.Error |
| 538 | if (options.output === 'json') { |
| 539 | outputJson({ success: false, error: message }) |
| 540 | process.exitCode = exitCode |
| 541 | return |
| 542 | } |
| 543 | if (options.output === 'toon') { |
| 544 | outputToon({ success: false, error: message }) |
| 545 | process.exitCode = exitCode |
| 546 | return |
| 547 | } |
no test coverage detected