Browse Source

typescripting

Daniel Zlotin 7 years ago
parent
commit
ce48e0032c

+ 29
- 16
lib/src/Navigation.ts View File

12
 import { Element } from './adapters/Element';
12
 import { Element } from './adapters/Element';
13
 
13
 
14
 class Navigation {
14
 class Navigation {
15
-  public readonly Element = Element;
16
-
17
-  private readonly store = new Store();
18
-  private readonly nativeEventsReceiver = new NativeEventsReceiver();
19
-  private readonly uniqueIdProvider = new UniqueIdProvider();
20
-  private readonly componentRegistry = new ComponentRegistry(this.store);
21
-  private readonly layoutTreeParser = new LayoutTreeParser();
22
-  private readonly layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store);
23
-  private readonly nativeCommandsSender = new NativeCommandsSender();
24
-  private readonly commands = new Commands(this.nativeCommandsSender, this.layoutTreeParser, this.layoutTreeCrawler);
25
-  private readonly publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
26
-  private readonly privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
15
+  public readonly Element;
16
+
17
+  private readonly store;
18
+  private readonly nativeEventsReceiver;
19
+  private readonly uniqueIdProvider;
20
+  private readonly componentRegistry;
21
+  private readonly layoutTreeParser;
22
+  private readonly layoutTreeCrawler;
23
+  private readonly nativeCommandsSender;
24
+  private readonly commands;
25
+  private readonly publicEventsRegistry;
26
+  private readonly privateEventsListener;
27
 
27
 
28
   constructor() {
28
   constructor() {
29
+    this.Element = Element;
30
+
31
+    this.store = new Store();
32
+    this.nativeEventsReceiver = new NativeEventsReceiver();
33
+    this.uniqueIdProvider = new UniqueIdProvider();
34
+    this.componentRegistry = new ComponentRegistry(this.store);
35
+    this.layoutTreeParser = new LayoutTreeParser();
36
+    this.layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store);
37
+    this.nativeCommandsSender = new NativeCommandsSender();
38
+    this.commands = new Commands(this.nativeCommandsSender, this.layoutTreeParser, this.layoutTreeCrawler);
39
+    this.publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
40
+    this.privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
41
+
29
     this.privateEventsListener.listenAndHandlePrivateEvents();
42
     this.privateEventsListener.listenAndHandlePrivateEvents();
30
   }
43
   }
31
 
44
 
108
    * Pop the stack to a given component
121
    * Pop the stack to a given component
109
    * @param {string} componentId The component's id.
122
    * @param {string} componentId The component's id.
110
    */
123
    */
111
-  popTo(componentId) {
124
+  popTo(componentId: string) {
112
     return this.commands.popTo(componentId);
125
     return this.commands.popTo(componentId);
113
   }
126
   }
114
 
127
 
116
    * Pop the component's stack to root.
129
    * Pop the component's stack to root.
117
    * @param {*} componentId
130
    * @param {*} componentId
118
    */
131
    */
119
-  popToRoot(componentId) {
132
+  popToRoot(componentId: string) {
120
     return this.commands.popToRoot(componentId);
133
     return this.commands.popToRoot(componentId);
121
   }
134
   }
122
 
135
 
132
    * dismiss overlay by componentId
145
    * dismiss overlay by componentId
133
    * @param {string} componentId
146
    * @param {string} componentId
134
    */
147
    */
135
-  dismissOverlay(componentId) {
148
+  dismissOverlay(componentId: string) {
136
     return this.commands.dismissOverlay(componentId);
149
     return this.commands.dismissOverlay(componentId);
137
   }
150
   }
138
 
151
 
139
   /**
152
   /**
140
-   * Obtain the events registery instance
153
+   * Obtain the events registry instance
141
    */
154
    */
