@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
108 lines (80 loc) • 2.6 kB
text/typescript
import { ContextKeysManager } from "./index";
import * as R from "ramda";
import * as _ from "lodash";
import { useScreenStateStore } from "../../reactHooks/navigation/useScreenStateStore";
export interface IResolver {
resolve: (string) => Promise<string | number | object>;
}
// TODO: Rename to ObjectKeyResolver or similar
export class EntryResolver implements IResolver {
entry: ZappEntry;
constructor(entry: ZappEntry) {
this.entry = entry;
}
async resolve(key: string) {
if (!key || key.length === 0) {
return this.entry;
}
return R.view(R.lensPath(key.split(".")), this.entry);
}
}
// TODO: Move to proper place
export class ScreenStateResolver implements IResolver {
constructor(
private screenStateStore: ReturnType<typeof useScreenStateStore>
) {}
async resolve(key: string) {
const screenState = this.screenStateStore.getState().data;
if (!key || key.length === 0) {
return screenState;
}
if (key.includes(".")) {
return R.view(R.lensPath(key.split(".")), screenState);
}
return screenState?.[key];
}
}
export class ContextResolver implements IResolver {
resolve = async (compositeKey: string) =>
ContextKeysManager.instance.getKey(compositeKey);
}
export const resolveObjectValues = async (
data: Record<string, any>,
resolvers: Record<string, IResolver> = null
) => {
const entries = Object.entries(data);
const exResolvers = { ctx: new ContextResolver(), ...resolvers };
const resolvedEntries = await Promise.all(
entries.map(async ([key, value]) => {
if (typeof value !== "string") {
return [key, value];
}
if (!value.startsWith("@")) {
return [key, value];
}
const regex = /@{([^/]+)\/([^}]*)}/;
const match = (value as string).match(regex);
if (match) {
const contextResolverName = match[1];
const compositeKey = match[2];
const resolver = exResolvers[contextResolverName] || exResolvers.ctx;
const resolvedValue = await resolver.resolve(compositeKey);
return [key, resolvedValue];
}
return [key, value];
})
);
return Object.fromEntries(resolvedEntries);
};
export const extractAtValues = _.memoize((input: any): string[] => {
return _.flatMapDeep(input, (value: any) => {
if (_.isString(value)) {
const matches = value.match(/@\{([^}]*)\}/g);
return matches ? matches.map((match) => match.slice(2, -1)) : [];
}
if (_.isObject(value)) {
return extractAtValues(_.values(value));
}
return [];
});
});