feat!: Introduce @seamapi/url-search-params-parser behind useLegacyQueryParamsParser - #182
Draft
razor-x wants to merge 1 commit into
Draft
feat!: Introduce @seamapi/url-search-params-parser behind useLegacyQueryParamsParser#182razor-x wants to merge 1 commit into
razor-x wants to merge 1 commit into
Conversation
This was referenced Aug 5, 2026
…eryParamsParser Add query string parsing with @seamapi/url-search-params-parser (in generous mode) behind a new useLegacyQueryParamsParser option, settable on createWithRouteSpec and per route via the route spec. The legacy hand-rolled coercion remains the default in v4, so upgrading changes no query parsing behavior; set useLegacyQueryParamsParser: false to opt into the new parser. The default will swap in v5. The parser module is loaded lazily, so routes on the legacy default never load it and CommonJS-transformed consumers do not need to resolve the ESM-only dependency. BREAKING CHANGE: The supportedArrayFormats setup option, the QueryArrayFormat and QueryArrayFormats types, and the DEFAULT_ARRAY_FORMATS export are removed. All routes now accept the repeated, bracket, and comma array formats, which was already the default behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015jWzL9LC7Q6bTGaXDoKq4z
razor-x
force-pushed
the
claude/url-param-parser-migration-i9foa1
branch
from
August 6, 2026 07:07
b52c8fc to
d55e304
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Targets
beta(v4). Introduces query string parsing with@seamapi/url-search-params-parser(in generous mode,strict: false) behind a newuseLegacyQueryParamsParseroption — with the legacy parser remaining the default.The release plan:
beta): dropping CJS/ESM-only is the headline breaking change (already onbetavia 4.0.0-beta.1). The new parser ships behind an option; upgrading changes no query parsing behavior by default.useLegacyQueryParamsParsersticks around as the escape hatch before being removed in a later release.The option
Settable in two places; the route spec overrides the factory:
The parser module is loaded lazily (dynamic
import()), so routes on the legacy default never load it, and consumers loading nextlove through a CommonJS transform (e.g. tsx/cjs, esbuild-register test setups) don't need to resolve the ESM-only dependency unless they opt in.Breaking change (beyond the ESM-only change already on beta)
supportedArrayFormatsis removed fromSetupParams/RequestInput, along with theQueryArrayFormat/QueryArrayFormatstypes and theDEFAULT_ARRAY_FORMATSexport. All callers were using the default (all three formats), and both parsers now accept the repeated, bracket, and comma formats on every route. Routes that restricted formats lose theBracket syntax not supported.../Repeated parameters not supported...400s.What changes when a route opts in (
useLegacyQueryParamsParser: false)None of this applies on the default; it's the v5 migration checklist.
New capabilities (previously rejected, now accepted):
z.number()/z.date()query params parse withoutz.coerce(?limit=5→5); whitespace is trimmed around numbers/booleans/dates.true/True/TRUE/yes/Yes/YES/1→true;false/False/FALSE/no/No/NO/0→false(legacy: only"true"is truthy, anything else isfalse).?address.city=SF,?tags.a=1&tags.b=2.z.union()/z.discriminatedUnion()of objects are parsed.Stricter parsing (previously accepted, now 400):
?flag=yolowas silentlyfalse, now400 invalid_input).null(?name=passedz.string()as"", now fails unless nullable; omitting the param still works for optional fields).400 invalid_query_params: repeated non-array params (?id=1&id=2), mixed array formats (?ids=1&ids[]=2), commas inside bracket values (?ids[]=a,b, previously split), repeated values containing commas (?ids=a,b&ids=c,d, previously literal), arrays mixing empty and non-empty values. Net: array values containing a literal comma can't be transmitted in generous mode.commonParamsbody values are no longer coerced ({"ids": "a,b"}was comma-split,{"flag": "true"}coerced) — bodies validate as-is.Schema restrictions (route authors): unsupported constructs fail every request with
500 unparseable_schemainstead of validating raw strings —z.array(z.boolean()), arrays of objects, nullable arrays,z.tuple()(see #180),z.any()/z.unknown()/z.bigint()props, intersections/maps/sets, records of non-primitives, unions of incompatible primitives. Inventory route schemas before opting in (or opt in per route and keep the offenders on legacy until adjusted). Errortypechanges: ambiguity errors move from Zod'sinvalid_inputtoinvalid_query_params.Implementation notes
req.url's search params (strict: false), strip absent (undefined) keys, overlay Next.js dynamic route params and unknown params (preserving.strict()/.passthrough()semantics), thenschema.parse.UnparseableSearchParamError→400 invalid_query_params;UnparseableSchemaError→500 unparseable_schema.commonParamsmerges the raw (pre-validation) body over the query in both paths.Testing
0.2.1, including:"yolo"→false, repeated values keeping commas