Git Product home page Git Product logo

react-route-manager's People

Contributors

miking-the-viking avatar

Stargazers

 avatar

react-route-manager's Issues

Improved means for ordering routes

Currently routes are implicitly ordered based upon their top level route array definition, by their order in the children route array, and by their order as a computed variant route.

To provide an alternate order that is up to consuming application, it should trivial and cleanly handled at a configuration level or by an exposed option/method of the React Route Manager to reduce the amount of boilerplate logic RRM-consuming applications are required to provide.

Typesafety for dynamic route path based on params object

Try to complete the idea below

type DynamicParam<S extends string> = `:${S}`
type DynamicParamRoute<T extends string> = `${string}/${DynamicParam<T>}/${string}` | `${DynamicParam<T>}/${string}` | `${string}/${DynamicParam<T>}` | `${DynamicParam<T>}`

type UserParamRoute = DynamicParamRoute<'user'>

const u1: UserParamRoute = ':user'
const u2: UserParamRoute = 'prefix/:user'
const u3: UserParamRoute = ':user/suffix'
const u4: UserParamRoute = 'prefix/:user/suffix'

type TeamParamRoute = DynamicParamRoute<'team'>

const t1: TeamParamRoute = ':team'
const t2: TeamParamRoute = 'prefix/:team'
const t3: TeamParamRoute = ':team/suffix'
const t4: TeamParamRoute = 'prefix/:team/suffix'

type UserTeamParamRoute = UserParamRoute & TeamParamRoute
// const ut1: UserTeamParamRoute = 'user/team'  // Type '"user/team"' is not assignable to type 'UserTeamParamRoute'.ts(2322)
// const ut1: UserTeamParamRoute = ':user'      // Type '":user"' is not assignable to type 'UserTeamParamRoute'.ts(2322)
// const ut1: UserTeamParamRoute = ':team'      // Type '":team"' is not assignable to type 'UserTeamParamRoute'.ts(2322)
const ut1: UserTeamParamRoute = ':user/:team'
const ut2: UserTeamParamRoute = 'prefix/:user/:team'
const ut3: UserTeamParamRoute = ':user/:team/suffix'
const ut4: UserTeamParamRoute = ':user/middle/params/:team'


const params = {
  currency: 'someting',
  meme: 'someotherthing'
} as const

const ps = ['currency', 'meme'] as const
const ps1 = ['currency', 'meme']

type Params = keyof typeof params
// type SafeParams = UnionToTuple<Params>

// type RouteParams = DynamicParamRoute<Params>
type RouteParams = DynamicParamRoute<'currency'> & DynamicParamRoute<'meme'>
const r1: RouteParams = ':currency'
const p1: RouteParams = ':meme'
// const rp: RouteParams = 'currencymeme'
// const rp0: RouteParams = ''
// const rp01: RouteParams = 'missingall'
const rp1: RouteParams = ':currency/:meme'
const rp2: RouteParams = 'prefix/:currency/:meme'
const rp3: RouteParams = ':currency/:meme/suffix'
const rp4: RouteParams = ':currency/middle/params/:meme'
const pr1: RouteParams = ':meme/:currency'
const pr2: RouteParams = 'prefix/:meme/:currency'
const pr3: RouteParams = ':meme/:currency/suffix'
const pr4: RouteParams = ':meme/middle/params/:currency'

// // // add an element to the end of a tuple
// type Push<L extends any[], T> =
//   ((r: any, ...x: L) => void) extends ((...x: infer L2) => void) ?
//   { [K in keyof L2]-?: K extends keyof L ? L[K] : T } : never

// // convert a union to an intersection: X | Y | Z ==> X & Y & Z
// type UnionToIntersection<U> =
//   (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

// // convert a union to an overloaded function X | Y ==> ((x: X)=>void) & ((y:Y)=>void)     
// type UnionToOvlds<U> = UnionToIntersection<U extends any ? (f: U) => void : never>;

// // convert a union to a tuple X | Y => [X, Y]
// // a union of too many elements will become an array instead
// type UnionToTuple<U> = UTT0<U> extends infer T ? T extends any[] ?
//   Exclude<U, T[number]> extends never ? T : U[] : never : never

// // each type function below pulls the last element off the union and 
// // pushes it onto the list it builds
// type UTT0<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTT1<Exclude<U, A>>, A> : []
// type UTT1<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTT2<Exclude<U, A>>, A> : []
// type UTT2<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTT3<Exclude<U, A>>, A> : []
// type UTT3<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTT4<Exclude<U, A>>, A> : []
// type UTT4<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTT5<Exclude<U, A>>, A> : []
// type UTT5<U> = UnionToOvlds<U> extends ((a: infer A) => void) ? Push<UTTX<Exclude<U, A>>, A> : []
// type UTTX<U> = []; // bail out

Add support for RouteRule to return parameterized route with parameters

ex: Crypto-Holdings redirect if you have no holdings should be that crypto's page /cypto/:whatever/, NOT /crypto

export const RequiresHoldingsInCryptoRedirectRule: RouteRuleGen<
  CryptoState,
  { currency?: string }
> = [
  ({ currency = undefined }) => RequiresHoldingsInCrypto({ currency }),
  CRYPTO,
];

MVP

  • State-update -> Apply redirect/access rules? (ex: if state-driven rule that was passing for this route stops passing due to an asynchronous state update then apply redirect rule)
  • Lots of tests
  • Change Route definition from name to title to align better with HTML
  • Allow overriding Loading Suspense fallback at both Router and individual Route levels

ACL Rule Conventions and DRY

ACL using RRM has a few rough conventions established which could be simplified into a reusable class.

Types of Rules and Redirects

Rules

Rules are either (1) static in their evaluation path (such as a boolean state-driven condition like isAuthenticated) or (2) dynamic in their evaluation path (such as RequiresMinimumClickCount, or a generic implementation).

This leads to two potential Rule definitions:

  1. Rule - static evaluation pathway
  2. RuleGenerator - dynamic evaluation pathway, function that generates a Rule

Rule

Fundamentally an atomic, synchronous function that takes in a generic of the RouterState and evaluates to true or false.

type Rule<
  RouteManagerState extends Record<string, unknown>
> = (state: RouteManagerState) => boolean

RuleGenerator

Due to the potential for unknown requirements and extensible implementations of a Rule, support for a RuleGenerator would be ideal.

type RuleGenerator<DynamicRequirements extends unknown, RouteManagerState extends Record<string, unknown>> = (dynamicReqs: DynamicRequirements) => Rule<RouteManagerState>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.