142
   events() {
155
   events() {
143
     return this.publicEventsRegistry;
156
     return this.publicEventsRegistry;

+ 5
- 4
lib/src/adapters/Element.tsx View File

3
 import { requireNativeComponent } from 'react-native';
3
 import { requireNativeComponent } from 'react-native';
4
 
4
 
5
 interface ElementProps {
5
 interface ElementProps {
6
-  elementId;
7
-  resizeMode;
6
+  elementId: PropTypes.Requireable<string>;
7
+  resizeMode: any;
8
 }
8
 }
9
 
9
 
10
-let RNNElement: React.ComponentClass;
10
+let RNNElement: React.ComponentType<any>;
11
 
11
 
12
-export class Element extends React.Component<ElementProps, object> {
12
+export class Element extends React.Component<ElementProps, any> {
13
   static propTypes = {
13
   static propTypes = {
14
     elementId: PropTypes.string.isRequired,
14
     elementId: PropTypes.string.isRequired,
15
     resizeMode: PropTypes.string
15
     resizeMode: PropTypes.string
26
 }
26
 }
27
 
27
 
28
 RNNElement = requireNativeComponent('RNNElement', Element);
28
 RNNElement = requireNativeComponent('RNNElement', Element);
29
+

+ 1
- 1
lib/src/commands/LayoutTreeParser.ts View File

42
     if (!api.center) {
42
     if (!api.center) {
43
       throw new Error(`sideMenu.center is required`);
43
       throw new Error(`sideMenu.center is required`);
44
     }
44
     }
45
-    const children = [];
45
+    const children: Array<LayoutNode> = [];
46
     if (api.left) {
46
     if (api.left) {
47
       children.push({
47
       children.push({
48
         type: LayoutType.SideMenuLeft,
48
         type: LayoutType.SideMenuLeft,

+ 0
- 2
lib/src/commands/LayoutType.test.ts View File

11
   });
11
   });
12
 
12
 
13
   it('isLayoutType', () => {
13
   it('isLayoutType', () => {
14
-    expect(isLayoutType(null)).toBe(false);
15
-    expect(isLayoutType(undefined)).toBe(false);
16
     expect(isLayoutType('')).toBe(false);
14
     expect(isLayoutType('')).toBe(false);
17
     expect(isLayoutType('asdasd')).toBe(false);
15
     expect(isLayoutType('asdasd')).toBe(false);
18
     expect(isLayoutType('TopTabs')).toBe(true);
16
     expect(isLayoutType('TopTabs')).toBe(true);

+ 1
- 1
lib/src/components/ComponentRegistry.test.tsx View File

46
     uut.registerComponent('example.MyComponent.name', () => MyComponent);
46
     uut.registerComponent('example.MyComponent.name', () => MyComponent);
47
     const Component = mockRegistry.mock.calls[0][1]();
47
     const Component = mockRegistry.mock.calls[0][1]();
48
     const tree = renderer.create(<Component componentId="123" />);
48
     const tree = renderer.create(<Component componentId="123" />);
49
-    expect(tree.toJSON().children).toEqual(['Hello, World!']);
49
+    expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
50
   });
50
   });
51
 });
51
 });

+ 0
- 1
lib/src/components/ComponentRegistry.ts View File

1
-import * as React from 'react';
2
 import { AppRegistry, ComponentProvider } from 'react-native';
1
 import { AppRegistry, ComponentProvider } from 'react-native';
3
 import { ComponentWrapper } from './ComponentWrapper';
2
 import { ComponentWrapper } from './ComponentWrapper';
4
 
3
 

+ 18
- 18
lib/src/components/ComponentWrapper.test.tsx View File

61
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
61
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
62
     expect(NavigationComponent).not.toBeInstanceOf(MyComponent);
62
     expect(NavigationComponent).not.toBeInstanceOf(MyComponent);
63
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
63
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
64
-    expect(tree.toJSON().children).toEqual(['Hello, World!']);
65
-    expect(tree.getInstance().originalComponentRef).toBeInstanceOf(MyComponent);
64
+    expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
65
+    expect(tree.getInstance()!.originalComponentRef).toBeInstanceOf(MyComponent);
66
   });
66
   });
67
 
67
 
68
   it('injects props from wrapper into original component', () => {
68
   it('injects props from wrapper into original component', () => {
69
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
69
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
70
     const tree = renderer.create(<NavigationComponent componentId={'component1'} myProp={'yo'} />);
70
     const tree = renderer.create(<NavigationComponent componentId={'component1'} myProp={'yo'} />);
71
-    expect(tree.getInstance().originalComponentRef.props.myProp).toEqual('yo');
71
+    expect(tree.getInstance()!.originalComponentRef.props.myProp).toEqual('yo');
72
   });
72
   });
73
 
73
 
74
   it('updates props from wrapper into original component', () => {
74
   it('updates props from wrapper into original component', () => {
75
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
75
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
76
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
76
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
77
     expect(childRef.props.foo).toEqual(undefined);
77
     expect(childRef.props.foo).toEqual(undefined);
78
-    tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
78
+    tree.getInstance()!.setState({ propsFromState: { foo: 'yo' } });
79
     expect(childRef.props.foo).toEqual('yo');
79
     expect(childRef.props.foo).toEqual('yo');
80
   });
80
   });
