├── .travis.yml ├── .editorconfig ├── .idea ├── misc.xml ├── vcs.xml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml ├── react-userbase.iml └── workspace.xml ├── example ├── public │ ├── manifest.json │ └── index.html ├── src │ ├── App.js │ ├── AuthStatusDisplay.js │ ├── index.js │ ├── index.css │ ├── App.css │ ├── Authentication.js │ └── Database.js └── package.json ├── src ├── index.js ├── UserbaseContext.tsx ├── currentState.tsx └── useUserbase.tsx ├── .gitignore ├── .npmignore ├── webpack.config.js ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 8 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "react-userbase", 3 | "name": "react-userbase", 4 | "start_url": "./index.html", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { UserbaseContext, UserbaseProvider } from "./UserbaseContext"; 2 | export { useUserbase } from "./useUserbase"; 3 | // TODO: secondary hooks for checking userbase state 4 | //export { useIsSignedIn, useCurrentSession } from "./currentState"; 5 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.css"; 3 | import { Authentication } from "./Authentication"; 4 | 5 | function App() { 6 | return ( 7 |
8 |

Userbase Hook Example

9 | 10 |
11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /example/src/AuthStatusDisplay.js: -------------------------------------------------------------------------------- 1 | /*import {useIsSignedIn} from "react-userbase"; 2 | import React from "react"; 3 | 4 | export const AuthStatusIndicator = () => { 5 | const isSignedIn = useIsSignedIn() 6 | 7 | return ( 8 |
9 | ) 10 | } 11 | */ 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/ignore-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules 6 | 7 | # builds 8 | build 9 | dist 10 | .rpt2_cache 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import { UserbaseProvider } from "react-userbase"; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById("root") 12 | ); 13 | -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .editorconfig 2 | .rollup.config.js 3 | tsconfig.json 4 | tsconfig.test.json 5 | src 6 | .idea 7 | # See https://help.github.com/ignore-files/ for more about ignoring files. 8 | 9 | # dependencies 10 | node_modules 11 | 12 | # example 13 | example 14 | .rpt2_cache 15 | 16 | # misc 17 | .DS_Store 18 | .env 19 | .env.local 20 | .env.development.local 21 | .env.test.local 22 | .env.production.local 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | -------------------------------------------------------------------------------- /.idea/react-userbase.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | react-userbase 11 | 12 | 13 | 14 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /src/UserbaseContext.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import userbase, { Session, UserResult } from "userbase-js"; 3 | 4 | export type UserbaseProviderProps = { 5 | appId: string; 6 | }; 7 | 8 | export const UserbaseContext = React.createContext | null>(null); 11 | 12 | export const UserbaseProvider: React.FunctionComponent = ({ 13 | appId, 14 | children 15 | }) => { 16 | const [initPromise] = React.useState(() => userbase.init({ appId })); 17 | 18 | return ( 19 | 20 | {children} 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /example/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | background-color: #282c34; 4 | color: wheat; 5 | height: 100vh; 6 | margin-top: -30px; 7 | padding-top: 30px; 8 | } 9 | 10 | .App-logo { 11 | height: 40vmin; 12 | pointer-events: none; 13 | } 14 | 15 | @media (prefers-reduced-motion: no-preference) { 16 | .App-logo { 17 | animation: App-logo-spin infinite 20s linear; 18 | } 19 | } 20 | 21 | .App-header { 22 | background-color: #282c34; 23 | min-height: 100vh; 24 | display: flex; 25 | flex-direction: column; 26 | align-items: center; 27 | justify-content: center; 28 | font-size: calc(10px + 2vmin); 29 | color: white; 30 | } 31 | 32 | .App-link { 33 | color: #61dafb; 34 | } 35 | 36 | @keyframes App-logo-spin { 37 | from { 38 | transform: rotate(0deg); 39 | } 40 | to { 41 | transform: rotate(360deg); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-userbase-example", 3 | "private": true, 4 | "license": "MIT", 5 | "version": "1.0.0", 6 | "dependencies": { 7 | "react": "react", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "react-userbase": "^1.5.6", 11 | "userbase-js": "^1.0.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "eject": "react-scripts eject" 17 | }, 18 | "eslintConfig": { 19 | "extends": "react-app" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | 3 | module.exports = { 4 | mode: "production", 5 | entry: "./src/index.js", 6 | resolve: { 7 | extensions: [".ts", ".tsx", ".js", ".json"] 8 | }, 9 | output: { 10 | path: path.resolve("dist"), 11 | libraryTarget: "commonjs" 12 | }, 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.js$/, 17 | exclude: /(node_modules|bower_components)/, 18 | use: { 19 | loader: "babel-loader", 20 | options: { 21 | presets: ["@babel/preset-env"] 22 | } 23 | } 24 | }, 25 | { 26 | test: /\.ts(x?)$/, 27 | exclude: /(node_modules)/, 28 | use: "ts-loader" 29 | } 30 | ] 31 | }, 32 | externals: { 33 | react: "react", 34 | "userbase-js": "userbase-js" 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "module": "esnext", 5 | "target": "es5", 6 | "lib": ["es6", "dom", "es2016", "es2017"], 7 | "sourceMap": true, 8 | "allowJs": false, 9 | "jsx": "react", 10 | "declaration": true, 11 | "moduleResolution": "node", 12 | "forceConsistentCasingInFileNames": true, 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noImplicitAny": false, 16 | "strictNullChecks": true, 17 | "suppressImplicitAnyIndexErrors": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "skipLibCheck": true, 21 | "esModuleInterop": true, 22 | "allowSyntheticDefaultImports": true, 23 | "strict": true, 24 | "resolveJsonModule": true, 25 | "isolatedModules": true, 26 | "noEmit": false 27 | }, 28 | "include": ["src"], 29 | "exclude": ["node_modules", "build", "dist", "example", "rollup.config.js"] 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrew E Jones 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/currentState.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useContext, useEffect } from "react"; 2 | import { Session } from "userbase-js"; 3 | import { UserbaseContext } from "./UserbaseContext"; 4 | 5 | // These hooks are a WIP. 6 | // They need to be independent of sessionStorage - will probably involve communication 7 | // with userbase-js itself. 8 | 9 | export const useIsSignedIn: () => boolean = () => { 10 | const [initHasResolved, setInitHasResolved] = useState(false); 11 | const initPromise = useContext(UserbaseContext); 12 | 13 | useEffect(() => { 14 | if (initPromise) initPromise.then(() => setInitHasResolved(true)); 15 | }, []); 16 | 17 | if (initHasResolved && sessionStorage.getItem("userbaseCurrentSession")) { 18 | return JSON.parse(sessionStorage.getItem("userbaseCurrentSession")!) 19 | .signedIn; 20 | } else return false; 21 | }; 22 | 23 | export const useCurrentSession: () => Session = () => { 24 | const [initHasResolved, setInitHasResolved] = useState(false); 25 | const initPromise = useContext(UserbaseContext); 26 | 27 | useEffect(() => { 28 | if (initPromise) initPromise.then(() => setInitHasResolved(true)); 29 | }, []); 30 | 31 | if (initHasResolved && sessionStorage.getItem("userbaseCurrentSession")) { 32 | return JSON.parse(sessionStorage.getItem("userbaseCurrentSession")!); 33 | } else return null; 34 | }; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-userbase", 3 | "version": "1.10.3", 4 | "description": "React Hooks for Userbase", 5 | "author": "aej11a", 6 | "license": "MIT", 7 | "repository": "https://github.com/aej11a/react-userbase", 8 | "main": "dist/main.js", 9 | "engines": { 10 | "node": ">=8", 11 | "npm": ">=5" 12 | }, 13 | "scripts": { 14 | "build": "webpack" 15 | }, 16 | "peerDependencies": { 17 | "react": "^16.9.0", 18 | "userbase-js": "^1.0.0" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.2.2", 22 | "@babel/preset-react": "^7.8.3", 23 | "@babel/runtime": "^7.3.1", 24 | "@testing-library/react-hooks": "^3.2.1", 25 | "@types/jest": "^23.3.13", 26 | "@types/react": "^16.9.19", 27 | "@types/react-dom": "^16.9.5", 28 | "babel-loader": "^8.0.6", 29 | "babel-minify-webpack-plugin": "^0.3.1", 30 | "babel-preset-react": "^6.24.1", 31 | "cross-env": "^5.2.0", 32 | "gh-pages": "^2.0.1", 33 | "husky": "^4.2.1", 34 | "prettier": "^1.19.1", 35 | "pretty-quick": "^2.0.1", 36 | "react": "^16.9.0", 37 | "react-scripts": "^3.0.1", 38 | "react-test-renderer": "^16.9.0", 39 | "source-map-loader": "^0.2.4", 40 | "terser-webpack-plugin": "^2.3.3", 41 | "uglifyjs-webpack-plugin": "^2.2.0", 42 | "webpack": "^4.41.5", 43 | "webpack-cli": "^3.3.10" 44 | }, 45 | "husky": { 46 | "hooks": { 47 | "pre-commit": "pretty-quick --staged" 48 | } 49 | }, 50 | "dependencies": { 51 | "userbase-js": "^1.0.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/src/Authentication.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useUserbase } from "react-userbase"; 3 | import { Database } from "./Database"; 4 | 5 | export const Authentication = () => { 6 | //const isSignedIn = useIsSignedIn() 7 | const [signIn, { response, loading, error }] = useUserbase("signIn"); 8 | const [mySignOutFunction, { response: signOutResponse }] = useUserbase( 9 | "signOut" 10 | ); 11 | const [signUp, signUpData] = useUserbase("signIn"); 12 | const [username, setUname] = useState(null); 13 | const [password, setPassword] = useState(null); 14 | 15 | const handleSignIn = () => { 16 | signIn({ username, password }); 17 | }; 18 | 19 | const handleSignUp = () => { 20 | signUp({ username, password }); 21 | }; 22 | 23 | useEffect(() => { 24 | console.log(response, loading, error); 25 | }, [response, loading, error]); 26 | 27 | useEffect(() => { 28 | console.log(signUpData); 29 | }, [signUpData]); 30 | 31 | if (loading || signUpData.loading) return

