Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions apps/kitchen-sink/src/ensemble/screens/home.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ View:
console.log('>>> secret variable >>>', ensemble.secrets.dummyOauthSecret)
ensemble.storage.set('products', []);
ensemble.invokeAPI('getDummyProducts').then((res) => ensemble.storage.set('products', (res?.body?.users || []).map((i) => ({ ...i, name: i.firstName + ' ' + i.lastName }))));
const res = await ensemble.invokeAPI('getDummyNumbers')
await new Promise((resolve) => setTimeout(resolve, 5000))
return res
ensemble.invokeAPI('getDummyNumbers')
onComplete:
executeCode: |
console.log('API triggered', result)
console.log('API triggered')

header:
title:
Expand Down
51 changes: 29 additions & 22 deletions packages/framework/src/api/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,38 @@ export const invokeAPI = async (
const useMockResponse =
has(api, "mockResponse") && isUsingMockResponse(screenContext.app?.id);

const response = await queryClient.fetchQuery({
queryKey: [hash],
queryFn: () =>
DataFetcher.fetch(
api,
{ ...apiInputs, ...context },
{
mockResponse: mockResponse(
evaluatedMockResponse ?? api.mockResponse,
try {
const response = await queryClient.fetchQuery({
queryKey: [hash],
queryFn: () =>
DataFetcher.fetch(
api,
{ ...apiInputs, ...context },
{
mockResponse: mockResponse(
evaluatedMockResponse ?? api.mockResponse,
useMockResponse,
),
useMockResponse,
),
useMockResponse,
},
),
staleTime:
api.cacheExpirySeconds && !options?.bypassCache
? api.cacheExpirySeconds * 1000
: 0,
});
},
),
staleTime:
api.cacheExpirySeconds && !options?.bypassCache
? api.cacheExpirySeconds * 1000
: 0,
});

if (setter) {
set(update, api.name, response);
setter(screenDataAtom, { ...update });
if (setter) {
set(update, api.name, response);
setter(screenDataAtom, { ...update });
}

api.onResponseAction?.callback({ ...context, response });

return response;
} catch (err) {
api.onErrorAction?.callback({ ...context, error: err });
}
return response;
};

export const handleConnectSocket = (
Expand Down
17 changes: 16 additions & 1 deletion packages/framework/src/hooks/useScreenData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useAtom, useAtomValue } from "jotai";
import { useCallback, useMemo } from "react";
import isEqual from "react-fast-compare";
import { clone } from "lodash-es";
import type { Response, WebSocketConnection } from "../data";
import type {
EnsembleAPIModel,
Expand All @@ -19,13 +20,14 @@ export const useScreenData = (): {
name: string,
response: Partial<Response> | WebSocketConnection,
) => void;
setApi: (apiData: EnsembleAPIModel) => void;
mockResponses: {
[apiName: string]: EnsembleMockResponse | string | undefined;
};
} => {
const apis = useAtomValue(screenApiAtom);
const sockets = useAtomValue(screenSocketAtom);
const [data, setDataAtom] = useAtom(screenDataAtom);
const [apis, setApiAtom] = useAtom(screenApiAtom);

const apiMockResponses = useMemo(() => {
return apis?.reduce(
Expand Down Expand Up @@ -53,11 +55,24 @@ export const useScreenData = (): {
[data, setDataAtom],
);

const setApi = useCallback(
(apiData: EnsembleAPIModel) => {
const index = apis?.findIndex((api) => api.name === apiData.name);
if (index === undefined || isEqual(apis?.[index], apiData) || !apis) {
return;
}
apis[index] = apiData;
setApiAtom(clone(apis));
},
[apis, setApiAtom],
);

return {
apis,
sockets,
data,
setData,
setApi,
mockResponses,
};
};
4 changes: 3 additions & 1 deletion packages/framework/src/shared/models.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { CSSProperties } from "react";
import type { EnsembleAction } from "./actions";
import type { EnsembleAction, EnsembleActionHookResult } from "./actions";
import type { EnsembleConfigYAML } from "./dto";

/**
Expand Down Expand Up @@ -74,6 +74,8 @@ export interface EnsembleAPIModel {
body?: string | object;
onResponse?: EnsembleAction;
onError?: EnsembleAction;
onResponseAction?: EnsembleActionHookResult;
onErrorAction?: EnsembleActionHookResult;
mockResponse?: EnsembleMockResponse | string;
}

Expand Down
15 changes: 13 additions & 2 deletions packages/framework/src/state/screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { focusAtom } from "jotai-optics";
import { assign } from "lodash-es";
import { atomFamily } from "jotai/utils";
import { type Response, type WebSocketConnection } from "../data";
import type { EnsembleAppModel, EnsembleScreenModel } from "../shared";
import type {
EnsembleAPIModel,
EnsembleAppModel,
EnsembleScreenModel,
} from "../shared";
import type { WidgetState } from "./widget";

export interface ScreenContextDefinition {
Expand Down Expand Up @@ -57,10 +61,17 @@ export const screenModelAtom = focusAtom(screenAtom, (optic) =>
optic.prop("model"),
);

export const screenApiAtom = focusAtom(screenAtom, (optic) => {
export const screenApiFocusAtom = focusAtom(screenAtom, (optic) => {
return optic.prop("model").optional().prop("apis");
});

export const screenApiAtom = atom(
(get) => get(screenApiFocusAtom),
(_, set, update: EnsembleAPIModel[]) => {
set(screenApiFocusAtom, update);
},
);

export const screenSocketAtom = focusAtom(screenAtom, (optic) => {
return optic.prop("model").optional().prop("sockets");
});
Expand Down
Loading