81
 
81
 
83
     store.setPropsForComponentId('component123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
83
     store.setPropsForComponentId('component123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
84
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
84
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
85
     const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
85
     const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
86
-    const originalComponentProps = tree.getInstance().originalComponentRef.props;
86
+    const originalComponentProps = tree.getInstance()!.originalComponentRef.props;
87
     expect(originalComponentProps).toEqual({ componentId: 'component123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
87
     expect(originalComponentProps).toEqual({ componentId: 'component123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
88
   });
88
   });
89
 
89
 
93
     store.setPropsForComponentId('component1', { myProp: 'hello' });
93
     store.setPropsForComponentId('component1', { myProp: 'hello' });
94
     expect(childRef.originalComponentRef.props.foo).toEqual(undefined);
94
     expect(childRef.originalComponentRef.props.foo).toEqual(undefined);
95
     expect(childRef.originalComponentRef.props.myProp).toEqual(undefined);
95
     expect(childRef.originalComponentRef.props.myProp).toEqual(undefined);
96
-    tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
96
+    tree.getInstance()!.setState({ propsFromState: { foo: 'yo' } });
97
     expect(childRef.originalComponentRef.props.foo).toEqual('yo');
97
     expect(childRef.originalComponentRef.props.foo).toEqual('yo');
98
     expect(childRef.originalComponentRef.props.myProp).toEqual('hello');
98
     expect(childRef.originalComponentRef.props.myProp).toEqual('hello');
99
   });
99
   });
102
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
102
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
103
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
103
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
104
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
104
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
105
-    tree.getInstance().setState({ propsFromState: { id: 'ERROR' } });
105
+    tree.getInstance()!.setState({ propsFromState: { id: 'ERROR' } });
106
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
106
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
107
   });
107
   });
108
 
108
 
109
   it('assignes key by id', () => {
109
   it('assignes key by id', () => {
110
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
110
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
111
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
111
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
112
-    expect(tree.getInstance().originalComponentRef.props.componentId).toEqual('component1');
113
-    expect(tree.getInstance().originalComponentRef._reactInternalInstance.key).toEqual('component1');
112
+    expect(tree.getInstance()!.originalComponentRef.props.componentId).toEqual('component1');
113
+    expect(tree.getInstance()!.originalComponentRef._reactInternalInstance.key).toEqual('component1');
114
   });
114
   });
115
 
115
 
116
   it('saves self ref into store', () => {
116
   it('saves self ref into store', () => {
131
   it('holds ref to OriginalComponent', () => {
131
   it('holds ref to OriginalComponent', () => {
132
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
132
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
133
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
133
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
134
-    expect(tree.getInstance().originalComponentRef).toBeDefined();
135
-    expect(tree.getInstance().originalComponentRef).toBeInstanceOf(MyComponent);
134
+    expect(tree.getInstance()!.originalComponentRef).toBeDefined();
135
+    expect(tree.getInstance()!.originalComponentRef).toBeInstanceOf(MyComponent);
136
   });
136
   });
137
 
137
 
138
   it('cleans ref to internal component on unount', () => {
138
   it('cleans ref to internal component on unount', () => {
139
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
139
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
140
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
140
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
141
-    const instance = tree.getInstance();
141
+    const instance = tree.getInstance()!;
142
     expect(instance.originalComponentRef).toBeInstanceOf(React.Component);
142
     expect(instance.originalComponentRef).toBeInstanceOf(React.Component);
143
     tree.unmount();
143
     tree.unmount();
144
     expect(instance.originalComponentRef).toBeFalsy();
144
     expect(instance.originalComponentRef).toBeFalsy();
166
     it('didAppear, didDisappear and onNavigationButtonPressed are optional', () => {
166
     it('didAppear, didDisappear and onNavigationButtonPressed are optional', () => {
167
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
167
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
168
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
168
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
169
-      expect(() => tree.getInstance().didAppear()).not.toThrow();
170
-      expect(() => tree.getInstance().didDisappear()).not.toThrow();
171
-      expect(() => tree.getInstance().onNavigationButtonPressed()).not.toThrow();
169
+      expect(() => tree.getInstance()!.didAppear()).not.toThrow();
170
+      expect(() => tree.getInstance()!.didDisappear()).not.toThrow();
171
+      expect(() => tree.getInstance()!.onNavigationButtonPressed()).not.toThrow();
172
     });
172
     });
173
 
173
 
174
     it('calls didAppear on OriginalComponent', () => {
174
     it('calls didAppear on OriginalComponent', () => {
175
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
175
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
176
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
176
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
177
       expect(didAppearCallback).toHaveBeenCalledTimes(0);
177
       expect(didAppearCallback).toHaveBeenCalledTimes(0);
178
-      tree.getInstance().didAppear();
178
+      tree.getInstance()!.didAppear();
179
       expect(didAppearCallback).toHaveBeenCalledTimes(1);
179
       expect(didAppearCallback).toHaveBeenCalledTimes(1);
180
     });
180
     });
181
 
181
 
183
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
183
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
184
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
184
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
185
       expect(didDisappearCallback).toHaveBeenCalledTimes(0);
185
       expect(didDisappearCallback).toHaveBeenCalledTimes(0);
186
-      tree.getInstance().didDisappear();
186
+      tree.getInstance()!.didDisappear();
187
       expect(didDisappearCallback).toHaveBeenCalledTimes(1);
187
       expect(didDisappearCallback).toHaveBeenCalledTimes(1);
188
     });
188
     });
189
 
189
 
191
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
191
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
192
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
192
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
193
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(0);
193
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(0);
194
-      tree.getInstance().onNavigationButtonPressed();
194
+      tree.getInstance()!.onNavigationButtonPressed();
195
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(1);
195
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(1);
196
     });
196
     });
