@applicaster/quick-brick-core
Version:
Core package for Applicaster's Quick Brick App
153 lines (119 loc) • 3.66 kB
text/typescript
import * as R from "ramda";
import { RequestBuilder } from "@applicaster/zapp-pipes-v2-client";
import { TYPE, SCREEN_ID, FEED_LOCATOR, OMITTED_PARAMS } from "../const";
type Query = Record<string, unknown> &
Partial<{
type: string;
screen_id: string;
feed_locator: string;
id: string;
position: number;
state: "inline" | "fullscreen";
}>;
type ResolveQueryDataArgs = {
query: Query;
rivers: Record<string, ZappRiver>;
contentTypes: ZappContentTypes;
};
type ResolvedQuery = {
targetScreen: ZappRiver;
entry?: Partial<ZappEntry>;
};
export const queryIsValid = R.anyPass([
R.has(TYPE),
R.has(SCREEN_ID),
R.has(FEED_LOCATOR),
]);
export const getTypeMappedScreen = (type, rivers, contentTypes) =>
R.compose(
R.propOr(null, R.__, rivers),
R.path([type, "screen_id"])
)(contentTypes);
export const getEntryById = R.curry(
(entries, { id }) => R.find(({ id: entryId }) => entryId == id, entries) // eslint-disable-line eqeqeq
);
export const getEntryByPosition = R.curry((entries, { position }) =>
R.nth(Math.max(position - 1, 0), entries)
);
// second arg is not used here, but required by R.curry
export const getFirstEntry = R.curry((entries, _) => R.nth(0, entries));
export const getEntry = R.curry((entries, query) =>
R.cond([
[R.has("id"), getEntryById(entries)],
[R.has("position"), getEntryByPosition(entries)],
[R.T, getFirstEntry(entries)],
])(query)
);
export const formatEntry = (query: Query): Partial<ZappEntry> => {
const params = R.omit([...OMITTED_PARAMS], query);
const extensions = R.clone(params);
if (query.type) {
params.type = { value: query.type };
}
params.extensions = extensions;
return params;
};
export const getHomeScreenId = R.compose(
R.prop("id"),
R.find(R.propEq("home", true)),
R.values
);
export async function resolveQueryData({
query,
rivers,
contentTypes,
}: ResolveQueryDataArgs): Promise<ResolvedQuery> {
const { type, screen_id, feed_locator } = query;
if (feed_locator) {
const url = decodeURIComponent(feed_locator);
const request = new RequestBuilder();
if (!url) {
throw new Error("Feed locator is missing");
}
const { response: feed, error } = await request
.setUrl(url)
.call<ZappFeed>();
if (error) {
throw error;
}
const entries = feed?.entry ?? [];
const selectedEntry = getEntry(entries, query);
const typeMappedScreen = getTypeMappedScreen(
type ?? selectedEntry?.type?.value,
rivers,
contentTypes
);
const screen = R.prop(selectedEntry?.screen_type ?? screen_id, rivers);
const targetScreen = screen ?? typeMappedScreen;
return {
targetScreen,
entry: selectedEntry,
};
}
const typeMappedScreen = getTypeMappedScreen(type, rivers, contentTypes);
const screenFromId = R.prop(screen_id, rivers);
const targetScreen = screenFromId ?? typeMappedScreen;
const data = {
targetScreen,
entry: formatEntry(query),
};
return data;
}
const normalizeInitialPlayerState = (initialPlayerState: string): string => {
return initialPlayerState.toLowerCase() === "inline"
? "inline"
: "fullscreen";
};
export const withInitialPlayerState = (query, entry) => {
const initialPlayerState = normalizeInitialPlayerState(
R.pathOr("fullscreen", ["state"], query)
);
const initialPlayerStateLens = R.lensPath([
"extensions",
"initial_player_state",
]);
return R.set(initialPlayerStateLens, initialPlayerState, entry);
};
export function wait(delay = 200) {
return new Promise((resolve) => setTimeout(resolve, delay));
}