@teardown/react-native 1.0.12 → 1.1.0-beta-04

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 (43) hide show
  1. package/dist/components/debugger-ui.d.ts +7 -0
  2. package/dist/components/debugger-ui.js +147 -0
  3. package/dist/components/index.js +17 -0
  4. package/dist/components/teardown-logo.d.ts +4 -0
  5. package/dist/components/teardown-logo.js +33 -0
  6. package/dist/containers/index.js +17 -0
  7. package/dist/containers/teardown.container.d.ts +11 -0
  8. package/dist/containers/teardown.container.js +13 -0
  9. package/dist/debugger.d.ts +13 -0
  10. package/dist/debugger.js +75 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.js +21 -0
  13. package/dist/metro/index.d.ts +2 -0
  14. package/dist/metro/index.js +5 -0
  15. package/dist/metro-plugin.d.ts +1 -0
  16. package/dist/metro-plugin.js +45 -0
  17. package/dist/plugins/http.plugin.d.ts +23 -0
  18. package/dist/plugins/http.plugin.js +144 -0
  19. package/{src/plugins/index.ts → dist/plugins/index.d.ts} +0 -1
  20. package/dist/plugins/index.js +19 -0
  21. package/dist/plugins/logging.plugin.d.ts +9 -0
  22. package/dist/plugins/logging.plugin.js +35 -0
  23. package/dist/plugins/websocket.plugin.d.ts +17 -0
  24. package/dist/plugins/websocket.plugin.js +102 -0
  25. package/dist/services/index.js +17 -0
  26. package/dist/services/teardown.service.d.ts +10 -0
  27. package/dist/services/teardown.service.js +21 -0
  28. package/dist/teardown.client.d.ts +44 -0
  29. package/dist/teardown.client.js +65 -0
  30. package/package.json +23 -14
  31. package/src/components/debugger-ui.tsx +0 -237
  32. package/src/components/teardown-logo.tsx +0 -16
  33. package/src/containers/teardown.container.tsx +0 -40
  34. package/src/debugger.ts +0 -72
  35. package/src/index.ts +0 -5
  36. package/src/plugins/http.plugin.ts +0 -171
  37. package/src/plugins/logging.plugin.ts +0 -52
  38. package/src/plugins/websocket.plugin.ts +0 -130
  39. package/src/services/teardown.service.ts +0 -27
  40. package/src/teardown.client.ts +0 -74
  41. /package/{src/components/index.ts → dist/components/index.d.ts} +0 -0
  42. /package/{src/containers/index.ts → dist/containers/index.d.ts} +0 -0
  43. /package/{src/services/index.ts → dist/services/index.d.ts} +0 -0
