-
-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@effect/platform
s Multipart
and UrlParams
modules do not support string[]
but should
#2873
Comments
@effect/platform
s Multipart
module does not support string[]
but should@effect/platform
s Multipart
and UrlParams
modules do not support string[]
but should
in my point of view these structures should only have fields parsed as as at the time of parsing you can never know if the user will want to parse the field as a string or an array with one element, in my opinion parsing a field as just string (in case there's only one entry) would be equivalent to database drivers returning
which looks like convenience but actually makes it harder to handle and a bit unpredictable recently I made a small utility just like this and I concluded it only makes sense to parse fields as and a convenience schema if the user wants just to use a single (the first value): const RequiredHead = <A, B, R>(s: S.Schema<A, B, R>) =>
S.NonEmptyArray(S.Any).pipe(
S.transform(s, {
decode: (a) => a[0],
encode: (s) => [s] as const,
strict: true,
}),
); the user then can always expect an array predictably, and doesn't need to handle unions of |
@arekmaz this would be right if we were validating, but we're parsing. And more importantly, multipart forms are designed such that you can take a single one, or get all of a thing. The schema should be accepting of schemas that take example: const MyForm = S.Struct({
thingId: S.String,
subthingIds: S.propertySignature(S.Array(S.String)).pipe(S.fromKey("subthingId[]"))
}) Also, the S.Array(mySchema).pipe(
S.headOrElse(),
) Would take the head of an array or fail the parse if it does not have a head. It optionally takes a thunk for a default value, and theres also the |
validation with your schema ‘MyForm’ will fail if there is only one element in the ‘subthingId’ which would be a perfectly valid one element array, unless you plan to include an array version alongside every field, thanks for the pointer on the head schema, but I think unless you plan to parse each field in two ways single and array eg ‘subthingIds[]’, the natural way for me would be array, you could say each field represents one or more values, and should be typed as or you could just say "I'm expecting every field to be an array of one or more values" which is in my opinion a better and simpler mental model |
@arekmaz I have no idea what you are basing this on... intuition? rationalization? You can check it out in the console if you wish, the difference is between |
that's exactly what I mean, the canonical shape should be |
But we're not whatwg, we don't get to decide, and they decided it's a sum type
every entry is a list of 0 or more values. With getting a single entry of key resulting in side note: I am completely ignoring file lists in the discussion because there are not changes that should be done there |
so how would you see parsing a field? let's see: single value const sp1 = new URLSearchParams([['a', 'a'], ['a', 'b']])
const s1 = Schema.Struct({
a: Schema.String
})
parseSearchParams(s1)(sp1) // fails multi value: const sp2 = new URLSearchParams([['a', 'a']])
const s2 = Schema.Struct({
a: Schema.Array(Schema.String)
})
parseSearchParams(s2)(sp2) // fails every field, doesn't matter what you expect would have to be parsed with something like: const StringOrArray = Schema.Union(Schema.String, Schema.Array(Schema.String))
const sp3 = new URLSearchParams([['a', 'a']])
const s3 = Schema.Struct({
a: StringOrArray
})
const r = parseSearchParams(s2)(sp2) // succeeds with { a: string | string[] }
// if I want a single value:
const a = Array.isArray(r.a) ? r.a[0] : r.a
// if I wanted an array:
const b = Array.isArray(r.a) ? r.a : [r.a] for me parsing everything as just an array is a way simpler mental model, in my opionion we don't have to follow the standards everywhere |
I don't understand, this is not an issue. We agree that this is not an issue. I showed exactly how this behaves. single value const sp1 = new URLSearchParams([['a', 'a'], ['a', 'b']])
const s1 = Schema.Struct({
a: Schema.String
})
parseSearchParams(s1)(sp1) // succeeds with { a: "a" } multi value const sp2 = new URLSearchParams([['a', 'a']])
const s2 = Schema.Struct({
a: Schema.Array(Schema.String)
})
parseSearchParams(s2)(sp2) // succeeds with { a: ["a"] } it is actually your case that is problematic const StringOrArray = Schema.Union(Schema.String, Schema.Array(Schema.String))
const sp3 = new URLSearchParams([['a', 'a']])
const s3 = Schema.Struct({
a: StringOrArray
})
const r = parseSearchParams(s2)(sp2) // fails. How can we decide if to `get` or `getAll`??? here is a quick mapping of value, expectation, operation, and result.
note that for So, why not always |
ah, ok, I see, the issue is, I'm assuming that the search params are parsed before they are decoded, as you saw the schema, has to take a parsing the what you are trying to suggest is to take this schema: export const schemaBodyUrlParams: <R, I extends Readonly<Record<string, string>>, A>(
schema: Schema.Schema<A, I, R>,
options?: ParseOptions | undefined
) => Effect.Effect<A, ParseResult.ParseError | Error.RequestError, R | ServerRequest> = internal.schemaBodyUrlParams somehow extract the "input" schema, and use that to decode the fields to achieve this intermediary object input form, before decoding it to the "output" A. If that's possible maybe that would work, even be more convenient, but also it would mean parsing search params for every "decoding". The thing is, this input object form, is supplied via a service What I'm proposing is that the "input" Maybe that was the misunderstanding. |
What version of Effect is running?
latested
What steps can reproduce the bug?
Try to work with multi-value fields on a
FormData
What is the expected behavior?
(and it's reprecussions)
What do you see instead?
The
Persisted
type of theMultipart
module and the general UrlParams and such:should also support
string[]
As supported by the
.append
and subsequently the.getAll
features ofFormData
Additional information
beep boop
The text was updated successfully, but these errors were encountered: