Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, unknown> }) => {
{ action_id: 'some_action_name', parameters: { param: 'some' } },
(data: { action_id: string; parameters: Record<string, unknown> }) => {
// Обработка данных, переданных от бэкенд
unsubscribe();
},
Expand Down Expand Up @@ -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<string, unknown> }, params?: { name?: string; requestId?: string }) => void
#### sendAction({ action_id: string; parameters?: Record<string, unknown> }, params?: { name?: string; requestId?: string }) => void

Передает ошибки и обработчики ответа от бэкенда. <br>
`sendAction` — отправляет server-action и типизирует сообщения data и error.<br>
Expand All @@ -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<SomeBackendMessage>({ type: 'some_action_name', payload: { someParam: 'some_value' } },
({ payload }) => {
// обработка payload.data
const unsubscribe = assistant.sendAction<SomeBackendMessage>({ action_id: 'some_action_name', parameters: { someParam: 'some_value' } },
({ parameters }) => {
// обработка parameters.data
unsubscribe();
}, (error) => {});
```
Expand All @@ -232,8 +232,8 @@ const unsubscribe = assistant.sendAction<SomeBackendMessage>({ 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();
... // обработка команды
}
Expand Down Expand Up @@ -314,9 +314,9 @@ interface AssistantViewItem {
```typescript
interface AssistantServerAction {
// Тип Server Action
type: string;
action_id: string;
// Любые параметры
payload?: Record<string, unknown>;
parameters?: Record<string, unknown>;
}
```

Expand Down Expand Up @@ -391,9 +391,9 @@ interface AssistantSmartAppCommand {
// Тип команды
type: "smart_app_data";
smart_app_data: {
type: string;
action_id: string;
// Любые данные, которые нужны смартапу
payload: Record<string, unknown>;
parameters: Record<string, unknown>;
};
sdk_meta: {
requestId: string;
Expand Down Expand Up @@ -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();
});
Expand Down
67 changes: 67 additions & 0 deletions src/iframe.ts
Original file line number Diff line number Diff line change
@@ -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');
}
});
}
72 changes: 3 additions & 69 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<A extends AssistantSmartAppData> {
start: () => void;
Expand All @@ -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 = <A extends AssistantSmartAppData>({
getState,
getRecoveryState,
Expand Down Expand Up @@ -253,8 +187,8 @@ export const createAssistant = <A extends AssistantSmartAppData>({
E extends AssistantSmartAppError['smart_app_error'] = AssistantSmartAppError['smart_app_error']
>(
action: {
type: string;
payload: Record<string, unknown>;
action_id: string;
parameters?: Record<string, unknown>;
},
onData?: ObserverFunc<D>,
onError?: ObserverFunc<E>,
Expand Down
4 changes: 2 additions & 2 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ export interface AssistantSmartAppError {

export interface AssistantSmartAppCommand extends AssistantSmartAppData {
smart_app_data: {
type: string;
payload?: Record<string, unknown>;
action_id: string;
parameters?: Record<string, unknown>;
};
sdk_meta?: SdkMeta;
}
Expand Down