Skip to content

refactor!: validate arguments with zod instead of ow - #986

Open
vdusek wants to merge 20 commits into
v3from
feat/replace-ow-with-zod
Open

refactor!: validate arguments with zod instead of ow#986
vdusek wants to merge 20 commits into
v3from
feat/replace-ow-with-zod

Conversation

@vdusek

@vdusek vdusek commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Replaces ow with zod for runtime argument validation, mirroring apify/apify-sdk-js#636 and apify/crawlee#3716 so all three packages share one error type and message format. Input validation only — response validation is a separate PR.

How it works

  • ArgumentValidationError and validate() are a hand-synced copy of the @crawlee/core / SDK ones — apify-client sits below both in the dependency graph.
  • zod ^4.0.0 matches the merged SDK PR.
  • Schemas use z.strictObject / z.looseObject / z.enum, not the deprecated .strict() / .passthrough() / z.nativeEnum().
  • chunkSize now works wherever the options interface extends PaginationOptions, via a shared paginationOptionsShape the schemas spread. It used to type-check but throw; ow's exactShape had the same gap.

Browser bundle

  • Tree-shaking and minification are back on in rsbuild.config.ts, off since the webpack-to-rsbuild migration in chore: update eslint, adopt prettier and rsbuild #671. Now 288 kB raw / 87 kB gzip, from 1439 kB / 273 kB — below the 946 kB / 203 kB before this PR. A 320 kB budget fails the build, so it cannot grow unnoticed again.

Breaking changes

  • Invalid arguments throw ArgumentValidationError (exported from apify-client), not ow's ArgumentError — different messages, the zod issues on issues, the original ZodError on cause.
  • Arrays and functions no longer pass where a plain object is expected: update() / create() fields, TaskClient.start() / call() input, the storage schema option, DatasetClient.pushItems() items.
  • Infinity no longer passes on numeric options such as waitSecs, timeoutSecs or memory, and an invalid Date no longer passes on startedBefore / startedAfterz.number() requires a finite number and z.date() a valid date, where ow only checked the type.
  • Options that were declared but always rejected at runtime are gone from the types: chunkSize on downloadItems() and createItemsPublicUrl(), signature on createItemsPublicUrl() and createKeysPublicUrl() — a compile error now instead of a throw.
  • Date, Map, Set and other class instances still pass as objects, as under ow.

✍️ Drafted by Claude Code

@vdusek vdusek added adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. labels Jul 30, 2026
@vdusek vdusek self-assigned this Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

⚠️ There are broken links in the documentation.

See more at https://github.com/apify/apify-client-js/actions/runs/31005542533#summary-92304422147

@vdusek vdusek changed the title refactor!: replace ow with zod for argument validation refactor!: validate arguments with zod instead of ow Jul 30, 2026
@vdusek
vdusek requested a review from B4nan July 31, 2026 09:40
@vdusek
vdusek marked this pull request as ready for review July 31, 2026 09:40
@vdusek
vdusek requested a review from szaganek as a code owner July 31, 2026 09:40
vdusek added 8 commits August 3, 2026 15:48
BREAKING CHANGE: runtime argument validation switched from `ow` to `zod`, so
every invalid-argument error message changed, and the thrown error is now an
`ArgumentValidationError` (newly exported from `apify-client`) instead of `ow`'s
`ArgumentError`. It exposes the structured zod issues on `issues` and keeps the
original `ZodError` on `cause`, so you can branch on them instead of parsing the
message. Values that `ow.object` accepted only incidentally are now rejected:
arrays no longer pass as objects for `update()` / `create()` fields, for
`TaskClient.start()` / `call()` input, for the storage `schema` option, or as
`DatasetClient.pushItems()` array items (which must be objects or strings).
@vdusek
vdusek force-pushed the feat/replace-ow-with-zod branch from 4e8b5c1 to b74a66e Compare August 3, 2026 13:48
B4nan added 4 commits August 3, 2026 17:19
The ow-based validation rejected symbol and bigint values loudly, but the
zod replacement only checked for undefined. A symbol value would then pass
validation, serialize to undefined, and silently PUT an empty record body.
Also fixes a pre-existing "validatioon" typo carried through two comments.
`describeReceived('')` used to produce bare backticks with nothing
between them, e.g. for `client.actor('')`.
@B4nan

B4nan commented Aug 3, 2026

Copy link
Copy Markdown
Member

Follow-ups: the browser bundle grows from 946 kB to 1446 kB raw (203 kB -> 272 kB gzip), because rsbuild.config.ts disables tree-shaking and minification; .strict(), .passthrough() and z.nativeEnum() are deprecated in zod 4 and could move to z.strictObject / z.looseObject / z.enum; chunkSize is missing from every .strict() list schema (pre-existing — ow's exactShape had the same gap).

I would rather fix it here before it gets merged. We don't want to use any deprecated methods, and this PR introduces the bundle size issue.

@vdusek

vdusek commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

I would rather fix it here before it gets merged. We don't want to use any deprecated methods, and this PR introduces the bundle size issue.

OK, I'll check it out

@vdusek
vdusek force-pushed the feat/replace-ow-with-zod branch from aa2684d to 41d769b Compare August 4, 2026 08:50
@vdusek

vdusek commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@B4nan it's ready for a re-check

@B4nan
B4nan requested a review from vladfrangu August 4, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants