add dev pipeline; babel; linter; typescript support; readme

This commit is contained in:
Iuri Matias 2018-12-03 20:02:24 -05:00
parent 3d6b97490b
commit bc09a910cc
10 changed files with 5252 additions and 34 deletions

292
.eslintrc.json Normal file
View File

@ -0,0 +1,292 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended"
],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2018,
"ecmaFeatures": {
"jsx": true
}
},
"globals": {
"__": true
},
"plugins": [
],
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "error",
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "off",
"arrow-parens": "off",
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": "off",
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "off",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": [
"error",
"last"
],
"complexity": "error",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "error",
"dot-location": [
"error",
"property"
],
"dot-notation": "off",
"eol-last": "error",
"eqeqeq": "error",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "error",
"func-names": "off",
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "off",
"handle-callback-err": "off",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": "off",
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "error",
"lines-around-directive": "error",
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-ternary": [
"error",
"never"
],
"new-parens": "off",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "error",
"no-buffer-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "error",
"no-confusing-arrow": "error",
"no-console": "off",
"no-continue": "off",
"no-debugger": "warn",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": 2,
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "off",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-coercion": [
"error",
{
"allow": ["!!"]
}
],
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "off",
"no-magic-numbers": "off",
"no-mixed-operators": "error",
"no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "off",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": "off",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error",
"no-unused-expressions": "error",
"no-unused-vars": ["error", {
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}],
"no-use-before-define": "off",
"no-useless-call": "off",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-escape": "off",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": "off",
"object-curly-spacing": [
"off"
],
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "error",
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": "error",
"require-await": "off",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "error",
"semi-spacing": [
"error",
{
"after": true,
"before": false
}
],
"semi-style": [
"error",
"last"
],
"sort-imports": "off",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "off",
"space-unary-ops": "error",
"spaced-comment": "off",
"strict": "error",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": [
"error",
"never"
],
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "error",
"vars-on-top": "off",
"wrap-iife": "error",
"wrap-regex": "error",
"yield-star-spacing": "error",
"yoda": [
"error",
"never"
]
}
}

5
.gitignore vendored
View File

@ -1 +1,4 @@
node_modules/
node_modules
dist
yarn-debug.log*
yarn-error.log*

View File

@ -1 +1,47 @@
# status-x
status-x
===
<p align="center">
Command line chat client for status
</p>
<p align="center">
<strong>WIP. DO NOT USE IN PRODUCTION. HIGH RISK ⚠</strong>
</p>
<br />
## Install
clone the repo via git:
```
$ git clone https://github.com/status-im/status-x.git
```
And then install the dependencies with `yarn`.
```
$ cd status-x
$ yarn
```
To develop:
```
$ yarn run start
$ yarn run lint
````
`status-x` requires `geth` or `murmur` to be able to connect to Whisper. If using `geth`, you may start it with the following flags.
`geth --testnet --syncmode=light --ws --wsport=8546 --wsaddr=localhost --wsorigins=statusjs --rpc --maxpeers=25 --shh --shh.pow=0.002 --wsapi=eth,web3,net,shh,debug,admin`
Also, due to the lack of nodes with Whisper enabled, you need to create a [static-nodes.json](https://github.com/status-im/murmur/blob/master/src/data/static-nodes.json) file, that must be placed in a specific path (if using testnet and Linux, `~/.ethereum/testnet/geth/static-nodes.json`
## Commands
*TODO*
* `/join #channelName` - join a channel
* `/s 1` - switch to channel or chat indexed 1
* `/msg 0xpubkey` - start a chat with user given his pubkey
## Contribution
Thank you for considering to help out with the source code! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
If you'd like to contribute to `status-js`, please fork, fix, commit and send a pull request for the maintainers to review and merge into the main code base. If you wish to submit more complex changes though, please check up with the core devs first on [#status-js channel](https://get.status.im/chat/public/status-js) to ensure those changes are in line with the general philosophy of the project and/or get some early feedback which can make both your efforts much lighter as well as our review and merge procedures quick and simple.

45
babel.config.js Normal file
View File

@ -0,0 +1,45 @@
/* global module */
module.exports = function (api) {
const node = {
ignore: [],
plugins: [
'babel-plugin-macros',
[
'@babel/plugin-proposal-decorators', {
legacy: true
}
],
'@babel/plugin-syntax-dynamic-import',
'babel-plugin-dynamic-import-node',
[
'@babel/plugin-proposal-class-properties', {
loose: true
}
],
'@babel/plugin-proposal-optional-chaining',
[
'@babel/plugin-transform-runtime', {
corejs: 2
}
]
],
presets: [
[
'@babel/preset-env', {
targets: {
node: '8.11.3'
}
}
],
'@babel/preset-typescript'
]
};
switch (api.env()) {
case 'node':
return node;
default:
throw new Error(`invalid babel env: ${api.env}`);
}
};