197
   });
197
   });

+ 2
- 2
package.json View File

69
     "shell-utils": "1.x.x",
69
     "shell-utils": "1.x.x",
70
     "xo": "0.18.x",
70
     "xo": "0.18.x",
71
     "typescript": "2.x.x",
71
     "typescript": "2.x.x",
72
-    "@types/react": "16.0.0",
72
+    "@types/react": "16.x.x",
73
     "@types/react-native": "0.49.x",
73
     "@types/react-native": "0.49.x",
74
     "@types/lodash": "4.x.x",
74
     "@types/lodash": "4.x.x",
75
     "@types/prop-types": "15.x.x",
75
     "@types/prop-types": "15.x.x",
76
-    "@types/react-test-renderer": "16.0.0",
76
+    "@types/react-test-renderer": "16.x.x",
77
     "@types/jest": "22.x.x"
77
     "@types/jest": "22.x.x"
78
   },
78
   },
79
   "babel": {
79
   "babel": {

+ 3
- 3
tsconfig-strict.json View File

10
     "importHelpers": true,
10
     "importHelpers": true,
11
     "noEmitOnError": true,
11
     "noEmitOnError": true,
12
     "noFallthroughCasesInSwitch": true,
12
     "noFallthroughCasesInSwitch": true,
13
-    "noImplicitAny": true,
14
     "noImplicitReturns": true,
13
     "noImplicitReturns": true,
15
     "noImplicitThis": true,
14
     "noImplicitThis": true,
16
     "noUnusedLocals": true,
15
     "noUnusedLocals": true,
17
     "noUnusedParameters": true,
16
     "noUnusedParameters": true,
18
     "pretty": true,
17
     "pretty": true,
19
-    "strictFunctionTypes": false,
18
+    "strictFunctionTypes": true,
20
     "strictNullChecks": true,
19
     "strictNullChecks": true,
21
-    "strict": true
20
+    "strict": true,
21
+    "noImplicitAny": true
22
   }
22
   }
23
 }
23
 }

+ 3
- 10
tsconfig.json View File

1
 {
1
 {
2
+  "extends": "./tsconfig-strict.json",
2
   "compilerOptions": {
3
   "compilerOptions": {
3
     "outDir": "./lib/dist",
4
     "outDir": "./lib/dist",
4
-    "allowJs": true,
5
+    "allowJs": false,
5
     "target": "esnext",
6
     "target": "esnext",
6
     "module": "commonjs",
7
     "module": "commonjs",
7
-    "jsx": "react-native",
8
-    "types": [
9
-      "lodash",
10
-      "react",
11
-      "react-native",
12
-      "prop-types",
13
-      "react-test-renderer",
14
-      "jest"
15
-    ]
8
+    "jsx": "react-native"
16
   },
9
   },
17
   "include": [
10
   "include": [
18
     "./lib/src/**/*"
11
     "./lib/src/**/*"