mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-09-17 10:37:16 +03:00
Update .build route helper
This commit is contained in:
parent
fc541ab861
commit
389713fe2e
@ -4,6 +4,7 @@ import type {
|
||||
RouteDefinitionsToRoutes,
|
||||
OptionalRouteOptions,
|
||||
ParamValue,
|
||||
ExpandRouteOnOptionalStaticSegments,
|
||||
} from './types'
|
||||
|
||||
// PUBLIC API
|
||||
@ -11,18 +12,14 @@ export const routes = {
|
||||
{=# routes =}
|
||||
{= name =}: {
|
||||
to: "{= urlPath =}",
|
||||
{=# hasUrlParams =}
|
||||
build: (
|
||||
options: {
|
||||
options{=^ hasUrlParams =}?{=/ hasUrlParams =}:
|
||||
OptionalRouteOptions
|
||||
{=# hasUrlParams =}& {
|
||||
params: {{=# urlParams =}{= name =}{=# isOptional =}?{=/ isOptional =}: ParamValue;{=/ urlParams =}}
|
||||
} & OptionalRouteOptions,
|
||||
) => interpolatePath("{= urlPath =}", options.params, options?.search, options?.hash),
|
||||
{=/ hasUrlParams =}
|
||||
{=^ hasUrlParams =}
|
||||
build: (
|
||||
options?: OptionalRouteOptions,
|
||||
) => interpolatePath("{= urlPath =}", undefined, options?.search, options?.hash),
|
||||
{=/ hasUrlParams =}
|
||||
}{=/ hasUrlParams =}
|
||||
{=# hasOptionalStaticSegments =}& { path: ExpandRouteOnOptionalStaticSegments<"{= urlPath =}"> }{=/ hasOptionalStaticSegments =}
|
||||
) => interpolatePath({=# hasOptionalStaticSegments =}options.path{=/ hasOptionalStaticSegments =}{=^ hasOptionalStaticSegments =}"{= urlPath =}"{=/ hasOptionalStaticSegments =}, {=^ hasUrlParams =}undefined{=/ hasUrlParams =}{=# hasUrlParams =}options.params{=/ hasUrlParams =}, options?.search, options?.hash),
|
||||
},
|
||||
{=/ routes =}
|
||||
} as const;
|
||||
|
@ -2,7 +2,7 @@
|
||||
export type RouteDefinitionsToRoutes<Routes extends RoutesDefinition> =
|
||||
RouteDefinitionsToRoutesObj<Routes>[keyof RouteDefinitionsToRoutesObj<Routes>]
|
||||
|
||||
// PRIVATE API
|
||||
// PRIVATE API
|
||||
export type OptionalRouteOptions = {
|
||||
search?: Search
|
||||
hash?: string
|
||||
@ -40,6 +40,7 @@ type ParamsFromBuildFn<BF extends BuildFn> = Parameters<BF>[0] extends {
|
||||
? { params: Params }
|
||||
: { params?: never }
|
||||
|
||||
// PRIVATE API (sdk)
|
||||
/**
|
||||
* Optional static segments handling: expands routes with optional segments
|
||||
* into multiple routes, one for each possible combination of optional segments.
|
||||
@ -48,7 +49,7 @@ type ParamsFromBuildFn<BF extends BuildFn> = Parameters<BF>[0] extends {
|
||||
* - /users/:id
|
||||
* - /users/tasks/:id
|
||||
*/
|
||||
type ExpandRouteOnOptionalStaticSegments<S extends string> = S extends '/'
|
||||
export type ExpandRouteOnOptionalStaticSegments<S extends string> = S extends '/'
|
||||
? '/'
|
||||
: `/${JoinPath<JoinSegments<ExpandOptionalSegments<SplitPath<S>>>>}`
|
||||
|
||||
|
@ -12,7 +12,7 @@ import qualified Wasp.AppSpec.Route as AS.Route
|
||||
import Wasp.Generator.FileDraft (FileDraft)
|
||||
import Wasp.Generator.Monad (Generator)
|
||||
import qualified Wasp.Generator.SdkGenerator.Common as C
|
||||
import Wasp.Util.WebRouterPath (Param (Optional, Required), extractPathParams)
|
||||
import qualified Wasp.Util.WebRouterPath as WebRouterPath
|
||||
|
||||
genNewClientRouterApi :: AppSpec -> Generator [FileDraft]
|
||||
genNewClientRouterApi spec =
|
||||
@ -37,13 +37,16 @@ createRouteTemplateData (name, route) =
|
||||
[ "name" .= name,
|
||||
"urlPath" .= path,
|
||||
"urlParams" .= map mapPathParamToJson urlParams,
|
||||
"hasUrlParams" .= (not . null $ urlParams)
|
||||
"hasUrlParams" .= (not . null $ urlParams),
|
||||
"hasOptionalStaticSegments" .= (not . null $ optionalStaticSegments)
|
||||
]
|
||||
where
|
||||
path = AS.Route.path route
|
||||
|
||||
urlParams = extractPathParams path
|
||||
routeSegments = WebRouterPath.getRouteSegments path
|
||||
urlParams = [param | WebRouterPath.ParamSegment param <- routeSegments]
|
||||
optionalStaticSegments = [segment | (WebRouterPath.StaticSegment (WebRouterPath.OptionalStaticSegment segment)) <- routeSegments]
|
||||
|
||||
mapPathParamToJson :: Param -> Aeson.Value
|
||||
mapPathParamToJson (Required paramName) = object ["name" .= paramName, "isOptional" .= False]
|
||||
mapPathParamToJson (Optional paramName) = object ["name" .= paramName, "isOptional" .= True]
|
||||
mapPathParamToJson :: WebRouterPath.ParamSegment -> Aeson.Value
|
||||
mapPathParamToJson (WebRouterPath.RequiredParamSegment paramName) = object ["name" .= paramName, "isOptional" .= False]
|
||||
mapPathParamToJson (WebRouterPath.OptionalParamSegment paramName) = object ["name" .= paramName, "isOptional" .= True]
|
||||
|
@ -1,22 +1,39 @@
|
||||
module Wasp.Util.WebRouterPath where
|
||||
module Wasp.Util.WebRouterPath
|
||||
( Segment (StaticSegment, ParamSegment),
|
||||
StaticSegment (RequiredStaticSegment, OptionalStaticSegment),
|
||||
ParamSegment (RequiredParamSegment, OptionalParamSegment),
|
||||
getRouteSegments,
|
||||
)
|
||||
where
|
||||
|
||||
import Data.List (isSuffixOf)
|
||||
import Data.List.Split (splitOn)
|
||||
import Data.Maybe (mapMaybe)
|
||||
|
||||
data Param = Optional String | Required String deriving (Show, Eq)
|
||||
data Segment = StaticSegment StaticSegment | ParamSegment ParamSegment deriving (Show, Eq)
|
||||
|
||||
-- TODO: upgrade to work with React Router v6: https://reactrouter.com/en/main/route/route#splats
|
||||
-- Maybe explode all optional segments and then compute the routes for the Link component
|
||||
-- This would mean we have two different lists: routes and links?
|
||||
extractPathParams :: String -> [Param]
|
||||
extractPathParams = mapMaybe parseParam . splitOn "/"
|
||||
data StaticSegment = RequiredStaticSegment StaticSegmentValue | OptionalStaticSegment StaticSegmentValue deriving (Show, Eq)
|
||||
|
||||
data ParamSegment = RequiredParamSegment ParamName | OptionalParamSegment ParamName deriving (Show, Eq)
|
||||
|
||||
type StaticSegmentValue = String
|
||||
|
||||
type ParamName = String
|
||||
|
||||
getRouteSegments :: String -> [Segment]
|
||||
getRouteSegments = map parseSegment . splitOn "/"
|
||||
where
|
||||
parseParam :: String -> Maybe Param
|
||||
parseParam "*" = Just $ Required "splat"
|
||||
parseParam (':' : xs) =
|
||||
Just $
|
||||
if "?" `isSuffixOf` xs
|
||||
then Optional (take (length xs - 1) xs)
|
||||
else Required xs
|
||||
parseParam _ = Nothing
|
||||
parseSegment :: String -> Segment
|
||||
parseSegment "*" = ParamSegment $ RequiredParamSegment "splat"
|
||||
parseSegment (':' : xs) =
|
||||
ParamSegment $
|
||||
if isSegmentOptional xs
|
||||
then OptionalParamSegment (take (length xs - 1) xs)
|
||||
else RequiredParamSegment xs
|
||||
parseSegment x =
|
||||
StaticSegment $
|
||||
if isSegmentOptional x
|
||||
then OptionalStaticSegment x
|
||||
else RequiredStaticSegment x
|
||||
|
||||
isSegmentOptional :: String -> Bool
|
||||
isSegmentOptional = isSuffixOf "?"
|
||||
|
Loading…
Reference in New Issue
Block a user