elysiajs / elysia

Ergonomic Framework for Humans
https://elysiajs.com
MIT License
9.23k stars 198 forks source link

Object encoding in query parameters #606

Open m1212e opened 3 months ago

m1212e commented 3 months ago

Calling the API via the treaty encodes objects passed as query params as literally "[object Object]" instead of URL encoding it.

      this.iam.auth.domain.user.get({
        query: {
          role: [{ id: orga.adminRoleId }, { id: orga.memberRoleId }],
        },
      })

and on the receiving end:

      query: t.Optional(
        t.Object({
          role: t.Optional(
            t.Array(t.Partial(t.Pick(Role, ["id", "name", "authProviderId"]))),
          ),
        }),
      ),

results in

   "type": "validation",
   "on": "query",
   "property": "/role",
   "message": "Expected array",
   "expected": {},
   "found": {
     "role": "[object Object],[object Object]"
   },
   "errors": [
     {
       "type": 6,
       "schema": {
         "type": "array",
         "items": {
           "description": "Composition of RolePlain, RoleRelations",
           "additionalProperties": false,
           "type": "object",
           "properties": {
             "id": {
               "type": "string"
             },
             "name": {
               "type": "string"
             },
             "authProviderId": {
               "type": "string"
             }
           }
         }
       },
       "path": "/role",
       "value": "[object Object],[object Object]",
       "message": "Expected array"
     }
   ]
 }. Thrown at Error: {
   "type": "validation",
   "on": "query",
   "property": "/role",
   "message": "Expected array",
   "expected": {},
   "found": {
     "role": "[object Object],[object Object]"
   },

Is this as it should work and we are just expected to only send primitive values via query parameters? Thanks!

m1212e commented 3 months ago

Just realized that it may not be the intended usage for query parameters to be anything beyond strings: https://elysiajs.com/validation/schema-type#query

If thats the case, maybe it would make sense to only every allow strings or optional strings to be passed as query schema to the handler?

SaltyAom commented 1 month ago

Object encoded query is implemented in 1.0.23, let me know if it works or not

m1212e commented 1 month ago

Hi @SaltyAom,

unfortunately I get some errors when I try to use object encoded queries:

  server.get(
    "/domain/:domainId/user",
    ({ params, query }) => {
      // this is a prisma db query
      return db.user.findMany({
        where: {
          domainId: params.domainId,
          roles: query?.role
            ? {
                some: query.role,
              }
            : undefined,
        },
      });
    },
    {
      response: t.Array(User),
      query: t.Optional(
        t.Object({
          // role: t.Optional(t.String()),
          role: t.Optional(t.Object({ id: t.Optional(t.String()) })),
        }),
      ),
    },
  )

results in

Error in GET /domain/2a42f947-93c9-4493-9f9a-93254a6e171f/user: UNKNOWN JSON Parse error: Unexpected identifier "undefined". Thrown at SyntaxError: JSON Parse error: Unexpected identifier "undefined"
    at <parse> (:0)
    at parse (native)
    at <anonymous> (:67:29)
    at handle (:50:32)
    at map (:259:35)
{"originalLine":67,"originalColumn":29}

which is probably not what should happen ? :D This happens on an empty query, I don't send along any query.

When using this endpoint from the treaty client like this:

.user.get({
  query: {
    role: {
      id: "054ce000-cc5a-4e5b-a7e1-1cfd45c18c3f",
    },
  },
});

I get

Error in GET /domain/2a42f947-93c9-4493-9f9a-93254a6e171f/user: UNKNOWN JSON Parse error: Unexpected identifier "object". Thrown at SyntaxError: JSON Parse error: Unexpected identifier "object"
    at <parse> (:0)
    at parse (native)
    at <anonymous> (:67:29)
    at handle (:50:32)
    at map (:256:32)
{"originalLine":67,"originalColumn":29}

instead. I have normalization enabled.

m1212e commented 1 month ago

Should I open a new issue?

SaltyAom commented 1 month ago

Should be related to #677, let me know if the latest commit fix the problem

MatthewAry commented 1 month ago

Still seeing this issue.

87 |                             Object.assign(c, transformed)
88 | 
89 | if(params.Check(c.params) === false) {
90 |                             c.set.status = 422; throw new ValidationError('params', params, c.params)
91 |                     }
92 | if(typeof c.query['ids'] === "object") c.query['ids'] = JSON.parse(c.query['ids'])
                                                                       ^
SyntaxError: JSON Parse error: Unable to parse JSON string

Where the validation is:

  query: t.Object({
    ids: t.Union([t.Array(t.Numeric()), t.Numeric()])
  })

On ElysiaJS 1.0.25

MatthewAry commented 4 weeks ago

Just some additional feedback related to query parameters. Trying to set up query param validations for sorting, filtering, grouping and such is very difficult right now. Would be awesome to see some design patterns, even something that would combine Drizzle ORM and ElysiaJS for filtering on a data table for strings, numbers, and dates.

SaltyAom commented 3 weeks ago

@MatthewAry should be fixed in 1e0331f, including test case, published under 1.0.27

adarshaacharya commented 1 week ago

Still getting the same issue, object aren't being encoded using eden + elysia.