Merge pull request #2 from status-im/pipeline

add dev pipeline; babel; linter; typescript support; readme
This commit is contained in:
Iuri Matias 2018-12-03 20:04:55 -05:00 committed by GitHub
commit 04f16d71fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 5257 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,52 @@
# 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
````
To run:
```
node dist/index.js
```
`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": "", "description": "",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "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": { "repository": {
"type": "git", "type": "git",
@ -17,9 +38,37 @@
}, },
"homepage": "https://github.com/status-im/status-x#readme", "homepage": "https://github.com/status-im/status-x#readme",
"dependencies": { "dependencies": {
"async": "^2.6.1",
"colors": "^1.3.2", "colors": "^1.3.2",
"neo-blessed": "^0.2.0", "neo-blessed": "^0.2.0",
"status-js-api": "^1.0.5" "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 { class Users {
constructor() { constructor() {
this.users = {} this.users = {};
} }
addUserOrUpdate(user) { addUserOrUpdate(user) {
this.users[user.pubkey] = user this.users[user.pubkey] = user;
} }
addOrUpdateUserKey(pubkey, username) { addOrUpdateUserKey(pubkey, username) {

View File

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