const React = require("react");
const { data, union, number, parameterized, string } = require("@algebraic/type");
const type = require("@algebraic/type");
const { List, Map, Set } = require("@algebraic/collections");
const collapse = require("@runkit/tolmasky/react-collapse/1.0.0");
const { isValidElement } = require("react");
const Match = union `Match` (
data `OnStatus` ( status => number ),
data `EverythingElse` () );
const Action = union `Action` (
data `ForwardResponse` (),
data `ReplaceResponse` (
replacement => Object ),
data `ModifyResponse` (
forwardedHeaders => Set(string),
overwrittenHeaders => Map(string, string) ) );
Action.ReplaceResponse.fromProperties = () => Action.ReplaceResponse({ replacement: {} });
const header = (name, f = x => x, prop = "value") =>
({ [prop]: value }) =>
<header { ...{ name, value: f(value) } } />;
const headers =
{
/* "attachment": header("Content-Disposition",
require("content-disposition"),
"filename"),*/
"content-type": header("Content-Type"),
"x-content-type-options": header("X-Content-Type-Options"),
// "content-security-policy": require("./content-security-policy"),
"access-control-allow-origin": header("Access-Control-Allow-Origin")
};
Action.ModifyResponse.fromProperties = (function ()
{
return toFromProperties(headers, (props, grouped) => Action.ModifyResponse
({
forwardedHeaders: Set(string)(grouped
.get("forward", List(string)())
.map(({ props }) => Object.keys(props)[0]))
.map(name => name.replace(/(?<=-|^)[a-z]/g,
character => character.toUpperCase())),
overwrittenHeaders: Map(string, string)(grouped
.get("header", List(Object)())
.map(({ props: { name, value } }) => [name, value]))
}));
})();
const Case = data `Case` (
status => number,
consequent => Action );
const Proxy = data `HTTP.Proxy` (
rerouteTo => string,
cases => List(Case),
fallback => Action );
Proxy.fromProperties = (function ()
{
const toCaseOrAction = T =>
(props) => //{ "everything-else": fallback, status, ...props }) =>
props["everything-else"] ? //fallback ?
T.fromProperties(props) :
Case({ status: props.status, consequent: T.fromProperties(props) });
const primitives =
{
"replace": toCaseOrAction(Action.ReplaceResponse),
"forward": toCaseOrAction(Action.ForwardResponse),
"modify": toCaseOrAction(Action.ModifyResponse)
};
return toFromProperties(primitives, (props, grouped) => Proxy
({
rerouteTo: props["reroute-to"],
cases: grouped.get(Case, List(Case)()),
fallback: grouped
.get(Action.ReplaceResponse, List(Action)([Action.ForwardResponse]))
.last()
}));
})();
const toArray = value => value === void(0) ? [] : [].concat(value);
function toFromProperties(primitives, fromGroupedChildren)
{
const pCollapse = collapse(primitives);
return props => //({ children, ...props }) =>
fromGroupedChildren(props,
List(Object)(pCollapse(toArray(props.children)))
.groupBy(child =>
isValidElement(child) ? child.type : type.of(child)));
}
/*
Proxy.fromElement = (function ()
{
const toCaseOrAction = fromElement =>
({ "everything-else": fallback, status, ...props }) =>
fallback ?
fromElement(props) :
Case({ status, consequent: fromElement(props) });
const group = toGroupedChildren
({
"replace": toCaseOrFallback(Action.ReplaceResponse),
"forward": toCaseOrFallback(Action.ForwardResponse),
"modify": toCaseOrFallback(Action.ModifyResponse)
});
return ({ props }) =>
(grouped = toGroupedChildren(props.children)) =>
Proxy
({
target: props.target,
cases: grouped.get(Case, List(Case)()),
fallback: grouped
.get(Action, List(Action)([Action.ForwardResponse]))
.last()
});
})();
function toFromElement(T, primitives)
{
const toCaseOrAction = fromElement =>
({ "everything-else": fallback, status, ...props }) =>
fallback ?
fromElement(props) :
Case({ status, consequent: fromElement(props) });
const collapse = require("@runkit/tolmasky/react-collapse/1.0.0")
({
"replace": toCaseOrFallback(Action.ReplaceResponse),
"forward": toCaseOrFallback(Action.ForwardResponse),
"modify": toCaseOrFallback(Action.ModifyResponse)
});
return fromElement (element)
{
const { children } = collapse(element).props;
const grouped = List(Object)(children)
.groupBy(child => child.type);
return T({ });
}
}*/
/*
Case.fromElement = toFromElement(children =>
{
const status = props.status;
const
const forwards = grouped.get("forward");
}
children.get(),
Case({ }),
{
});
Proxy.fromElement = function ({ props })
{
const grouped = List(Object)(props.children)
.groupBy(child => child.type);
const cases = grouped
.get("case", List(Case)())
.map(Case.fromElement)
.
Proxy({ cases: List(Case)(), fallback: Action.ForwardResponse });
}
const header = (name, f = x => x, prop = "value") =>
({ [prop]: value }) =>
<http-header { ...{ name, value: f(value) } } />;
const ProxyCollapse = require("@runkit/tolmasky/react-collapse/1.0.0")
({
"http-proxy": Proxy.fromElement
});*/
require("@runkit/tolmasky/react-collapse/1.0.0")
({
"http-proxy": Proxy.fromProperties
})(
<http-proxy reroute-to = "https://pizza.com" >
<modify status = { 200 } >
<forward content-type />
<forward content-length />
<x-content-type-options value = "no-sniff"/>
</modify>
<replace everything-else>
</replace>
</http-proxy>);
/*
<case status = "" />
</case>
<case>
<replace>
<ErrorResponse/>
</replace>
</case>
/*
const Proxy = data `HTTP.Proxy` (
rerouteTo => string,
modifications => List(Rule) );
<http-proxy route-to = "http://somewhere-else.com" >
<forward status = "200">
<forward>
<forward>
</forward>
<replace everything-else>
<ErrorResponse/>
</replace>
<fallback>
<replace>
</replace>
</fallback>
<modify status = "200">
</>
</modify>
<modify everything-else>
<ErrorResponse/>
</modify>
</http-proxy>*/