View File

@ -4,7 +4,28 @@
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"babel": "babel",
"babel:node": "npm-run-all babel:node:*",
"babel:node:src": "cross-env BABEL_ENV=node babel src --copy-files --extensions \".js,.ts\" --out-dir dist --source-maps",
"babel:watch": "run-p babel:watch:*",
"babel:watch:src": "npm run babel:node:src -- --verbose --watch",
"build": "npm-run-all build:*",
"build:node": "npm run babel:node",
"clean": "rimraf dist",
"lint": "npm-run-all lint:*",
"lint:js": "npm-run-all lint:js:*",
"lint:js:core": "eslint babel.config.js src/",
"lint:ts": "tslint -c tslint.json 'src/**/*.ts'",
"prepublishOnly": "npm-run-all clean build test",
"test": "npm-run-all lint test:*",
"test:core": "mocha dist/test/ --exit --no-timeouts --require source-map-support/register",
"start": "run-p start:*",
"start:babel": "npm run babel:watch",
"start:type-check": "npm run type-check:watch",
"tsc": "tsc",
"tslint": "tslint",
"type-check": "tsc",
"type-check:watch": "npm run type-check -- --watch"
},
"repository": {
"type": "git",
@ -17,9 +38,37 @@
},
"homepage": "https://github.com/status-im/status-x#readme",
"dependencies": {
"async": "^2.6.1",
"colors": "^1.3.2",
"neo-blessed": "^0.2.0",
"status-js-api": "^1.0.5"
},
"devDependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-decorators": "^7.1.6",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-transform-destructuring": "^7.1.3",
"@babel/plugin-transform-flow-strip-types": "^7.1.6",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.6",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.1.0",
"@babel/runtime-corejs2": "^7.1.5",
"@types/web3": "^1.0.12",
"babel-loader": "^8.0.4",
"babel-plugin-dynamic-import-node": "^2.2.0",
"babel-plugin-macros": "^2.4.2",
"babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-transform-react-remove-prop-types": "^0.4.20",
"cross-env": "^5.2.0",
"eslint": "^5.9.0",
"npm-run-all": "^4.1.5",
"rimraf": "^2.6.2",
"tape-async": "^2.3.0",
"tslint": "^5.11.0",
"typescript": "^3.2.1"
}
}

View File

