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,400 @@
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: 9090,
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
+ }
120
+ /**
121
+ * Connect to the Reactotron server.
122
+ */
123
+ connect() {
124
+ this.connected = true;
125
+ const { createSocket, secure, host, environment, port, name, client = {}, getClientId, } = this.options;
126
+ const { onCommand, onConnect, onDisconnect } = this.options;
127
+ // establish a connection to the server
128
+ const protocol = secure ? 'wss' : 'ws';
129
+ const socket = createSocket(`${protocol}://${host}:${port}`);
130
+ // fires when we talk to the server
131
+ const onOpen = () => {
132
+ // fire our optional onConnect handler
133
+ onConnect && onConnect();
134
+ // trigger our plugins onConnect
135
+ this.plugins.forEach((p) => p.onConnect && p.onConnect());
136
+ const getClientIdPromise = getClientId || emptyPromise;
137
+ getClientIdPromise(name).then((clientId) => {
138
+ this.isReady = true;
139
+ // introduce ourselves
140
+ this.send('client.intro', {
141
+ environment,
142
+ ...client,
143
+ name,
144
+ clientId,
145
+ reactotronCoreClientVersion: 'REACTOTRON_CORE_CLIENT_VERSION',
146
+ });
147
+ // flush the send queue
148
+ while (this.sendQueue.length > 0) {
149
+ const h = this.sendQueue[0];
150
+ this.sendQueue = this.sendQueue.slice(1);
151
+ this.socket.send(h);
152
+ }
153
+ });
154
+ };
155
+ // fires when we disconnect
156
+ const onClose = () => {
157
+ this.isReady = false;
158
+ // trigger our disconnect handler
159
+ onDisconnect && onDisconnect();
160
+ // as well as the plugin's onDisconnect
161
+ this.plugins.forEach((p) => p.onDisconnect && p.onDisconnect());
162
+ };
163
+ const decodeCommandData = (data) => {
164
+ if (typeof data === 'string') {
165
+ return JSON.parse(data);
166
+ }
167
+ if (Buffer.isBuffer(data)) {
168
+ return JSON.parse(data.toString());
169
+ }
170
+ return data;
171
+ };
172
+ // fires when we receive a command, just forward it off
173
+ const onMessage = (data) => {
174
+ const command = decodeCommandData(data);
175
+ // trigger our own command handler
176
+ onCommand && onCommand(command);
177
+ // trigger our plugins onCommand
178
+ this.plugins.forEach((p) => p.onCommand && p.onCommand(command));
179
+ // trigger our registered custom commands
180
+ if (command.type === 'custom') {
181
+ this.customCommands
182
+ .filter((cc) => {
183
+ if (typeof command.payload === 'string') {
184
+ return cc.command === command.payload;
185
+ }
186
+ return cc.command === command.payload.command;
187
+ })
188
+ .forEach((cc) => cc.handler(typeof command.payload === 'object'
189
+ ? command.payload.args
190
+ : undefined));
191
+ }
192
+ else if (command.type === 'setClientId') {
193
+ this.options.setClientId && this.options.setClientId(command.payload);
194
+ }
195
+ };
196
+ // this is ws style from require('ws') on node js
197
+ if ('on' in socket && socket.on) {
198
+ const nodeWebSocket = socket;
199
+ nodeWebSocket.on('open', onOpen);
200
+ nodeWebSocket.on('close', onClose);
201
+ nodeWebSocket.on('message', onMessage);
202
+ // assign the socket to the instance
203
+ this.socket = socket;
204
+ }
205
+ else {
206
+ // this is a browser
207
+ const browserWebSocket = socket;
208
+ socket.onopen = onOpen;
209
+ socket.onclose = onClose;
210
+ socket.onmessage = (evt) => onMessage(evt.data);
211
+ // assign the socket to the instance
212
+ this.socket = browserWebSocket;
213
+ }
214
+ return this;
215
+ }
216
+ /**
217
+ * Sends a command to the server
218
+ */
219
+ send = (type, payload, important) => {
220
+ // set the timing info
221
+ const date = new Date();
222
+ let deltaTime = date.getTime() - this.lastMessageDate.getTime();
223
+ // glitches in the matrix
224
+ if (deltaTime < 0) {
225
+ deltaTime = 0;
226
+ }
227
+ this.lastMessageDate = date;
228
+ const fullMessage = {
229
+ type,
230
+ payload,
231
+ important: !!important,
232
+ date: date.toISOString(),
233
+ deltaTime,
234
+ };
235
+ const serializedMessage = (0, serialize_1.default)(fullMessage, this.options.proxyHack);
236
+ if (this.isReady) {
237
+ // send this command
238
+ try {
239
+ this.socket.send(serializedMessage);
240
+ }
241
+ catch {
242
+ this.isReady = false;
243
+ console.log('An error occurred communicating with reactotron. Please reload your app');
244
+ }
245
+ }
246
+ else {
247
+ // queue it up until we can connect
248
+ this.sendQueue.push(serializedMessage);
249
+ }
250
+ };
251
+ /**
252
+ * Sends a custom command to the server to displays nicely.
253
+ */
254
+ display(config) {
255
+ const { name, value, preview, image: img, important = false } = config;
256
+ const payload = {
257
+ name,
258
+ value: value || null,
259
+ preview: preview || null,
260
+ image: img || null,
261
+ };
262
+ this.send('display', payload, important);
263
+ }
264
+ /**
265
+ * Client libraries can hijack this to report errors.
266
+ */
267
+ reportError(error) {
268
+ this.error(error);
269
+ }
270
+ /**
271
+ * Adds a plugin to the system
272
+ */
273
+ use(pluginCreator) {
274
+ // we're supposed to be given a function
275
+ if (typeof pluginCreator !== 'function') {
276
+ throw new Error('plugins must be a function');
277
+ }
278
+ // execute it immediately passing the send function
279
+ const plugin = pluginCreator.bind(this)(this);
280
+ // ensure we get an Object-like creature back
281
+ if (typeof plugin !== 'object') {
282
+ throw new Error('plugins must return an object');
283
+ }
284
+ // do we have features to mixin?
285
+ if (plugin.features) {
286
+ // validate
287
+ if (typeof plugin.features !== 'object') {
288
+ throw new Error('features must be an object');
289
+ }
290
+ // here's how we're going to inject these in
291
+ const inject = (key) => {
292
+ // grab the function
293
+ const featureFunction = plugin.features[key];
294
+ // only functions may pass
295
+ if (typeof featureFunction !== 'function') {
296
+ throw new Error(`feature ${key} is not a function`);
297
+ }
298
+ // ditch reserved names
299
+ if (isReservedFeature(key)) {
300
+ throw new Error(`feature ${key} is a reserved name`);
301
+ }
302
+ // ok, let's glue it up... and lose all respect from elite JS champions.
303
+ this[key] = featureFunction;
304
+ };
305
+ // let's inject
306
+ Object.keys(plugin.features).forEach((key) => inject(key));
307
+ }
308
+ // add it to the list
309
+ this.plugins.push(plugin);
310
+ // call the plugins onPlugin
311
+ plugin.onPlugin &&
312
+ typeof plugin.onPlugin === 'function' &&
313
+ plugin.onPlugin.bind(this)(this);
314
+ // chain-friendly
315
+ return this;
316
+ }
317
+ onCustomCommand(config, optHandler) {
318
+ let command;
319
+ let handler;
320
+ let title;
321
+ let description;
322
+ let args;
323
+ if (typeof config === 'string') {
324
+ command = config;
325
+ handler = optHandler;
326
+ }
327
+ else {
328
+ command = config.command;
329
+ handler = config.handler;
330
+ title = config.title;
331
+ description = config.description;
332
+ args = config.args;
333
+ }
334
+ // Validations
335
+ // Make sure there is a command
336
+ if (!command) {
337
+ throw new Error('A command is required');
338
+ }
339
+ // Make sure there is a handler
340
+ if (!handler) {
341
+ throw new Error(`A handler is required for command "${command}"`);
342
+ }
343
+ // Make sure the command doesn't already exist
344
+ const existingCommands = this.customCommands.filter((cc) => cc.command === command);
345
+ if (existingCommands.length > 0) {
346
+ existingCommands.forEach((command) => {
347
+ this.customCommands = this.customCommands.filter((cc) => cc.id !== command.id);
348
+ this.send('customCommand.unregister', {
349
+ id: command.id,
350
+ command: command.command,
351
+ });
352
+ });
353
+ }
354
+ if (args) {
355
+ const argNames = [];
356
+ args.forEach((arg) => {
357
+ if (!arg.name) {
358
+ throw new Error(`A arg on the command "${command}" is missing a name`);
359
+ }
360
+ if (argNames.indexOf(arg.name) > -1) {
361
+ throw new Error(`A arg with the name "${arg.name}" already exists in the command "${command}"`);
362
+ }
363
+ argNames.push(arg.name);
364
+ });
365
+ }
366
+ // Create this command handlers object
367
+ const customHandler = {
368
+ id: this.customCommandLatestId,
369
+ command,
370
+ handler,
371
+ title,
372
+ description,
373
+ args,
374
+ };
375
+ // Increment our id counter
376
+ this.customCommandLatestId += 1;
377
+ // Add it to our array
378
+ this.customCommands.push(customHandler);
379
+ this.send('customCommand.register', {
380
+ id: customHandler.id,
381
+ command: customHandler.command,
382
+ title: customHandler.title,
383
+ description: customHandler.description,
384
+ args: customHandler.args,
385
+ });
386
+ return () => {
387
+ this.customCommands = this.customCommands.filter((cc) => cc.id !== customHandler.id);
388
+ this.send('customCommand.unregister', {
389
+ id: customHandler.id,
390
+ command: customHandler.command,
391
+ });
392
+ };
393
+ }
394
+ }
395
+ exports.ReactotronImpl = ReactotronImpl;
396
+ // convenience factory function
397
+ function createClient(options) {
398
+ const client = new ReactotronImpl();
399
+ return client.configure(options);
400
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Fix BigInt serialization
3
+ * BigInts are not supported by JSON.stringify in Hermes android.
4
+ * This is a workaround.
5
+ * https://github.com/GoogleChromeLabs/jsbi/issues/30#issuecomment-953187833
6
+ * https://github.com/infinitered/reactotron/issues/1436
7
+ */
8
+ declare global {
9
+ interface BigInt {
10
+ toJSON(): string;
11
+ }
12
+ }
13
+ /**
14
+ * Serializes an object to JSON.
15
+ *
16
+ * @param {any} source - The victim.
17
+ */
18
+ declare function serialize(source: any, proxyHack?: boolean): string;
19
+ export default serialize;
20
+ //# sourceMappingURL=serialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,IAAI,MAAM,CAAC;KAClB;CACF;AAsBD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,UAAQ,UAmEhD;AAED,eAAe,SAAS,CAAC"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ // JSON.stringify() doesn't support circular dependencies or keeping
3
+ // falsy values. This does.
4
+ //
5
+ // Mostly adapted from https://github.com/isaacs/json-stringify-safe
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ // replacement tokens
8
+ const UNDEFINED = '~~~ undefined ~~~';
9
+ const NULL = `~~~ null ~~~`;
10
+ const FALSE = `~~~ false ~~~`;
11
+ const ZERO = `~~~ zero ~~~`;
12
+ const EMPTY_STRING = `~~~ empty string ~~~`;
13
+ const CIRCULAR = '~~~ Circular Reference ~~~';
14
+ const ANONYMOUS = '~~~ anonymous function ~~~';
15
+ const INFINITY = '~~~ Infinity ~~~';
16
+ const NEGATIVE_INFINITY = '~~~ -Infinity ~~~';
17
+ if (typeof BigInt !== 'undefined') {
18
+ // eslint-disable-next-line no-extend-native
19
+ BigInt.prototype.toJSON = function () {
20
+ return this.toString();
21
+ };
22
+ }
23
+ /**
24
+ * Attempts to give a name to a function.
25
+ *
26
+ * @param {Function} fn - The function to name.
27
+ */
28
+ function getFunctionName(fn) {
29
+ const n = fn.name;
30
+ if (n === null || n === undefined || n === '') {
31
+ return ANONYMOUS;
32
+ }
33
+ else {
34
+ return `~~~ ${n}() ~~~`;
35
+ }
36
+ }
37
+ /**
38
+ * Serializes an object to JSON.
39
+ *
40
+ * @param {any} source - The victim.
41
+ */
42
+ function serialize(source, proxyHack = false) {
43
+ const stack = [];
44
+ const keys = [];
45
+ /**
46
+ * Replace this object node with something potentially custom.
47
+ *
48
+ * @param {*} key - The key currently visited.
49
+ * @param {*} value - The value to replace.
50
+ */
51
+ function serializer(replacer) {
52
+ return function (key, value) {
53
+ // slam dunks
54
+ if (value === true)
55
+ return true;
56
+ // weird stuff
57
+ // if (Object.is(value, NaN)) return NAN // OK, apparently this is hard... leaving out for now
58
+ if (value === Infinity)
59
+ return INFINITY;
60
+ if (value === -Infinity)
61
+ return NEGATIVE_INFINITY;
62
+ if (value === 0)
63
+ return ZERO;
64
+ // classic javascript
65
+ if (value === undefined)
66
+ return UNDEFINED;
67
+ if (value === null)
68
+ return NULL;
69
+ if (value === false)
70
+ return FALSE;
71
+ // head shakers
72
+ if (value === -0)
73
+ return ZERO; // eslint-disable-line
74
+ if (value === '')
75
+ return EMPTY_STRING;
76
+ if (proxyHack && typeof value === 'object' && value.nativeEvent) {
77
+ return value.nativeEvent;
78
+ }
79
+ // known types that have easy resolving
80
+ switch (typeof value) {
81
+ case 'string':
82
+ return value;
83
+ case 'number':
84
+ return value;
85
+ case 'bigint':
86
+ return value.toString();
87
+ case 'function':
88
+ return getFunctionName(value);
89
+ }
90
+ // Tough things to crack
91
+ // If we have an iterator but are not an array (because arrays are easily seralizeable already)...
92
+ if (value[Symbol.iterator] && !Array.isArray(value)) {
93
+ // Convert to an array!
94
+ return [...value];
95
+ }
96
+ if (stack.length > 0) {
97
+ // check for prior existance
98
+ const thisPos = stack.indexOf(this);
99
+ ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
100
+ ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
101
+ if (~stack.indexOf(value))
102
+ value = CIRCULAR;
103
+ }
104
+ else {
105
+ stack.push(value);
106
+ }
107
+ return replacer == null ? value : replacer.call(this, key, value);
108
+ };
109
+ }
110
+ return JSON.stringify(source, serializer(null));
111
+ }
112
+ exports.default = serialize;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Starts a lame, low-res timer. Returns a function which when invoked,
3
+ * gives you the number of milliseconds since passing. ish.
4
+ */
5
+ export declare const start: () => () => number;
6
+ //# sourceMappingURL=stopwatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stopwatch.d.ts","sourceRoot":"","sources":["../src/stopwatch.ts"],"names":[],"mappings":"AAyCA;;;GAGG;AACH,eAAO,MAAM,KAAK,oBAIjB,CAAC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /// <reference types="node" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.start = void 0;
5
+ const hasHirezNodeTimer = false &&
6
+ typeof process === 'object' &&
7
+ process &&
8
+ process.hrtime &&
9
+ typeof process.hrtime === 'function';
10
+ // the default timer
11
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+ const defaultPerformanceNow = (started) => Date.now();
13
+ // try to find the browser-based performance timer
14
+ const nativePerformance = typeof window !== 'undefined' &&
15
+ window &&
16
+ (window.performance ||
17
+ window.msPerformance ||
18
+ window.webkitPerformance);
19
+ // the function we're trying to assign
20
+ let performanceNow = defaultPerformanceNow;
21
+ // accepts an already started time and returns the number of milliseconds
22
+ let delta = (started) => performanceNow() - started;
23
+ if (hasHirezNodeTimer) {
24
+ performanceNow = process.hrtime;
25
+ // delta = (started) => performanceNow(started)[1] / 1000000;
26
+ delta = (started) => performanceNow(started) / 1000000;
27
+ }
28
+ else if (global.nativePerformanceNow) {
29
+ // react native 47
30
+ performanceNow = global.nativePerformanceNow;
31
+ }
32
+ else if (nativePerformance) {
33
+ // browsers + safely check for react native < 47
34
+ performanceNow = () => nativePerformance.now && nativePerformance.now();
35
+ }
36
+ /**
37
+ * Starts a lame, low-res timer. Returns a function which when invoked,
38
+ * gives you the number of milliseconds since passing. ish.
39
+ */
40
+ const start = () => {
41
+ // record the start time
42
+ const started = performanceNow();
43
+ return () => delta(started);
44
+ };
45
+ exports.start = start;
@@ -0,0 +1,9 @@
1
+ import type { ClientOptions } from './client-options';
2
+ import type { DReactionCore } from './';
3
+ /**
4
+ * Ensures the options are sane to run this baby. Throw if not. These
5
+ * are basically sanity checks.
6
+ */
7
+ declare const validate: (options: ClientOptions<DReactionCore>) => void;
8
+ export default validate;
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAYxC;;;GAGG;AACH,QAAA,MAAM,QAAQ,YAAa,aAAa,CAAC,aAAa,CAAC,SAkBtD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const isCreateSocketValid = (createSocket) => typeof createSocket !== 'undefined' && createSocket !== null;
4
+ const isHostValid = (host) => (typeof host === 'string' && host && host !== '');
5
+ const isPortValid = (port) => typeof port === 'number' && port >= 1 && port <= 65535;
6
+ const onCommandValid = (fn) => typeof fn === 'function';
7
+ /**
8
+ * Ensures the options are sane to run this baby. Throw if not. These
9
+ * are basically sanity checks.
10
+ */
11
+ const validate = (options) => {
12
+ const { createSocket, host, port, onCommand } = options;
13
+ if (!isCreateSocketValid(createSocket)) {
14
+ throw new Error('invalid createSocket function');
15
+ }
16
+ if (!isHostValid(host)) {
17
+ throw new Error('invalid host');
18
+ }
19
+ if (!isPortValid(port)) {
20
+ throw new Error('invalid port');
21
+ }
22
+ if (!onCommandValid(onCommand)) {
23
+ throw new Error('invalid onCommand handler');
24
+ }
25
+ };
26
+ exports.default = validate;
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "dreaction-client-core",
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "description": "",
6
+ "main": "lib/index.js",
7
+ "files": [
8
+ "lib",
9
+ "src"
10
+ ],
11
+ "keywords": [
12
+ "dreaction"
13
+ ],
14
+ "author": "moonrailgun <moonrailgun@gmail.com>",
15
+ "license": "MIT",
16
+ "dependencies": {
17
+ "@types/ws": "^8.5.13",
18
+ "eventemitter-strict": "^1.0.1",
19
+ "ws": "^8.18.0",
20
+ "dreaction-protocol": "1.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "typescript": "^5.4.5"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "test": "vitest"
28
+ }
29
+ }