@player-devtools/plugin 0.0.2-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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/index.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/state.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/reducer.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/constants.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/uuid.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/genDataChangeTransaction.ts"],"sourcesContent":["export {\n DevtoolsPlugin,\n type DevtoolsPluginOptions,\n type PluginStore,\n type DevtoolsHandler,\n} from \"./plugin\";\nexport * from \"./helpers\";\nexport { PLUGIN_INACTIVE_WARNING } from \"./constants\";\n","import type { Messenger } from \"@player-devtools/messenger\";\nimport {\n PluginData,\n DevtoolsPluginsStore,\n PlayerInitEvent,\n ExtensionSupportedEvents,\n Transaction,\n DevtoolsPluginInteractionEvent,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport type { DataModel, Player, PlayerPlugin } from \"@player-ui/player\";\nimport { produce } from \"immer\";\nimport { useStateReducer, type Store, type Unsubscribe } from \"./state\";\nimport { reducer } from \"./reducer\";\nimport { PLUGIN_INACTIVE_WARNING, INTERACTIONS } from \"./constants\";\nimport { genDataChangeTransaction } from \"./helpers\";\nimport { dequal } from \"dequal\";\n\nexport interface DevtoolsHandler {\n // TODO: Could return bool to signifiy handled to avoid double processing?\n processInteraction(interaction: DevtoolsPluginInteractionEvent): void;\n checkIfDevtoolsIsActive(): boolean;\n log?(message: string): void;\n}\n\nexport interface DevtoolsPluginOptions {\n playerID: string;\n pluginData: PluginData;\n handler: DevtoolsHandler;\n}\n\nconst INITIAL_STATE: DevtoolsPluginsStore = {\n messages: [],\n plugins: {},\n interactions: [],\n currentPlayer: \"\",\n};\n\n// TODO: Rename to DevtoolsPluginStore? Need to rename DevtoolsPluginsStore to DevtoolsPluginState\nexport type PluginStore = Store<\n DevtoolsPluginsStore,\n Transaction<ExtensionSupportedEvents>\n>;\n\n/** Entrypoint for devtools plugins with platform-agnostic components */\nexport class DevtoolsPlugin implements PlayerPlugin, DevtoolsHandler {\n name: string = \"DevtoolsPlugin\";\n\n private loggedWarning = false;\n\n store: PluginStore = useStateReducer(reducer, INITIAL_STATE);\n protected lastProcessedInteraction = 0;\n\n get pluginID(): string {\n return this.options.pluginData.id;\n }\n\n get playerID(): string {\n return this.options.playerID;\n }\n\n constructor(protected options: DevtoolsPluginOptions) {\n this.store.subscribe(({ interactions }) => {\n if (this.lastProcessedInteraction < (interactions.length ?? 0)) {\n interactions\n .slice(this.lastProcessedInteraction)\n .forEach(this.processInteraction.bind(this));\n }\n });\n }\n\n registerMessenger(\n messenger: Messenger<ExtensionSupportedEvents>,\n ): Unsubscribe {\n // Propagate new messages from state to devtools via the messenger\n let lastMessageIndex = -1;\n return this.store.subscribe(({ messages }) => {\n const start = lastMessageIndex + 1;\n if (messages.length > start) {\n const newlyAdded = messages.slice(start);\n lastMessageIndex = messages.length - 1;\n for (const msg of newlyAdded) {\n messenger.sendMessage(msg);\n }\n }\n });\n }\n\n protected dispatchPlayerInit(): void {\n // Initial plugin content\n const transaction: Transaction<PlayerInitEvent> = {\n id: -1,\n type: \"PLAYER_DEVTOOLS_PLAYER_INIT\",\n payload: {\n plugins: {\n [this.pluginID]: this.options.pluginData,\n },\n },\n sender: this.options.playerID,\n context: \"player\",\n target: \"player\",\n timestamp: Date.now(),\n _messenger_: true,\n };\n\n this.store.dispatch(transaction);\n }\n\n // By default, we'll only write to the keys defined in data -- if undefined, data will be cleared\n protected dispatchDataUpdate(data?: DataModel): void {\n const state = this.store.getState();\n\n const { plugins } = produce(this.store.getState(), (draft) => {\n if (!data)\n dsetAssign(draft, [\"plugins\", this.pluginID, \"flow\", \"data\"], data);\n else\n Object.entries(data).forEach(([key, value]) => {\n dsetAssign(\n draft,\n [\"plugins\", this.pluginID, \"flow\", \"data\", key],\n value,\n );\n });\n });\n\n const newData = plugins[this.pluginID]!.flow.data;\n if (dequal(state.plugins[this.pluginID]?.flow?.data, newData)) return;\n\n const transaction = genDataChangeTransaction({\n playerID: this.playerID,\n pluginID: this.pluginID,\n data: newData,\n });\n\n this.store.dispatch(transaction);\n }\n\n checkIfDevtoolsIsActive(): boolean {\n const isActive = this.options.handler.checkIfDevtoolsIsActive();\n if (!isActive && !this.loggedWarning) {\n this.options.handler.log?.(PLUGIN_INACTIVE_WARNING);\n this.loggedWarning = true;\n }\n\n return isActive;\n }\n\n processInteraction(interaction: DevtoolsPluginInteractionEvent): void {\n this.options.handler.processInteraction(interaction);\n\n const {\n payload: { type, payload },\n } = interaction;\n\n if (type === INTERACTIONS.PLAYER_SELECTED && payload) {\n this.store.dispatch({\n id: -1,\n type: \"PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE\",\n payload: { playerID: payload },\n sender: this.playerID,\n context: \"player\",\n target: this.playerID,\n timestamp: Date.now(),\n _messenger_: true,\n });\n }\n\n this.lastProcessedInteraction += 1;\n }\n\n apply(player: Player): void {\n if (!this.checkIfDevtoolsIsActive()) return;\n\n this.dispatchPlayerInit();\n }\n}\n","export type Reducer<T, A> = (state: T, action: A) => T;\nexport type Dispatch<A> = (action: A) => void;\nexport type Subscriber<T> = (state: T) => void;\nexport type Subscribe<T> = (subscriber: Subscriber<T>) => Unsubscribe;\nexport type Unsubscribe = () => void;\n\nexport interface Store<State, Action> {\n getState: () => State;\n subscribe: Subscribe<State>;\n dispatch: Dispatch<Action>;\n}\n\nexport const useStateReducer = <State, Action>(\n reducer: Reducer<State, Action>,\n initialState: State,\n): Store<State, Action> => {\n let state = initialState;\n const subscribers = new Set<Subscriber<State>>();\n return {\n getState: () => state,\n\n /** Subscribe to state changes; returns an unsubscribe function. */\n subscribe(subscriber: Subscriber<State>): Unsubscribe {\n subscribers.add(subscriber);\n subscriber(state);\n return () => subscribers.delete(subscriber);\n },\n\n /** Dispatch an action through the reducer, then run side-effects. */\n dispatch(action: Action): void {\n const prevState = state;\n const nextState = reducer(prevState, action);\n\n // Only proceed if state actually changed by reference\n if (nextState !== prevState) {\n state = nextState;\n\n // Notify subscribers\n for (const sub of subscribers) sub(state);\n }\n },\n };\n};\n","import { produce } from \"immer\";\nimport { dequal } from \"dequal\";\nimport type {\n DevtoolsDataChangeEvent,\n DevtoolsPluginsStore,\n ExtensionSupportedEvents,\n PlayerInitEvent,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\n\nconst containsInteraction = (\n interactions: DevtoolsPluginsStore[\"interactions\"],\n interaction: DevtoolsPluginsStore[\"interactions\"][number],\n) => {\n return interactions.filter((i) => dequal(i, interaction)).length > 0;\n};\n\n/** devtools plugin state reducer */\nexport const reducer = (\n state: DevtoolsPluginsStore,\n transaction: Transaction<ExtensionSupportedEvents>,\n): DevtoolsPluginsStore => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const { payload } = transaction;\n dsetAssign(draft, [\"plugins\"], payload.plugins);\n\n const message: PlayerInitEvent = {\n type: \"PLAYER_DEVTOOLS_PLAYER_INIT\",\n payload,\n };\n\n draft.messages.push(message);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const { payload } = transaction;\n\n if (!payload.data) return state;\n\n try {\n dsetAssign(\n draft,\n [\"plugins\", transaction.payload.pluginID, \"flow\", \"data\"],\n transaction.payload.data,\n );\n } catch {\n console.error(\"error setting data:\", transaction.payload.data);\n }\n const message: DevtoolsDataChangeEvent = {\n type: \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\",\n payload,\n };\n\n draft.messages.push(message);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\":\n return produce(state, (draft) => {\n if (containsInteraction(draft.interactions, transaction)) return state;\n\n dsetAssign(\n draft,\n [\"interactions\"],\n [...draft.interactions, transaction],\n );\n });\n case \"PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE\": {\n const { playerID } = transaction.payload;\n\n if (!playerID) return state;\n return produce(state, (draft) => {\n dsetAssign(draft, [\"currentPlayer\"], playerID);\n });\n }\n default:\n return state;\n }\n};\n","export const INTERACTIONS = {\n PLAYER_SELECTED: \"player-selected\",\n};\n\nexport const PLUGIN_INACTIVE_WARNING =\n \"The plugin has been registered, but the Player development tools are not active. If you are working in a production environment, it is recommended to remove the plugin. To activate, enable through the browser extension popup for web or configure the FlipperClient for mobile.\";\n","export function generateUUID(): string {\n // Public Domain/MIT\n let d = new Date().getTime(); //Timestamp\n let d2 =\n (typeof performance !== \"undefined\" &&\n performance.now &&\n performance.now() * 1000) ||\n 0; //Time in microseconds since page-load or 0 if unsupported\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n let r = Math.random() * 16; //random number between 0 and 16\n if (d > 0) {\n //Use timestamp until depleted\n r = (d + r) % 16 | 0;\n d = Math.floor(d / 16);\n } else {\n //Use microseconds since page-load if supported\n r = (d2 + r) % 16 | 0;\n d2 = Math.floor(d2 / 16);\n }\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","import type {\n DevtoolsDataChangeEvent,\n Transaction,\n} from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nconst NOOP_ID = -1;\n\n/**\n * Generates a data change transaction for the player devtools plugin.\n *\n * This function creates a transaction object that represents a change in data\n * within a player devtools plugin. The transaction includes details such as the\n * plugin ID, the changed data, and the player ID. It is used to communicate\n * changes between the plugin and devtools.\n */\nexport const genDataChangeTransaction = ({\n playerID,\n data,\n pluginID,\n}: {\n playerID: string;\n data: Flow[\"data\"];\n pluginID: string;\n}): Transaction<DevtoolsDataChangeEvent> => {\n return {\n id: NOOP_ID,\n type: \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\",\n payload: {\n pluginID,\n data,\n },\n sender: playerID,\n context: \"player\",\n target: \"player\",\n timestamp: Date.now(),\n _messenger_: true,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACSA,IAAAA,gBAA2B;AAE3B,IAAAC,gBAAwB;;;ACCjB,IAAM,kBAAkB,CAC7BC,UACA,iBACyB;AACzB,MAAI,QAAQ;AACZ,QAAM,cAAc,oBAAI,IAAuB;AAC/C,SAAO;AAAA,IACL,UAAU,MAAM;AAAA;AAAA,IAGhB,UAAU,YAA4C;AACpD,kBAAY,IAAI,UAAU;AAC1B,iBAAW,KAAK;AAChB,aAAO,MAAM,YAAY,OAAO,UAAU;AAAA,IAC5C;AAAA;AAAA,IAGA,SAAS,QAAsB;AAC7B,YAAM,YAAY;AAClB,YAAM,YAAYA,SAAQ,WAAW,MAAM;AAG3C,UAAI,cAAc,WAAW;AAC3B,gBAAQ;AAGR,mBAAW,OAAO,YAAa,KAAI,KAAK;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AACF;;;AC1CA,mBAAwB;AACxB,oBAAuB;AAQvB,mBAA2B;AAE3B,IAAM,sBAAsB,CAC1B,cACA,gBACG;AACH,SAAO,aAAa,OAAO,CAAC,UAAM,sBAAO,GAAG,WAAW,CAAC,EAAE,SAAS;AACrE;AAGO,IAAM,UAAU,CACrB,OACA,gBACyB;AACzB,UAAQ,YAAY,MAAM;AAAA,IACxB,KAAK;AACH,iBAAO,sBAAQ,OAAO,CAAC,UAAU;AAC/B,cAAM,EAAE,QAAQ,IAAI;AACpB,qCAAW,OAAO,CAAC,SAAS,GAAG,QAAQ,OAAO;AAE9C,cAAM,UAA2B;AAAA,UAC/B,MAAM;AAAA,UACN;AAAA,QACF;AAEA,cAAM,SAAS,KAAK,OAAO;AAAA,MAC7B,CAAC;AAAA,IACH,KAAK;AACH,iBAAO,sBAAQ,OAAO,CAAC,UAAU;AAC/B,cAAM,EAAE,QAAQ,IAAI;AAEpB,YAAI,CAAC,QAAQ,KAAM,QAAO;AAE1B,YAAI;AACF;AAAA,YACE;AAAA,YACA,CAAC,WAAW,YAAY,QAAQ,UAAU,QAAQ,MAAM;AAAA,YACxD,YAAY,QAAQ;AAAA,UACtB;AAAA,QACF,QAAQ;AACN,kBAAQ,MAAM,uBAAuB,YAAY,QAAQ,IAAI;AAAA,QAC/D;AACA,cAAM,UAAmC;AAAA,UACvC,MAAM;AAAA,UACN;AAAA,QACF;AAEA,cAAM,SAAS,KAAK,OAAO;AAAA,MAC7B,CAAC;AAAA,IACH,KAAK;AACH,iBAAO,sBAAQ,OAAO,CAAC,UAAU;AAC/B,YAAI,oBAAoB,MAAM,cAAc,WAAW,EAAG,QAAO;AAEjE;AAAA,UACE;AAAA,UACA,CAAC,cAAc;AAAA,UACf,CAAC,GAAG,MAAM,cAAc,WAAW;AAAA,QACrC;AAAA,MACF,CAAC;AAAA,IACH,KAAK,0CAA0C;AAC7C,YAAM,EAAE,SAAS,IAAI,YAAY;AAEjC,UAAI,CAAC,SAAU,QAAO;AACtB,iBAAO,sBAAQ,OAAO,CAAC,UAAU;AAC/B,qCAAW,OAAO,CAAC,eAAe,GAAG,QAAQ;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;;;AC/EO,IAAM,eAAe;AAAA,EAC1B,iBAAiB;AACnB;AAEO,IAAM,0BACX;;;ACLK,SAAS,eAAuB;AAErC,MAAI,KAAI,oBAAI,KAAK,GAAE,QAAQ;AAC3B,MAAI,KACD,OAAO,gBAAgB,eACtB,YAAY,OACZ,YAAY,IAAI,IAAI,OACtB;AACF,SAAO,uCAAuC,QAAQ,SAAS,SAAU,GAAG;AAC1E,QAAI,IAAI,KAAK,OAAO,IAAI;AACxB,QAAI,IAAI,GAAG;AAET,WAAK,IAAI,KAAK,KAAK;AACnB,UAAI,KAAK,MAAM,IAAI,EAAE;AAAA,IACvB,OAAO;AAEL,WAAK,KAAK,KAAK,KAAK;AACpB,WAAK,KAAK,MAAM,KAAK,EAAE;AAAA,IACzB;AACA,YAAQ,MAAM,MAAM,IAAK,IAAI,IAAO,GAAK,SAAS,EAAE;AAAA,EACtD,CAAC;AACH;;;ACfA,IAAM,UAAU;AAUT,IAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF,MAI4C;AAC1C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW,KAAK,IAAI;AAAA,IACpB,aAAa;AAAA,EACf;AACF;;;ALtBA,IAAAC,iBAAuB;AAevB,IAAM,gBAAsC;AAAA,EAC1C,UAAU,CAAC;AAAA,EACX,SAAS,CAAC;AAAA,EACV,cAAc,CAAC;AAAA,EACf,eAAe;AACjB;AASO,IAAM,iBAAN,MAA8D;AAAA,EAgBnE,YAAsB,SAAgC;AAAhC;AAftB,gBAAe;AAEf,SAAQ,gBAAgB;AAExB,iBAAqB,gBAAgB,SAAS,aAAa;AAC3D,SAAU,2BAA2B;AAWnC,SAAK,MAAM,UAAU,CAAC,EAAE,aAAa,MAAM;AACzC,UAAI,KAAK,4BAA4B,aAAa,UAAU,IAAI;AAC9D,qBACG,MAAM,KAAK,wBAAwB,EACnC,QAAQ,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAhBA,IAAI,WAAmB;AACrB,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAYA,kBACE,WACa;AAEb,QAAI,mBAAmB;AACvB,WAAO,KAAK,MAAM,UAAU,CAAC,EAAE,SAAS,MAAM;AAC5C,YAAM,QAAQ,mBAAmB;AACjC,UAAI,SAAS,SAAS,OAAO;AAC3B,cAAM,aAAa,SAAS,MAAM,KAAK;AACvC,2BAAmB,SAAS,SAAS;AACrC,mBAAW,OAAO,YAAY;AAC5B,oBAAU,YAAY,GAAG;AAAA,QAC3B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEU,qBAA2B;AAEnC,UAAM,cAA4C;AAAA,MAChD,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,QACP,SAAS;AAAA,UACP,CAAC,KAAK,QAAQ,GAAG,KAAK,QAAQ;AAAA,QAChC;AAAA,MACF;AAAA,MACA,QAAQ,KAAK,QAAQ;AAAA,MACrB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW,KAAK,IAAI;AAAA,MACpB,aAAa;AAAA,IACf;AAEA,SAAK,MAAM,SAAS,WAAW;AAAA,EACjC;AAAA;AAAA,EAGU,mBAAmB,MAAwB;AACnD,UAAM,QAAQ,KAAK,MAAM,SAAS;AAElC,UAAM,EAAE,QAAQ,QAAI,uBAAQ,KAAK,MAAM,SAAS,GAAG,CAAC,UAAU;AAC5D,UAAI,CAAC;AACH,sCAAW,OAAO,CAAC,WAAW,KAAK,UAAU,QAAQ,MAAM,GAAG,IAAI;AAAA;AAElE,eAAO,QAAQ,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC7C;AAAA,YACE;AAAA,YACA,CAAC,WAAW,KAAK,UAAU,QAAQ,QAAQ,GAAG;AAAA,YAC9C;AAAA,UACF;AAAA,QACF,CAAC;AAAA,IACL,CAAC;AAED,UAAM,UAAU,QAAQ,KAAK,QAAQ,EAAG,KAAK;AAC7C,YAAI,uBAAO,MAAM,QAAQ,KAAK,QAAQ,GAAG,MAAM,MAAM,OAAO,EAAG;AAE/D,UAAM,cAAc,yBAAyB;AAAA,MAC3C,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,MAAM;AAAA,IACR,CAAC;AAED,SAAK,MAAM,SAAS,WAAW;AAAA,EACjC;AAAA,EAEA,0BAAmC;AACjC,UAAM,WAAW,KAAK,QAAQ,QAAQ,wBAAwB;AAC9D,QAAI,CAAC,YAAY,CAAC,KAAK,eAAe;AACpC,WAAK,QAAQ,QAAQ,MAAM,uBAAuB;AAClD,WAAK,gBAAgB;AAAA,IACvB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB,aAAmD;AACpE,SAAK,QAAQ,QAAQ,mBAAmB,WAAW;AAEnD,UAAM;AAAA,MACJ,SAAS,EAAE,MAAM,QAAQ;AAAA,IAC3B,IAAI;AAEJ,QAAI,SAAS,aAAa,mBAAmB,SAAS;AACpD,WAAK,MAAM,SAAS;AAAA,QAClB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,EAAE,UAAU,QAAQ;AAAA,QAC7B,QAAQ,KAAK;AAAA,QACb,SAAS;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,WAAW,KAAK,IAAI;AAAA,QACpB,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,SAAK,4BAA4B;AAAA,EACnC;AAAA,EAEA,MAAM,QAAsB;AAC1B,QAAI,CAAC,KAAK,wBAAwB,EAAG;AAErC,SAAK,mBAAmB;AAAA,EAC1B;AACF;","names":["import_utils","import_immer","reducer","import_dequal"]}
@@ -0,0 +1,252 @@
1
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts
2
+ import { dsetAssign as dsetAssign2 } from "@player-devtools/utils";
3
+ import { produce as produce2 } from "immer";
4
+
5
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/state.ts
6
+ var useStateReducer = (reducer2, initialState) => {
7
+ let state = initialState;
8
+ const subscribers = /* @__PURE__ */ new Set();
9
+ return {
10
+ getState: () => state,
11
+ /** Subscribe to state changes; returns an unsubscribe function. */
12
+ subscribe(subscriber) {
13
+ subscribers.add(subscriber);
14
+ subscriber(state);
15
+ return () => subscribers.delete(subscriber);
16
+ },
17
+ /** Dispatch an action through the reducer, then run side-effects. */
18
+ dispatch(action) {
19
+ const prevState = state;
20
+ const nextState = reducer2(prevState, action);
21
+ if (nextState !== prevState) {
22
+ state = nextState;
23
+ for (const sub of subscribers) sub(state);
24
+ }
25
+ }
26
+ };
27
+ };
28
+
29
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/reducer.ts
30
+ import { produce } from "immer";
31
+ import { dequal } from "dequal";
32
+ import { dsetAssign } from "@player-devtools/utils";
33
+ var containsInteraction = (interactions, interaction) => {
34
+ return interactions.filter((i) => dequal(i, interaction)).length > 0;
35
+ };
36
+ var reducer = (state, transaction) => {
37
+ switch (transaction.type) {
38
+ case "PLAYER_DEVTOOLS_PLAYER_INIT":
39
+ return produce(state, (draft) => {
40
+ const { payload } = transaction;
41
+ dsetAssign(draft, ["plugins"], payload.plugins);
42
+ const message = {
43
+ type: "PLAYER_DEVTOOLS_PLAYER_INIT",
44
+ payload
45
+ };
46
+ draft.messages.push(message);
47
+ });
48
+ case "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE":
49
+ return produce(state, (draft) => {
50
+ const { payload } = transaction;
51
+ if (!payload.data) return state;
52
+ try {
53
+ dsetAssign(
54
+ draft,
55
+ ["plugins", transaction.payload.pluginID, "flow", "data"],
56
+ transaction.payload.data
57
+ );
58
+ } catch {
59
+ console.error("error setting data:", transaction.payload.data);
60
+ }
61
+ const message = {
62
+ type: "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE",
63
+ payload
64
+ };
65
+ draft.messages.push(message);
66
+ });
67
+ case "PLAYER_DEVTOOLS_PLUGIN_INTERACTION":
68
+ return produce(state, (draft) => {
69
+ if (containsInteraction(draft.interactions, transaction)) return state;
70
+ dsetAssign(
71
+ draft,
72
+ ["interactions"],
73
+ [...draft.interactions, transaction]
74
+ );
75
+ });
76
+ case "PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE": {
77
+ const { playerID } = transaction.payload;
78
+ if (!playerID) return state;
79
+ return produce(state, (draft) => {
80
+ dsetAssign(draft, ["currentPlayer"], playerID);
81
+ });
82
+ }
83
+ default:
84
+ return state;
85
+ }
86
+ };
87
+
88
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/constants.ts
89
+ var INTERACTIONS = {
90
+ PLAYER_SELECTED: "player-selected"
91
+ };
92
+ var PLUGIN_INACTIVE_WARNING = "The plugin has been registered, but the Player development tools are not active. If you are working in a production environment, it is recommended to remove the plugin. To activate, enable through the browser extension popup for web or configure the FlipperClient for mobile.";
93
+
94
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/uuid.ts
95
+ function generateUUID() {
96
+ let d = (/* @__PURE__ */ new Date()).getTime();
97
+ let d2 = typeof performance !== "undefined" && performance.now && performance.now() * 1e3 || 0;
98
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
99
+ let r = Math.random() * 16;
100
+ if (d > 0) {
101
+ r = (d + r) % 16 | 0;
102
+ d = Math.floor(d / 16);
103
+ } else {
104
+ r = (d2 + r) % 16 | 0;
105
+ d2 = Math.floor(d2 / 16);
106
+ }
107
+ return (c === "x" ? r : r & 3 | 8).toString(16);
108
+ });
109
+ }
110
+
111
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/genDataChangeTransaction.ts
112
+ var NOOP_ID = -1;
113
+ var genDataChangeTransaction = ({
114
+ playerID,
115
+ data,
116
+ pluginID
117
+ }) => {
118
+ return {
119
+ id: NOOP_ID,
120
+ type: "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE",
121
+ payload: {
122
+ pluginID,
123
+ data
124
+ },
125
+ sender: playerID,
126
+ context: "player",
127
+ target: "player",
128
+ timestamp: Date.now(),
129
+ _messenger_: true
130
+ };
131
+ };
132
+
133
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts
134
+ import { dequal as dequal2 } from "dequal";
135
+ var INITIAL_STATE = {
136
+ messages: [],
137
+ plugins: {},
138
+ interactions: [],
139
+ currentPlayer: ""
140
+ };
141
+ var DevtoolsPlugin = class {
142
+ constructor(options) {
143
+ this.options = options;
144
+ this.name = "DevtoolsPlugin";
145
+ this.loggedWarning = false;
146
+ this.store = useStateReducer(reducer, INITIAL_STATE);
147
+ this.lastProcessedInteraction = 0;
148
+ this.store.subscribe(({ interactions }) => {
149
+ if (this.lastProcessedInteraction < (interactions.length ?? 0)) {
150
+ interactions.slice(this.lastProcessedInteraction).forEach(this.processInteraction.bind(this));
151
+ }
152
+ });
153
+ }
154
+ get pluginID() {
155
+ return this.options.pluginData.id;
156
+ }
157
+ get playerID() {
158
+ return this.options.playerID;
159
+ }
160
+ registerMessenger(messenger) {
161
+ let lastMessageIndex = -1;
162
+ return this.store.subscribe(({ messages }) => {
163
+ const start = lastMessageIndex + 1;
164
+ if (messages.length > start) {
165
+ const newlyAdded = messages.slice(start);
166
+ lastMessageIndex = messages.length - 1;
167
+ for (const msg of newlyAdded) {
168
+ messenger.sendMessage(msg);
169
+ }
170
+ }
171
+ });
172
+ }
173
+ dispatchPlayerInit() {
174
+ const transaction = {
175
+ id: -1,
176
+ type: "PLAYER_DEVTOOLS_PLAYER_INIT",
177
+ payload: {
178
+ plugins: {
179
+ [this.pluginID]: this.options.pluginData
180
+ }
181
+ },
182
+ sender: this.options.playerID,
183
+ context: "player",
184
+ target: "player",
185
+ timestamp: Date.now(),
186
+ _messenger_: true
187
+ };
188
+ this.store.dispatch(transaction);
189
+ }
190
+ // By default, we'll only write to the keys defined in data -- if undefined, data will be cleared
191
+ dispatchDataUpdate(data) {
192
+ const state = this.store.getState();
193
+ const { plugins } = produce2(this.store.getState(), (draft) => {
194
+ if (!data)
195
+ dsetAssign2(draft, ["plugins", this.pluginID, "flow", "data"], data);
196
+ else
197
+ Object.entries(data).forEach(([key, value]) => {
198
+ dsetAssign2(
199
+ draft,
200
+ ["plugins", this.pluginID, "flow", "data", key],
201
+ value
202
+ );
203
+ });
204
+ });
205
+ const newData = plugins[this.pluginID].flow.data;
206
+ if (dequal2(state.plugins[this.pluginID]?.flow?.data, newData)) return;
207
+ const transaction = genDataChangeTransaction({
208
+ playerID: this.playerID,
209
+ pluginID: this.pluginID,
210
+ data: newData
211
+ });
212
+ this.store.dispatch(transaction);
213
+ }
214
+ checkIfDevtoolsIsActive() {
215
+ const isActive = this.options.handler.checkIfDevtoolsIsActive();
216
+ if (!isActive && !this.loggedWarning) {
217
+ this.options.handler.log?.(PLUGIN_INACTIVE_WARNING);
218
+ this.loggedWarning = true;
219
+ }
220
+ return isActive;
221
+ }
222
+ processInteraction(interaction) {
223
+ this.options.handler.processInteraction(interaction);
224
+ const {
225
+ payload: { type, payload }
226
+ } = interaction;
227
+ if (type === INTERACTIONS.PLAYER_SELECTED && payload) {
228
+ this.store.dispatch({
229
+ id: -1,
230
+ type: "PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE",
231
+ payload: { playerID: payload },
232
+ sender: this.playerID,
233
+ context: "player",
234
+ target: this.playerID,
235
+ timestamp: Date.now(),
236
+ _messenger_: true
237
+ });
238
+ }
239
+ this.lastProcessedInteraction += 1;
240
+ }
241
+ apply(player) {
242
+ if (!this.checkIfDevtoolsIsActive()) return;
243
+ this.dispatchPlayerInit();
244
+ }
245
+ };
246
+ export {
247
+ DevtoolsPlugin,
248
+ PLUGIN_INACTIVE_WARNING,
249
+ genDataChangeTransaction,
250
+ generateUUID
251
+ };
252
+ //# sourceMappingURL=index.mjs.map
package/dist/index.mjs ADDED
@@ -0,0 +1,252 @@
1
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts
2
+ import { dsetAssign as dsetAssign2 } from "@player-devtools/utils";
3
+ import { produce as produce2 } from "immer";
4
+
5
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/state.ts
6
+ var useStateReducer = (reducer2, initialState) => {
7
+ let state = initialState;
8
+ const subscribers = /* @__PURE__ */ new Set();
9
+ return {
10
+ getState: () => state,
11
+ /** Subscribe to state changes; returns an unsubscribe function. */
12
+ subscribe(subscriber) {
13
+ subscribers.add(subscriber);
14
+ subscriber(state);
15
+ return () => subscribers.delete(subscriber);
16
+ },
17
+ /** Dispatch an action through the reducer, then run side-effects. */
18
+ dispatch(action) {
19
+ const prevState = state;
20
+ const nextState = reducer2(prevState, action);
21
+ if (nextState !== prevState) {
22
+ state = nextState;
23
+ for (const sub of subscribers) sub(state);
24
+ }
25
+ }
26
+ };
27
+ };
28
+
29
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/reducer.ts
30
+ import { produce } from "immer";
31
+ import { dequal } from "dequal";
32
+ import { dsetAssign } from "@player-devtools/utils";
33
+ var containsInteraction = (interactions, interaction) => {
34
+ return interactions.filter((i) => dequal(i, interaction)).length > 0;
35
+ };
36
+ var reducer = (state, transaction) => {
37
+ switch (transaction.type) {
38
+ case "PLAYER_DEVTOOLS_PLAYER_INIT":
39
+ return produce(state, (draft) => {
40
+ const { payload } = transaction;
41
+ dsetAssign(draft, ["plugins"], payload.plugins);
42
+ const message = {
43
+ type: "PLAYER_DEVTOOLS_PLAYER_INIT",
44
+ payload
45
+ };
46
+ draft.messages.push(message);
47
+ });
48
+ case "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE":
49
+ return produce(state, (draft) => {
50
+ const { payload } = transaction;
51
+ if (!payload.data) return state;
52
+ try {
53
+ dsetAssign(
54
+ draft,
55
+ ["plugins", transaction.payload.pluginID, "flow", "data"],
56
+ transaction.payload.data
57
+ );
58
+ } catch {
59
+ console.error("error setting data:", transaction.payload.data);
60
+ }
61
+ const message = {
62
+ type: "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE",
63
+ payload
64
+ };
65
+ draft.messages.push(message);
66
+ });
67
+ case "PLAYER_DEVTOOLS_PLUGIN_INTERACTION":
68
+ return produce(state, (draft) => {
69
+ if (containsInteraction(draft.interactions, transaction)) return state;
70
+ dsetAssign(
71
+ draft,
72
+ ["interactions"],
73
+ [...draft.interactions, transaction]
74
+ );
75
+ });
76
+ case "PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE": {
77
+ const { playerID } = transaction.payload;
78
+ if (!playerID) return state;
79
+ return produce(state, (draft) => {
80
+ dsetAssign(draft, ["currentPlayer"], playerID);
81
+ });
82
+ }
83
+ default:
84
+ return state;
85
+ }
86
+ };
87
+
88
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/constants.ts
89
+ var INTERACTIONS = {
90
+ PLAYER_SELECTED: "player-selected"
91
+ };
92
+ var PLUGIN_INACTIVE_WARNING = "The plugin has been registered, but the Player development tools are not active. If you are working in a production environment, it is recommended to remove the plugin. To activate, enable through the browser extension popup for web or configure the FlipperClient for mobile.";
93
+
94
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/uuid.ts
95
+ function generateUUID() {
96
+ let d = (/* @__PURE__ */ new Date()).getTime();
97
+ let d2 = typeof performance !== "undefined" && performance.now && performance.now() * 1e3 || 0;
98
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
99
+ let r = Math.random() * 16;
100
+ if (d > 0) {
101
+ r = (d + r) % 16 | 0;
102
+ d = Math.floor(d / 16);
103
+ } else {
104
+ r = (d2 + r) % 16 | 0;
105
+ d2 = Math.floor(d2 / 16);
106
+ }
107
+ return (c === "x" ? r : r & 3 | 8).toString(16);
108
+ });
109
+ }
110
+
111
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/genDataChangeTransaction.ts
112
+ var NOOP_ID = -1;
113
+ var genDataChangeTransaction = ({
114
+ playerID,
115
+ data,
116
+ pluginID
117
+ }) => {
118
+ return {
119
+ id: NOOP_ID,
120
+ type: "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE",
121
+ payload: {
122
+ pluginID,
123
+ data
124
+ },
125
+ sender: playerID,
126
+ context: "player",
127
+ target: "player",
128
+ timestamp: Date.now(),
129
+ _messenger_: true
130
+ };
131
+ };
132
+
133
+ // ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts
134
+ import { dequal as dequal2 } from "dequal";
135
+ var INITIAL_STATE = {
136
+ messages: [],
137
+ plugins: {},
138
+ interactions: [],
139
+ currentPlayer: ""
140
+ };
141
+ var DevtoolsPlugin = class {
142
+ constructor(options) {
143
+ this.options = options;
144
+ this.name = "DevtoolsPlugin";
145
+ this.loggedWarning = false;
146
+ this.store = useStateReducer(reducer, INITIAL_STATE);
147
+ this.lastProcessedInteraction = 0;
148
+ this.store.subscribe(({ interactions }) => {
149
+ if (this.lastProcessedInteraction < (interactions.length ?? 0)) {
150
+ interactions.slice(this.lastProcessedInteraction).forEach(this.processInteraction.bind(this));
151
+ }
152
+ });
153
+ }
154
+ get pluginID() {
155
+ return this.options.pluginData.id;
156
+ }
157
+ get playerID() {
158
+ return this.options.playerID;
159
+ }
160
+ registerMessenger(messenger) {
161
+ let lastMessageIndex = -1;
162
+ return this.store.subscribe(({ messages }) => {
163
+ const start = lastMessageIndex + 1;
164
+ if (messages.length > start) {
165
+ const newlyAdded = messages.slice(start);
166
+ lastMessageIndex = messages.length - 1;
167
+ for (const msg of newlyAdded) {
168
+ messenger.sendMessage(msg);
169
+ }
170
+ }
171
+ });
172
+ }
173
+ dispatchPlayerInit() {
174
+ const transaction = {
175
+ id: -1,
176
+ type: "PLAYER_DEVTOOLS_PLAYER_INIT",
177
+ payload: {
178
+ plugins: {
179
+ [this.pluginID]: this.options.pluginData
180
+ }
181
+ },
182
+ sender: this.options.playerID,
183
+ context: "player",
184
+ target: "player",
185
+ timestamp: Date.now(),
186
+ _messenger_: true
187
+ };
188
+ this.store.dispatch(transaction);
189
+ }
190
+ // By default, we'll only write to the keys defined in data -- if undefined, data will be cleared
191
+ dispatchDataUpdate(data) {
192
+ const state = this.store.getState();
193
+ const { plugins } = produce2(this.store.getState(), (draft) => {
194
+ if (!data)
195
+ dsetAssign2(draft, ["plugins", this.pluginID, "flow", "data"], data);
196
+ else
197
+ Object.entries(data).forEach(([key, value]) => {
198
+ dsetAssign2(
199
+ draft,
200
+ ["plugins", this.pluginID, "flow", "data", key],
201
+ value
202
+ );
203
+ });
204
+ });
205
+ const newData = plugins[this.pluginID].flow.data;
206
+ if (dequal2(state.plugins[this.pluginID]?.flow?.data, newData)) return;
207
+ const transaction = genDataChangeTransaction({
208
+ playerID: this.playerID,
209
+ pluginID: this.pluginID,
210
+ data: newData
211
+ });
212
+ this.store.dispatch(transaction);
213
+ }
214
+ checkIfDevtoolsIsActive() {
215
+ const isActive = this.options.handler.checkIfDevtoolsIsActive();
216
+ if (!isActive && !this.loggedWarning) {
217
+ this.options.handler.log?.(PLUGIN_INACTIVE_WARNING);
218
+ this.loggedWarning = true;
219
+ }
220
+ return isActive;
221
+ }
222
+ processInteraction(interaction) {
223
+ this.options.handler.processInteraction(interaction);
224
+ const {
225
+ payload: { type, payload }
226
+ } = interaction;
227
+ if (type === INTERACTIONS.PLAYER_SELECTED && payload) {
228
+ this.store.dispatch({
229
+ id: -1,
230
+ type: "PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE",
231
+ payload: { playerID: payload },
232
+ sender: this.playerID,
233
+ context: "player",
234
+ target: this.playerID,
235
+ timestamp: Date.now(),
236
+ _messenger_: true
237
+ });
238
+ }
239
+ this.lastProcessedInteraction += 1;
240
+ }
241
+ apply(player) {
242
+ if (!this.checkIfDevtoolsIsActive()) return;
243
+ this.dispatchPlayerInit();
244
+ }
245
+ };
246
+ export {
247
+ DevtoolsPlugin,
248
+ PLUGIN_INACTIVE_WARNING,
249
+ genDataChangeTransaction,
250
+ generateUUID
251
+ };
252
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/plugin.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/state.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/reducer.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/constants.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/uuid.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/plugin/core/src/helpers/genDataChangeTransaction.ts"],"sourcesContent":["import type { Messenger } from \"@player-devtools/messenger\";\nimport {\n PluginData,\n DevtoolsPluginsStore,\n PlayerInitEvent,\n ExtensionSupportedEvents,\n Transaction,\n DevtoolsPluginInteractionEvent,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport type { DataModel, Player, PlayerPlugin } from \"@player-ui/player\";\nimport { produce } from \"immer\";\nimport { useStateReducer, type Store, type Unsubscribe } from \"./state\";\nimport { reducer } from \"./reducer\";\nimport { PLUGIN_INACTIVE_WARNING, INTERACTIONS } from \"./constants\";\nimport { genDataChangeTransaction } from \"./helpers\";\nimport { dequal } from \"dequal\";\n\nexport interface DevtoolsHandler {\n // TODO: Could return bool to signifiy handled to avoid double processing?\n processInteraction(interaction: DevtoolsPluginInteractionEvent): void;\n checkIfDevtoolsIsActive(): boolean;\n log?(message: string): void;\n}\n\nexport interface DevtoolsPluginOptions {\n playerID: string;\n pluginData: PluginData;\n handler: DevtoolsHandler;\n}\n\nconst INITIAL_STATE: DevtoolsPluginsStore = {\n messages: [],\n plugins: {},\n interactions: [],\n currentPlayer: \"\",\n};\n\n// TODO: Rename to DevtoolsPluginStore? Need to rename DevtoolsPluginsStore to DevtoolsPluginState\nexport type PluginStore = Store<\n DevtoolsPluginsStore,\n Transaction<ExtensionSupportedEvents>\n>;\n\n/** Entrypoint for devtools plugins with platform-agnostic components */\nexport class DevtoolsPlugin implements PlayerPlugin, DevtoolsHandler {\n name: string = \"DevtoolsPlugin\";\n\n private loggedWarning = false;\n\n store: PluginStore = useStateReducer(reducer, INITIAL_STATE);\n protected lastProcessedInteraction = 0;\n\n get pluginID(): string {\n return this.options.pluginData.id;\n }\n\n get playerID(): string {\n return this.options.playerID;\n }\n\n constructor(protected options: DevtoolsPluginOptions) {\n this.store.subscribe(({ interactions }) => {\n if (this.lastProcessedInteraction < (interactions.length ?? 0)) {\n interactions\n .slice(this.lastProcessedInteraction)\n .forEach(this.processInteraction.bind(this));\n }\n });\n }\n\n registerMessenger(\n messenger: Messenger<ExtensionSupportedEvents>,\n ): Unsubscribe {\n // Propagate new messages from state to devtools via the messenger\n let lastMessageIndex = -1;\n return this.store.subscribe(({ messages }) => {\n const start = lastMessageIndex + 1;\n if (messages.length > start) {\n const newlyAdded = messages.slice(start);\n lastMessageIndex = messages.length - 1;\n for (const msg of newlyAdded) {\n messenger.sendMessage(msg);\n }\n }\n });\n }\n\n protected dispatchPlayerInit(): void {\n // Initial plugin content\n const transaction: Transaction<PlayerInitEvent> = {\n id: -1,\n type: \"PLAYER_DEVTOOLS_PLAYER_INIT\",\n payload: {\n plugins: {\n [this.pluginID]: this.options.pluginData,\n },\n },\n sender: this.options.playerID,\n context: \"player\",\n target: \"player\",\n timestamp: Date.now(),\n _messenger_: true,\n };\n\n this.store.dispatch(transaction);\n }\n\n // By default, we'll only write to the keys defined in data -- if undefined, data will be cleared\n protected dispatchDataUpdate(data?: DataModel): void {\n const state = this.store.getState();\n\n const { plugins } = produce(this.store.getState(), (draft) => {\n if (!data)\n dsetAssign(draft, [\"plugins\", this.pluginID, \"flow\", \"data\"], data);\n else\n Object.entries(data).forEach(([key, value]) => {\n dsetAssign(\n draft,\n [\"plugins\", this.pluginID, \"flow\", \"data\", key],\n value,\n );\n });\n });\n\n const newData = plugins[this.pluginID]!.flow.data;\n if (dequal(state.plugins[this.pluginID]?.flow?.data, newData)) return;\n\n const transaction = genDataChangeTransaction({\n playerID: this.playerID,\n pluginID: this.pluginID,\n data: newData,\n });\n\n this.store.dispatch(transaction);\n }\n\n checkIfDevtoolsIsActive(): boolean {\n const isActive = this.options.handler.checkIfDevtoolsIsActive();\n if (!isActive && !this.loggedWarning) {\n this.options.handler.log?.(PLUGIN_INACTIVE_WARNING);\n this.loggedWarning = true;\n }\n\n return isActive;\n }\n\n processInteraction(interaction: DevtoolsPluginInteractionEvent): void {\n this.options.handler.processInteraction(interaction);\n\n const {\n payload: { type, payload },\n } = interaction;\n\n if (type === INTERACTIONS.PLAYER_SELECTED && payload) {\n this.store.dispatch({\n id: -1,\n type: \"PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE\",\n payload: { playerID: payload },\n sender: this.playerID,\n context: \"player\",\n target: this.playerID,\n timestamp: Date.now(),\n _messenger_: true,\n });\n }\n\n this.lastProcessedInteraction += 1;\n }\n\n apply(player: Player): void {\n if (!this.checkIfDevtoolsIsActive()) return;\n\n this.dispatchPlayerInit();\n }\n}\n","export type Reducer<T, A> = (state: T, action: A) => T;\nexport type Dispatch<A> = (action: A) => void;\nexport type Subscriber<T> = (state: T) => void;\nexport type Subscribe<T> = (subscriber: Subscriber<T>) => Unsubscribe;\nexport type Unsubscribe = () => void;\n\nexport interface Store<State, Action> {\n getState: () => State;\n subscribe: Subscribe<State>;\n dispatch: Dispatch<Action>;\n}\n\nexport const useStateReducer = <State, Action>(\n reducer: Reducer<State, Action>,\n initialState: State,\n): Store<State, Action> => {\n let state = initialState;\n const subscribers = new Set<Subscriber<State>>();\n return {\n getState: () => state,\n\n /** Subscribe to state changes; returns an unsubscribe function. */\n subscribe(subscriber: Subscriber<State>): Unsubscribe {\n subscribers.add(subscriber);\n subscriber(state);\n return () => subscribers.delete(subscriber);\n },\n\n /** Dispatch an action through the reducer, then run side-effects. */\n dispatch(action: Action): void {\n const prevState = state;\n const nextState = reducer(prevState, action);\n\n // Only proceed if state actually changed by reference\n if (nextState !== prevState) {\n state = nextState;\n\n // Notify subscribers\n for (const sub of subscribers) sub(state);\n }\n },\n };\n};\n","import { produce } from \"immer\";\nimport { dequal } from \"dequal\";\nimport type {\n DevtoolsDataChangeEvent,\n DevtoolsPluginsStore,\n ExtensionSupportedEvents,\n PlayerInitEvent,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\n\nconst containsInteraction = (\n interactions: DevtoolsPluginsStore[\"interactions\"],\n interaction: DevtoolsPluginsStore[\"interactions\"][number],\n) => {\n return interactions.filter((i) => dequal(i, interaction)).length > 0;\n};\n\n/** devtools plugin state reducer */\nexport const reducer = (\n state: DevtoolsPluginsStore,\n transaction: Transaction<ExtensionSupportedEvents>,\n): DevtoolsPluginsStore => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const { payload } = transaction;\n dsetAssign(draft, [\"plugins\"], payload.plugins);\n\n const message: PlayerInitEvent = {\n type: \"PLAYER_DEVTOOLS_PLAYER_INIT\",\n payload,\n };\n\n draft.messages.push(message);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const { payload } = transaction;\n\n if (!payload.data) return state;\n\n try {\n dsetAssign(\n draft,\n [\"plugins\", transaction.payload.pluginID, \"flow\", \"data\"],\n transaction.payload.data,\n );\n } catch {\n console.error(\"error setting data:\", transaction.payload.data);\n }\n const message: DevtoolsDataChangeEvent = {\n type: \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\",\n payload,\n };\n\n draft.messages.push(message);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\":\n return produce(state, (draft) => {\n if (containsInteraction(draft.interactions, transaction)) return state;\n\n dsetAssign(\n draft,\n [\"interactions\"],\n [...draft.interactions, transaction],\n );\n });\n case \"PLAYER_DEVTOOLS_SELECTED_PLAYER_CHANGE\": {\n const { playerID } = transaction.payload;\n\n if (!playerID) return state;\n return produce(state, (draft) => {\n dsetAssign(draft, [\"currentPlayer\"], playerID);\n });\n }\n default:\n return state;\n }\n};\n","export const INTERACTIONS = {\n PLAYER_SELECTED: \"player-selected\",\n};\n\nexport const PLUGIN_INACTIVE_WARNING =\n \"The plugin has been registered, but the Player development tools are not active. If you are working in a production environment, it is recommended to remove the plugin. To activate, enable through the browser extension popup for web or configure the FlipperClient for mobile.\";\n","export function generateUUID(): string {\n // Public Domain/MIT\n let d = new Date().getTime(); //Timestamp\n let d2 =\n (typeof performance !== \"undefined\" &&\n performance.now &&\n performance.now() * 1000) ||\n 0; //Time in microseconds since page-load or 0 if unsupported\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n let r = Math.random() * 16; //random number between 0 and 16\n if (d > 0) {\n //Use timestamp until depleted\n r = (d + r) % 16 | 0;\n d = Math.floor(d / 16);\n } else {\n //Use microseconds since page-load if supported\n r = (d2 + r) % 16 | 0;\n d2 = Math.floor(d2 / 16);\n }\n return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","import type {\n DevtoolsDataChangeEvent,\n Transaction,\n} from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nconst NOOP_ID = -1;\n\n/**\n * Generates a data change transaction for the player devtools plugin.\n *\n * This function creates a transaction object that represents a change in data\n * within a player devtools plugin. The transaction includes details such as the\n * plugin ID, the changed data, and the player ID. It is used to communicate\n * changes between the plugin and devtools.\n */\nexport const genDataChangeTransaction = ({\n playerID,\n data,\n pluginID,\n}: {\n playerID: string;\n data: Flow[\"data\"];\n pluginID: string;\n}): Transaction<DevtoolsDataChangeEvent> => {\n return {\n id: NOOP_ID,\n type: \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\",\n payload: {\n pluginID,\n data,\n },\n sender: playerID,\n context: \"player\",\n target: \"player\",\n timestamp: Date.now(),\n _messenger_: true,\n };\n};\n"],"mappings":"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","names":["dsetAssign","produce","reducer","dequal","produce","dsetAssign"]}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "sideEffects": false,
3
+ "files": [
4
+ "dist",
5
+ "src",
6
+ "types"
7
+ ],
8
+ "name": "@player-devtools/plugin",
9
+ "version": "0.0.2-next.0",
10
+ "main": "dist/cjs/index.cjs",
11
+ "dependencies": {
12
+ "@player-devtools/messenger": "0.0.2-next.0",
13
+ "@player-devtools/types": "0.0.2-next.0",
14
+ "@player-devtools/utils": "0.0.2-next.0",
15
+ "@player-ui/player": "0.12.0-next.1",
16
+ "@swc/core": "1.3.74",
17
+ "dequal": "^2.0.2",
18
+ "immer": "^10.0.3",
19
+ "tslib": "^2.6.2"
20
+ },
21
+ "module": "dist/index.legacy-esm.js",
22
+ "types": "types/index.d.ts",
23
+ "bundle": "dist/DevtoolsPlugin.native.js",
24
+ "exports": {
25
+ "./package.json": "./package.json",
26
+ "./dist/index.css": "./dist/index.css",
27
+ ".": {
28
+ "types": "./types/index.d.ts",
29
+ "import": "./dist/index.mjs",
30
+ "default": "./dist/cjs/index.cjs"
31
+ }
32
+ },
33
+ "peerDependencies": {}
34
+ }
@@ -0,0 +1,6 @@
1
+ export const INTERACTIONS = {
2
+ PLAYER_SELECTED: "player-selected",
3
+ };
4
+
5
+ export const PLUGIN_INACTIVE_WARNING =
6
+ "The plugin has been registered, but the Player development tools are not active. If you are working in a production environment, it is recommended to remove the plugin. To activate, enable through the browser extension popup for web or configure the FlipperClient for mobile.";
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import type {
3
+ DevtoolsDataChangeEvent,
4
+ Transaction,
5
+ } from "@player-devtools/types";
6
+ import { genDataChangeTransaction } from "..";
7
+
8
+ describe("genDataChangeTransaction", () => {
9
+ it("should correctly generate a data change transaction for valid input", () => {
10
+ const input = {
11
+ playerID: "player1",
12
+ data: {
13
+ key: "value",
14
+ anotherKey: 123,
15
+ },
16
+ pluginID: "pluginA",
17
+ };
18
+
19
+ const expectedOutput: Transaction<DevtoolsDataChangeEvent> = {
20
+ id: -1,
21
+ type: "PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE",
22
+ payload: {
23
+ pluginID: "pluginA",
24
+ data: {
25
+ key: "value",
26
+ anotherKey: 123,
27
+ },
28
+ },
29
+ sender: "player1",
30
+ context: "player",
31
+ target: "player",
32
+ timestamp: expect.any(Number),
33
+ _messenger_: true,
34
+ };
35
+
36
+ const result = genDataChangeTransaction(input);
37
+
38
+ expect(result).toEqual(expect.objectContaining(expectedOutput));
39
+ });
40
+ });