dreaction-client-core 1.0.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.
Files changed (52) hide show
  1. package/lib/client-options.d.ts +77 -0
  2. package/lib/client-options.d.ts.map +1 -0
  3. package/lib/client-options.js +2 -0
  4. package/lib/index.d.ts +190 -0
  5. package/lib/index.d.ts.map +1 -0
  6. package/lib/index.js +401 -0
  7. package/lib/plugins/api-response.d.ts +13 -0
  8. package/lib/plugins/api-response.d.ts.map +1 -0
  9. package/lib/plugins/api-response.js +23 -0
  10. package/lib/plugins/benchmark.d.ts +15 -0
  11. package/lib/plugins/benchmark.d.ts.map +1 -0
  12. package/lib/plugins/benchmark.js +31 -0
  13. package/lib/plugins/clear.d.ts +11 -0
  14. package/lib/plugins/clear.d.ts.map +1 -0
  15. package/lib/plugins/clear.js +13 -0
  16. package/lib/plugins/image.d.ts +19 -0
  17. package/lib/plugins/image.d.ts.map +1 -0
  18. package/lib/plugins/image.js +24 -0
  19. package/lib/plugins/logger.d.ts +18 -0
  20. package/lib/plugins/logger.d.ts.map +1 -0
  21. package/lib/plugins/logger.js +44 -0
  22. package/lib/plugins/repl.d.ts +10 -0
  23. package/lib/plugins/repl.d.ts.map +1 -0
  24. package/lib/plugins/repl.js +55 -0
  25. package/lib/plugins/state-responses.d.ts +20 -0
  26. package/lib/plugins/state-responses.d.ts.map +1 -0
  27. package/lib/plugins/state-responses.js +38 -0
  28. package/lib/reactotron-core-client.d.ts +191 -0
  29. package/lib/reactotron-core-client.d.ts.map +1 -0
  30. package/lib/reactotron-core-client.js +400 -0
  31. package/lib/serialize.d.ts +20 -0
  32. package/lib/serialize.d.ts.map +1 -0
  33. package/lib/serialize.js +112 -0
  34. package/lib/stopwatch.d.ts +6 -0
  35. package/lib/stopwatch.d.ts.map +1 -0
  36. package/lib/stopwatch.js +45 -0
  37. package/lib/validate.d.ts +9 -0
  38. package/lib/validate.d.ts.map +1 -0
  39. package/lib/validate.js +26 -0
  40. package/package.json +29 -0
  41. package/src/client-options.ts +95 -0
  42. package/src/index.ts +654 -0
  43. package/src/plugins/api-response.ts +32 -0
  44. package/src/plugins/benchmark.ts +35 -0
  45. package/src/plugins/clear.ts +14 -0
  46. package/src/plugins/image.ts +34 -0
  47. package/src/plugins/logger.ts +59 -0
  48. package/src/plugins/repl.ts +63 -0
  49. package/src/plugins/state-responses.ts +75 -0
  50. package/src/serialize.ts +125 -0
  51. package/src/stopwatch.ts +50 -0
  52. package/src/validate.ts +38 -0
