hypertune
Version:
[Hypertune](https://www.hypertune.com/) is the most flexible platform for feature flags, A/B testing, analytics and app configuration. Built with full end-to-end type-safety, Git-style version control and local, synchronous, in-memory flag evaluation. Opt
164 lines (153 loc) • 3.96 kB
text/typescript
import {
BooleanExpression,
Expression,
FloatExpression,
IntExpression,
ListExpression,
NoOpExpression,
ObjectExpression,
ObjectValue,
StringExpression,
SwitchExpression,
Value,
} from "../types";
import uniqueId from "./uniqueId";
// When modifying expression constructors, ensure that they properly thread
// through optional fields like isTransient and don't accidentally drop them
export function getAnonymousExpression(
value: Value,
isTransient?: boolean
): Expression {
if (typeof value === "boolean") {
return getBooleanExpression(value, isTransient);
}
if (typeof value === "number") {
if (Number.isInteger(value)) {
return getIntExpression(value, isTransient);
}
return getFloatExpression(value, isTransient);
}
if (typeof value === "string") {
return getStringExpression(value, isTransient);
}
if (Array.isArray(value)) {
return getAnonymousListExpression(value, isTransient);
}
if (typeof value === "object") {
return getAnonymousObjectExpression(value, isTransient);
}
const neverValue: never = value;
throw new Error(`Unexpected value: ${neverValue}`);
}
export function getNoOpExpression(isTransient?: boolean): NoOpExpression {
const expression: NoOpExpression = {
id: uniqueId(),
isTransient,
type: "NoOpExpression",
valueType: { type: "VoidValueType" },
};
return expression;
}
export function getBooleanIfExpression(
value: boolean,
isTransient?: boolean
): SwitchExpression {
const expression: SwitchExpression = {
id: uniqueId(),
isTransient,
type: "SwitchExpression",
valueType: { type: "BooleanValueType" },
control: getBooleanExpression(true),
cases: [],
default: getBooleanExpression(value, isTransient),
};
return expression;
}
export function getBooleanExpression(
value: boolean,
isTransient?: boolean
): BooleanExpression {
const expression: BooleanExpression = {
id: uniqueId(),
isTransient,
type: "BooleanExpression",
valueType: { type: "BooleanValueType" },
value,
};
return expression;
}
export function getIntExpression(
value: number,
isTransient?: boolean
): IntExpression {
const expression: IntExpression = {
id: uniqueId(),
isTransient,
type: "IntExpression",
valueType: { type: "IntValueType" },
value: Math.round(value),
};
return expression;
}
export function getFloatExpression(
value: number,
isTransient?: boolean
): FloatExpression {
const expression: FloatExpression = {
id: uniqueId(),
isTransient,
type: "FloatExpression",
valueType: { type: "FloatValueType" },
value,
};
return expression;
}
export function getStringExpression(
value: string,
isTransient?: boolean
): StringExpression {
const expression: StringExpression = {
id: uniqueId(),
isTransient,
type: "StringExpression",
valueType: { type: "StringValueType" },
value,
};
return expression;
}
export function getAnonymousListExpression(
value: Value[],
isTransient?: boolean
): ListExpression {
const expression: ListExpression = {
id: uniqueId(),
isTransient,
type: "ListExpression",
valueType: {
type: "ListValueType",
itemValueType: { type: "VoidValueType" },
}, // Dummy
items: value.map((item) => getAnonymousExpression(item, isTransient)),
};
return expression;
}
export function getAnonymousObjectExpression(
value: ObjectValue,
isTransient?: boolean
): ObjectExpression {
const objectTypeName = ""; // Dummy
const expression: ObjectExpression = {
id: uniqueId(),
isTransient,
type: "ObjectExpression",
valueType: { type: "ObjectValueType", objectTypeName },
objectTypeName,
fields: Object.fromEntries(
Object.entries(value).map(([fieldName, fieldValue]) => [
fieldName,
getAnonymousExpression(fieldValue, isTransient),
])
),
};
return expression;
}