@player-tools/devtools-client 0.2.2--canary.17.363 → 0.3.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,70 @@
1
+ import {
2
+ type Message,
3
+ clearStore,
4
+ playerFlowStartAction,
5
+ playerInitAction,
6
+ playerRemoveAction,
7
+ playerTimelineAction,
8
+ playerViewUpdateAction,
9
+ selectedPlayerAction,
10
+ } from '@player-tools/devtools-common';
11
+ import type { Store } from 'redux';
12
+ import { GET_DATA_BINDING_DETAILS } from './aliases';
13
+
1
14
  export * from './actions';
2
15
  export * from './aliases';
3
- export * from './listeners';
4
16
  export * from './reducers';
5
- export * from './selectors';
6
- export * from './state';
7
- export * from './store';
17
+
18
+ export function handleMessage(store: Store, message: Message) {
19
+ switch (message.type) {
20
+ case 'runtime-init':
21
+ store.dispatch(clearStore());
22
+ break;
23
+ case 'player-init':
24
+ store.dispatch(playerInitAction(message));
25
+ store.dispatch(selectedPlayerAction());
26
+ break;
27
+ case 'player-removed':
28
+ store.dispatch(playerRemoveAction(message.playerID));
29
+ store.dispatch(selectedPlayerAction());
30
+ break;
31
+ case 'player-flow-start':
32
+ store.dispatch(playerFlowStartAction(message));
33
+ store.dispatch(playerTimelineAction(message));
34
+ store.dispatch({
35
+ type: GET_DATA_BINDING_DETAILS,
36
+ payload: { playerID: message.playerID, binding: '' },
37
+ });
38
+ break;
39
+ case 'player-log-event':
40
+ store.dispatch(playerTimelineAction(message));
41
+ break;
42
+ case 'player-view-update-event':
43
+ store.dispatch(playerViewUpdateAction(message));
44
+ break;
45
+ case 'player-data-change-event': {
46
+ const { players } = store.getState();
47
+
48
+ if (
49
+ players.activePlayers[message.playerID] &&
50
+ players.activePlayers[message.playerID].dataState.selectedBinding
51
+ ) {
52
+ store.dispatch({
53
+ type: GET_DATA_BINDING_DETAILS,
54
+ payload: message,
55
+ });
56
+ }
57
+
58
+ store.dispatch({
59
+ type: GET_DATA_BINDING_DETAILS,
60
+ payload: { playerID: message.playerID, binding: '' },
61
+ });
62
+ store.dispatch(playerTimelineAction(message));
63
+ break;
64
+ }
65
+
66
+ default:
67
+ console.warn(`Unhandled event: ${JSON.stringify(message)}`);
68
+ break;
69
+ }
70
+ }
@@ -1,248 +1,118 @@
1
- import { ActionReducerMapBuilder, createReducer } from '@reduxjs/toolkit';
2
- import type { PlayersState } from './state';
3
- import { Actions, Events, Methods } from './actions';
4
-
5
- const initialState = {
6
- selectedPlayerId: null,
7
- activePlayers: {},
8
- } as PlayersState;
9
-
10
- // TODO: It'd be nice if methodThunks didn't have to be passed in - but it is kinda client dependent
11
- export const methodsReducer = (methods: Methods.MethodThunks) => (builder: ActionReducerMapBuilder<PlayersState>) => {
12
- builder.addCase(
13
- methods['player-runtime-info-request'].fulfilled,
14
- (state, action) => {
15
- const { activePlayers, selectedPlayerId } = state;
16
-
17
- if (!selectedPlayerId) {
18
- return;
1
+ import type { ActionReducerMapBuilder } from '@reduxjs/toolkit';
2
+ import type { PlayersState } from '@player-tools/devtools-common';
3
+ import type { AsyncRPCActions } from './actions';
4
+
5
+ /**
6
+ * Callback function that adds cases for async actions for the player.
7
+ * @param playerReducerCallback
8
+ * @returns
9
+ */
10
+ export const buildPlayerReducerCallback =
11
+ (actions: AsyncRPCActions) =>
12
+ (builder: ActionReducerMapBuilder<PlayersState>) => {
13
+ builder.addCase(
14
+ actions['player-runtime-info-request'].fulfilled,
15
+ (state, action) => {
16
+ const { activePlayers, selectedPlayerId } = state;
17
+
18
+ if (!selectedPlayerId) {
19
+ return;
20
+ }
21
+
22
+ const data =
23
+ action.payload && Object.keys(action.payload).length > 0
24
+ ? action.payload
25
+ : null;
26
+ activePlayers[selectedPlayerId].flowInfo = data;
19
27
  }
28
+ );
20
29
 
21
- const data =
22
- action.payload && Object.keys(action.payload).length > 0
23
- ? action.payload
24
- : null;
25
- activePlayers[selectedPlayerId].flowInfo = data;
26
- }
27
- );
28
-
29
- builder.addCase(
30
- methods['player-config-request'].fulfilled,
31
- (state, action) => {
32
- const { activePlayers, selectedPlayerId } = state;
33
-
34
- if (!selectedPlayerId) {
35
- return;
30
+ builder.addCase(
31
+ actions['player-config-request'].fulfilled,
32
+ (state, action) => {
33
+ const { activePlayers, selectedPlayerId } = state;
34
+
35
+ if (!selectedPlayerId) {
36
+ return;
37
+ }
38
+
39
+ activePlayers[selectedPlayerId].configState = action.payload;
36
40
  }
41
+ );
37
42
 
38
- activePlayers[selectedPlayerId].configState = action.payload;
39
- }
40
- );
43
+ builder.addCase(
44
+ actions['player-view-details-request'].fulfilled,
45
+ (state, action) => {
46
+ const { activePlayers, selectedPlayerId } = state;
41
47
 
42
- builder.addCase(
43
- methods['player-view-details-request'].fulfilled,
44
- (state, action) => {
45
- const { activePlayers, selectedPlayerId } = state;
48
+ if (!selectedPlayerId) {
49
+ return;
50
+ }
46
51
 
47
- if (!selectedPlayerId) {
48
- return;
52
+ activePlayers[selectedPlayerId].view = action.payload?.lastViewUpdate;
49
53
  }
50
-
51
- activePlayers[selectedPlayerId].view = action.payload?.lastViewUpdate;
52
- }
53
- );
54
-
55
- builder.addCase(
56
- methods['player-data-binding-details'].fulfilled,
57
- (state, action) => {
58
- const {
59
- meta: {
60
- arg: { params: { binding, playerID } },
61
- },
62
- payload,
63
- } = action;
64
- const { activePlayers } = state;
65
-
66
- if (!playerID || !activePlayers[playerID]) {
67
- return;
54
+ );
55
+
56
+ builder.addCase(
57
+ actions['player-data-binding-details'].fulfilled,
58
+ (state, action) => {
59
+ const {
60
+ meta: {
61
+ arg: { binding, playerID },
62
+ },
63
+ payload,
64
+ } = action;
65
+ const { activePlayers } = state;
66
+
67
+ if (!playerID || !activePlayers[playerID]) {
68
+ return;
69
+ }
70
+
71
+ if (binding === '') {
72
+ activePlayers[playerID].dataState.allBindings = payload;
73
+ return;
74
+ }
75
+
76
+ activePlayers[playerID].dataState.selectedBinding = payload;
68
77
  }
69
-
70
- if (binding === '') {
71
- activePlayers[playerID].dataState.allBindings = payload;
72
- return;
78
+ );
79
+
80
+ builder.addCase(
81
+ actions['player-execute-expression'].fulfilled,
82
+ (state, action) => {
83
+ const { activePlayers, selectedPlayerId } = state;
84
+
85
+ if (!selectedPlayerId) {
86
+ return;
87
+ }
88
+
89
+ activePlayers[selectedPlayerId].consoleState?.history?.push({
90
+ id: action.meta.requestId,
91
+ result: action.payload,
92
+ expression: action.payload?.exp ?? '',
93
+ });
73
94
  }
95
+ );
74
96
 
75
- activePlayers[playerID].dataState.selectedBinding = payload;
76
- }
77
- );
97
+ builder.addCase(
98
+ actions['player-start-profiler-request'].fulfilled,
99
+ (state, action) => {
100
+ const { activePlayers, selectedPlayerId } = state;
78
101
 
79
- builder.addCase(
80
- methods['player-execute-expression'].fulfilled,
81
- (state, action) => {
82
- const { activePlayers, selectedPlayerId } = state;
102
+ if (!selectedPlayerId) return;
83
103
 
84
- if (!selectedPlayerId) {
85
- return;
104
+ activePlayers[selectedPlayerId].profilerInfo = action.payload?.data;
86
105
  }
106
+ );
87
107
 
88
- activePlayers[selectedPlayerId].consoleState?.history?.push({
89
- id: action.meta.requestId,
90
- result: action.payload,
91
- expression: action.payload?.exp ?? '',
92
- });
93
- }
94
- );
95
-
96
- builder.addCase(
97
- methods['player-start-profiler-request'].fulfilled,
98
- (state, action) => {
99
- const { activePlayers, selectedPlayerId } = state;
100
-
101
- if (!selectedPlayerId) return;
102
-
103
- activePlayers[selectedPlayerId].profilerInfo = action.payload?.data;
104
- }
105
- );
106
-
107
- builder.addCase(
108
- methods['player-stop-profiler-request'].fulfilled,
109
- (state, action) => {
110
- const { activePlayers, selectedPlayerId } = state;
111
-
112
- if (!selectedPlayerId) return;
113
-
114
- activePlayers[selectedPlayerId].profilerInfo = action.payload?.data;
115
- }
116
- );
117
- };
118
-
119
- export const eventsReducer = (builder: ActionReducerMapBuilder<PlayersState>) => {
120
- builder.addCase(Events.actions['player-init'], (state, action) => {
121
- const {
122
- payload: { version, playerID },
123
- } = action;
124
- state.activePlayers[playerID] = {
125
- timelineEvents: [],
126
- dataState: {},
127
- consoleState: { history: [] },
128
- };
129
- state.version = version;
130
- });
131
-
132
- builder.addCase(Events.actions['player-removed'], (state, action) => {
133
- delete state.activePlayers[action.payload.playerID];
134
- });
135
-
136
- builder.addCase(Events.actions['player-flow-start'], (state, action) => {
137
- const {
138
- payload: { flow, playerID },
139
- } = action;
140
-
141
- if (!state.activePlayers[playerID]) {
142
- state.activePlayers[playerID] = {
143
- flowInfo: { currentFlow: flow },
144
- timelineEvents: [],
145
- dataState: {},
146
- consoleState: { history: [] },
147
- };
148
- state.selectedPlayerId = playerID;
149
- return;
150
- }
151
-
152
- state.activePlayers[playerID].flowInfo = {
153
- ...state.activePlayers[playerID].flowInfo,
154
- currentFlow: flow,
155
- };
156
- });
157
-
158
- builder.addCase(Events.actions['player-view-update-event'], (state, action) => {
159
- const {
160
- payload: { playerID, update },
161
- } = action;
162
-
163
- if (!state.activePlayers[playerID]) {
164
- state.activePlayers[playerID] = {
165
- view: update,
166
- timelineEvents: [],
167
- dataState: {},
168
- consoleState: { history: [] },
169
- };
170
- state.selectedPlayerId = playerID;
171
- return;
172
- }
173
-
174
- state.activePlayers[playerID].view = update;
175
- });
176
- };
177
-
178
- export const actionsReducer = (builder: ActionReducerMapBuilder<PlayersState>) => {
179
- builder.addCase(Actions['selected-player'], (state, action) => {
180
- if (action.payload) {
181
- state.selectedPlayerId = action.payload;
182
- return;
183
- }
184
-
185
- state.selectedPlayerId = Object.keys(state.activePlayers)[0] || null;
186
- });
187
-
188
- builder.addCase(Actions['player-timeline-event'], (state, action) => {
189
- const {
190
- payload: { playerID },
191
- } = action;
192
-
193
- if (!state.activePlayers[playerID]) {
194
- state.activePlayers[playerID] = {
195
- timelineEvents: [action.payload],
196
- dataState: {},
197
- consoleState: { history: [] },
198
- };
199
- state.selectedPlayerId = playerID;
200
- return;
201
- }
202
-
203
- state.activePlayers[playerID].timelineEvents.push(action.payload);
204
- });
205
-
206
- builder.addCase(Actions['clear-selected-data-details'], (state) => {
207
- const { activePlayers, selectedPlayerId } = state;
208
-
209
- if (!selectedPlayerId || !activePlayers[selectedPlayerId]) {
210
- return;
211
- }
212
-
213
- activePlayers[selectedPlayerId].dataState.selectedBinding = undefined;
214
- });
215
-
216
- builder.addCase(Actions['clear-console'], (state) => {
217
- const { activePlayers, selectedPlayerId } = state;
218
-
219
- if (!selectedPlayerId) {
220
- return;
221
- }
222
-
223
- activePlayers[selectedPlayerId].consoleState = {
224
- history: [],
225
- };
226
- });
227
-
228
- builder.addCase(Actions['clear-logs'], (state) => {
229
- const { activePlayers, selectedPlayerId } = state;
230
-
231
- if (!selectedPlayerId) {
232
- return;
233
- }
234
-
235
- activePlayers[selectedPlayerId].timelineEvents = [];
236
- });
237
-
238
- builder.addCase(Actions['clear-store'], () => {
239
- return initialState;
240
- });
241
- };
242
-
243
- export const playersReducer = (methods: Methods.MethodThunks) =>
244
- createReducer<PlayersState>(initialState, (builder) => {
245
- actionsReducer(builder)
246
- eventsReducer(builder)
247
- methodsReducer(methods)(builder)
248
- });
108
+ builder.addCase(
109
+ actions['player-stop-profiler-request'].fulfilled,
110
+ (state, action) => {
111
+ const { activePlayers, selectedPlayerId } = state;
112
+
113
+ if (!selectedPlayerId) return;
114
+
115
+ activePlayers[selectedPlayerId].profilerInfo = action.payload?.data;
116
+ }
117
+ );
118
+ };
@@ -0,0 +1,21 @@
1
+ import {
2
+ type RPCRequestMessageEvent,
3
+ type RPCRequestHandler,
4
+ createRPCRequest,
5
+ Runtime,
6
+ PANEL_SOURCE,
7
+ } from '@player-tools/devtools-common';
8
+
9
+ export type RuntimeRPCRequestHandlers = {
10
+ [key in Runtime.RuntimeRPCTypes]: RPCRequestHandler<any>;
11
+ };
12
+
13
+ export const buildRPCRequests = (
14
+ onRequestMessage: (
15
+ message: RPCRequestMessageEvent<Runtime.RuntimeRPC>
16
+ ) => void
17
+ ): RuntimeRPCRequestHandlers =>
18
+ Runtime.RuntimeRPCTypes.reduce((acc, rpcType) => {
19
+ acc[rpcType] = createRPCRequest(rpcType, PANEL_SOURCE, onRequestMessage);
20
+ return acc;
21
+ }, {} as RuntimeRPCRequestHandlers);
@@ -1,10 +0,0 @@
1
- import { Events, Message } from "@player-tools/devtools-common";
2
- import { Events as EventActions } from "./actions";
3
-
4
- export function handleMessage(message: Message) {
5
- // propagate message to default event handlers
6
- const { type } = message;
7
- if (type in Events.EventTypes) {
8
- EventActions.actions[type as Events.EventTypes](message as any)
9
- }
10
- }
@@ -1,63 +0,0 @@
1
- import { StoreState } from "@player-tools/devtools-client";
2
- import { createListenerMiddleware, isAnyOf } from "@reduxjs/toolkit";
3
- import { Actions, Events } from "./actions";
4
- import { GET_DATA_BINDING_DETAILS } from "./aliases";
5
-
6
- export const listenerMiddleware = createListenerMiddleware();
7
-
8
- listenerMiddleware.startListening({
9
- matcher: isAnyOf(
10
- Events.actions['player-data-change-event'],
11
- Events.actions['player-log-event'],
12
- Events.actions['player-flow-start'],
13
- // TODO: I don't actually think this _was_ included
14
- Events.actions['player-view-update-event']
15
- ),
16
- effect: (action, api) => {
17
- api.dispatch(Actions['player-timeline-event'](action.payload));
18
- },
19
- });
20
-
21
- listenerMiddleware.startListening({
22
- actionCreator: Events.actions['runtime-init'],
23
- effect: (_, api) => {
24
- api.dispatch(Actions["clear-store"]())
25
- }
26
- })
27
-
28
- listenerMiddleware.startListening({
29
- matcher: isAnyOf(
30
- Events.actions["player-init"],
31
- Events.actions["player-removed"],
32
- ),
33
- effect: (_, api) => {
34
- api.dispatch(Actions["selected-player"]())
35
- }
36
- });
37
-
38
- listenerMiddleware.startListening({
39
- matcher: isAnyOf(
40
- Events.actions["player-flow-start"],
41
- Events.actions["player-data-change-event"],
42
- ),
43
- effect: (action, api) => {
44
- // TODO: Just appropriately type the middleware
45
- const { players } = api.getState() as StoreState;
46
- const { playerID } = action.payload;
47
-
48
- if (
49
- players.activePlayers[playerID] &&
50
- players.activePlayers[playerID].dataState.selectedBinding
51
- ) {
52
- api.dispatch({
53
- type: GET_DATA_BINDING_DETAILS,
54
- payload: { playerID, binding: players.activePlayers[playerID].dataState.selectedBinding },
55
- });
56
- }
57
-
58
- api.dispatch({
59
- type: GET_DATA_BINDING_DETAILS,
60
- payload: { playerID, binding: '' },
61
- })
62
- }
63
- })
@@ -1,133 +0,0 @@
1
- import { createSelector } from '@reduxjs/toolkit';
2
- import type { StoreState, PlayersState } from './state';
3
-
4
- /**
5
- * Selects the player state
6
- * @param state
7
- * @returns
8
- */
9
- const selectPlayers = (state: StoreState) => {
10
- return state.players;
11
- };
12
-
13
- /**
14
- * Selects all the active players.
15
- */
16
- const selectActivePlayers = createSelector(
17
- selectPlayers,
18
- (players: PlayersState) => players.activePlayers
19
- );
20
-
21
- export const selectPlayerVersion = createSelector(
22
- selectPlayers,
23
- (players: PlayersState) => players.version
24
- );
25
-
26
- export const selectPlayerIds = createSelector(
27
- selectActivePlayers,
28
- (activePlayers) => Object.keys(activePlayers) || []
29
- );
30
-
31
- /**
32
- * Selects the selected/currently active player Id.
33
- */
34
- export const selectSelectedPlayerId = createSelector(
35
- selectPlayers,
36
- (players: PlayersState) => players.selectedPlayerId
37
- );
38
-
39
- export const selectCurrentPlayer = createSelector(
40
- selectActivePlayers,
41
- selectSelectedPlayerId,
42
- (activePlayers, selectedPlayerId) => {
43
- if (!selectedPlayerId) {
44
- return null;
45
- }
46
-
47
- return activePlayers[selectedPlayerId];
48
- }
49
- );
50
-
51
- export const selectConfig = createSelector(
52
- selectCurrentPlayer,
53
- (currentPlayer) => {
54
- return currentPlayer?.configState ?? null;
55
- }
56
- );
57
-
58
- const selectData = createSelector(selectCurrentPlayer, (currentPlayer) => {
59
- return currentPlayer?.dataState;
60
- });
61
-
62
- export const selectFlowInfo = createSelector(
63
- selectCurrentPlayer,
64
- (currentPlayer) => {
65
- if (!currentPlayer) {
66
- return null;
67
- }
68
-
69
- return currentPlayer?.flowInfo;
70
- }
71
- );
72
-
73
- export const selectCurrentFlow = createSelector(
74
- selectFlowInfo,
75
- (flowInfo) => {
76
- return flowInfo?.currentFlow;
77
- }
78
- );
79
-
80
- export const selectCurrentTopic = createSelector(
81
- selectCurrentFlow,
82
- (currentFlow) => {
83
- return currentFlow?.topic;
84
- }
85
- );
86
-
87
- export const selectEvents = createSelector(
88
- selectCurrentPlayer,
89
- (currentPlayer) => {
90
- if (!currentPlayer) {
91
- return [];
92
- }
93
-
94
- return currentPlayer?.timelineEvents;
95
- }
96
- );
97
-
98
- export const selectView = createSelector(
99
- selectCurrentPlayer,
100
- (currentPlayer) => {
101
- if (!currentPlayer) {
102
- return null;
103
- }
104
-
105
- return currentPlayer?.view;
106
- }
107
- );
108
-
109
- export const selectAllBindings = createSelector(selectData, (data) => {
110
- return data?.allBindings;
111
- });
112
-
113
- export const selectSelectedBinding = createSelector(selectData, (data) => {
114
- return data?.selectedBinding;
115
- });
116
-
117
- export const selectConsole = createSelector(
118
- selectCurrentPlayer,
119
- (currentPlayer) => {
120
- if (!currentPlayer) {
121
- return { history: [] };
122
- }
123
-
124
- return currentPlayer.consoleState;
125
- }
126
- );
127
-
128
- export const selectProfiler = createSelector(
129
- selectCurrentPlayer,
130
- (currentPlayer) => {
131
- return currentPlayer?.profilerInfo;
132
- }
133
- );