gcanti / fp-ts-routing

A type-safe bidirectional routing library for TypeScript

Home Page:https://gcanti.github.io/fp-ts-routing/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Path parameters placed into query

chasent opened this issue · comments

I have noticed that when using path and query parameters together, the formatter toString() function returns a URI with the path parameters.

For example:

const t = require('io-ts')
const fpr = require('fp-ts-routing')

const result = fpr.lit('accounts')
  .then(fpr.str('accountId'))
  .then(fpr.lit('files'))
  .then(fpr.query(t.interface({ pathparam: t.string })))
  .formatter
  .run(fpr.Route.empty, { accountId: 'testId', pathparam: '123' })
  .toString()

 // result -> /accounts/testId/files?accountId=testId&pathparam=123

Is this behavior intended?

Looking at the implementation of the query function, it could possibly be modified so that only properties in the io-ts type are added tothe query.

Thanks,
Marc.

It would seem that the type.encode function from io-ts does not remove excess proeprties. As a workaround, I created a query function that uses only the types of the query.

export function query<A extends object, T>(type: t.InterfaceType<A, Record<keyof T, fpr.QueryValues>>): fpr.Match<A> {
  return new fpr.Match(
    new fpr.Parser((r: any) => { throw new Error() }),
    new fpr.Formatter((r, query: any) => {
      const p = r.parts
      const q = type.encode(Object.keys(type.props).reduce<any>((p, key) => ({ ...p, [key]: query[key] }), {} as any))
      return new fpr.Route(p, q)
    })
  )
}

It would seem that the type.encode function from io-ts does not remove excess proeprties

@chasent that's right, io-ts's interface doesn't cut excess properties. In order to do that you can use strict instead

assert.strictEqual(
  fpr
    .lit('accounts')
    .then(fpr.str('accountId'))
    .then(fpr.lit('files'))
    .then(fpr.query(t.strict({ pathparam: t.string })))
    .formatter.run(fpr.Route.empty, { accountId: 'testId', pathparam: '123' })
    .toString(),
  '/accounts/testId/files?pathparam=123'
)

@chasent I've added some documentation, thanks for pointing out.