feat(workflow-executor): workflow executor package (rebased)#1525
feat(workflow-executor): workflow executor package (rebased)#1525matthv wants to merge 100 commits intofeat/prd-214-setup-workflow-executor-packagefrom
Conversation
# @forestadmin/datasource-toolkit [1.53.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-toolkit@1.52.0...@forestadmin/datasource-toolkit@1.53.0) (2026-03-18) ### Features * **api chart:** allow customizing api chart with query or body parameters ([#1491](#1491)) ([a7237f2](a7237f2))
## @forestadmin/ai-proxy [1.6.2](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/ai-proxy@1.6.1...@forestadmin/ai-proxy@1.6.2) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
# @forestadmin/datasource-customizer [1.69.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-customizer@1.68.2...@forestadmin/datasource-customizer@1.69.0) (2026-03-18) ### Features * **api chart:** allow customizing api chart with query or body parameters ([#1491](#1491)) ([a7237f2](a7237f2)) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-dummy [1.1.66](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-dummy@1.1.65...@forestadmin/datasource-dummy@1.1.66) (2026-03-18) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-mongoose [1.13.3](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-mongoose@1.13.2...@forestadmin/datasource-mongoose@1.13.3) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-sequelize [1.13.6](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-sequelize@1.13.5...@forestadmin/datasource-sequelize@1.13.6) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-sql [1.17.8](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-sql@1.17.7...@forestadmin/datasource-sql@1.17.8) (2026-03-18) ### Dependencies * **@forestadmin/datasource-sequelize:** upgraded to 1.13.6 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/forestadmin-client [1.37.18](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/forestadmin-client@1.37.17...@forestadmin/forestadmin-client@1.37.18) (2026-03-18) ### Dependencies * **@forestadmin/ai-proxy:** upgraded to 1.6.2 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/plugin-aws-s3 [1.5.10](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-aws-s3@1.5.9...@forestadmin/plugin-aws-s3@1.5.10) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0 * **@forestadmin/datasource-customizer:** upgraded to 1.69.0
## @forestadmin/plugin-export-advanced [1.1.40](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-export-advanced@1.1.39...@forestadmin/plugin-export-advanced@1.1.40) (2026-03-18) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/plugin-flattener [1.4.24](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-flattener@1.4.23...@forestadmin/plugin-flattener@1.4.24) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0 * **@forestadmin/datasource-customizer:** upgraded to 1.69.0
## @forestadmin/agent-client [1.4.14](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.13...@forestadmin/agent-client@1.4.14) (2026-03-18) ### Dependencies * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0 * **@forestadmin/forestadmin-client:** upgraded to 1.37.18
## @forestadmin/datasource-replica [1.8.4](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-replica@1.8.3...@forestadmin/datasource-replica@1.8.4) (2026-03-18) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-sequelize:** upgraded to 1.13.6 * **@forestadmin/datasource-sql:** upgraded to 1.17.8 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-mongo [1.6.7](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-mongo@1.6.6...@forestadmin/datasource-mongo@1.6.7) (2026-03-18) ### Dependencies * **@forestadmin/datasource-mongoose:** upgraded to 1.13.3 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/mcp-server [1.8.9](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/mcp-server@1.8.8...@forestadmin/mcp-server@1.8.9) (2026-03-18) ### Dependencies * **@forestadmin/agent-client:** upgraded to 1.4.14 * **@forestadmin/forestadmin-client:** upgraded to 1.37.18
# @forestadmin/agent [1.75.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.74.1...@forestadmin/agent@1.75.0) (2026-03-18) ### Features * **api chart:** allow customizing api chart with query or body parameters ([#1491](#1491)) ([a7237f2](a7237f2)) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0 * **@forestadmin/forestadmin-client:** upgraded to 1.37.18 * **@forestadmin/mcp-server:** upgraded to 1.8.9 * **@forestadmin/datasource-sql:** upgraded to 1.17.8
## @forestadmin/agent-testing [1.0.23](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-testing@1.0.22...@forestadmin/agent-testing@1.0.23) (2026-03-18) ### Dependencies * **@forestadmin/agent-client:** upgraded to 1.4.14 * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0 * **@forestadmin/forestadmin-client:** upgraded to 1.37.18 * **@forestadmin/agent:** upgraded to 1.75.0 * **@forestadmin/datasource-sql:** upgraded to 1.17.8
## @forestadmin/forest-cloud [1.12.98](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/forest-cloud@1.12.97...@forestadmin/forest-cloud@1.12.98) (2026-03-18) ### Dependencies * **@forestadmin/agent:** upgraded to 1.75.0 * **@forestadmin/datasource-customizer:** upgraded to 1.69.0 * **@forestadmin/datasource-mongo:** upgraded to 1.6.7 * **@forestadmin/datasource-mongoose:** upgraded to 1.13.3 * **@forestadmin/datasource-sequelize:** upgraded to 1.13.6 * **@forestadmin/datasource-sql:** upgraded to 1.17.8 * **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
## @forestadmin/datasource-customizer [1.69.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-customizer@1.69.0...@forestadmin/datasource-customizer@1.69.1) (2026-03-31) ### Bug Fixes * **capabilities:** fix aggregation validation on computed field ([#1519](#1519)) ([79056f7](79056f7))
## @forestadmin/datasource-dummy [1.1.67](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-dummy@1.1.66...@forestadmin/datasource-dummy@1.1.67) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/plugin-aws-s3 [1.5.11](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-aws-s3@1.5.10...@forestadmin/plugin-aws-s3@1.5.11) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/plugin-export-advanced [1.1.41](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-export-advanced@1.1.40...@forestadmin/plugin-export-advanced@1.1.41) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/plugin-flattener [1.4.25](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/plugin-flattener@1.4.24...@forestadmin/plugin-flattener@1.4.25) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/datasource-replica [1.8.5](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/datasource-replica@1.8.4...@forestadmin/datasource-replica@1.8.5) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/agent [1.75.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.75.0...@forestadmin/agent@1.75.1) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
## @forestadmin/agent-testing [1.0.24](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-testing@1.0.23...@forestadmin/agent-testing@1.0.24) (2026-03-31) ### Dependencies * **@forestadmin/datasource-customizer:** upgraded to 1.69.1 * **@forestadmin/agent:** upgraded to 1.75.1
## @forestadmin/forest-cloud [1.12.99](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/forest-cloud@1.12.98...@forestadmin/forest-cloud@1.12.99) (2026-03-31) ### Dependencies * **@forestadmin/agent:** upgraded to 1.75.1 * **@forestadmin/datasource-customizer:** upgraded to 1.69.1
- Bump sequelize ^6.37.8 (SQL injection CVE) - Bump @modelcontextprotocol/sdk ^1.28.0 (fixes transitive hono, @hono/node-server, express-rate-limit) - Bump typedoc ^0.28.18 (fixes transitive markdown-it) - Bump forest-cli 5.3.9 (ships fixed sequelize) - Re-resolve @aws-sdk/xml-builder to 3.972.16 (ships fixed fast-xml-parser 5.5.8) - Remove 6 stale resolutions now covered by parent package bumps Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…premature deps, add smoke test - Rewrite CLAUDE.md with project overview and architecture principles, remove changelog - Remove unused dependencies (ai-proxy, sequelize, zod) per YAGNI - Add smoke test so CI passes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… document system architecture
- Lint now covers src and test directories
- Replace require() with import, use stronger assertion (toHaveLength)
- Add System Architecture section describing Front/Orchestrator/Executor/Agent
- Mark Architecture Principles as planned (not yet implemented)
- Remove redundant test/.gitkeep
- Make index.ts a valid module with export {}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…erver (#1504) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: alban bertolini <albanb@forestadmin.com>
…+ DatabaseStore) (#1506)
…xecutor factories (#1510)
…ain (#1512) Co-authored-by: alban bertolini <albanb@forestadmin.com>
- Fix ai-proxy McpClient API changes (tools → loadTools, closeConnections → dispose) - Merge ai-proxy router imports (BraveToolProvider + validateAiConfigurations) - Update internal dependency versions to match main Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
16 new issues
|
| pendingStepExecutions: '/liana/v1/workflow-step-executions/pending', | ||
| pendingStepExecutionForRun: (runId: string) => | ||
| `/liana/v1/workflow-step-executions/pending?runId=${encodeURIComponent(runId)}`, | ||
| updateStepExecution: (runId: string) => `/liana/v1/workflow-step-executions/${runId}/complete`, |
There was a problem hiding this comment.
🟡 Medium adapters/forest-server-workflow-port.ts:14
When runId contains URL-reserved characters (like /, ?, or #), ROUTES.updateStepExecution produces a malformed path because the parameter is not encoded. Unlike ROUTES.pendingStepExecutionForRun which correctly uses encodeURIComponent, the unencoded runId in line 14 causes incorrect routing or 404 errors when the value is interpolated into the path.
- updateStepExecution: (runId: string) => `/liana/v1/workflow-step-executions/${runId}/complete`,
+ updateStepExecution: (runId: string) => `/liana/v1/workflow-step-executions/${encodeURIComponent(runId)}/complete`,🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/adapters/forest-server-workflow-port.ts around line 14:
When `runId` contains URL-reserved characters (like `/`, `?`, or `#`), `ROUTES.updateStepExecution` produces a malformed path because the parameter is not encoded. Unlike `ROUTES.pendingStepExecutionForRun` which correctly uses `encodeURIComponent`, the unencoded `runId` in line 14 causes incorrect routing or 404 errors when the value is interpolated into the path.
Evidence trail:
packages/workflow-executor/src/adapters/forest-server-workflow-port.ts lines 12-14 at REVIEWED_COMMIT:
- Line 12-13: `pendingStepExecutionForRun` uses `encodeURIComponent(runId)`
- Line 14: `updateStepExecution` does NOT use `encodeURIComponent(runId)`
| }; | ||
| } | ||
|
|
||
| function createWorkflowExecutor( |
There was a problem hiding this comment.
🟢 Low src/build-workflow-executor.ts:77
The stopTimeoutMs option is accepted in ExecutorOptions and passed through buildCommonDependencies, but createWorkflowExecutor never receives it. The force exit timeout on line 115 always uses the hardcoded FORCE_EXIT_DELAY_MS (5000ms), making the user-configured value ineffective.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/build-workflow-executor.ts around line 77:
The `stopTimeoutMs` option is accepted in `ExecutorOptions` and passed through `buildCommonDependencies`, but `createWorkflowExecutor` never receives it. The force exit timeout on line 115 always uses the hardcoded `FORCE_EXIT_DELAY_MS` (5000ms), making the user-configured value ineffective.
Evidence trail:
packages/workflow-executor/src/build-workflow-executor.ts lines 20, 37, 70, 73, 108-111, 145, 165 at REVIEWED_COMMIT. Key evidence: `stopTimeoutMs` defined in ExecutorOptions (line 37), included in buildCommonDependencies return (line 70), but createWorkflowExecutor signature only accepts (runner, server, logger) (line 73), and uses hardcoded FORCE_EXIT_DELAY_MS=5000 (lines 20, 108-111).
| return promise; | ||
| } | ||
|
|
||
| private async doExecuteStep(step: PendingStepExecution, key: string): Promise<void> { |
There was a problem hiding this comment.
🟠 High src/runner.ts:236
The finally block deletes the step key from inFlightSteps before updateStepExecution reports the outcome. During this window, a concurrent runPollCycle can fetch the same pending step, see it's not in-flight, and spawn a duplicate execution. Move the deletion to after the outcome is successfully reported.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/runner.ts around line 236:
The `finally` block deletes the step key from `inFlightSteps` before `updateStepExecution` reports the outcome. During this window, a concurrent `runPollCycle` can fetch the same pending step, see it's not in-flight, and spawn a duplicate execution. Move the deletion to after the outcome is successfully reported.
Evidence trail:
packages/workflow-executor/src/runner.ts lines 237-268: `doExecuteStep` method shows `finally` block at line 253 with `this.inFlightSteps.delete(key)` executing before `updateStepExecution` call at line 256. packages/workflow-executor/src/runner.ts lines 200-206: `runPollCycle` filters steps using `!this.inFlightSteps.has(Runner.stepKey(s))` check.
| user: StepUser, | ||
| ): Promise<RecordData[]> { | ||
| const client = this.createClient(user); | ||
| const relatedSchema = this.resolveSchema(relation); |
There was a problem hiding this comment.
🟢 Low adapters/agent-client-agent-port.ts:92
In getRelatedData, resolveSchema(relation) passes the relation name (e.g., "orders") to the schema cache, but relation names often differ from their target collection names. When the lookup fails, it silently falls back to primaryKeyFields: ['id'] on line 155. This causes extractRecordId on line 104 to extract wrong primary key values when the actual related collection has a composite key or differently-named primary key field, producing RecordData with incorrect recordId values.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/adapters/agent-client-agent-port.ts around line 92:
In `getRelatedData`, `resolveSchema(relation)` passes the relation name (e.g., "orders") to the schema cache, but relation names often differ from their target collection names. When the lookup fails, it silently falls back to `primaryKeyFields: ['id']` on line 155. This causes `extractRecordId` on line 104 to extract wrong primary key values when the actual related collection has a composite key or differently-named primary key field, producing `RecordData` with incorrect `recordId` values.
Evidence trail:
packages/workflow-executor/src/adapters/agent-client-agent-port.ts:87-106 (getRelatedData method, line 92 calls resolveSchema(relation)), packages/workflow-executor/src/adapters/agent-client-agent-port.ts:148-157 (resolveSchema method with fallback to primaryKeyFields: ['id']), packages/workflow-executor/src/schema-cache.ts:15,26 (cache is keyed by collectionName), packages/workflow-executor/src/types/record.ts:11-13 (FieldSchema has relatedCollectionName property that should be used), packages/workflow-executor/test/adapters/agent-client-agent-port.test.ts:55-65 (test setup shows 'orders' collection with composite key ['tenantId', 'orderId'])
| export interface ReadRecordStepExecutionData extends BaseStepExecutionData { | ||
| type: 'read-record'; | ||
| executionParams: { fields: FieldRef[] }; | ||
| executionResult: { fields: FieldReadResult[] }; |
There was a problem hiding this comment.
🟢 Low types/step-execution-data.ts:38
ReadRecordStepExecutionData marks executionResult as required, but every other step type has executionResult?: (optional). This breaks the incremental data-building pattern used elsewhere—code that creates a ReadRecordStepExecutionData before execution completes will fail TypeScript compilation. Consider adding ? to make it optional like the other step types.
- executionResult: { fields: FieldReadResult[] };
+ executionResult?: { fields: FieldReadResult[] };🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/types/step-execution-data.ts around lines 38-41:
`ReadRecordStepExecutionData` marks `executionResult` as required, but every other step type has `executionResult?:` (optional). This breaks the incremental data-building pattern used elsewhere—code that creates a `ReadRecordStepExecutionData` before execution completes will fail TypeScript compilation. Consider adding `?` to make it optional like the other step types.
Evidence trail:
packages/workflow-executor/src/types/step-execution-data.ts at REVIEWED_COMMIT:
- Line 40: `executionResult: { fields: FieldReadResult[] };` (required, no `?`)
- Line 16: `executionResult?: { answer: string };` (optional)
- Line 49: `executionResult?: { updatedValues: Record<string, unknown> } | { skipped: true };` (optional)
- Line 72: `executionResult?: { success: true; actionResult: unknown } | { skipped: true };` (optional)
- Line 93: `executionResult?: ...` (optional)
- Line 103: `executionResult?: Record<string, unknown>;` (optional)
- Line 125: `executionResult?: { relation: RelationRef; record: RecordRef } | { skipped: true };` (optional)
| // NOTE: The Zod schema's .min(0).max(maxIndex) shapes the tool prompt only — it is NOT | ||
| // validated against the AI response. This guard is the sole runtime enforcement. | ||
| if (recordIndex < 0 || recordIndex > maxIndex) { | ||
| throw new InvalidAIResponseError( |
There was a problem hiding this comment.
🟢 Low executors/load-related-record-step-executor.ts:442
The runtime validation in selectBestRecordIndex only checks range, not integer type. If the AI returns a float like 1.5, it passes the range check but candidates[1.5] returns undefined (JavaScript arrays only accept integer indices), causing a TypeError when callers access .recordId on the result.
- if (recordIndex < 0 || recordIndex > maxIndex) {
+ if (!Number.isInteger(recordIndex) || recordIndex < 0 || recordIndex > maxIndex) {🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/executors/load-related-record-step-executor.ts around line 442:
The runtime validation in `selectBestRecordIndex` only checks range, not integer type. If the AI returns a float like `1.5`, it passes the range check but `candidates[1.5]` returns `undefined` (JavaScript arrays only accept integer indices), causing a TypeError when callers access `.recordId` on the result.
Evidence trail:
packages/workflow-executor/src/executors/load-related-record-step-executor.ts lines 410-419 (Zod schema with .int()), lines 440-445 (comment stating Zod is not validated + runtime guard without integer check), lines 233-236 (caller using returned index for array access), lines 203-210 (preRecordedArgs path showing integer check pattern that's missing from AI path), lines 447-454 (toRecordRef function that would receive undefined).
Summary
Rebased version of #1493 onto current
main(was 76 commits behind).@forestadmin/workflow-executorpackage: step executors, HTTP server, RunStore (in-memory + Sequelize), adapters, graceful shutdownbuildDatabaseExecutor/buildInMemoryExecutorfactory functionsReplaces #1493 (protected branch prevented force-push after rebase).
Test plan
yarn workspace @forestadmin/workflow-executor test— 427 tests passyarn workspace @forestadmin/workflow-executor lint— cleanyarn workspace @forestadmin/ai-proxy build— compiles after rebase conflict resolution🤖 Generated with Claude Code
Note
Add workflow-executor package with AI-driven step executors and HTTP server
@forestadmin/workflow-executorpackage that polls for pending workflow steps, executes them via AI-backed executors, and exposes a Koa HTTP server for run access and triggering.condition,read-record,update-record,trigger-action,load-related-record, andmcpstep types, each supporting automatic execution or user-confirmation flows with persistence viaRunStore.InMemoryStoreandDatabaseStore(Sequelize + Umzug migrations) run store backends, exposed throughbuildInMemoryExecutorandbuildDatabaseExecutorfactory functions.ai-proxyto use aToolProviderinterface, addingForestIntegrationClientfor Zendesk tools,BraveToolProvider, and acreateToolProvidersfactory that replaces the previous MCP-onlymcpConfigswith a unifiedtoolConfigsmap.renderCharton datasource, collection, and decorators) to accept and forward an optionalparametersrecord, parsed from request query/body by a newQueryStringParser.parseChartParametersmethod.mcpConfigsis renamed totoolConfigsacross route args and public interfaces; consumers passingmcpConfigsdirectly will break.📊 Macroscope summarized 2ea7e95. 55 files reviewed, 10 issues evaluated, 1 issue filtered, 2 comments posted
🗂️ Filtered Issues
packages/workflow-executor/src/adapters/agent-client-agent-port.ts — 0 comments posted, 2 evaluated, 1 filtered
limit !== nullon line 98 does not handleundefined. Iflimitis omitted from the query (making itundefined),undefined !== nullevaluates totrue, causing{ pagination: { size: undefined, number: 1 } }to be passed to the API. The check should use loose equalitylimit != nullto correctly handle bothnullandundefined. [ Failed validation ]