diff --git a/README.md b/README.md index 7a03abc..7379072 100644 --- a/README.md +++ b/README.md @@ -116,15 +116,15 @@ assistant.on('data', (command) => { const handleOnClick = () => { // Отправка сообщения ассистенту с фронтенд. // Структура может меняться на усмотрение разработчика, в зависимости от бэкенд - assistant.sendData({ action: { type: 'some_action_name', payload: { param: 'some' } } }); + assistant.sendData({ action: { action_id: 'some_action_name', parameters: { param: 'some' } } }); }; const handleOnRefreshClick = () => { // Отправка сообщения бэкенду с возможностью подписки на ответ. // В обработчик assistant.on('data') сообщение не передается const unsubscribe = assistant.sendAction( - { type: 'some_action_name', payload: { param: 'some' } }, - (data: { type: string; payload: Record }) => { + { action_id: 'some_action_name', parameters: { param: 'some' } }, + (data: { action_id: string; parameters: Record }) => { // Обработка данных, переданных от бэкенд unsubscribe(); }, @@ -194,9 +194,9 @@ ____ #### on('data', cb: (data: [AssistantCharacterCommand](#AssistantCharacterCommand) | [AssistantNavigationCommand](#AssistantNavigationCommand) | [AssistantInsetsCommand](#AssistantInsetsCommand) | [AssistantSmartAppError](#AssistantSmartAppError) | [AssistantSmartAppCommand](#AssistantSmartAppCommand)) => {}): void -Осуществляет подписку на событие получения данных с бэкенда. Получает команды из `appInitialData`, если при запуске смартапа не была вызвана команда `getInitialData()`. +Осуществляет подписку на событие получения данных с бэкенда. Получает команды из `appInitialData`, если при запуске смартапа не была вызвана команда `getInitialData()`. -#### sendAction({ type: string; payload: Record }, params?: { name?: string; requestId?: string }) => void +#### sendAction({ action_id: string; parameters?: Record }, params?: { name?: string; requestId?: string }) => void Передает ошибки и обработчики ответа от бэкенда.
`sendAction` — отправляет server-action и типизирует сообщения data и error.
@@ -208,15 +208,15 @@ ____ import { AssistantSmartAppCommand } from '@sberdevices/assistant-client'; interface SomeBackendMessage extends AssistantSmartAppCommand['smart_app_data'] { - type: 'target_action', - payload: { + action_id: 'target_action', + parameters: { data: ['some_data'], }, } -const unsubscribe = assistant.sendAction({ type: 'some_action_name', payload: { someParam: 'some_value' } }, - ({ payload }) => { - // обработка payload.data +const unsubscribe = assistant.sendAction({ action_id: 'some_action_name', parameters: { someParam: 'some_value' } }, + ({ parameters }) => { + // обработка parameters.data unsubscribe(); }, (error) => {}); ``` @@ -232,8 +232,8 @@ const unsubscribe = assistant.sendAction({ type: 'some_actio ```ts ... -const unsubscribe = assistant.sendData({ action: { type: 'some_action_name' } }, (data: command) => { - if (data.type === 'smart_app_data' && data.smart_app_data.type === 'target_action') { +const unsubscribe = assistant.sendData({ action: { action_id: 'some_action_name' } }, (data: command) => { + if (data.type === 'smart_app_data' && data.smart_app_data.action_id === 'target_action') { unsubsribe(); ... // обработка команды } @@ -314,9 +314,9 @@ interface AssistantViewItem { ```typescript interface AssistantServerAction { // Тип Server Action - type: string; + action_id: string; // Любые параметры - payload?: Record; + parameters?: Record; } ``` @@ -391,9 +391,9 @@ interface AssistantSmartAppCommand { // Тип команды type: "smart_app_data"; smart_app_data: { - type: string; + action_id: string; // Любые данные, которые нужны смартапу - payload: Record; + parameters: Record; }; sdk_meta: { requestId: string; @@ -489,20 +489,20 @@ describe('Мой список дел', () => { mock.receiveCommand({ type: 'smart_app_data', action: { - type: 'init', - notes: [...ITEMS], + action_id: 'init', + parameters: { notes: [...ITEMS] }, }, }) .then(() => // ожидаем вызов assistantClient.sendData mock.waitAction(() => - // эмулируем отметку выполнения пользователем, который должен вызвать sendData({ action: { type: 'done } }) + // эмулируем отметку выполнения пользователем, который должен вызвать sendData({ action: { action_id: 'done } }) window.document.getElementById(`checkbox-note-${selected.id}`).click(), ), ) .then(({ action, state }) => { - expect(action.type).to.equal('done'); // ожидаем экшен data_note - expect(action.payload?.title).to.equal(selected.title); // ожидаем в параметрах title экшена + expect(action.action_id).to.equal('done'); // ожидаем экшен data_note + expect(action.parameters?.title).to.equal(selected.title); // ожидаем в параметрах title экшена expect(state?.item_selector.items).to.deep.equal(ITEMS); // ожидаем отправку списка в стейте done(); }); diff --git a/src/iframe.ts b/src/iframe.ts new file mode 100644 index 0000000..a96a1ee --- /dev/null +++ b/src/iframe.ts @@ -0,0 +1,67 @@ +import { AssistantPostMessage } from './typings'; + +const inIframe = () => { + try { + return window.self !== window.top; + } catch (e) { + return true; + } +}; + +if (typeof window !== 'undefined' && inIframe()) { + const postMessage = (action: AssistantPostMessage) => { + window.top.postMessage(JSON.stringify(action), '*'); + }; + + window.AssistantHost = { + sendDataContainer(json: string) { + postMessage({ type: 'sendDataContainer', payload: json }); + }, + close() { + postMessage({ type: 'close' }); + }, + sendData(json: string) { + postMessage({ type: 'sendData', payload: json }); + }, + setSuggest(suggests: string) { + postMessage({ type: 'setSuggest', payload: suggests }); + }, + ready() { + postMessage({ type: 'ready' }); + }, + }; + + window.addEventListener('message', (e) => { + try { + if (typeof e.data === 'string') { + const data = JSON.parse(e.data); + + switch (data.type) { + case 'onData': + window.AssistantClient?.onData?.(data.payload); + break; + case 'onRequestState': { + const state = window.AssistantClient?.onRequestState?.(); + postMessage({ type: 'state', payload: state, requestId: data.requestId }); + break; + } + case 'onRequestRecoveryState': { + const recoverystate = window.AssistantClient?.onRequestRecoveryState?.(); + postMessage({ type: 'recoveryState', payload: recoverystate }); + break; + } + case 'onStart': + window.AssistantClient?.onStart?.(); + break; + default: + // eslint-disable-next-line no-console + console.error(e, 'Unknown parsed message'); + break; + } + } + } catch (err) { + // eslint-disable-next-line no-console + console.error(err, 'Unknown message'); + } + }); +} diff --git a/src/index.ts b/src/index.ts index 441d51e..098799b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,11 +11,11 @@ import { AssistantClientCommand, AssistantSmartAppError, AssistantSmartAppCommand, - AssistantPostMessage, } from './typings'; import { createNanoEvents } from './nanoevents'; import { initializeAssistantSDK, InitializeAssistantSDKParams } from './dev'; import { createNanoObservable, ObserverFunc } from './nanoobservable'; +import './iframe'; export interface AssistantEvents { start: () => void; @@ -34,72 +34,6 @@ export interface SendDataParams { requestId?: string; } -function inIframe() { - try { - return window.self !== window.top; - } catch (e) { - return true; - } -} - -if (typeof window !== 'undefined' && inIframe()) { - const postMessage = (action: AssistantPostMessage) => { - window.top.postMessage(JSON.stringify(action), '*'); - }; - - window.AssistantHost = { - sendDataContainer(json: string) { - postMessage({ type: 'sendDataContainer', payload: json }); - }, - close() { - postMessage({ type: 'close' }); - }, - sendData(json: string) { - postMessage({ type: 'sendData', payload: json }); - }, - setSuggest(suggests: string) { - postMessage({ type: 'setSuggest', payload: suggests }); - }, - ready() { - postMessage({ type: 'ready' }); - }, - }; - - window.addEventListener('message', (e) => { - try { - if (typeof e.data === 'string') { - const data = JSON.parse(e.data); - - switch (data.type) { - case 'onData': - window.AssistantClient?.onData?.(data.payload); - break; - case 'onRequestState': { - const state = window.AssistantClient?.onRequestState?.(); - postMessage({ type: 'state', payload: state, requestId: data.requestId }); - break; - } - case 'onRequestRecoveryState': { - const recoverystate = window.AssistantClient?.onRequestRecoveryState?.(); - postMessage({ type: 'recoveryState', payload: recoverystate }); - break; - } - case 'onStart': - window.AssistantClient?.onStart?.(); - break; - default: - // eslint-disable-next-line no-console - console.error(e, 'Unknown parsed message'); - break; - } - } - } catch (err) { - // eslint-disable-next-line no-console - console.error(err, 'Unknown message'); - } - }); -} - export const createAssistant = ({ getState, getRecoveryState, @@ -253,8 +187,8 @@ export const createAssistant = ({ E extends AssistantSmartAppError['smart_app_error'] = AssistantSmartAppError['smart_app_error'] >( action: { - type: string; - payload: Record; + action_id: string; + parameters?: Record; }, onData?: ObserverFunc, onError?: ObserverFunc, diff --git a/src/typings.ts b/src/typings.ts index 8648803..73a641c 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -159,8 +159,8 @@ export interface AssistantSmartAppError { export interface AssistantSmartAppCommand extends AssistantSmartAppData { smart_app_data: { - type: string; - payload?: Record; + action_id: string; + parameters?: Record; }; sdk_meta?: SdkMeta; }