@ -11,11 +11,11 @@ class User {
class Users {
constructor() {
this.users = {}
this.users = {};
}
addUserOrUpdate(user) {
this.users[user.pubkey] = user
this.users[user.pubkey] = user;
}
addOrUpdateUserKey(pubkey, username) {
@ -27,17 +27,17 @@ class Users {
return this.users[pubkey];
}
getUsers() {
getUsers() {
let userList = [];
for (let pubkey in this.users) {
for (let pubkey in this.users) {
userList.push(pubkey);
}
return userList;
}
}
updateUsersState() {
let currentTime = (new Date().getTime());
for (let pubkey in this.users) {
for (let pubkey in this.users) {
let user = this.users[pubkey];
if (currentTime - user.lastSeen > 10*1000) {
user.online = false;
@ -114,14 +114,14 @@ class ChannelManager {
});
}
getUsersInCurrentChannel() {
getUsersInCurrentChannel() {
let channel = this.getCurrentChannel();
let user_keys = channel.users.getUsers();
let users = user_keys.map((pubkey) => {
let users = user_keys.map((pubkey) => {
return this.allUsers.users[pubkey];
});
});
return users;
}
}
}
module.exports = ChannelManager;

View File

@ -1,5 +1,3 @@
const async = require('async');
var UI = require('./ui.js');
var StatusJS = require('status-js-api');
var ChannelManager = require('./channelManager.js');
@ -35,10 +33,10 @@ channels.events.on('newMessage', (channelName, username, message) => {
var updateUsers = function() {
let users = channels.getUsersInCurrentChannel().map((x) => {
return {name: x.username, status: (x.online ? "on" : "offline")}
return {name: x.username, status: (x.online ? "on" : "offline")};
});
ui.availableUsers(users)
}
ui.availableUsers(users);
};
var handleProtocolMessages = function(channelName, data) {
// TODO: yes this is ugly, can be moved to the lib level
@ -56,7 +54,7 @@ var handleProtocolMessages = function(channelName, data) {
if (fromUser === userPubKey) return; // ignore typing events from self
usersTyping[fromUser] = (new Date().getTime());
}
}
};
channels.events.on('update', updateUsers);
channels.events.on('channelSwitch', updateUsers);
@ -95,7 +93,7 @@ ui.logEntry(`
/ \\| | / __ \\| | | | /\\___ \\ / \\
/_______ /|__| (____ /__| |____//____ >___/\\ \\
\\/ \\/ \\/ \\_/
`)
`);
ui.logEntry(`Generating Identity....`);
ui.logEntry(`Connecting to Peers....`);
@ -129,7 +127,7 @@ ui.logEntry(`Rejoining Channels....`);
status.joinChat(DEFAULT_CHANNEL, () => {
ui.logEntry(("Joined #" + DEFAULT_CHANNEL).green.underline)
ui.logEntry(("Joined #" + DEFAULT_CHANNEL).green.underline);
channels.addChannel(DEFAULT_CHANNEL, 'channel');
@ -139,8 +137,8 @@ ui.logEntry(`Rejoining Channels....`);
if (JSON.parse(data.payload)[1][1] === 'content/json') {
handleProtocolMessages(DEFAULT_CHANNEL, data);
} else {
usersTyping[data.data.sig] = 0 // user is likley no longer typing if a message was received
channels.addMessage(DEFAULT_CHANNEL, msg, data.data.sig, data.username)
usersTyping[data.data.sig] = 0; // user is likley no longer typing if a message was received
channels.addMessage(DEFAULT_CHANNEL, msg, data.data.sig, data.username);
}
});
});
@ -152,16 +150,16 @@ ui.logEntry(`Rejoining Channels....`);
if (JSON.parse(data.payload)[1][1] === 'content/json') {
handleProtocolMessages(data.username, data);
} else {
channels.addMessage(data.username, msg, data.data.sig, data.username)
channels.addMessage(data.username, msg, data.data.sig, data.username);
}
})
});
ui.events.on('cmd', (cmd) => {
if (cmd.split(' ')[0] === '/join') {
let channelName = cmd.split(' ')[1].replace('#','');
ui.logEntry("joining " + channelName)
ui.logEntry("joining " + channelName);
status.joinChat(channelName).then(() => {
ui.logEntry("joined #" + channelName)
ui.logEntry("joined #" + channelName);
channels.addChannel(channelName, 'channel');
@ -171,11 +169,11 @@ ui.logEntry(`Rejoining Channels....`);
if (JSON.parse(data.payload)[1][1] === 'content/json') {
handleProtocolMessages(channelName, data);
} else {
channels.addMessage(channelName, msg, data.data.sig, data.username)
channels.addMessage(channelName, msg, data.data.sig, data.username);
}
});
})
});
return;
}
if (cmd.split(' ')[0] === '/s') {
@ -187,13 +185,13 @@ ui.logEntry(`Rejoining Channels....`);
if(cmd.split(' ')[0] === '/msg') {
let destination = cmd.substr(5);
if (!(CONTACT_CODE_REGEXP.test(destination) || /^[a-z0-9A-Z\s]{4,}$/.test(destination))) {
if (!(CONTACT_CODE_REGEXP.test(destination) || (/^[a-z0-9A-Z\s]{4,}$/).test(destination))) {
ui.logEntry(`Invalid account`.red);
return;
}
// TODO:resolve ens username
const user = Object.values(channels.allUsers.users).find(x => x.username == destination);
const user = Object.values(channels.allUsers.users).find(x => x.username === destination);
if(user){
channels.addChannel(user.username, 'contact', {pubKey: user.pubkey});
channels.switchChannelIndex(channels.channels.length - 1);
@ -218,7 +216,7 @@ ui.logEntry(`Rejoining Channels....`);
// keep track of each channel typing sent for throttling purposes
let typingNotificationsTimestamp = {
}
};
ui.events.on('typing', (currentText) => {
// TODO: use async.cargo instead and/or a to avoid unnecessary requests
@ -230,7 +228,7 @@ ui.logEntry(`Rejoining Channels....`);
typingNotificationsTimestamp[channelName] = {
timeout: 0,
lastEvent: 0
}
};
}
let now = (new Date().getTime());

21
tsconfig.json Normal file
View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es2017", "dom"],
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"isolatedModules": true,
"resolveJsonModule": true,
"suppressImplicitAnyIndexErrors": true,
"esModuleInterop": true,
"typeRoots": ["node_modules/@types"],
"rootDir": ".",
"baseUrl": ".",
"paths": {
"*": ["./typings/*"]
}
},
"include": ["./src/**/*"]
}

17
tslint.json Normal file
View File

@ -0,0 +1,17 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"max-line-length": [true, 200],
"interface-name": [true, "never-prefix"],
"member-ordering": [false],
"no-var-requires": false,
"ordered-imports": false,
"no-empty": false,
"no-console": false
},
"rulesDirectory": []
}

4747
yarn.lock Normal file

File diff suppressed because it is too large Load Diff