package/src/debugger.ts DELETED
@@ -1,72 +0,0 @@
1
- import {NativeModules, Platform} from 'react-native';
2
- import {
3
- ClientWebsocketEvents,
4
- ConnectionEstablishedWebsocketEvent,
5
- WebsocketClient,
6
- WebsocketClientOptions,
7
- WebsocketConnectionStatus,
8
- } from '@teardown/websocket';
9
-
10
- export type DebuggerStatus = WebsocketConnectionStatus;
11
-
12
- export type DebuggerOptions = WebsocketClientOptions;
13
-
14
- export class Debugger extends WebsocketClient<ClientWebsocketEvents> {
15
-
16
- constructor(options?: DebuggerOptions) {
17
- super(options);
18
- }
19
-
20
- public onEvent(event: ClientWebsocketEvents[keyof ClientWebsocketEvents]) {
21
- this.logger.log('onEvent', event);
22
- return event;
23
- }
24
-
25
- public onConnectionEstablished(event: ConnectionEstablishedWebsocketEvent) {
26
- this.logger.log('Connection established', event);
27
-
28
- this.client_id = event.client_id;
29
-
30
- this.send('CLIENT_CONNECTION_ESTABLISHED', {
31
- deviceName: '~~~--- device name here ---~~~',
32
- platform: Platform.OS,
33
- platformVersion: Platform.Version,
34
- reactNativeVersion: Platform.constants.reactNativeVersion,
35
- isDisableAnimations: Platform.constants.isDisableAnimations ?? false,
36
- isTesting: Platform.constants.isTesting,
37
- });
38
- }
39
-
40
- getHostFromUrl(url: string) {
41
- const host = url.match(
42
- /^(?:https?:\/\/)?(\[[^\]]+\]|[^/:\s]+)(?::\d+)?(?:[/?#]|$)/,
43
- )?.[1];
44
-
45
- if (typeof host !== 'string') {
46
- throw new Error('Invalid URL - host not found');
47
- }
48
- return host;
49
- }
50
-
51
- getHost() {
52
- try {
53
- // https://github.com/facebook/react-native/blob/2a7f969500cef73b621269299619ee1f0ee9521a/packages/react-native/src/private/specs/modules/NativeSourceCode.js#L16
54
- const scriptURL = NativeModules?.SourceCode?.getConstants().scriptURL
55
- if (typeof scriptURL !== "string") throw new Error("Invalid non-string URL")
56
- console.log('scriptURL', scriptURL);
57
-
58
- return this.getHostFromUrl(scriptURL)
59
- } catch (error) {
60
- const superHost = super.getHost();
61
- this.logger.warn(`Failed to get host: "${error.message}" - Falling back to ${superHost}`);
62
- return superHost;
63
- }
64
- }
65
-
66
- public send<
67
- Type extends keyof ClientWebsocketEvents,
68
- Payload extends ClientWebsocketEvents[Type]['payload'],
69
- >(type: Type, payload: Payload) {
70
- super.send(type, payload);
71
- }
72
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- // export * from './components';
2
- // export * from './containers';
3
- // export * from './services';
4
- export * from './teardown.client';
5
- export * from './plugins';
@@ -1,171 +0,0 @@
1
- // @ts-ignore
2
- import XHRInterceptor from 'react-native/Libraries/Network/XHRInterceptor';
3
- import type {Plugin, TeardownClient} from '../teardown.client';
4
- import {Logger} from '@teardown/logger';
5
- import {Util} from '@teardown/util';
6
- import type {HTTPRequestInfo, RequestMethod} from '@teardown/websocket';
7
-
8
- interface ExtendedXMLHttpRequest extends XMLHttpRequest {
9
- _id: number;
10
- }
11
-
12
- export type HTTPPluginOptions = {
13
- ignoreURLs?: RegExp[];
14
- };
15
-
16
- export class HTTPPlugin implements Plugin {
17
- private logger = new Logger('HTTPPlugin');
18
- private client: TeardownClient<any> | null = null;
19
- private requests: Map<number, HTTPRequestInfo> = new Map();
20
- private ignoreURLs: RegExp[];
21
-
22
- constructor(options: HTTPPluginOptions = {}) {
23
- this.ignoreURLs = options.ignoreURLs || [];
24
- }
25
-
26
- install(client: TeardownClient<any>): void {
27
- this.client = client;
28
- this.setupXHRInterceptor();
29
- }
30
-
31
- private setupXHRInterceptor(): void {
32
- if (XHRInterceptor.isInterceptorEnabled()) {
33
- this.logger.warn(
34
- 'XHRInterceptor is already enabled by another library. Disable it or run this plugin first when your app loads.',
35
- );
36
- }
37
-
38
- XHRInterceptor.setOpenCallback(this.xhrOpenCallback);
39
- XHRInterceptor.setRequestHeaderCallback(this.xhrRequestHeaderCallback);
40
- XHRInterceptor.setSendCallback(this.xhrSendCallback);
41
- XHRInterceptor.setResponseCallback(this.xhrResponseCallback);
42
-
43
- XHRInterceptor.enableInterception();
44
- }
45
-
46
- private shouldIgnoreURL(url: string): boolean {
47
- return this.ignoreURLs.some(ignoreRegex => ignoreRegex.test(url));
48
- }
49
-
50
- private xhrOpenCallback = (
51
- method: string,
52
- url: string,
53
- xhr: ExtendedXMLHttpRequest,
54
- ): void => {
55
- if (this.shouldIgnoreURL(url)) {
56
- return;
57
- }
58
-
59
- const requestId = Util.generateUUID();
60
-
61
- const HTTPRequestInfo: HTTPRequestInfo = {
62
- id: requestId,
63
- type: 'XMLHttpRequest',
64
- url,
65
- method: method as RequestMethod,
66
- requestHeaders: {'TD-Request-ID': requestId},
67
- startTime: Date.now(),
68
- updatedAt: Date.now(),
69
- };
70
-
71
- this.requests.set(xhr._id, HTTPRequestInfo);
72
- };
73
-
74
- private xhrRequestHeaderCallback = (
75
- header: string,
76
- value: string,
77
- xhr: ExtendedXMLHttpRequest,
78
- ): void => {
79
- const request = this.requests.get(xhr._id);
80
- if (request) {
81
- request.requestHeaders[header] = value;
82
- request.updatedAt = Date.now();
83
- }
84
- };
85
-
86
- private xhrSendCallback = (data: any, xhr: ExtendedXMLHttpRequest): void => {
87
- const request = this.requests.get(xhr._id);
88
- if (request) {
89
- xhr.setRequestHeader('TD-Request-ID', request.id);
90
-
91
- request.dataSent = this.serializeRequestBody(data);
92
- request.updatedAt = Date.now();
93
- this.sendHTTPEvent(request);
94
- }
95
- };
96
-
97
- private serializeRequestBody(data: any): string {
98
- if (typeof data === 'string') {
99
- return data;
100
- }
101
- try {
102
- return JSON.stringify(data);
103
- } catch (error) {
104
- this.logger.warn('Failed to stringify request body', error);
105
- return '[Unable to serialize request body]';
106
- }
107
- }
108
-
109
- private xhrResponseCallback = (
110
- status: number,
111
- timeout: number,
112
- response: string,
113
- responseURL: string,
114
- responseType: XMLHttpRequestResponseType,
115
- xhr: ExtendedXMLHttpRequest,
116
- ): void => {
117
- const request = this.requests.get(xhr._id);
118
- if (request) {
119
- request.status = status;
120
- request.responseHeaders = this.parseResponseHeaders(
121
- xhr.getAllResponseHeaders(),
122
- );
123
- request.response = this.parseResponseBody(response, responseType);
124
- request.responseURL = responseURL;
125
- request.responseType = responseType;
126
- request.timeout = timeout;
127
- request.endTime = Date.now();
128
- request.updatedAt = Date.now();
129
-
130
- this.sendHTTPEvent(request);
131
- this.requests.delete(xhr._id);
132
- }
133
- };
134
-
135
- private parseResponseHeaders(headersString: string): Record<string, string> {
136
- const headersObject: Record<string, string> = {};
137
- if (headersString) {
138
- const headerPairs = headersString.trim().split(/[\r\n]+/);
139
- headerPairs.forEach(headerPair => {
140
- const [key, value] = headerPair.split(': ');
141
- headersObject[key] = value;
142
- });
143
- }
144
- return headersObject;
145
- }
146
-
147
- private parseResponseBody(
148
- response: string,
149
- responseType: XMLHttpRequestResponseType,
150
- ): string {
151
- if (responseType === 'json') {
152
- try {
153
- return JSON.stringify(JSON.parse(response), null, 2);
154
- } catch (error) {
155
- this.logger.warn('Failed to parse JSON response', error);
156
- }
157
- }
158
- return response;
159
- }
160
-
161
- private sendHTTPEvent(httpRequestInfo: HTTPRequestInfo): void {
162
- if (this.client?.debugger) {
163
- this.client.debugger.send('NETWORK_HTTP_REQUEST', httpRequestInfo);
164
- }
165
- }
166
-
167
- disableInterception(): void {
168
- XHRInterceptor.disableInterception();
169
- this.requests.clear();
170
- }
171
- }
@@ -1,52 +0,0 @@
1
- import {Plugin, TeardownClient} from '../teardown.client';
2
-
3
- const originalConsoleLog = console.log;
4
- const originalConsoleWarn = console.warn;
5
- const originalConsoleDebug = console.debug;
6
- const originalConsoleError = console.error;
7
-
8
- export class LoggingPlugin implements Plugin {
9
- private client: TeardownClient<any> | null = null;
10
-
11
- install(client: TeardownClient<any>): void {
12
- this.client = client;
13
-
14
- console.log = (...args: Parameters<typeof console.log>) => {
15
- originalConsoleLog(...args);
16
-
17
- this.client?.debugger?.send('CONSOLE_LOG', {
18
- type: 'log',
19
- args,
20
- });
21
- };
22
-
23
- console.warn = (...args: Parameters<typeof console.warn>) => {
24
- originalConsoleWarn(...args);
25
-
26
- this.client?.debugger?.send('CONSOLE_LOG', {
27
- type: 'warn',
28
- args,
29
- });
30
- };
31
-
32
- console.debug = (...args: Parameters<typeof console.debug>) => {
33
- originalConsoleDebug(...args);
34
-
35
- this.client?.debugger?.send('CONSOLE_LOG', {
36
- type: 'debug',
37
- args,
38
- });
39
- };
40
-
41
- console.error = (...args: Parameters<typeof console.error>) => {
42
- originalConsoleError(...args);
43
-
44
- this.client?.debugger?.send('CONSOLE_LOG', {
45
- type: 'error',
46
- args,
47
- });
48
- };
49
- }
50
-
51
- uninstall() {}
52
- }
@@ -1,130 +0,0 @@
1
- // @ts-ignore
2
- import WebSocketInterceptor from 'react-native/Libraries/WebSocket/WebSocketInterceptor';
3
-
4
- import type {Plugin, TeardownClient} from '../teardown.client';
5
- import {Logger} from '@teardown/logger';
6
- import {Util} from '@teardown/util';
7
- import {
8
- WebSocketInfo,
9
- WebSocketMessageInfo,
10
- WebSocketCloseInfo,
11
- } from '@teardown/websocket';
12
-
13
- export class WebSocketPlugin implements Plugin {
14
- private logger = new Logger('WebSocketPlugin');
15
- private client: TeardownClient<any> | null = null;
16
- private sockets: Map<string, WebSocketInfo> = new Map();
17
-
18
- constructor() {
19
- this.setupWebSocketInterceptor();
20
- }
21
-
22
- install(client: TeardownClient<any>): void {
23
- this.client = client;
24
- }
25
-
26
- private setupWebSocketInterceptor(): void {
27
- if (WebSocketInterceptor.isInterceptorEnabled()) {
28
- this.logger.warn(
29
- 'WebSocketInterceptor is already enabled by another library, disable it or run this first when your app loads',
30
- );
31
- this.disableInterception();
32
- }
33
-
34
- WebSocketInterceptor.setConnectCallback(this.wsConnectCallback);
35
- WebSocketInterceptor.setSendCallback(this.wsSendCallback);
36
- WebSocketInterceptor.setOnMessageCallback(this.wsOnMessageCallback);
37
- WebSocketInterceptor.setOnCloseCallback(this.wsOnCloseCallback);
38
-
39
- WebSocketInterceptor.enableInterception();
40
-
41
- this.logger.log('WebSocketInterceptor enabled');
42
- }
43
-
44
- private wsConnectCallback = (
45
- url: string,
46
- protocols: string | string[] | undefined,
47
- options: Object,
48
- socketId: string,
49
- ): void => {
50
- const requestId = Util.generateUUID();
51
- const socketInfo: WebSocketInfo = {
52
- id: requestId,
53
- url,
54
- protocols,
55
- timestamp: Date.now(),
56
- };
57
- this.sockets.set(socketId, socketInfo);
58
- this.sendOpenEvent(socketInfo);
59
- };
60
-
61
- private wsSendCallback = (
62
- data: string | ArrayBuffer | ArrayBufferView,
63
- socketId: string,
64
- ): void => {
65
- const socket = this.sockets.get(socketId);
66
- if (socket) {
67
- const messageInfo: WebSocketMessageInfo = {
68
- id: socket.id,
69
- data: '', // TODO: Currently getting array buffer length errors here when sending data
70
- timestamp: Date.now(),
71
- direction: 'sent',
72
- };
73
- console.log('messageInfo', messageInfo);
74
- // this.sendMessageEvent(messageInfo);
75
- }
76
- };
77
-
78
- private wsOnMessageCallback = (
79
- socketId: string,
80
- message: WebSocketMessageEvent,
81
- ): void => {
82
- const socket = this.sockets.get(socketId);
83
- if (socket) {
84
- const messageInfo: WebSocketMessageInfo = {
85
- id: socket.id,
86
- data: '', // TODO: Currently getting array buffer length errors here when sending data
87
- timestamp: Date.now(),
88
- direction: 'received',
89
- };
90
- this.sendMessageEvent(messageInfo);
91
- }
92
- };
93
-
94
- private wsOnCloseCallback = (socketId: string, event: any): void => {
95
- const socket = this.sockets.get(socketId);
96
- if (socket) {
97
- const closeInfo: WebSocketCloseInfo = {
98
- id: socket.id,
99
- code: event.code,
100
- reason: event.reason,
101
- timestamp: Date.now(),
102
- };
103
- this.sendCloseEvent(closeInfo);
104
- this.sockets.delete(socketId);
105
- }
106
- };
107
-
108
- private sendOpenEvent(info: WebSocketInfo): void {
109
- if (this.client && this.client.debugger) {
110
- this.client.debugger.send('NETWORK_WEBSOCKET_OPEN', info);
111
- }
112
- }
113
-
114
- private sendMessageEvent(info: WebSocketMessageInfo): void {
115
- if (this.client && this.client.debugger) {
116
- this.client.debugger.send('NETWORK_WEBSOCKET_MESSAGE', info);
117
- }
118
- }
119
-
120
- private sendCloseEvent(info: WebSocketCloseInfo): void {
121
- if (this.client && this.client.debugger) {
122
- this.client.debugger.send('NETWORK_WEBSOCKET_CLOSE', info);
123
- }
124
- }
125
-
126
- disableInterception(): void {
127
- WebSocketInterceptor.disableInterception();
128
- this.sockets.clear();
129
- }
130
- }
@@ -1,27 +0,0 @@
1
- import {useContext, createContext} from "react";
2
- import type {PluginTuple, TeardownClient} from "../teardown.client";
3
-
4
- export type TeardownServiceContextType<T extends readonly PluginTuple[]> = {
5
- client: TeardownClient<T>
6
- };
7
-
8
- const Context = createContext<TeardownServiceContextType<any> | null>(null);
9
-
10
- export const TeardownService = {
11
- Context,
12
- Provider: Context.Provider,
13
-
14
- useState<T extends readonly PluginTuple[]>() {
15
- const state = useContext(Context);
16
- if (state == null) {
17
- throw new Error("TeardownService not found");
18
- }
19
- return state as TeardownServiceContextType<T>
20
- },
21
-
22
- useProvidedState<T extends readonly PluginTuple[]>(client: TeardownClient<T>): TeardownServiceContextType<T> {
23
- return {
24
- client
25
- };
26
- },
27
- };
@@ -1,74 +0,0 @@
1
- import {Logger} from '@teardown/logger';
2
- import {Debugger, DebuggerOptions} from './debugger';
3
-
4
- export interface Plugin {
5
- install?(client: TeardownClient<any>): void;
6
- uninstall?(): void;
7
- }
8
-
9
- export type PluginTuple = readonly [string, Plugin];
10
-
11
- type InferPluginFromTuple<T extends PluginTuple> = {
12
- [K in T[0]]: Omit<T[1], 'install' | 'uninstall'>;
13
- };
14
-
15
- type InferPluginsFromArray<T extends readonly PluginTuple[]> =
16
- UnionToIntersection<InferPluginFromTuple<T[number]>>;
17
-
18
- type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
19
- k: infer I,
20
- ) => void
21
- ? I
22
- : never;
23
-
24
- export type TeardownClientOptions<T extends readonly PluginTuple[]> = {
25
- plugins?: T;
26
- debug?: boolean;
27
- } & DebuggerOptions;
28
-
29
- export class TeardownClient<T extends readonly PluginTuple[]> {
30
- private logger = new Logger('TeardownClient');
31
-
32
- private readonly plugins: Map<string, Plugin> = new Map();
33
-
34
- public debugger: Debugger | null;
35
-
36
- public api: InferPluginsFromArray<T> = {} as InferPluginsFromArray<T>;
37
-
38
- constructor(options?: TeardownClientOptions<T>) {
39
- this.debugger = __DEV__ ? new Debugger(options) : null;
40
-
41
- options?.plugins?.forEach(([key, plugin]) => {
42
- this.plugins.set(key, plugin);
43
- });
44
-
45
- this.installPlugins();
46
- }
47
-
48
- private installPlugins() {
49
- this.logger.log('Installing plugins');
50
- this.plugins.forEach((plugin, key) => {
51
- plugin.install?.(this);
52
- (this.api as any)[key] = plugin;
53
- });
54
- this.logger.log('Plugins installed');
55
- }
56
-
57
- uninstallPlugin(key: string) {
58
- const plugin = this.plugins.get(key);
59
- if (plugin) {
60
- plugin.uninstall?.();
61
- this.plugins.delete(key);
62
- delete (this.api as any)[key];
63
- }
64
- }
65
-
66
- uninstallAllPlugins() {
67
- this.plugins.forEach((_, key) => this.uninstallPlugin(key));
68
- }
69
-
70
- reinstallPlugins() {
71
- this.uninstallAllPlugins();
72
- this.installPlugins();
73
- }
74
- }