Loading...

; 32 | return ( 33 |
34 | Username:{" "} 35 | setUname(e.target.value)} /> 36 |
37 | Password:{" "} 38 | setPassword(e.target.value)} /> 39 |
40 | 41 | 42 |
43 |
44 | 45 | 46 |
47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /example/src/Database.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useUserbase } from "react-userbase"; 3 | 4 | export const Database = () => { 5 | const [inputValue, setInputValue] = useState(null); 6 | const [dbItems, setDbItems] = useState(null); 7 | 8 | const databaseName = "todos"; 9 | 10 | const [ 11 | openTodoDb, 12 | { response: openResponse, loading: openingDb, error: openError } 13 | ] = useUserbase("openDatabase", { 14 | databaseName: databaseName, 15 | changeHandler: items => setDbItems(items) 16 | }); 17 | 18 | const [addItem, { response, loading, error }] = useUserbase("insertItem", { 19 | databaseName 20 | }); 21 | 22 | // open the DB on load 23 | useEffect(() => { 24 | openTodoDb().then(() => console.log("Opened Todo Database!")); 25 | }, []); 26 | 27 | useEffect(() => { 28 | console.log(dbItems); 29 | }, [dbItems]); 30 | 31 | if (openingDb) return

Loading...

; 32 | return ( 33 |
34 | New Todo:{" "} 35 | setInputValue(event.target.value)} 38 | style={{ marginTop: "20px" }} 39 | /> 40 | 43 |
44 | {dbItems ? ( 45 |
    48 | {dbItems.map(record => ( 49 |
  1. {record.item}
  2. 50 | ))} 51 |
52 | ) : null} 53 |
54 | ); 55 | }; 56 | -------------------------------------------------------------------------------- /src/useUserbase.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState, useContext } from "react"; 2 | import { UserbaseContext } from "./UserbaseContext"; 3 | import userbase, { Session, UserResult } from "userbase-js"; 4 | 5 | export interface UserbaseActionState { 6 | response: object | null; 7 | loading: boolean; 8 | error: object | null; 9 | } 10 | 11 | export type GeneratedUserbasePromise = ( 12 | options?: object 13 | ) => Promise; 14 | 15 | type UserActionStrings = 16 | | "signUp" 17 | | "signIn" 18 | | "signOut" 19 | | "updateUser" 20 | | "deleteUser"; 21 | type DbActionStrings = 22 | | "openDatabase" 23 | | "insertItem" 24 | | "updateItem" 25 | | "deleteItem" 26 | | "putTransaction"; 27 | 28 | export const useUserbase = ( 29 | action: UserActionStrings | DbActionStrings, 30 | parentOptions?: object 31 | ): [Function, UserbaseActionState] => { 32 | const initPromise = useContext(UserbaseContext); 33 | 34 | const [userbaseActionState, setUserbaseActionState] = useState< 35 | UserbaseActionState 36 | >({ 37 | response: null, 38 | loading: false, 39 | error: null 40 | }); 41 | 42 | const userbaseFunction: GeneratedUserbasePromise = useCallback( 43 | (options?: object): Promise => { 44 | setUserbaseActionState({ 45 | response: null, 46 | error: null, 47 | loading: true 48 | }); 49 | // @ts-ignore 50 | return initPromise.then(res => { 51 | // @ts-ignore 52 | return userbase[action]({ ...parentOptions, ...options }) 53 | .then((res: object) => { 54 | setUserbaseActionState({ 55 | response: res, 56 | loading: false, 57 | error: null 58 | }); 59 | }) 60 | .catch((e: Error) => { 61 | setUserbaseActionState({ 62 | error: e, 63 | loading: false, 64 | response: null 65 | }); 66 | }); 67 | }); 68 | }, 69 | [action, parentOptions] 70 | ); 71 | 72 | return [userbaseFunction, userbaseActionState]; 73 | }; 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-userbase 2 | 3 | > React Hooks for [Userbase](https://userbase.com/) 4 | 5 | [![NPM](https://img.shields.io/npm/v/react-userbase.svg)](https://www.npmjs.com/package/react-userbase) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 6 | 7 | ## Install 8 | 9 | You need to install Userbase separately from this package 10 | 11 | ```bash 12 | yarn add userbase-js react-userbase 13 | ``` 14 | 15 | or 16 | 17 | ```bash 18 | npm install userbase-js react-userbase --save 19 | ``` 20 | 21 | ## Usage 22 | 23 | First, wrap your app with UserbaseProvider like this: 24 | 25 | ```jsx 26 | import { UserbaseProvider } from 'react-userbase'; 27 | 28 | 29 | 30 | 31 | ``` 32 | 33 | Then, any component within the UserbaseProvider can use the hook. 34 | 35 | The hook takes arguments like these: 36 | 37 | ```tsx 38 | useUserbase(action, options?) 39 | ``` 40 | 41 | where action is one of the Userbase functions from their [SDK](https://userbase.com/docs/sdk/) and `options` is an object of options to pass to the function. 42 | 43 | The hook returns an array with a function and an object as shown in the example below. 44 | 45 | The generated function will trigger its Userbase function, and the object properties will track that function's state. The generated function also returns its promise. 46 | 47 | You can also pass options to the function when you call it, as shown below. 48 | 49 | ```tsx 50 | import * as React from "react"; 51 | import { useUserbase } from "react-userbase"; 52 | 53 | const Example = () => { 54 | const [signIn, { response, loading, error }] = useUserbase("signIn"); 55 | const [ 56 | signOut, 57 | { 58 | response: signOutResponse, 59 | loading: signOutLoading, 60 | error: signOutError 61 | } 62 | ] = useUserbase("signOut"); 63 | 64 | const username = "aej11a"; 65 | const password = "Password123"; 66 | 67 | useEffect(() => { 68 | console.log(response, loading, error); 69 | }); 70 | 71 | if (loading) return ; 72 | return ( 73 | 74 | ); 75 | }; 76 | ``` 77 | 78 | ## Example Project 79 | 80 | Clone/download the repo locally and add a `.env.local` file at `react-userbase/example/.env.local` 81 | 82 | In that file, add `REACT_APP_USERBASE_APP_ID=` 83 | 84 | Start the dev server to test. You can see a few different uses of the hook in `react-userbase/example/src/App.js` 85 | 86 | ## License 87 | 88 | MIT © [aej11a](https://github.com/aej11a) 89 | 90 | --- 91 | 92 | This hook was created using [create-react-hook](https://github.com/hermanya/create-react-hook). 93 | 94 | Excellent explanation of the object syntax instead of using an array: https://github.com/zeit/swr/issues/9#issuecomment-547224457 95 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | noim 120 | console.log 121 | typescript2 122 | roll 123 | exter 124 | main.js 125 | decla 126 | yarn run 127 | yarn 128 | lib 129 | export 130 | common 131 | typesc 132 | ts 133 | 134 | 135 | 136 | 138 | 139 | 173 | 174 | 175 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |