import { fold } from "fp-ts/lib/Either" import { pipe } from "fp-ts/lib/function" import * as t from "io-ts" const CustomParam = t.type({ isOptional: t.boolean, name: t.string, type: t.literal("custom"), }) export type CustomParam = t.TypeOf const UIDParam = t.type({ isOptional: t.boolean, type: t.literal("uid"), }) export type UIDParam = t.TypeOf const LangParam = t.type({ isOptional: t.boolean, type: t.literal("lang"), }) export type LangParam = t.TypeOf //TODO: think about removing dynamic param const DynamicParam = t.union([CustomParam, UIDParam, LangParam]) export type DynamicParam = t.TypeOf const StaticParam = t.type({ value: t.string, type: t.literal("static"), }) export type StaticParam = t.TypeOf const URLParam = t.union([StaticParam, DynamicParam]) export type URLParam = t.TypeOf const URLPattern = t.type({ trailingSlash: t.boolean, params: t.array(URLParam), }) export type URLPattern = t.TypeOf const CustomTypeObject = t.type({ id: t.string, }) export type CustomTypeObject = t.TypeOf const CustomTypeObjectWithStringId = new t.Type( "CustomTypeObjectWithStringId", (u): u is string => typeof u === "string", (u, c) => { if (typeof u === "string") { return t.success(u) } const validation = CustomTypeObject.validate(u, c) return pipe( validation, fold( () => t.failure(u, c, "Invalid CustomTypeObject"), (obj) => t.success(obj.id), ), ) }, (id) => id, ) const Relation = t.type({ customTypeID: t.string, relationName: t.string, targetCustomTypeID: CustomTypeObjectWithStringId, }) const URLResolver = t.record(t.string, t.array(Relation)) export type URLResolver = t.TypeOf export const Rule = t.type({ pattern: URLPattern, resolvers: URLResolver, }) export type Rule = t.TypeOf export const LinkResolver = t.record(t.string, t.record(t.string, t.record(t.string, Rule))) export type LinkResolver = t.TypeOf export type URLPart = { value: string withSeparator: boolean } export function staticParam(value: string): StaticParam { return { value, type: "static", } } export function uidParam(isOptional: boolean): UIDParam { return { isOptional, type: "uid", } } export function langParam(isOptional: boolean): LangParam { return { isOptional, type: "lang", } } export function customParam(name: string, isOptional: boolean): CustomParam { return { name, isOptional, type: "custom", } }