@@ -0,0 +1,77 @@
1
+ import type { LifeCycleMethods, PluginCreator } from './';
2
+ import NodeWebSocket from 'ws';
3
+ type BrowserWebSocket = WebSocket;
4
+ /**
5
+ * Configuration options for the Reactotron Client.
6
+ */
7
+ export interface ClientOptions<Client> extends Omit<LifeCycleMethods, 'onCommand'> {
8
+ /**
9
+ * A function which returns a websocket.
10
+ *
11
+ * This is over-engineered because we need the ability to create different
12
+ * types of websockets for React Native, React, and NodeJS. :|
13
+ */
14
+ createSocket?: ((path: string) => BrowserWebSocket) | ((path: string) => NodeWebSocket) | null;
15
+ /**
16
+ * The hostname or ip address of the server. Default: localhost.
17
+ */
18
+ host?: string | null;
19
+ /**
20
+ * The port to connect to the server on. Default: 9090.
21
+ */
22
+ port?: number | null;
23
+ /**
24
+ * The name of this client. Usually the app name.
25
+ */
26
+ name?: string;
27
+ /**
28
+ * Will we be connecting via SSL?
29
+ */
30
+ secure?: boolean;
31
+ /**
32
+ * A list of plugins.
33
+ */
34
+ plugins?: PluginCreator<Client>[];
35
+ /**
36
+ * Performs safety checks when serializing. Default: true.
37
+ *
38
+ * Will do things like:
39
+ * - remap falsy values to transport-friendly version
40
+ * - remove any circular dependencies
41
+ * - remap functions to something that shows their name
42
+ *
43
+ * Hooray for JavaScript!
44
+ */
45
+ safeRecursion?: boolean;
46
+ /**
47
+ * Fires when the server sends a command.
48
+ */
49
+ onCommand?: ((command: any) => void) | null;
50
+ /**
51
+ * Fires when we connect to the server.
52
+ */
53
+ onConnect?: () => void;
54
+ /**
55
+ * Fires when we disconnect from the server.
56
+ */
57
+ onDisconnect?: () => void;
58
+ /**
59
+ * The NODE_ENV environment, if any.
60
+ */
61
+ environment?: string;
62
+ /**
63
+ * A way for the client libraries to identify themselves.
64
+ */
65
+ client?: Record<string, string | number | boolean>;
66
+ /**
67
+ * Save the client id provided by the server
68
+ */
69
+ setClientId?: (clientId: string) => Promise<void>;
70
+ /**
71
+ * Get the client id provided by the server
72
+ */
73
+ getClientId?: (name: string) => Promise<string>;
74
+ proxyHack?: boolean;
75
+ }
76
+ export {};
77
+ //# sourceMappingURL=client-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-options.d.ts","sourceRoot":"","sources":["../src/client-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,aAAa,MAAM,IAAI,CAAC;AAE/B,KAAK,gBAAgB,GAAG,SAAS,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM,CACnC,SAAQ,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC;IAC3C;;;;;OAKG;IACH,YAAY,CAAC,EACT,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC,GACpC,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,CAAC,GACjC,IAAI,CAAC;IAET;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;IAElC;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAE5C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAEnD;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/index.d.ts ADDED
@@ -0,0 +1,190 @@
1
+ import WebSocket from 'ws';
2
+ import type { Command, CommandMap, CommandTypeKey } from 'dreaction-protocol';
3
+ import { ClientOptions } from './client-options';
4
+ export type { ClientOptions };
5
+ export { assertHasLoggerPlugin } from './plugins/logger';
6
+ export type { LoggerPlugin } from './plugins/logger';
7
+ export { assertHasStateResponsePlugin, hasStateResponsePlugin, } from './plugins/state-responses';
8
+ export type { StateResponsePlugin } from './plugins/state-responses';
9
+ export declare enum ArgType {
10
+ String = "string"
11
+ }
12
+ export interface CustomCommandArg {
13
+ name: string;
14
+ type: ArgType;
15
+ }
16
+ export interface LifeCycleMethods {
17
+ onCommand?: (command: Command) => void;
18
+ onConnect?: () => void;
19
+ onDisconnect?: () => void;
20
+ }
21
+ type AnyFunction = (...args: any[]) => any;
22
+ export interface Plugin<Client> extends LifeCycleMethods {
23
+ features?: {
24
+ [key: string]: AnyFunction;
25
+ };
26
+ onPlugin?: (client: Client) => void;
27
+ }
28
+ export type PluginCreator<Client> = (client: Client) => Plugin<Client>;
29
+ interface DisplayConfig {
30
+ name: string;
31
+ value?: object | string | number | boolean | null | undefined;
32
+ preview?: string;
33
+ image?: string | {
34
+ uri: string;
35
+ };
36
+ important?: boolean;
37
+ }
38
+ interface ArgTypeMap {
39
+ [ArgType.String]: string;
40
+ }
41
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
42
+ export type CustomCommandArgs<Args extends CustomCommandArg[]> = UnionToIntersection<Args extends Array<infer U> ? U extends CustomCommandArg ? {
43
+ [K in U as U['name']]: ArgTypeMap[U['type']];
44
+ } : never : never>;
45
+ export interface CustomCommand<Args extends CustomCommandArg[] = CustomCommandArg[]> {
46
+ id?: number;
47
+ command: string;
48
+ handler: (args?: CustomCommandArgs<Args>) => void;
49
+ title?: string;
50
+ description?: string;
51
+ args?: Args;
52
+ }
53
+ type ExtractFeatures<T> = T extends {
54
+ features: infer U;
55
+ } ? U : never;
56
+ type PluginFeatures<Client, P extends PluginCreator<Client>> = ExtractFeatures<ReturnType<P>>;
57
+ export type InferFeaturesFromPlugins<Client, Plugins extends PluginCreator<Client>[]> = UnionToIntersection<PluginFeatures<Client, Plugins[number]>>;
58
+ type InferFeaturesFromPlugin<Client, P extends PluginCreator<Client>> = UnionToIntersection<PluginFeatures<Client, P>>;
59
+ export interface DReactionCore {
60
+ options: ClientOptions<this>;
61
+ plugins: Plugin<this>[];
62
+ startTimer: () => () => number;
63
+ close: () => this;
64
+ send: <Type extends keyof CommandMap>(type: Type, payload?: CommandMap[Type], important?: boolean) => void;
65
+ display: (config: DisplayConfig) => void;
66
+ onCustomCommand: <Args extends CustomCommandArg[] = Exclude<CustomCommand['args'], undefined>>(config: CustomCommand<Args>) => () => void | ((config: string, optHandler?: () => void) => () => void);
67
+ /**
68
+ * Set the configuration options.
69
+ */
70
+ configure: (options: ClientOptions<this>) => ClientOptions<this>['plugins'] extends PluginCreator<this>[] ? this & InferFeaturesFromPlugins<this, ClientOptions<this>['plugins']> : this;
71
+ use: <P extends PluginCreator<this>>(pluginCreator: P) => this & InferFeaturesFromPlugin<this, P>;
72
+ connect: () => this;
73
+ }
74
+ export type InferFeatures<Client = DReactionCore, PC extends PluginCreator<Client> = PluginCreator<Client>> = PC extends (client: Client) => {
75
+ features: infer U;
76
+ } ? U : never;
77
+ export declare const corePlugins: (((dreaction: DReactionCore) => {
78
+ features: {
79
+ log: (...args: any[]) => void;
80
+ logImportant: (...args: any[]) => void;
81
+ debug: (message: any, important?: any) => void;
82
+ warn: (message: any) => void;
83
+ error: (message: any, stack: any) => void;
84
+ };
85
+ }) | ((reactotron: DReactionCore) => {
86
+ features: {
87
+ image: (payload: import("./plugins/image").ImagePayload) => void;
88
+ };
89
+ }) | ((reactotron: DReactionCore) => {
90
+ features: {
91
+ benchmark: (title: string) => {
92
+ step: (stepTitle: string) => void;
93
+ stop: (stopTitle: string) => void;
94
+ last: (stopTitle: string) => void;
95
+ };
96
+ };
97
+ }) | ((reactotron: DReactionCore) => {
98
+ features: {
99
+ stateActionComplete: (name: import("dreaction-protocol").StateActionCompletePayload["name"], action: import("dreaction-protocol").StateActionCompletePayload["action"], important?: any) => void;
100
+ stateValuesResponse: (path: import("dreaction-protocol").StateValuesResponsePayload["path"], value: import("dreaction-protocol").StateValuesResponsePayload["value"], valid?: import("dreaction-protocol").StateValuesResponsePayload["value"]) => void;
101
+ stateKeysResponse: (path: import("dreaction-protocol").StateKeysResponsePayload["path"], keys: import("dreaction-protocol").StateKeysResponsePayload["keys"], valid?: import("dreaction-protocol").StateKeysResponsePayload["valid"]) => void;
102
+ stateValuesChange: (changes: import("dreaction-protocol").StateValuesChangePayload["changes"]) => false | void;
103
+ stateBackupResponse: (state: import("dreaction-protocol").StateBackupResponsePayload["state"]) => void;
104
+ };
105
+ }) | ((reactotron: DReactionCore) => {
106
+ features: {
107
+ apiResponse: (request: {
108
+ status: number;
109
+ }, response: any, duration: number) => void;
110
+ };
111
+ }) | ((reactotron: DReactionCore) => {
112
+ features: {
113
+ clear: () => void;
114
+ };
115
+ }) | ((reactotron: DReactionCore) => {
116
+ onCommand: ({ type, payload }: Command) => void;
117
+ features: {
118
+ repl: (name: string, value: import("./plugins/repl").AcceptableRepls) => void;
119
+ };
120
+ }))[];
121
+ export type InferPluginsFromCreators<Client, PC extends PluginCreator<Client>[]> = PC extends Array<infer P extends PluginCreator<Client>> ? ReturnType<P>[] : never;
122
+ export interface Reactotron extends DReactionCore {
123
+ }
124
+ export declare class ReactotronImpl implements Omit<DReactionCore, 'options' | 'plugins' | 'configure' | 'connect' | 'use' | 'close'> {
125
+ options: ClientOptions<DReactionCore>;
126
+ /**
127
+ * Are we connected to a server?
128
+ */
129
+ connected: boolean;
130
+ /**
131
+ * The socket we're using.
132
+ */
133
+ socket: WebSocket;
134
+ /**
135
+ * Available plugins.
136
+ */
137
+ plugins: Plugin<this>[];
138
+ /**
139
+ * Messages that need to be sent.
140
+ */
141
+ sendQueue: string[];
142
+ /**
143
+ * Are we ready to start communicating?
144
+ */
145
+ isReady: boolean;
146
+ /**
147
+ * The last time we sent a message.
148
+ */
149
+ lastMessageDate: Date;
150
+ /**
151
+ * The registered custom commands
152
+ */
153
+ customCommands: CustomCommand[];
154
+ /**
155
+ * The current ID for custom commands
156
+ */
157
+ customCommandLatestId: number;
158
+ /**
159
+ * Starts a timer and returns a function you can call to stop it and return the elapsed time.
160
+ */
161
+ startTimer: () => () => number;
162
+ /**
163
+ * Set the configuration options.
164
+ */
165
+ configure(options: ClientOptions<this>): ClientOptions<this>['plugins'] extends PluginCreator<this>[] ? this & InferFeaturesFromPlugins<this, ClientOptions<this>['plugins']> : this;
166
+ close(): this;
167
+ /**
168
+ * Connect to the Reactotron server.
169
+ */
170
+ connect(): this;
171
+ /**
172
+ * Sends a command to the server
173
+ */
174
+ send: <Type extends CommandTypeKey>(type: Type, payload?: CommandMap[Type]["payload"], important?: boolean) => void;
175
+ /**
176
+ * Sends a custom command to the server to displays nicely.
177
+ */
178
+ display(config: DisplayConfig): void;
179
+ /**
180
+ * Client libraries can hijack this to report errors.
181
+ */
182
+ reportError(this: any, error: Error): void;
183
+ /**
184
+ * Adds a plugin to the system
185
+ */
186
+ use(pluginCreator: PluginCreator<this>): this & PluginFeatures<this, typeof pluginCreator>;
187
+ onCustomCommand(config: CustomCommand | string, optHandler?: () => void): () => void;
188
+ }
189
+ export declare function createClient<Client extends DReactionCore = DReactionCore>(options?: ClientOptions<Client>): Client;
190
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js ADDED
@@ -0,0 +1,401 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ReactotronImpl = exports.corePlugins = exports.ArgType = exports.hasStateResponsePlugin = exports.assertHasStateResponsePlugin = exports.assertHasLoggerPlugin = void 0;
7
+ exports.createClient = createClient;
8
+ const validate_1 = __importDefault(require("./validate"));
9
+ const logger_1 = __importDefault(require("./plugins/logger"));
10
+ const image_1 = __importDefault(require("./plugins/image"));
11
+ const benchmark_1 = __importDefault(require("./plugins/benchmark"));
12
+ const state_responses_1 = __importDefault(require("./plugins/state-responses"));
13
+ const api_response_1 = __importDefault(require("./plugins/api-response"));
14
+ const clear_1 = __importDefault(require("./plugins/clear"));
15
+ const repl_1 = __importDefault(require("./plugins/repl"));
16
+ const serialize_1 = __importDefault(require("./serialize"));
17
+ const stopwatch_1 = require("./stopwatch");
18
+ var logger_2 = require("./plugins/logger");
19
+ Object.defineProperty(exports, "assertHasLoggerPlugin", { enumerable: true, get: function () { return logger_2.assertHasLoggerPlugin; } });
20
+ var state_responses_2 = require("./plugins/state-responses");
21
+ Object.defineProperty(exports, "assertHasStateResponsePlugin", { enumerable: true, get: function () { return state_responses_2.assertHasStateResponsePlugin; } });
22
+ Object.defineProperty(exports, "hasStateResponsePlugin", { enumerable: true, get: function () { return state_responses_2.hasStateResponsePlugin; } });
23
+ var ArgType;
24
+ (function (ArgType) {
25
+ ArgType["String"] = "string";
26
+ })(ArgType || (exports.ArgType = ArgType = {}));
27
+ exports.corePlugins = [
28
+ (0, image_1.default)(),
29
+ (0, logger_1.default)(),
30
+ (0, benchmark_1.default)(),
31
+ (0, state_responses_1.default)(),
32
+ (0, api_response_1.default)(),
33
+ (0, clear_1.default)(),
34
+ (0, repl_1.default)(),
35
+ ];
36
+ // these are not for you.
37
+ const reservedFeatures = [
38
+ 'configure',
39
+ 'connect',
40
+ 'connected',
41
+ 'options',
42
+ 'plugins',
43
+ 'send',
44
+ 'socket',
45
+ 'startTimer',
46
+ 'use',
47
+ ];
48
+ const isReservedFeature = (value) => reservedFeatures.some((res) => res === value);
49
+ function emptyPromise() {
50
+ return Promise.resolve('');
51
+ }
52
+ class ReactotronImpl {
53
+ // the configuration options
54
+ options;
55
+ /**
56
+ * Are we connected to a server?
57
+ */
58
+ connected = false;
59
+ /**
60
+ * The socket we're using.
61
+ */
62
+ socket = null;
63
+ /**
64
+ * Available plugins.
65
+ */
66
+ plugins = [];
67
+ /**
68
+ * Messages that need to be sent.
69
+ */
70
+ sendQueue = [];
71
+ /**
72
+ * Are we ready to start communicating?
73
+ */
74
+ isReady = false;
75
+ /**
76
+ * The last time we sent a message.
77
+ */
78
+ lastMessageDate = new Date();
79
+ /**
80
+ * The registered custom commands
81
+ */
82
+ customCommands = [];
83
+ /**
84
+ * The current ID for custom commands
85
+ */
86
+ customCommandLatestId = 1;
87
+ /**
88
+ * Starts a timer and returns a function you can call to stop it and return the elapsed time.
89
+ */
90
+ startTimer = () => (0, stopwatch_1.start)();
91
+ /**
92
+ * Set the configuration options.
93
+ */
94
+ configure(options) {
95
+ // options get merged & validated before getting set
96
+ const newOptions = Object.assign({
97
+ createSocket: null,
98
+ host: 'localhost',
99
+ port: 9600,
100
+ name: 'reactotron-core-client',
101
+ secure: false,
102
+ plugins: exports.corePlugins,
103
+ safeRecursion: true,
104
+ onCommand: () => null,
105
+ onConnect: () => null,
106
+ onDisconnect: () => null,
107
+ }, this.options, options);
108
+ (0, validate_1.default)(newOptions);
109
+ this.options = newOptions;
110
+ // if we have plugins, let's add them here
111
+ if (Array.isArray(this.options.plugins)) {
112
+ this.options.plugins.forEach((p) => this.use(p));
113
+ }
114
+ return this;
115
+ }
116
+ close() {
117
+ this.connected = false;
118
+ this.socket && this.socket.close && this.socket.close();
119
+ return this;
120
+ }
121
+ /**
122
+ * Connect to the Reactotron server.
123
+ */
124
+ connect() {
125
+ this.connected = true;
126
+ const { createSocket, secure, host, environment, port, name, client = {}, getClientId, } = this.options;
127
+ const { onCommand, onConnect, onDisconnect } = this.options;
128
+ // establish a connection to the server
129
+ const protocol = secure ? 'wss' : 'ws';
130
+ const socket = createSocket(`${protocol}://${host}:${port}`);
131
+ // fires when we talk to the server
132
+ const onOpen = () => {
133
+ // fire our optional onConnect handler
134
+ onConnect && onConnect();
135
+ // trigger our plugins onConnect
136
+ this.plugins.forEach((p) => p.onConnect && p.onConnect());
137
+ const getClientIdPromise = getClientId || emptyPromise;
138
+ getClientIdPromise(name).then((clientId) => {
139
+ this.isReady = true;
140
+ // introduce ourselves
141
+ this.send('client.intro', {
142
+ environment,
143
+ ...client,
144
+ name,
145
+ clientId,
146
+ dreactionCoreClientVersion: 'DREACTION_CORE_CLIENT_VERSION',
147
+ });
148
+ // flush the send queue
149
+ while (this.sendQueue.length > 0) {
150
+ const h = this.sendQueue[0];
151
+ this.sendQueue = this.sendQueue.slice(1);
152
+ this.socket.send(h);
153
+ }
154
+ });
155
+ };
156
+ // fires when we disconnect
157
+ const onClose = () => {
158
+ this.isReady = false;
159
+ // trigger our disconnect handler
160
+ onDisconnect && onDisconnect();
161
+ // as well as the plugin's onDisconnect
162
+ this.plugins.forEach((p) => p.onDisconnect && p.onDisconnect());
163
+ };
164
+ const decodeCommandData = (data) => {
165
+ if (typeof data === 'string') {
166
+ return JSON.parse(data);
167
+ }
168
+ if (Buffer.isBuffer(data)) {
169
+ return JSON.parse(data.toString());
170
+ }
171
+ return data;
172
+ };
173
+ // fires when we receive a command, just forward it off
174
+ const onMessage = (data) => {
175
+ const command = decodeCommandData(data);
176
+ // trigger our own command handler
177
+ onCommand && onCommand(command);
178
+ // trigger our plugins onCommand
179
+ this.plugins.forEach((p) => p.onCommand && p.onCommand(command));
180
+ // trigger our registered custom commands
181
+ if (command.type === 'custom') {
182
+ this.customCommands
183
+ .filter((cc) => {
184
+ if (typeof command.payload === 'string') {
185
+ return cc.command === command.payload;
186
+ }
187
+ return cc.command === command.payload.command;
188
+ })
189
+ .forEach((cc) => cc.handler(typeof command.payload === 'object'
190
+ ? command.payload.args
191
+ : undefined));
192
+ }
193
+ else if (command.type === 'setClientId') {
194
+ this.options.setClientId && this.options.setClientId(command.payload);
195
+ }
196
+ };
197
+ // this is ws style from require('ws') on node js
198
+ if ('on' in socket && socket.on) {
199
+ const nodeWebSocket = socket;
200
+ nodeWebSocket.on('open', onOpen);
201
+ nodeWebSocket.on('close', onClose);
202
+ nodeWebSocket.on('message', onMessage);
203
+ // assign the socket to the instance
204
+ this.socket = socket;
205
+ }
206
+ else {
207
+ // this is a browser
208
+ const browserWebSocket = socket;
209
+ socket.onopen = onOpen;
210
+ socket.onclose = onClose;
211
+ socket.onmessage = (evt) => onMessage(evt.data);
212
+ // assign the socket to the instance
213
+ this.socket = browserWebSocket;
214
+ }
215
+ return this;
216
+ }
217
+ /**
218
+ * Sends a command to the server
219
+ */
220
+ send = (type, payload, important) => {
221
+ // set the timing info
222
+ const date = new Date();
223
+ let deltaTime = date.getTime() - this.lastMessageDate.getTime();
224
+ // glitches in the matrix
225
+ if (deltaTime < 0) {
226
+ deltaTime = 0;
227
+ }
228
+ this.lastMessageDate = date;
229
+ const fullMessage = {
230
+ type,
231
+ payload,
232
+ important: !!important,
233
+ date: date.toISOString(),
234
+ deltaTime,
235
+ };
236
+ const serializedMessage = (0, serialize_1.default)(fullMessage, this.options.proxyHack);
237
+ if (this.isReady) {
238
+ // send this command
239
+ try {
240
+ this.socket.send(serializedMessage);
241
+ }
242
+ catch {
243
+ this.isReady = false;
244
+ console.log('An error occurred communicating with reactotron. Please reload your app');
245
+ }
246
+ }
247
+ else {
248
+ // queue it up until we can connect
249
+ this.sendQueue.push(serializedMessage);
250
+ }
251
+ };
252
+ /**
253
+ * Sends a custom command to the server to displays nicely.
254
+ */
255
+ display(config) {
256
+ const { name, value, preview, image: img, important = false } = config;
257
+ const payload = {
258
+ name,
259
+ value: value || null,
260
+ preview: preview || null,
261
+ image: img || null,
262
+ };
263
+ this.send('display', payload, important);
264
+ }
265
+ /**
266
+ * Client libraries can hijack this to report errors.
267
+ */
268
+ reportError(error) {
269
+ this.error(error);
270
+ }
271
+ /**
272
+ * Adds a plugin to the system
273
+ */
274
+ use(pluginCreator) {
275
+ // we're supposed to be given a function
276
+ if (typeof pluginCreator !== 'function') {
277
+ throw new Error('plugins must be a function');
278
+ }
279
+ // execute it immediately passing the send function
280
+ const plugin = pluginCreator.bind(this)(this);
281
+ // ensure we get an Object-like creature back
282
+ if (typeof plugin !== 'object') {
283
+ throw new Error('plugins must return an object');
284
+ }
285
+ // do we have features to mixin?
286
+ if (plugin.features) {
287
+ // validate
288
+ if (typeof plugin.features !== 'object') {
289
+ throw new Error('features must be an object');
290
+ }
291
+ // here's how we're going to inject these in
292
+ const inject = (key) => {
293
+ // grab the function
294
+ const featureFunction = plugin.features[key];
295
+ // only functions may pass
296
+ if (typeof featureFunction !== 'function') {
297
+ throw new Error(`feature ${key} is not a function`);
298
+ }
299
+ // ditch reserved names
300
+ if (isReservedFeature(key)) {
301
+ throw new Error(`feature ${key} is a reserved name`);
302
+ }
303
+ // ok, let's glue it up... and lose all respect from elite JS champions.
304
+ this[key] = featureFunction;
305
+ };
306
+ // let's inject
307
+ Object.keys(plugin.features).forEach((key) => inject(key));
308
+ }
309
+ // add it to the list
310
+ this.plugins.push(plugin);
311
+ // call the plugins onPlugin
312
+ plugin.onPlugin &&
313
+ typeof plugin.onPlugin === 'function' &&
314
+ plugin.onPlugin.bind(this)(this);
315
+ // chain-friendly
316
+ return this;
317
+ }
318
+ onCustomCommand(config, optHandler) {
319
+ let command;
320
+ let handler;
321
+ let title;
322
+ let description;
323
+ let args;
324
+ if (typeof config === 'string') {
325
+ command = config;
326
+ handler = optHandler;
327
+ }
328
+ else {
329
+ command = config.command;
330
+ handler = config.handler;
331
+ title = config.title;
332
+ description = config.description;
333
+ args = config.args;
334
+ }
335
+ // Validations
336
+ // Make sure there is a command
337
+ if (!command) {
338
+ throw new Error('A command is required');
339
+ }
340
+ // Make sure there is a handler
341
+ if (!handler) {
342
+ throw new Error(`A handler is required for command "${command}"`);
343
+ }
344
+ // Make sure the command doesn't already exist
345
+ const existingCommands = this.customCommands.filter((cc) => cc.command === command);
346
+ if (existingCommands.length > 0) {
347
+ existingCommands.forEach((command) => {
348
+ this.customCommands = this.customCommands.filter((cc) => cc.id !== command.id);
349
+ this.send('customCommand.unregister', {
350
+ id: command.id,
351
+ command: command.command,
352
+ });
353
+ });
354
+ }
355
+ if (args) {
356
+ const argNames = [];
357
+ args.forEach((arg) => {
358
+ if (!arg.name) {
359
+ throw new Error(`A arg on the command "${command}" is missing a name`);
360
+ }
361
+ if (argNames.indexOf(arg.name) > -1) {
362
+ throw new Error(`A arg with the name "${arg.name}" already exists in the command "${command}"`);
363
+ }
364
+ argNames.push(arg.name);
365
+ });
366
+ }
367
+ // Create this command handlers object
368
+ const customHandler = {
369
+ id: this.customCommandLatestId,
370
+ command,
371
+ handler,
372
+ title,
373
+ description,
374
+ args,
375
+ };
376
+ // Increment our id counter
377
+ this.customCommandLatestId += 1;
378
+ // Add it to our array
379
+ this.customCommands.push(customHandler);
380
+ this.send('customCommand.register', {
381
+ id: customHandler.id,
382
+ command: customHandler.command,
383
+ title: customHandler.title,
384
+ description: customHandler.description,
385
+ args: customHandler.args,
386
+ });
387
+ return () => {
388
+ this.customCommands = this.customCommands.filter((cc) => cc.id !== customHandler.id);
389
+ this.send('customCommand.unregister', {
390
+ id: customHandler.id,
391
+ command: customHandler.command,
392
+ });
393
+ };
394
+ }
395
+ }
396
+ exports.ReactotronImpl = ReactotronImpl;
397
+ // convenience factory function
398
+ function createClient(options) {
399
+ const client = new ReactotronImpl();
400
+ return client.configure(options);
401
+ }