mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-11-04 18:07:27 +03:00 
			
		
		
		
	chore(cli): convert to TypeScript (#656)
* chore(cli): convert to TypeScript * Fix knex usage * Fix eslintrc * Ignore dist
This commit is contained in:
		
							parent
							
								
									ee52c29a8d
								
							
						
					
					
						commit
						c91471a41d
					
				
							
								
								
									
										2
									
								
								packages/redux-devtools-cli/.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/redux-devtools-cli/.eslintignore
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
 | 
					umd
 | 
				
			||||||
							
								
								
									
										21
									
								
								packages/redux-devtools-cli/.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/redux-devtools-cli/.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  extends: '../../.eslintrc',
 | 
				
			||||||
 | 
					  overrides: [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      files: ['*.ts', '*.tsx'],
 | 
				
			||||||
 | 
					      extends: '../../eslintrc.ts.base.json',
 | 
				
			||||||
 | 
					      parserOptions: {
 | 
				
			||||||
 | 
					        tsconfigRootDir: __dirname,
 | 
				
			||||||
 | 
					        project: ['./tsconfig.json'],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      files: ['test/*.ts', 'test/*.tsx'],
 | 
				
			||||||
 | 
					      extends: '../../eslintrc.ts.jest.base.json',
 | 
				
			||||||
 | 
					      parserOptions: {
 | 
				
			||||||
 | 
					        tsconfigRootDir: __dirname,
 | 
				
			||||||
 | 
					        project: ['./test/tsconfig.json'],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1,95 +0,0 @@
 | 
				
			||||||
var fs = require('fs');
 | 
					 | 
				
			||||||
var path = require('path');
 | 
					 | 
				
			||||||
var semver = require('semver');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var name = 'redux-devtools-cli';
 | 
					 | 
				
			||||||
var startFlag = '/* ' + name + ' start */';
 | 
					 | 
				
			||||||
var endFlag = '/* ' + name + ' end */';
 | 
					 | 
				
			||||||
var serverFlags = {
 | 
					 | 
				
			||||||
  'react-native': {
 | 
					 | 
				
			||||||
    '0.0.1': '    _server(argv, config, resolve, reject);',
 | 
					 | 
				
			||||||
    '0.31.0':
 | 
					 | 
				
			||||||
      "  runServer(args, config, () => console.log('\\nReact packager ready.\\n'));",
 | 
					 | 
				
			||||||
    '0.44.0-rc.0': '  runServer(args, config, startedCallback, readyCallback);',
 | 
					 | 
				
			||||||
    '0.46.0-rc.0':
 | 
					 | 
				
			||||||
      '  runServer(runServerArgs, configT, startedCallback, readyCallback);',
 | 
					 | 
				
			||||||
    '0.57.0': '  runServer(args, configT);',
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  'react-native-desktop': {
 | 
					 | 
				
			||||||
    '0.0.1': '    _server(argv, config, resolve, reject);',
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getModuleVersion(modulePath) {
 | 
					 | 
				
			||||||
  return JSON.parse(
 | 
					 | 
				
			||||||
    fs.readFileSync(path.join(modulePath, 'package.json'), 'utf-8')
 | 
					 | 
				
			||||||
  ).version;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getServerFlag(moduleName, version) {
 | 
					 | 
				
			||||||
  var flags = serverFlags[moduleName || 'react-native'];
 | 
					 | 
				
			||||||
  var versions = Object.keys(flags);
 | 
					 | 
				
			||||||
  var flag;
 | 
					 | 
				
			||||||
  for (var i = 0; i < versions.length; i++) {
 | 
					 | 
				
			||||||
    if (semver.gte(version, versions[i])) {
 | 
					 | 
				
			||||||
      flag = flags[versions[i]];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return flag;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.dir = 'local-cli/server';
 | 
					 | 
				
			||||||
exports.file = 'server.js';
 | 
					 | 
				
			||||||
exports.fullPath = path.join(exports.dir, exports.file);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.inject = function (modulePath, options, moduleName) {
 | 
					 | 
				
			||||||
  var filePath = path.join(modulePath, exports.fullPath);
 | 
					 | 
				
			||||||
  if (!fs.existsSync(filePath)) return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
 | 
					 | 
				
			||||||
  var code = [
 | 
					 | 
				
			||||||
    startFlag,
 | 
					 | 
				
			||||||
    '    require("' + name + '")(' + JSON.stringify(options) + ')',
 | 
					 | 
				
			||||||
    '      .then(_remotedev =>',
 | 
					 | 
				
			||||||
    '        _remotedev.on("ready", () => {',
 | 
					 | 
				
			||||||
    '          if (!_remotedev.portAlreadyUsed) console.log("-".repeat(80));',
 | 
					 | 
				
			||||||
    '      ' + serverFlag,
 | 
					 | 
				
			||||||
    '        })',
 | 
					 | 
				
			||||||
    '      );',
 | 
					 | 
				
			||||||
    endFlag,
 | 
					 | 
				
			||||||
  ].join('\n');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var serverCode = fs.readFileSync(filePath, 'utf-8');
 | 
					 | 
				
			||||||
  var start = serverCode.indexOf(startFlag); // already injected ?
 | 
					 | 
				
			||||||
  var end = serverCode.indexOf(endFlag) + endFlag.length;
 | 
					 | 
				
			||||||
  if (start === -1) {
 | 
					 | 
				
			||||||
    start = serverCode.indexOf(serverFlag);
 | 
					 | 
				
			||||||
    end = start + serverFlag.length;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  fs.writeFileSync(
 | 
					 | 
				
			||||||
    filePath,
 | 
					 | 
				
			||||||
    serverCode.substr(0, start) +
 | 
					 | 
				
			||||||
      code +
 | 
					 | 
				
			||||||
      serverCode.substr(end, serverCode.length)
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.revert = function (modulePath, moduleName) {
 | 
					 | 
				
			||||||
  var filePath = path.join(modulePath, exports.fullPath);
 | 
					 | 
				
			||||||
  if (!fs.existsSync(filePath)) return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
 | 
					 | 
				
			||||||
  var serverCode = fs.readFileSync(filePath, 'utf-8');
 | 
					 | 
				
			||||||
  var start = serverCode.indexOf(startFlag); // already injected ?
 | 
					 | 
				
			||||||
  var end = serverCode.indexOf(endFlag) + endFlag.length;
 | 
					 | 
				
			||||||
  if (start !== -1) {
 | 
					 | 
				
			||||||
    fs.writeFileSync(
 | 
					 | 
				
			||||||
      filePath,
 | 
					 | 
				
			||||||
      serverCode.substr(0, start) +
 | 
					 | 
				
			||||||
        serverFlag +
 | 
					 | 
				
			||||||
        serverCode.substr(end, serverCode.length)
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										93
									
								
								packages/redux-devtools-cli/bin/redux-devtools.js
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										93
									
								
								packages/redux-devtools-cli/bin/redux-devtools.js
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| 
						 | 
					@ -1,94 +1,3 @@
 | 
				
			||||||
#! /usr/bin/env node
 | 
					#! /usr/bin/env node
 | 
				
			||||||
var fs = require('fs');
 | 
					 | 
				
			||||||
var path = require('path');
 | 
					 | 
				
			||||||
var argv = require('minimist')(process.argv.slice(2));
 | 
					 | 
				
			||||||
var chalk = require('chalk');
 | 
					 | 
				
			||||||
var injectServer = require('./injectServer');
 | 
					 | 
				
			||||||
var getOptions = require('./../src/options');
 | 
					 | 
				
			||||||
var server = require('../index');
 | 
					 | 
				
			||||||
var openApp = require('./openApp');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
var options = getOptions(argv);
 | 
					require('../dist/bin/redux-devtools.js');
 | 
				
			||||||
 | 
					 | 
				
			||||||
function readFile(filePath) {
 | 
					 | 
				
			||||||
  return fs.readFileSync(path.resolve(process.cwd(), filePath), 'utf-8');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (argv.protocol === 'https') {
 | 
					 | 
				
			||||||
  argv.key = argv.key ? readFile(argv.key) : null;
 | 
					 | 
				
			||||||
  argv.cert = argv.cert ? readFile(argv.cert) : null;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function log(pass, msg) {
 | 
					 | 
				
			||||||
  var prefix = pass ? chalk.green.bgBlack('PASS') : chalk.red.bgBlack('FAIL');
 | 
					 | 
				
			||||||
  var color = pass ? chalk.blue : chalk.red;
 | 
					 | 
				
			||||||
  console.log(prefix, color(msg)); // eslint-disable-line no-console
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getModuleName(type) {
 | 
					 | 
				
			||||||
  switch (type) {
 | 
					 | 
				
			||||||
    case 'macos':
 | 
					 | 
				
			||||||
      return 'react-native-macos';
 | 
					 | 
				
			||||||
    // react-native-macos is renamed from react-native-desktop
 | 
					 | 
				
			||||||
    case 'desktop':
 | 
					 | 
				
			||||||
      return 'react-native-desktop';
 | 
					 | 
				
			||||||
    case 'reactnative':
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return 'react-native';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getModulePath(moduleName) {
 | 
					 | 
				
			||||||
  return path.join(process.cwd(), 'node_modules', moduleName);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getModule(type) {
 | 
					 | 
				
			||||||
  var moduleName = getModuleName(type);
 | 
					 | 
				
			||||||
  var modulePath = getModulePath(moduleName);
 | 
					 | 
				
			||||||
  if (type === 'desktop' && !fs.existsSync(modulePath)) {
 | 
					 | 
				
			||||||
    moduleName = getModuleName('macos');
 | 
					 | 
				
			||||||
    modulePath = getModulePath(moduleName);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    name: moduleName,
 | 
					 | 
				
			||||||
    path: modulePath,
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function injectRN(type, msg) {
 | 
					 | 
				
			||||||
  var module = getModule(type);
 | 
					 | 
				
			||||||
  var fn = type === 'revert' ? injectServer.revert : injectServer.inject;
 | 
					 | 
				
			||||||
  var pass = fn(module.path, options, module.name);
 | 
					 | 
				
			||||||
  log(
 | 
					 | 
				
			||||||
    pass,
 | 
					 | 
				
			||||||
    msg +
 | 
					 | 
				
			||||||
      (pass
 | 
					 | 
				
			||||||
        ? '.'
 | 
					 | 
				
			||||||
        : ', the file `' +
 | 
					 | 
				
			||||||
          path.join(module.name, injectServer.fullPath) +
 | 
					 | 
				
			||||||
          '` not found.')
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  process.exit(pass ? 0 : 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (argv.revert) {
 | 
					 | 
				
			||||||
  injectRN(
 | 
					 | 
				
			||||||
    argv.revert,
 | 
					 | 
				
			||||||
    'Revert injection of ReduxDevTools server from React Native local server'
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
if (argv.injectserver) {
 | 
					 | 
				
			||||||
  injectRN(
 | 
					 | 
				
			||||||
    argv.injectserver,
 | 
					 | 
				
			||||||
    'Inject ReduxDevTools server into React Native local server'
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
server(argv).then(function (r) {
 | 
					 | 
				
			||||||
  if (argv.open && argv.open !== 'false') {
 | 
					 | 
				
			||||||
    r.on('ready', function () {
 | 
					 | 
				
			||||||
      openApp(argv.open, options);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								packages/redux-devtools-cli/jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/redux-devtools-cli/jest.config.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  preset: 'ts-jest',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,12 @@
 | 
				
			||||||
  "name": "redux-devtools-cli",
 | 
					  "name": "redux-devtools-cli",
 | 
				
			||||||
  "version": "1.0.0-4",
 | 
					  "version": "1.0.0-4",
 | 
				
			||||||
  "description": "CLI for remote debugging with Redux DevTools.",
 | 
					  "description": "CLI for remote debugging with Redux DevTools.",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli",
 | 
				
			||||||
  "bin": {
 | 
					  "bugs": {
 | 
				
			||||||
    "redux-devtools": "bin/redux-devtools.js"
 | 
					    "url": "https://github.com/reduxjs/redux-devtools/issues"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
 | 
				
			||||||
  "files": [
 | 
					  "files": [
 | 
				
			||||||
    "bin",
 | 
					    "bin",
 | 
				
			||||||
    "src",
 | 
					    "src",
 | 
				
			||||||
| 
						 | 
					@ -13,25 +15,31 @@
 | 
				
			||||||
    "index.js",
 | 
					    "index.js",
 | 
				
			||||||
    "defaultDbOptions.json"
 | 
					    "defaultDbOptions.json"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "scripts": {
 | 
					  "main": "dist/index.js",
 | 
				
			||||||
    "start": "node ./bin/redux-devtools.js",
 | 
					  "types": "dist/index.d.ts",
 | 
				
			||||||
    "start:electron": "node ./bin/redux-devtools.js --open",
 | 
					  "bin": {
 | 
				
			||||||
    "test": "jest",
 | 
					    "redux-devtools": "bin/redux-devtools.js"
 | 
				
			||||||
    "prepublishOnly": "npm run test"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
    "url": "https://github.com/reduxjs/redux-devtools.git"
 | 
					    "url": "https://github.com/reduxjs/redux-devtools.git"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "build": "tsc && ncp ./src/api/schema_def.graphql ./dist/api/schema_def.graphql",
 | 
				
			||||||
 | 
					    "start": "node ./bin/redux-devtools.js",
 | 
				
			||||||
 | 
					    "start:electron": "node ./bin/redux-devtools.js --open",
 | 
				
			||||||
 | 
					    "clean": "rimraf dist",
 | 
				
			||||||
 | 
					    "test": "jest",
 | 
				
			||||||
 | 
					    "lint": "eslint . --ext .ts,.tsx",
 | 
				
			||||||
 | 
					    "lint:fix": "eslint . --ext .ts,.tsx --fix",
 | 
				
			||||||
 | 
					    "type-check": "tsc --noEmit",
 | 
				
			||||||
 | 
					    "type-check:watch": "npm run type-check -- --watch",
 | 
				
			||||||
 | 
					    "preversion": "npm run type-check && npm run lint && npm run test",
 | 
				
			||||||
 | 
					    "prepublishOnly": "npm run clean && npm run build"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  "engines": {
 | 
					  "engines": {
 | 
				
			||||||
    "node": ">=6.0.0"
 | 
					    "node": ">=10.0.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
 | 
					 | 
				
			||||||
  "license": "MIT",
 | 
					 | 
				
			||||||
  "bugs": {
 | 
					 | 
				
			||||||
    "url": "https://github.com/reduxjs/redux-devtools/issues"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "homepage": "https://github.com/reduxjs/redux-devtools",
 | 
					 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "apollo-server": "^2.18.2",
 | 
					    "apollo-server": "^2.18.2",
 | 
				
			||||||
    "apollo-server-express": "^2.18.2",
 | 
					    "apollo-server-express": "^2.18.2",
 | 
				
			||||||
| 
						 | 
					@ -42,7 +50,7 @@
 | 
				
			||||||
    "electron": "^9.2.0",
 | 
					    "electron": "^9.2.0",
 | 
				
			||||||
    "express": "^4.17.1",
 | 
					    "express": "^4.17.1",
 | 
				
			||||||
    "getport": "^0.1.0",
 | 
					    "getport": "^0.1.0",
 | 
				
			||||||
    "graphql": "^15.3.0",
 | 
					    "graphql": "^14.7.0",
 | 
				
			||||||
    "knex": "^0.19.5",
 | 
					    "knex": "^0.19.5",
 | 
				
			||||||
    "lodash": "^4.17.19",
 | 
					    "lodash": "^4.17.19",
 | 
				
			||||||
    "minimist": "^1.2.5",
 | 
					    "minimist": "^1.2.5",
 | 
				
			||||||
| 
						 | 
					@ -57,7 +65,13 @@
 | 
				
			||||||
    "uuid": "^8.3.0"
 | 
					    "uuid": "^8.3.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@types/cross-spawn": "^6.0.2",
 | 
				
			||||||
 | 
					    "@types/morgan": "^1.9.1",
 | 
				
			||||||
 | 
					    "@types/semver": "^7.3.4",
 | 
				
			||||||
 | 
					    "@types/supertest": "^2.0.10",
 | 
				
			||||||
 | 
					    "@types/uuid": "^8.3.0",
 | 
				
			||||||
    "jest": "^26.2.2",
 | 
					    "jest": "^26.2.2",
 | 
				
			||||||
 | 
					    "ncp": "^2.0.0",
 | 
				
			||||||
    "socketcluster-client": "^14.3.1",
 | 
					    "socketcluster-client": "^14.3.1",
 | 
				
			||||||
    "supertest": "^4.0.2"
 | 
					    "supertest": "^4.0.2"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +0,0 @@
 | 
				
			||||||
var makeExecutableSchema = require('apollo-server').makeExecutableSchema;
 | 
					 | 
				
			||||||
var requireSchema = require('../utils/requireSchema');
 | 
					 | 
				
			||||||
var schema = requireSchema('./schema_def.graphql', require);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var resolvers = {
 | 
					 | 
				
			||||||
  Query: {
 | 
					 | 
				
			||||||
    reports: function report(source, args, context) {
 | 
					 | 
				
			||||||
      return context.store.listAll();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    report: function report(source, args, context) {
 | 
					 | 
				
			||||||
      return context.store.get(args.id);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var executableSchema = makeExecutableSchema({
 | 
					 | 
				
			||||||
  typeDefs: schema,
 | 
					 | 
				
			||||||
  resolvers: resolvers,
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = executableSchema;
 | 
					 | 
				
			||||||
							
								
								
									
										33
									
								
								packages/redux-devtools-cli/src/api/schema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								packages/redux-devtools-cli/src/api/schema.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,33 @@
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import { makeExecutableSchema } from 'apollo-server';
 | 
				
			||||||
 | 
					import { Store } from '../store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const schema = fs
 | 
				
			||||||
 | 
					  .readFileSync(require.resolve('./schema_def.graphql'))
 | 
				
			||||||
 | 
					  .toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const resolvers = {
 | 
				
			||||||
 | 
					  Query: {
 | 
				
			||||||
 | 
					    reports: function report(
 | 
				
			||||||
 | 
					      source: unknown,
 | 
				
			||||||
 | 
					      args: unknown,
 | 
				
			||||||
 | 
					      context: { store: Store }
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					      return context.store.listAll();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    report: function report(
 | 
				
			||||||
 | 
					      source: unknown,
 | 
				
			||||||
 | 
					      args: { id: string },
 | 
				
			||||||
 | 
					      context: { store: Store }
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					      return context.store.get(args.id);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const executableSchema = makeExecutableSchema({
 | 
				
			||||||
 | 
					  typeDefs: schema,
 | 
				
			||||||
 | 
					  resolvers: resolvers,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default executableSchema;
 | 
				
			||||||
							
								
								
									
										104
									
								
								packages/redux-devtools-cli/src/bin/injectServer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								packages/redux-devtools-cli/src/bin/injectServer.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,104 @@
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import semver from 'semver';
 | 
				
			||||||
 | 
					import { Options } from '../options';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const name = 'redux-devtools-cli';
 | 
				
			||||||
 | 
					const startFlag = '/* ' + name + ' start */';
 | 
				
			||||||
 | 
					const endFlag = '/* ' + name + ' end */';
 | 
				
			||||||
 | 
					const serverFlags: { [moduleName: string]: { [version: string]: string } } = {
 | 
				
			||||||
 | 
					  'react-native': {
 | 
				
			||||||
 | 
					    '0.0.1': '    _server(argv, config, resolve, reject);',
 | 
				
			||||||
 | 
					    '0.31.0':
 | 
				
			||||||
 | 
					      "  runServer(args, config, () => console.log('\\nReact packager ready.\\n'));",
 | 
				
			||||||
 | 
					    '0.44.0-rc.0': '  runServer(args, config, startedCallback, readyCallback);',
 | 
				
			||||||
 | 
					    '0.46.0-rc.0':
 | 
				
			||||||
 | 
					      '  runServer(runServerArgs, configT, startedCallback, readyCallback);',
 | 
				
			||||||
 | 
					    '0.57.0': '  runServer(args, configT);',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'react-native-desktop': {
 | 
				
			||||||
 | 
					    '0.0.1': '    _server(argv, config, resolve, reject);',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getModuleVersion(modulePath: string) {
 | 
				
			||||||
 | 
					  return JSON.parse(
 | 
				
			||||||
 | 
					    fs.readFileSync(path.join(modulePath, 'package.json'), 'utf-8')
 | 
				
			||||||
 | 
					  ).version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getServerFlag(moduleName: string, version: string): string {
 | 
				
			||||||
 | 
					  const flags = serverFlags[moduleName || 'react-native'];
 | 
				
			||||||
 | 
					  const versions = Object.keys(flags);
 | 
				
			||||||
 | 
					  let flag;
 | 
				
			||||||
 | 
					  for (let i = 0; i < versions.length; i++) {
 | 
				
			||||||
 | 
					    if (semver.gte(version, versions[i])) {
 | 
				
			||||||
 | 
					      flag = flags[versions[i]];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return flag as string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const dir = 'local-cli/server';
 | 
				
			||||||
 | 
					export const file = 'server.js';
 | 
				
			||||||
 | 
					export const fullPath = path.join(exports.dir, exports.file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function inject(
 | 
				
			||||||
 | 
					  modulePath: string,
 | 
				
			||||||
 | 
					  options: Options,
 | 
				
			||||||
 | 
					  moduleName: string
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  const filePath = path.join(modulePath, exports.fullPath);
 | 
				
			||||||
 | 
					  if (!fs.existsSync(filePath)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
 | 
				
			||||||
 | 
					  const code = [
 | 
				
			||||||
 | 
					    startFlag,
 | 
				
			||||||
 | 
					    '    require("' + name + '")(' + JSON.stringify(options) + ')',
 | 
				
			||||||
 | 
					    '      .then(_remotedev =>',
 | 
				
			||||||
 | 
					    '        _remotedev.on("ready", () => {',
 | 
				
			||||||
 | 
					    '          if (!_remotedev.portAlreadyUsed) console.log("-".repeat(80));',
 | 
				
			||||||
 | 
					    '      ' + serverFlag,
 | 
				
			||||||
 | 
					    '        })',
 | 
				
			||||||
 | 
					    '      );',
 | 
				
			||||||
 | 
					    endFlag,
 | 
				
			||||||
 | 
					  ].join('\n');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const serverCode = fs.readFileSync(filePath, 'utf-8');
 | 
				
			||||||
 | 
					  let start = serverCode.indexOf(startFlag); // already injected ?
 | 
				
			||||||
 | 
					  let end = serverCode.indexOf(endFlag) + endFlag.length;
 | 
				
			||||||
 | 
					  if (start === -1) {
 | 
				
			||||||
 | 
					    start = serverCode.indexOf(serverFlag);
 | 
				
			||||||
 | 
					    end = start + serverFlag.length;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  fs.writeFileSync(
 | 
				
			||||||
 | 
					    filePath,
 | 
				
			||||||
 | 
					    serverCode.substr(0, start) +
 | 
				
			||||||
 | 
					      code +
 | 
				
			||||||
 | 
					      serverCode.substr(end, serverCode.length)
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function revert(
 | 
				
			||||||
 | 
					  modulePath: string,
 | 
				
			||||||
 | 
					  options: Options,
 | 
				
			||||||
 | 
					  moduleName: string
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  const filePath = path.join(modulePath, exports.fullPath);
 | 
				
			||||||
 | 
					  if (!fs.existsSync(filePath)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
 | 
				
			||||||
 | 
					  const serverCode = fs.readFileSync(filePath, 'utf-8');
 | 
				
			||||||
 | 
					  const start = serverCode.indexOf(startFlag); // already injected ?
 | 
				
			||||||
 | 
					  const end = serverCode.indexOf(endFlag) + endFlag.length;
 | 
				
			||||||
 | 
					  if (start !== -1) {
 | 
				
			||||||
 | 
					    fs.writeFileSync(
 | 
				
			||||||
 | 
					      filePath,
 | 
				
			||||||
 | 
					      serverCode.substr(0, start) +
 | 
				
			||||||
 | 
					        serverFlag +
 | 
				
			||||||
 | 
					        serverCode.substr(end, serverCode.length)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,13 @@
 | 
				
			||||||
var open = require('open');
 | 
					import open from 'open';
 | 
				
			||||||
var path = require('path');
 | 
					import path from 'path';
 | 
				
			||||||
var spawn = require('cross-spawn');
 | 
					import spawn from 'cross-spawn';
 | 
				
			||||||
 | 
					import { Options } from '../options';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function openApp(app, options) {
 | 
					export default function openApp(app: boolean | string, options: Options) {
 | 
				
			||||||
  if (app === true || app === 'electron') {
 | 
					  if (app === true || app === 'electron') {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      var port = options.port ? '--port=' + options.port : '';
 | 
					      const port = options.port ? `--port=${options.port}` : '';
 | 
				
			||||||
 | 
					      // eslint-disable-next-line @typescript-eslint/no-var-requires
 | 
				
			||||||
      spawn.sync(require('electron'), [
 | 
					      spawn.sync(require('electron'), [
 | 
				
			||||||
        path.join(__dirname, '..', 'app'),
 | 
					        path.join(__dirname, '..', 'app'),
 | 
				
			||||||
        port,
 | 
					        port,
 | 
				
			||||||
| 
						 | 
					@ -29,10 +31,9 @@ function openApp(app, options) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
  open(
 | 
					  open(
 | 
				
			||||||
    'http://localhost:' + options.port + '/',
 | 
					    `http://localhost:${options.port}/`,
 | 
				
			||||||
    app !== 'browser' ? { app: app } : undefined
 | 
					    app !== 'browser' ? { app: app as string } : undefined
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = openApp;
 | 
					 | 
				
			||||||
							
								
								
									
										97
									
								
								packages/redux-devtools-cli/src/bin/redux-devtools.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								packages/redux-devtools-cli/src/bin/redux-devtools.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,97 @@
 | 
				
			||||||
 | 
					#! /usr/bin/env node
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import parseArgs from 'minimist';
 | 
				
			||||||
 | 
					import chalk from 'chalk';
 | 
				
			||||||
 | 
					import * as injectServer from './injectServer';
 | 
				
			||||||
 | 
					import getOptions from '../options';
 | 
				
			||||||
 | 
					import server from '../index';
 | 
				
			||||||
 | 
					import openApp from './openApp';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const argv = parseArgs(process.argv.slice(2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const options = getOptions(argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function readFile(filePath: string) {
 | 
				
			||||||
 | 
					  return fs.readFileSync(path.resolve(process.cwd(), filePath), 'utf-8');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (argv.protocol === 'https') {
 | 
				
			||||||
 | 
					  argv.key = argv.key ? readFile(argv.key) : null;
 | 
				
			||||||
 | 
					  argv.cert = argv.cert ? readFile(argv.cert) : null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function log(pass: boolean, msg: string) {
 | 
				
			||||||
 | 
					  const prefix = pass ? chalk.green.bgBlack('PASS') : chalk.red.bgBlack('FAIL');
 | 
				
			||||||
 | 
					  const color = pass ? chalk.blue : chalk.red;
 | 
				
			||||||
 | 
					  console.log(prefix, color(msg)); // eslint-disable-line no-console
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getModuleName(type: string) {
 | 
				
			||||||
 | 
					  switch (type) {
 | 
				
			||||||
 | 
					    case 'macos':
 | 
				
			||||||
 | 
					      return 'react-native-macos';
 | 
				
			||||||
 | 
					    // react-native-macos is renamed from react-native-desktop
 | 
				
			||||||
 | 
					    case 'desktop':
 | 
				
			||||||
 | 
					      return 'react-native-desktop';
 | 
				
			||||||
 | 
					    case 'reactnative':
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return 'react-native';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getModulePath(moduleName: string) {
 | 
				
			||||||
 | 
					  return path.join(process.cwd(), 'node_modules', moduleName);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getModule(type: string) {
 | 
				
			||||||
 | 
					  let moduleName = getModuleName(type);
 | 
				
			||||||
 | 
					  let modulePath = getModulePath(moduleName);
 | 
				
			||||||
 | 
					  if (type === 'desktop' && !fs.existsSync(modulePath)) {
 | 
				
			||||||
 | 
					    moduleName = getModuleName('macos');
 | 
				
			||||||
 | 
					    modulePath = getModulePath(moduleName);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    name: moduleName,
 | 
				
			||||||
 | 
					    path: modulePath,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function injectRN(type: string, msg: string) {
 | 
				
			||||||
 | 
					  const module = getModule(type);
 | 
				
			||||||
 | 
					  const fn = type === 'revert' ? injectServer.revert : injectServer.inject;
 | 
				
			||||||
 | 
					  const pass = fn(module.path, options, module.name);
 | 
				
			||||||
 | 
					  log(
 | 
				
			||||||
 | 
					    pass,
 | 
				
			||||||
 | 
					    msg +
 | 
				
			||||||
 | 
					      (pass
 | 
				
			||||||
 | 
					        ? '.'
 | 
				
			||||||
 | 
					        : ', the file `' +
 | 
				
			||||||
 | 
					          path.join(module.name, injectServer.fullPath) +
 | 
				
			||||||
 | 
					          '` not found.')
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  process.exit(pass ? 0 : 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (argv.revert) {
 | 
				
			||||||
 | 
					  injectRN(
 | 
				
			||||||
 | 
					    argv.revert,
 | 
				
			||||||
 | 
					    'Revert injection of ReduxDevTools server from React Native local server'
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					if (argv.injectserver) {
 | 
				
			||||||
 | 
					  injectRN(
 | 
				
			||||||
 | 
					    argv.injectserver,
 | 
				
			||||||
 | 
					    'Inject ReduxDevTools server into React Native local server'
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					server(argv).then(function (r) {
 | 
				
			||||||
 | 
					  if (argv.open && argv.open !== 'false') {
 | 
				
			||||||
 | 
					    r.on('ready', function () {
 | 
				
			||||||
 | 
					      openApp(argv.open, options);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
var path = require('path');
 | 
					import path from 'path';
 | 
				
			||||||
var knexModule = require('knex');
 | 
					import knexModule from 'knex';
 | 
				
			||||||
 | 
					import { SCServer } from 'socketcluster-server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function connector(options) {
 | 
					export default function connector(options: SCServer.SCServerOptions) {
 | 
				
			||||||
  var dbOptions = options.dbOptions;
 | 
					  const dbOptions = options.dbOptions;
 | 
				
			||||||
  dbOptions.useNullAsDefault = true;
 | 
					  dbOptions.useNullAsDefault = true;
 | 
				
			||||||
  if (!dbOptions.migrate) {
 | 
					  if (!dbOptions.migrate) {
 | 
				
			||||||
    return knexModule(dbOptions);
 | 
					    return knexModule(dbOptions);
 | 
				
			||||||
| 
						 | 
					@ -10,13 +11,13 @@ module.exports = function connector(options) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dbOptions.migrations = { directory: path.resolve(__dirname, 'migrations') };
 | 
					  dbOptions.migrations = { directory: path.resolve(__dirname, 'migrations') };
 | 
				
			||||||
  dbOptions.seeds = { directory: path.resolve(__dirname, 'seeds') };
 | 
					  dbOptions.seeds = { directory: path.resolve(__dirname, 'seeds') };
 | 
				
			||||||
  var knex = knexModule(dbOptions);
 | 
					  const knex = knexModule(dbOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* eslint-disable no-console */
 | 
					  /* eslint-disable no-console */
 | 
				
			||||||
  knex.migrate
 | 
					  knex.migrate
 | 
				
			||||||
    .latest()
 | 
					    .latest({ loadExtensions: ['.js'] })
 | 
				
			||||||
    .then(function () {
 | 
					    .then(function () {
 | 
				
			||||||
      return knex.seed.run();
 | 
					      return knex.seed.run({ loadExtensions: ['.js'] });
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .then(function () {
 | 
					    .then(function () {
 | 
				
			||||||
      console.log('   \x1b[0;32m[Done]\x1b[0m Migrations are finished\n');
 | 
					      console.log('   \x1b[0;32m[Done]\x1b[0m Migrations are finished\n');
 | 
				
			||||||
| 
						 | 
					@ -27,4 +28,4 @@ module.exports = function connector(options) {
 | 
				
			||||||
  /* eslint-enable no-console */
 | 
					  /* eslint-enable no-console */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return knex;
 | 
					  return knex;
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,6 @@
 | 
				
			||||||
exports.up = function (knex) {
 | 
					import type knexModule from 'knex';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function up(knex: knexModule) {
 | 
				
			||||||
  return Promise.all([
 | 
					  return Promise.all([
 | 
				
			||||||
    knex.schema.createTable('remotedev_reports', function (table) {
 | 
					    knex.schema.createTable('remotedev_reports', function (table) {
 | 
				
			||||||
      table.uuid('id').primary();
 | 
					      table.uuid('id').primary();
 | 
				
			||||||
| 
						 | 
					@ -75,11 +77,11 @@ exports.up = function (knex) {
 | 
				
			||||||
        .onUpdate('CASCADE');
 | 
					        .onUpdate('CASCADE');
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
  ]);
 | 
					  ]);
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exports.down = function (knex) {
 | 
					export function down(knex: knexModule) {
 | 
				
			||||||
  return Promise.all([
 | 
					  return Promise.all([
 | 
				
			||||||
    knex.schema.dropTable('remotedev_reports'),
 | 
					    knex.schema.dropTable('remotedev_reports'),
 | 
				
			||||||
    knex.schema.dropTable('remotedev_apps'),
 | 
					    knex.schema.dropTable('remotedev_apps'),
 | 
				
			||||||
  ]);
 | 
					  ]);
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,6 @@
 | 
				
			||||||
exports.seed = function (knex) {
 | 
					import type knexModule from 'knex';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function seed(knex: knexModule) {
 | 
				
			||||||
  return Promise.all([knex('remotedev_apps').del()]).then(function () {
 | 
					  return Promise.all([knex('remotedev_apps').del()]).then(function () {
 | 
				
			||||||
    return Promise.all([
 | 
					    return Promise.all([
 | 
				
			||||||
      knex('remotedev_apps').insert({
 | 
					      knex('remotedev_apps').insert({
 | 
				
			||||||
| 
						 | 
					@ -7,4 +9,4 @@ exports.seed = function (knex) {
 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								packages/redux-devtools-cli/src/getport.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								packages/redux-devtools-cli/src/getport.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					declare module 'getport' {
 | 
				
			||||||
 | 
					  export default function getport(
 | 
				
			||||||
 | 
					    start: number,
 | 
				
			||||||
 | 
					    callback: (e: Error | undefined, port: number) => void
 | 
				
			||||||
 | 
					  ): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,29 @@
 | 
				
			||||||
var getPort = require('getport');
 | 
					import getPort from 'getport';
 | 
				
			||||||
var SocketCluster = require('socketcluster');
 | 
					import SocketCluster from 'socketcluster';
 | 
				
			||||||
var getOptions = require('./src/options');
 | 
					import getOptions, { Options } from './options';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// var LOG_LEVEL_NONE = 0;
 | 
					// var LOG_LEVEL_NONE = 0;
 | 
				
			||||||
var LOG_LEVEL_ERROR = 1;
 | 
					const LOG_LEVEL_ERROR = 1;
 | 
				
			||||||
var LOG_LEVEL_WARN = 2;
 | 
					const LOG_LEVEL_WARN = 2;
 | 
				
			||||||
var LOG_LEVEL_INFO = 3;
 | 
					const LOG_LEVEL_INFO = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function (argv) {
 | 
					export interface ExtendedOptions extends Options {
 | 
				
			||||||
  var options = Object.assign(getOptions(argv), {
 | 
					  workerController: string;
 | 
				
			||||||
    workerController: __dirname + '/src/worker.js',
 | 
					  allowClientPublish: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function (argv: {
 | 
				
			||||||
 | 
					  [arg: string]: any;
 | 
				
			||||||
 | 
					}): Promise<{
 | 
				
			||||||
 | 
					  portAlreadyUsed?: boolean;
 | 
				
			||||||
 | 
					  on: (status: 'ready', cb: () => void) => void;
 | 
				
			||||||
 | 
					}> {
 | 
				
			||||||
 | 
					  const options = Object.assign(getOptions(argv), {
 | 
				
			||||||
 | 
					    workerController: __dirname + '/worker.js',
 | 
				
			||||||
    allowClientPublish: false,
 | 
					    allowClientPublish: false,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  var port = options.port;
 | 
					  const port = options.port;
 | 
				
			||||||
  var logLevel =
 | 
					  const logLevel =
 | 
				
			||||||
    options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
 | 
					    options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
 | 
				
			||||||
  return new Promise(function (resolve) {
 | 
					  return new Promise(function (resolve) {
 | 
				
			||||||
    // Check port already used
 | 
					    // Check port already used
 | 
				
			||||||
| 
						 | 
					@ -27,13 +37,11 @@ module.exports = function (argv) {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (port !== p) {
 | 
					      if (port !== p) {
 | 
				
			||||||
        if (logLevel >= LOG_LEVEL_WARN) {
 | 
					        if (logLevel >= LOG_LEVEL_WARN) {
 | 
				
			||||||
          console.log(
 | 
					          console.log(`[ReduxDevTools] Server port ${port} is already used.`);
 | 
				
			||||||
            '[ReduxDevTools] Server port ' + port + ' is already used.'
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        resolve({
 | 
					        resolve({
 | 
				
			||||||
          portAlreadyUsed: true,
 | 
					          portAlreadyUsed: true,
 | 
				
			||||||
          on: function (status, cb) {
 | 
					          on: function (status: string, cb: () => void) {
 | 
				
			||||||
            cb();
 | 
					            cb();
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
| 
						 | 
					@ -47,4 +55,4 @@ module.exports = function (argv) {
 | 
				
			||||||
      /* eslint-enable no-console */
 | 
					      /* eslint-enable no-console */
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,8 @@
 | 
				
			||||||
var ApolloServer = require('apollo-server-express').ApolloServer;
 | 
					import { ApolloServer } from 'apollo-server-express';
 | 
				
			||||||
var schema = require('../api/schema');
 | 
					import schema from '../api/schema';
 | 
				
			||||||
 | 
					import { Store } from '../store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function (store) {
 | 
					export default function (store: Store) {
 | 
				
			||||||
  return new ApolloServer({
 | 
					  return new ApolloServer({
 | 
				
			||||||
    schema,
 | 
					    schema,
 | 
				
			||||||
    context: {
 | 
					    context: {
 | 
				
			||||||
| 
						 | 
					@ -24,4 +25,4 @@ module.exports = function (store) {
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,33 +0,0 @@
 | 
				
			||||||
var path = require('path');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = function getOptions(argv) {
 | 
					 | 
				
			||||||
  var dbOptions = argv.dbOptions;
 | 
					 | 
				
			||||||
  if (typeof dbOptions === 'string') {
 | 
					 | 
				
			||||||
    dbOptions = require(path.resolve(process.cwd(), argv.dbOptions));
 | 
					 | 
				
			||||||
  } else if (typeof dbOptions === 'undefined') {
 | 
					 | 
				
			||||||
    dbOptions = require('../defaultDbOptions.json');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    host: argv.hostname || process.env.npm_package_remotedev_hostname || null,
 | 
					 | 
				
			||||||
    port: Number(argv.port || process.env.npm_package_remotedev_port) || 8000,
 | 
					 | 
				
			||||||
    protocol:
 | 
					 | 
				
			||||||
      argv.protocol || process.env.npm_package_remotedev_protocol || 'http',
 | 
					 | 
				
			||||||
    protocolOptions: !(argv.protocol === 'https')
 | 
					 | 
				
			||||||
      ? null
 | 
					 | 
				
			||||||
      : {
 | 
					 | 
				
			||||||
          key: argv.key || process.env.npm_package_remotedev_key || null,
 | 
					 | 
				
			||||||
          cert: argv.cert || process.env.npm_package_remotedev_cert || null,
 | 
					 | 
				
			||||||
          passphrase:
 | 
					 | 
				
			||||||
            argv.passphrase ||
 | 
					 | 
				
			||||||
            process.env.npm_package_remotedev_passphrase ||
 | 
					 | 
				
			||||||
            null,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    dbOptions: dbOptions,
 | 
					 | 
				
			||||||
    maxRequestBody: argv.passphrase || '16mb',
 | 
					 | 
				
			||||||
    logHTTPRequests: argv.logHTTPRequests,
 | 
					 | 
				
			||||||
    logLevel: argv.logLevel || 3,
 | 
					 | 
				
			||||||
    wsEngine:
 | 
					 | 
				
			||||||
      argv.wsEngine || process.env.npm_package_remotedev_wsengine || 'ws',
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										63
									
								
								packages/redux-devtools-cli/src/options.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								packages/redux-devtools-cli/src/options.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface ProtocolOptions {
 | 
				
			||||||
 | 
					  key: string | undefined;
 | 
				
			||||||
 | 
					  cert: string | undefined;
 | 
				
			||||||
 | 
					  passphrase: string | undefined;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface DbOptions {
 | 
				
			||||||
 | 
					  client: string;
 | 
				
			||||||
 | 
					  connection: {
 | 
				
			||||||
 | 
					    filename: string;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  useNullAsDefault: boolean;
 | 
				
			||||||
 | 
					  debug: boolean;
 | 
				
			||||||
 | 
					  migrate: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Options {
 | 
				
			||||||
 | 
					  host: string | undefined;
 | 
				
			||||||
 | 
					  port: number;
 | 
				
			||||||
 | 
					  protocol: 'http' | 'https';
 | 
				
			||||||
 | 
					  protocolOptions: ProtocolOptions | undefined;
 | 
				
			||||||
 | 
					  dbOptions: DbOptions;
 | 
				
			||||||
 | 
					  maxRequestBody: string;
 | 
				
			||||||
 | 
					  logHTTPRequests?: boolean;
 | 
				
			||||||
 | 
					  logLevel: 0 | 1 | 3 | 2;
 | 
				
			||||||
 | 
					  wsEngine: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function getOptions(argv: { [arg: string]: any }): Options {
 | 
				
			||||||
 | 
					  let dbOptions = argv.dbOptions;
 | 
				
			||||||
 | 
					  if (typeof dbOptions === 'string') {
 | 
				
			||||||
 | 
					    dbOptions = require(path.resolve(process.cwd(), argv.dbOptions));
 | 
				
			||||||
 | 
					  } else if (typeof dbOptions === 'undefined') {
 | 
				
			||||||
 | 
					    dbOptions = require('../defaultDbOptions.json');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    host:
 | 
				
			||||||
 | 
					      argv.hostname || process.env.npm_package_remotedev_hostname || undefined,
 | 
				
			||||||
 | 
					    port: Number(argv.port || process.env.npm_package_remotedev_port) || 8000,
 | 
				
			||||||
 | 
					    protocol:
 | 
				
			||||||
 | 
					      argv.protocol || process.env.npm_package_remotedev_protocol || 'http',
 | 
				
			||||||
 | 
					    protocolOptions: !(argv.protocol === 'https')
 | 
				
			||||||
 | 
					      ? undefined
 | 
				
			||||||
 | 
					      : {
 | 
				
			||||||
 | 
					          key: argv.key || process.env.npm_package_remotedev_key || undefined,
 | 
				
			||||||
 | 
					          cert:
 | 
				
			||||||
 | 
					            argv.cert || process.env.npm_package_remotedev_cert || undefined,
 | 
				
			||||||
 | 
					          passphrase:
 | 
				
			||||||
 | 
					            argv.passphrase ||
 | 
				
			||||||
 | 
					            process.env.npm_package_remotedev_passphrase ||
 | 
				
			||||||
 | 
					            undefined,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    dbOptions: dbOptions,
 | 
				
			||||||
 | 
					    maxRequestBody: argv.passphrase || '16mb',
 | 
				
			||||||
 | 
					    logHTTPRequests: argv.logHTTPRequests,
 | 
				
			||||||
 | 
					    logLevel: argv.logLevel || 3,
 | 
				
			||||||
 | 
					    wsEngine:
 | 
				
			||||||
 | 
					      argv.wsEngine || process.env.npm_package_remotedev_wsengine || 'ws',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,15 @@
 | 
				
			||||||
var path = require('path');
 | 
					import path from 'path';
 | 
				
			||||||
var express = require('express');
 | 
					import express from 'express';
 | 
				
			||||||
var morgan = require('morgan');
 | 
					import morgan from 'morgan';
 | 
				
			||||||
var bodyParser = require('body-parser');
 | 
					import bodyParser from 'body-parser';
 | 
				
			||||||
var cors = require('cors');
 | 
					import cors from 'cors';
 | 
				
			||||||
var graphqlMiddleware = require('./middleware/graphql');
 | 
					import { SCServer } from 'socketcluster-server';
 | 
				
			||||||
 | 
					import graphqlMiddleware from './middleware/graphql';
 | 
				
			||||||
 | 
					import { ReportBaseFields, Store } from './store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var app = express.Router();
 | 
					const app = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function serveUmdModule(name) {
 | 
					function serveUmdModule(name: string) {
 | 
				
			||||||
  app.use(
 | 
					  app.use(
 | 
				
			||||||
    express.static(
 | 
					    express.static(
 | 
				
			||||||
      path.dirname(require.resolve(name + '/package.json')) + '/umd'
 | 
					      path.dirname(require.resolve(name + '/package.json')) + '/umd'
 | 
				
			||||||
| 
						 | 
					@ -15,9 +17,13 @@ function serveUmdModule(name) {
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function routes(options, store, scServer) {
 | 
					function routes(
 | 
				
			||||||
  var limit = options.maxRequestBody;
 | 
					  options: SCServer.SCServerOptions,
 | 
				
			||||||
  var logHTTPRequests = options.logHTTPRequests;
 | 
					  store: Store,
 | 
				
			||||||
 | 
					  scServer: SCServer
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  const limit = options.maxRequestBody;
 | 
				
			||||||
 | 
					  const logHTTPRequests = options.logHTTPRequests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (logHTTPRequests) {
 | 
					  if (logHTTPRequests) {
 | 
				
			||||||
    if (typeof logHTTPRequests === 'object')
 | 
					    if (typeof logHTTPRequests === 'object')
 | 
				
			||||||
| 
						 | 
					@ -25,14 +31,16 @@ function routes(options, store, scServer) {
 | 
				
			||||||
    else app.use(morgan('combined'));
 | 
					    else app.use(morgan('combined'));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  graphqlMiddleware(store).applyMiddleware({ app });
 | 
					  graphqlMiddleware(store).applyMiddleware({ app } as {
 | 
				
			||||||
 | 
					    app: express.Application;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  serveUmdModule('react');
 | 
					  serveUmdModule('react');
 | 
				
			||||||
  serveUmdModule('react-dom');
 | 
					  serveUmdModule('react-dom');
 | 
				
			||||||
  serveUmdModule('redux-devtools-core');
 | 
					  serveUmdModule('redux-devtools-core');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  app.get('/port.js', function (req, res) {
 | 
					  app.get('/port.js', function (req, res) {
 | 
				
			||||||
    res.send('reduxDevToolsPort = ' + options.port);
 | 
					    res.send(`reduxDevToolsPort = ${options.port!}`);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  app.get('*', function (req, res) {
 | 
					  app.get('*', function (req, res) {
 | 
				
			||||||
    res.sendFile(path.join(__dirname, '../app/index.html'));
 | 
					    res.sendFile(path.join(__dirname, '../app/index.html'));
 | 
				
			||||||
| 
						 | 
					@ -71,7 +79,10 @@ function routes(options, store, scServer) {
 | 
				
			||||||
        store
 | 
					        store
 | 
				
			||||||
          .add(req.body)
 | 
					          .add(req.body)
 | 
				
			||||||
          .then(function (r) {
 | 
					          .then(function (r) {
 | 
				
			||||||
            res.send({ id: r.id, error: r.error });
 | 
					            res.send({
 | 
				
			||||||
 | 
					              id: (r as ReportBaseFields).id,
 | 
				
			||||||
 | 
					              error: (r as { error: string }).error,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
            scServer.exchange.publish('report', {
 | 
					            scServer.exchange.publish('report', {
 | 
				
			||||||
              type: 'add',
 | 
					              type: 'add',
 | 
				
			||||||
              data: r,
 | 
					              data: r,
 | 
				
			||||||
| 
						 | 
					@ -86,4 +97,4 @@ function routes(options, store, scServer) {
 | 
				
			||||||
  return app;
 | 
					  return app;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = routes;
 | 
					export default routes;
 | 
				
			||||||
| 
						 | 
					@ -1,106 +0,0 @@
 | 
				
			||||||
var { v4: uuidV4 } = require('uuid');
 | 
					 | 
				
			||||||
var pick = require('lodash/pick');
 | 
					 | 
				
			||||||
var connector = require('./db/connector');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var reports = 'remotedev_reports';
 | 
					 | 
				
			||||||
// var payloads = 'remotedev_payloads';
 | 
					 | 
				
			||||||
var knex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var baseFields = ['id', 'title', 'added'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function error(msg) {
 | 
					 | 
				
			||||||
  return new Promise(function (resolve) {
 | 
					 | 
				
			||||||
    return resolve({ error: msg });
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function list(query, fields) {
 | 
					 | 
				
			||||||
  var r = knex.select(fields || baseFields).from(reports);
 | 
					 | 
				
			||||||
  if (query) return r.where(query);
 | 
					 | 
				
			||||||
  return r;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function listAll(query) {
 | 
					 | 
				
			||||||
  var r = knex.select().from(reports);
 | 
					 | 
				
			||||||
  if (query) return r.where(query);
 | 
					 | 
				
			||||||
  return r;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function get(id) {
 | 
					 | 
				
			||||||
  if (!id) return error('No id specified.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return knex(reports).where('id', id).first();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function add(data) {
 | 
					 | 
				
			||||||
  if (!data.type || !data.payload) {
 | 
					 | 
				
			||||||
    return error("Required parameters aren't specified.");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (data.type !== 'ACTIONS' && data.type !== 'STATE') {
 | 
					 | 
				
			||||||
    return error('Type ' + data.type + ' is not supported yet.');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var reportId = uuidV4();
 | 
					 | 
				
			||||||
  var report = {
 | 
					 | 
				
			||||||
    id: reportId,
 | 
					 | 
				
			||||||
    type: data.type,
 | 
					 | 
				
			||||||
    title:
 | 
					 | 
				
			||||||
      data.title || (data.exception && data.exception.message) || data.action,
 | 
					 | 
				
			||||||
    description: data.description,
 | 
					 | 
				
			||||||
    action: data.action,
 | 
					 | 
				
			||||||
    payload: data.payload,
 | 
					 | 
				
			||||||
    preloadedState: data.preloadedState,
 | 
					 | 
				
			||||||
    screenshot: data.screenshot,
 | 
					 | 
				
			||||||
    version: data.version,
 | 
					 | 
				
			||||||
    userAgent: data.userAgent,
 | 
					 | 
				
			||||||
    user: data.user,
 | 
					 | 
				
			||||||
    userId: typeof data.user === 'object' ? data.user.id : data.user,
 | 
					 | 
				
			||||||
    instanceId: data.instanceId,
 | 
					 | 
				
			||||||
    meta: data.meta,
 | 
					 | 
				
			||||||
    exception: composeException(data.exception),
 | 
					 | 
				
			||||||
    added: new Date().toISOString(),
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  if (data.appId) report.appId = data.appId; // TODO check if the id exists and we have access to link it
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  var payload = {
 | 
					 | 
				
			||||||
    id: uuid.v4(),
 | 
					 | 
				
			||||||
    reportId: reportId,
 | 
					 | 
				
			||||||
    state: data.payload
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return knex
 | 
					 | 
				
			||||||
    .insert(report)
 | 
					 | 
				
			||||||
    .into(reports)
 | 
					 | 
				
			||||||
    .then(function () {
 | 
					 | 
				
			||||||
      return byBaseFields(report);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function byBaseFields(data) {
 | 
					 | 
				
			||||||
  return pick(data, baseFields);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function createStore(options) {
 | 
					 | 
				
			||||||
  knex = connector(options);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    list: list,
 | 
					 | 
				
			||||||
    listAll: listAll,
 | 
					 | 
				
			||||||
    get: get,
 | 
					 | 
				
			||||||
    add: add,
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function composeException(exception) {
 | 
					 | 
				
			||||||
  var message = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (exception) {
 | 
					 | 
				
			||||||
    message = 'Exception thrown: ';
 | 
					 | 
				
			||||||
    if (exception.message) message += exception.message;
 | 
					 | 
				
			||||||
    if (exception.stack) message += '\n' + exception.stack;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return message;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = createStore;
 | 
					 | 
				
			||||||
							
								
								
									
										164
									
								
								packages/redux-devtools-cli/src/store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								packages/redux-devtools-cli/src/store.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,164 @@
 | 
				
			||||||
 | 
					import { v4 as uuidV4 } from 'uuid';
 | 
				
			||||||
 | 
					import pick from 'lodash/pick';
 | 
				
			||||||
 | 
					import { SCServer } from 'socketcluster-server';
 | 
				
			||||||
 | 
					import knexModule from 'knex';
 | 
				
			||||||
 | 
					import connector from './db/connector';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const reports = 'remotedev_reports';
 | 
				
			||||||
 | 
					// var payloads = 'remotedev_payloads';
 | 
				
			||||||
 | 
					let knex: knexModule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const baseFields = ['id', 'title', 'added'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function error(msg: string): Promise<{ error: string }> {
 | 
				
			||||||
 | 
					  return new Promise(function (resolve) {
 | 
				
			||||||
 | 
					    return resolve({ error: msg });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReportType = 'STATE' | 'ACTION' | 'STATES' | 'ACTIONS';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Report {
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  type: ReportType | null;
 | 
				
			||||||
 | 
					  title: string | null;
 | 
				
			||||||
 | 
					  description: string | null;
 | 
				
			||||||
 | 
					  action: string | null;
 | 
				
			||||||
 | 
					  payload: string;
 | 
				
			||||||
 | 
					  preloadedState: string | null;
 | 
				
			||||||
 | 
					  screenshot: string | null;
 | 
				
			||||||
 | 
					  userAgent: string | null;
 | 
				
			||||||
 | 
					  version: string | null;
 | 
				
			||||||
 | 
					  userId: string | null;
 | 
				
			||||||
 | 
					  user: string | null;
 | 
				
			||||||
 | 
					  meta: string | null;
 | 
				
			||||||
 | 
					  exception: string | null;
 | 
				
			||||||
 | 
					  instanceId: string | null;
 | 
				
			||||||
 | 
					  added: string | null;
 | 
				
			||||||
 | 
					  appId?: string | null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReportBaseFields {
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  title: string | null;
 | 
				
			||||||
 | 
					  added: string | null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function list(query?: unknown, fields?: string[]): Promise<ReportBaseFields[]> {
 | 
				
			||||||
 | 
					  const r = knex.select(fields || baseFields).from(reports);
 | 
				
			||||||
 | 
					  if (query) return r.where(query);
 | 
				
			||||||
 | 
					  return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function listAll(query: unknown): Promise<Report[]> {
 | 
				
			||||||
 | 
					  const r = knex.select().from(reports);
 | 
				
			||||||
 | 
					  if (query) return r.where(query);
 | 
				
			||||||
 | 
					  return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function get(id: string): Promise<Report | { error: string }> {
 | 
				
			||||||
 | 
					  if (!id) return error('No id specified.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return knex(reports).where('id', id).first();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface AddData {
 | 
				
			||||||
 | 
					  type: ReportType | null;
 | 
				
			||||||
 | 
					  title: string | null;
 | 
				
			||||||
 | 
					  description: string | null;
 | 
				
			||||||
 | 
					  action: string | null;
 | 
				
			||||||
 | 
					  payload: string;
 | 
				
			||||||
 | 
					  preloadedState: string | null;
 | 
				
			||||||
 | 
					  screenshot: string | null;
 | 
				
			||||||
 | 
					  version: string | null;
 | 
				
			||||||
 | 
					  userAgent: string | null;
 | 
				
			||||||
 | 
					  userId: string | null;
 | 
				
			||||||
 | 
					  user: { id: string } | string | null;
 | 
				
			||||||
 | 
					  instanceId: string | null;
 | 
				
			||||||
 | 
					  meta: string | null;
 | 
				
			||||||
 | 
					  exception?: Error;
 | 
				
			||||||
 | 
					  appId?: string | null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function add(data: AddData): Promise<ReportBaseFields | { error: string }> {
 | 
				
			||||||
 | 
					  if (!data.type || !data.payload) {
 | 
				
			||||||
 | 
					    return error("Required parameters aren't specified.");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (data.type !== 'ACTIONS' && data.type !== 'STATE') {
 | 
				
			||||||
 | 
					    return error('Type ' + data.type + ' is not supported yet.');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const reportId = uuidV4();
 | 
				
			||||||
 | 
					  const report: Report = {
 | 
				
			||||||
 | 
					    id: reportId,
 | 
				
			||||||
 | 
					    type: data.type,
 | 
				
			||||||
 | 
					    title:
 | 
				
			||||||
 | 
					      data.title || (data.exception && data.exception.message) || data.action,
 | 
				
			||||||
 | 
					    description: data.description,
 | 
				
			||||||
 | 
					    action: data.action,
 | 
				
			||||||
 | 
					    payload: data.payload,
 | 
				
			||||||
 | 
					    preloadedState: data.preloadedState,
 | 
				
			||||||
 | 
					    screenshot: data.screenshot,
 | 
				
			||||||
 | 
					    version: data.version,
 | 
				
			||||||
 | 
					    userAgent: data.userAgent,
 | 
				
			||||||
 | 
					    user: data.user as string,
 | 
				
			||||||
 | 
					    userId:
 | 
				
			||||||
 | 
					      typeof data.user === 'object'
 | 
				
			||||||
 | 
					        ? (data.user as { id: string }).id
 | 
				
			||||||
 | 
					        : data.user,
 | 
				
			||||||
 | 
					    instanceId: data.instanceId,
 | 
				
			||||||
 | 
					    meta: data.meta,
 | 
				
			||||||
 | 
					    exception: composeException(data.exception),
 | 
				
			||||||
 | 
					    added: new Date().toISOString(),
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (data.appId) report.appId = data.appId; // TODO check if the id exists and we have access to link it
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					  var payload = {
 | 
				
			||||||
 | 
					    id: uuid.v4(),
 | 
				
			||||||
 | 
					    reportId: reportId,
 | 
				
			||||||
 | 
					    state: data.payload
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return knex
 | 
				
			||||||
 | 
					    .insert(report)
 | 
				
			||||||
 | 
					    .into(reports)
 | 
				
			||||||
 | 
					    .then(function () {
 | 
				
			||||||
 | 
					      return byBaseFields(report);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function byBaseFields(data: Report): ReportBaseFields {
 | 
				
			||||||
 | 
					  return pick(data, baseFields) as ReportBaseFields;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Store {
 | 
				
			||||||
 | 
					  list: (query?: unknown, fields?: string[]) => Promise<ReportBaseFields[]>;
 | 
				
			||||||
 | 
					  listAll: (query?: unknown) => Promise<Report[]>;
 | 
				
			||||||
 | 
					  get: (id: string) => Promise<Report | { error: string }>;
 | 
				
			||||||
 | 
					  add: (data: AddData) => Promise<ReportBaseFields | { error: string }>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function createStore(options: SCServer.SCServerOptions): Store {
 | 
				
			||||||
 | 
					  knex = connector(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    list: list,
 | 
				
			||||||
 | 
					    listAll: listAll,
 | 
				
			||||||
 | 
					    get: get,
 | 
				
			||||||
 | 
					    add: add,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function composeException(exception: Error | undefined) {
 | 
				
			||||||
 | 
					  let message = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (exception) {
 | 
				
			||||||
 | 
					    message = 'Exception thrown: ';
 | 
				
			||||||
 | 
					    if (exception.message) message += exception.message;
 | 
				
			||||||
 | 
					    if (exception.stack) message += '\n' + exception.stack;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return message;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default createStore;
 | 
				
			||||||
| 
						 | 
					@ -1,6 +0,0 @@
 | 
				
			||||||
var fs = require('fs');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = function (name, require) {
 | 
					 | 
				
			||||||
  return fs.readFileSync(require.resolve(name)).toString();
 | 
					 | 
				
			||||||
  // return GraphQL.buildSchema(schema);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,24 @@
 | 
				
			||||||
var SCWorker = require('socketcluster/scworker');
 | 
					import SCWorker from 'socketcluster/scworker';
 | 
				
			||||||
var express = require('express');
 | 
					import express from 'express';
 | 
				
			||||||
var app = express();
 | 
					import routes from './routes';
 | 
				
			||||||
var routes = require('./routes');
 | 
					import createStore from './store';
 | 
				
			||||||
var createStore = require('./store');
 | 
					
 | 
				
			||||||
 | 
					const app = express();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Worker extends SCWorker {
 | 
					class Worker extends SCWorker {
 | 
				
			||||||
  run() {
 | 
					  run() {
 | 
				
			||||||
    var httpServer = this.httpServer;
 | 
					    const httpServer = this.httpServer;
 | 
				
			||||||
    var scServer = this.scServer;
 | 
					    const scServer = this.scServer;
 | 
				
			||||||
    var options = this.options;
 | 
					    const options = this.options;
 | 
				
			||||||
    var store = createStore(options);
 | 
					    const store = createStore(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    httpServer.on('request', app);
 | 
					    httpServer.on('request', app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app.use(routes(options, store, scServer));
 | 
					    app.use(routes(options, store, scServer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scServer.addMiddleware(scServer.MIDDLEWARE_EMIT, function (req, next) {
 | 
					    scServer.addMiddleware(scServer.MIDDLEWARE_EMIT, function (req, next) {
 | 
				
			||||||
      var channel = req.event;
 | 
					      const channel = req.event;
 | 
				
			||||||
      var data = req.data;
 | 
					      const data = req.data;
 | 
				
			||||||
      if (
 | 
					      if (
 | 
				
			||||||
        channel.substr(0, 3) === 'sc-' ||
 | 
					        channel.substr(0, 3) === 'sc-' ||
 | 
				
			||||||
        channel === 'respond' ||
 | 
					        channel === 'respond' ||
 | 
				
			||||||
| 
						 | 
					@ -36,7 +37,7 @@ class Worker extends SCWorker {
 | 
				
			||||||
        store
 | 
					        store
 | 
				
			||||||
          .list()
 | 
					          .list()
 | 
				
			||||||
          .then(function (data) {
 | 
					          .then(function (data) {
 | 
				
			||||||
            req.socket.emit(req.channel, { type: 'list', data: data });
 | 
					            req.socket.emit(req.channel!, { type: 'list', data: data });
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
          .catch(function (error) {
 | 
					          .catch(function (error) {
 | 
				
			||||||
            console.error(error); // eslint-disable-line no-console
 | 
					            console.error(error); // eslint-disable-line no-console
 | 
				
			||||||
| 
						 | 
					@ -45,8 +46,8 @@ class Worker extends SCWorker {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scServer.on('connection', function (socket) {
 | 
					    scServer.on('connection', function (socket) {
 | 
				
			||||||
      var channelToWatch, channelToEmit;
 | 
					      let channelToWatch: string, channelToEmit: string;
 | 
				
			||||||
      socket.on('login', function (credentials, respond) {
 | 
					      socket.on('login', function (this: Worker, credentials, respond) {
 | 
				
			||||||
        if (credentials === 'master') {
 | 
					        if (credentials === 'master') {
 | 
				
			||||||
          channelToWatch = 'respond';
 | 
					          channelToWatch = 'respond';
 | 
				
			||||||
          channelToEmit = 'log';
 | 
					          channelToEmit = 'log';
 | 
				
			||||||
| 
						 | 
					@ -69,8 +70,8 @@ class Worker extends SCWorker {
 | 
				
			||||||
            console.error(error); // eslint-disable-line no-console
 | 
					            console.error(error); // eslint-disable-line no-console
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      socket.on('disconnect', function () {
 | 
					      socket.on('disconnect', function (this: Worker) {
 | 
				
			||||||
        var channel = this.exchange.channel('sc-' + socket.id);
 | 
					        const channel = this.exchange.channel('sc-' + socket.id);
 | 
				
			||||||
        channel.unsubscribe();
 | 
					        channel.unsubscribe();
 | 
				
			||||||
        channel.destroy();
 | 
					        channel.destroy();
 | 
				
			||||||
        scServer.exchange.publish(channelToEmit, {
 | 
					        scServer.exchange.publish(channelToEmit, {
 | 
				
			||||||
| 
						 | 
					@ -1,199 +0,0 @@
 | 
				
			||||||
var childProcess = require('child_process');
 | 
					 | 
				
			||||||
var request = require('supertest');
 | 
					 | 
				
			||||||
var scClient = require('socketcluster-client');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe('Server', function () {
 | 
					 | 
				
			||||||
  var scServer;
 | 
					 | 
				
			||||||
  beforeAll(function (done) {
 | 
					 | 
				
			||||||
    scServer = childProcess.fork(__dirname + '/../bin/redux-devtools.js');
 | 
					 | 
				
			||||||
    setTimeout(done, 3000);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  afterAll(function () {
 | 
					 | 
				
			||||||
    if (scServer) {
 | 
					 | 
				
			||||||
      scServer.kill();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe('Express backend', function () {
 | 
					 | 
				
			||||||
    it('loads main page', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000')
 | 
					 | 
				
			||||||
        .get('/')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /text\/html/)
 | 
					 | 
				
			||||||
        .expect(200)
 | 
					 | 
				
			||||||
        .then(function (res) {
 | 
					 | 
				
			||||||
          expect(res.text).toMatch(/<title>Redux DevTools<\/title>/);
 | 
					 | 
				
			||||||
          done();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('resolves an inexistent url', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000/jreerfr/123')
 | 
					 | 
				
			||||||
        .get('/')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /text\/html/)
 | 
					 | 
				
			||||||
        .expect(200, done);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe('Realtime monitoring', function () {
 | 
					 | 
				
			||||||
    var socket, socket2, channel;
 | 
					 | 
				
			||||||
    beforeAll(function () {
 | 
					 | 
				
			||||||
      socket = scClient.connect({ hostname: 'localhost', port: 8000 });
 | 
					 | 
				
			||||||
      socket.connect();
 | 
					 | 
				
			||||||
      socket.on('error', function (error) {
 | 
					 | 
				
			||||||
        console.error('Socket1 error', error); // eslint-disable-line no-console
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      socket2 = scClient.connect({ hostname: 'localhost', port: 8000 });
 | 
					 | 
				
			||||||
      socket2.connect();
 | 
					 | 
				
			||||||
      socket.on('error', function (error) {
 | 
					 | 
				
			||||||
        console.error('Socket2 error', error); // eslint-disable-line no-console
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    afterAll(function () {
 | 
					 | 
				
			||||||
      socket.disconnect();
 | 
					 | 
				
			||||||
      socket2.disconnect();
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('should connect', function (done) {
 | 
					 | 
				
			||||||
      socket.on('connect', function (status) {
 | 
					 | 
				
			||||||
        expect(status.id).toBeTruthy();
 | 
					 | 
				
			||||||
        done();
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('should login', function () {
 | 
					 | 
				
			||||||
      socket.emit('login', 'master', function (error, channelName) {
 | 
					 | 
				
			||||||
        if (error) {
 | 
					 | 
				
			||||||
          /* eslint-disable-next-line no-console */
 | 
					 | 
				
			||||||
          console.log(error);
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        expect(channelName).toBe('respond');
 | 
					 | 
				
			||||||
        channel = socket.subscribe(channelName);
 | 
					 | 
				
			||||||
        expect(channel.SUBSCRIBED).toBe('subscribed');
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('should send message', function (done) {
 | 
					 | 
				
			||||||
      var data = {
 | 
					 | 
				
			||||||
        type: 'ACTION',
 | 
					 | 
				
			||||||
        payload: {
 | 
					 | 
				
			||||||
          todos: 'do some',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        action: {
 | 
					 | 
				
			||||||
          timestamp: 1483349708506,
 | 
					 | 
				
			||||||
          action: {
 | 
					 | 
				
			||||||
            type: 'ADD_TODO',
 | 
					 | 
				
			||||||
            text: 'hggg',
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        instanceId: 'tAmA7H5fclyWhvizAAAi',
 | 
					 | 
				
			||||||
        name: 'LoggerInstance',
 | 
					 | 
				
			||||||
        id: 'tAmA7H5fclyWhvizAAAi',
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      socket2.emit('login', '', function (error, channelName) {
 | 
					 | 
				
			||||||
        if (error) {
 | 
					 | 
				
			||||||
          /* eslint-disable-next-line no-console */
 | 
					 | 
				
			||||||
          console.log(error);
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        expect(channelName).toBe('log');
 | 
					 | 
				
			||||||
        var channel2 = socket2.subscribe(channelName);
 | 
					 | 
				
			||||||
        expect(channel2.SUBSCRIBED).toBe('subscribed');
 | 
					 | 
				
			||||||
        channel2.on('subscribe', function () {
 | 
					 | 
				
			||||||
          channel2.watch(function (message) {
 | 
					 | 
				
			||||||
            expect(message).toEqual(data);
 | 
					 | 
				
			||||||
            done();
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
          socket.emit(channelName, data);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe('REST backend', function () {
 | 
					 | 
				
			||||||
    var id;
 | 
					 | 
				
			||||||
    var report = {
 | 
					 | 
				
			||||||
      type: 'ACTIONS',
 | 
					 | 
				
			||||||
      title: 'Test report',
 | 
					 | 
				
			||||||
      description: 'Test body report',
 | 
					 | 
				
			||||||
      action: 'SOME_FINAL_ACTION',
 | 
					 | 
				
			||||||
      payload: '[{"type":"ADD_TODO","text":"hi"},{"type":"SOME_FINAL_ACTION"}]',
 | 
					 | 
				
			||||||
      preloadedState:
 | 
					 | 
				
			||||||
        '{"todos":[{"text":"Use Redux","completed":false,"id":0}]}',
 | 
					 | 
				
			||||||
      userAgent:
 | 
					 | 
				
			||||||
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) ' +
 | 
					 | 
				
			||||||
        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36',
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    it('should add a report', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000')
 | 
					 | 
				
			||||||
        .post('/')
 | 
					 | 
				
			||||||
        .send(report)
 | 
					 | 
				
			||||||
        .set('Accept', 'application/json')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /application\/json/)
 | 
					 | 
				
			||||||
        .expect(200)
 | 
					 | 
				
			||||||
        .then(function (res) {
 | 
					 | 
				
			||||||
          id = res.body.id;
 | 
					 | 
				
			||||||
          expect(id).toBeTruthy();
 | 
					 | 
				
			||||||
          done();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('should get the report', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000')
 | 
					 | 
				
			||||||
        .post('/')
 | 
					 | 
				
			||||||
        .send({
 | 
					 | 
				
			||||||
          op: 'get',
 | 
					 | 
				
			||||||
          id: id,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .set('Accept', 'application/json')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /application\/json/)
 | 
					 | 
				
			||||||
        .expect(200)
 | 
					 | 
				
			||||||
        .then(function (res) {
 | 
					 | 
				
			||||||
          expect.objectContaining(res.body, report);
 | 
					 | 
				
			||||||
          done();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it('should list reports', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000')
 | 
					 | 
				
			||||||
        .post('/')
 | 
					 | 
				
			||||||
        .send({
 | 
					 | 
				
			||||||
          op: 'list',
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .set('Accept', 'application/json')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /application\/json/)
 | 
					 | 
				
			||||||
        .expect(200)
 | 
					 | 
				
			||||||
        .then(function (res) {
 | 
					 | 
				
			||||||
          expect(res.body.length).toBe(1);
 | 
					 | 
				
			||||||
          expect(res.body[0].id).toBe(id);
 | 
					 | 
				
			||||||
          expect(res.body[0].title).toBe('Test report');
 | 
					 | 
				
			||||||
          expect(res.body[0].added).toBeTruthy();
 | 
					 | 
				
			||||||
          done();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  describe('GraphQL backend', function () {
 | 
					 | 
				
			||||||
    it('should get the report', function (done) {
 | 
					 | 
				
			||||||
      request('http://localhost:8000')
 | 
					 | 
				
			||||||
        .post('/graphql')
 | 
					 | 
				
			||||||
        .send({
 | 
					 | 
				
			||||||
          query: '{ reports { id, type, title } }',
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .set('Accept', 'application/json')
 | 
					 | 
				
			||||||
        .expect('Content-Type', /application\/json/)
 | 
					 | 
				
			||||||
        .expect(200)
 | 
					 | 
				
			||||||
        .then(function (res) {
 | 
					 | 
				
			||||||
          var reports = res.body.data.reports;
 | 
					 | 
				
			||||||
          expect(reports.length).toBe(1);
 | 
					 | 
				
			||||||
          expect(reports[0].id).toBeTruthy();
 | 
					 | 
				
			||||||
          expect(reports[0].title).toBe('Test report');
 | 
					 | 
				
			||||||
          expect(reports[0].type).toBe('ACTIONS');
 | 
					 | 
				
			||||||
          done();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
							
								
								
									
										241
									
								
								packages/redux-devtools-cli/test/integration.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								packages/redux-devtools-cli/test/integration.spec.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,241 @@
 | 
				
			||||||
 | 
					import childProcess from 'child_process';
 | 
				
			||||||
 | 
					import request from 'supertest';
 | 
				
			||||||
 | 
					import scClient from 'socketcluster-client';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Server', function () {
 | 
				
			||||||
 | 
					  let scServer: childProcess.ChildProcess;
 | 
				
			||||||
 | 
					  beforeAll(function (done) {
 | 
				
			||||||
 | 
					    scServer = childProcess.fork(__dirname + '/../bin/redux-devtools.js');
 | 
				
			||||||
 | 
					    setTimeout(done, 3000);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  afterAll(function () {
 | 
				
			||||||
 | 
					    if (scServer) {
 | 
				
			||||||
 | 
					      scServer.kill();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('Express backend', function () {
 | 
				
			||||||
 | 
					    it('loads main page', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000')
 | 
				
			||||||
 | 
					          .get('/')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /text\/html/)
 | 
				
			||||||
 | 
					          .expect(200)
 | 
				
			||||||
 | 
					          .then(function (res: { text: string }) {
 | 
				
			||||||
 | 
					            expect(res.text).toMatch(/<title>Redux DevTools<\/title>/);
 | 
				
			||||||
 | 
					            done();
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('resolves an inexistent url', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000/jreerfr/123')
 | 
				
			||||||
 | 
					          .get('/')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /text\/html/)
 | 
				
			||||||
 | 
					          .expect(200, done);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('Realtime monitoring', function () {
 | 
				
			||||||
 | 
					    let socket: scClient.SCClientSocket,
 | 
				
			||||||
 | 
					      socket2: scClient.SCClientSocket,
 | 
				
			||||||
 | 
					      channel;
 | 
				
			||||||
 | 
					    beforeAll(function () {
 | 
				
			||||||
 | 
					      socket = scClient.connect({ hostname: 'localhost', port: 8000 });
 | 
				
			||||||
 | 
					      socket.connect();
 | 
				
			||||||
 | 
					      socket.on('error', function (error) {
 | 
				
			||||||
 | 
					        console.error('Socket1 error', error); // eslint-disable-line no-console
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      socket2 = scClient.connect({ hostname: 'localhost', port: 8000 });
 | 
				
			||||||
 | 
					      socket2.connect();
 | 
				
			||||||
 | 
					      socket.on('error', function (error) {
 | 
				
			||||||
 | 
					        console.error('Socket2 error', error); // eslint-disable-line no-console
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    afterAll(function () {
 | 
				
			||||||
 | 
					      socket.disconnect();
 | 
				
			||||||
 | 
					      socket2.disconnect();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should connect', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        socket.on('connect', function (status) {
 | 
				
			||||||
 | 
					          expect(status.id).toBeTruthy();
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should login', function () {
 | 
				
			||||||
 | 
					      socket.emit('login', 'master', function (
 | 
				
			||||||
 | 
					        error: Error | undefined,
 | 
				
			||||||
 | 
					        channelName: string
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					        if (error) {
 | 
				
			||||||
 | 
					          /* eslint-disable-next-line no-console */
 | 
				
			||||||
 | 
					          console.log(error);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        expect(channelName).toBe('respond');
 | 
				
			||||||
 | 
					        channel = socket.subscribe(channelName);
 | 
				
			||||||
 | 
					        expect(channel.SUBSCRIBED).toBe('subscribed');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should send message', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        const data = {
 | 
				
			||||||
 | 
					          type: 'ACTION',
 | 
				
			||||||
 | 
					          payload: {
 | 
				
			||||||
 | 
					            todos: 'do some',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          action: {
 | 
				
			||||||
 | 
					            timestamp: 1483349708506,
 | 
				
			||||||
 | 
					            action: {
 | 
				
			||||||
 | 
					              type: 'ADD_TODO',
 | 
				
			||||||
 | 
					              text: 'hggg',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          instanceId: 'tAmA7H5fclyWhvizAAAi',
 | 
				
			||||||
 | 
					          name: 'LoggerInstance',
 | 
				
			||||||
 | 
					          id: 'tAmA7H5fclyWhvizAAAi',
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket2.emit('login', '', function (
 | 
				
			||||||
 | 
					          error: Error | undefined,
 | 
				
			||||||
 | 
					          channelName: string
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					          if (error) {
 | 
				
			||||||
 | 
					            /* eslint-disable-next-line no-console */
 | 
				
			||||||
 | 
					            console.log(error);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          expect(channelName).toBe('log');
 | 
				
			||||||
 | 
					          const channel2 = socket2.subscribe(channelName);
 | 
				
			||||||
 | 
					          expect(channel2.SUBSCRIBED).toBe('subscribed');
 | 
				
			||||||
 | 
					          channel2.on('subscribe', function () {
 | 
				
			||||||
 | 
					            channel2.watch(function (message) {
 | 
				
			||||||
 | 
					              expect(message).toEqual(data);
 | 
				
			||||||
 | 
					              done();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            socket.emit(channelName, data);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('REST backend', function () {
 | 
				
			||||||
 | 
					    let id: string;
 | 
				
			||||||
 | 
					    const report = {
 | 
				
			||||||
 | 
					      type: 'ACTIONS',
 | 
				
			||||||
 | 
					      title: 'Test report',
 | 
				
			||||||
 | 
					      description: 'Test body report',
 | 
				
			||||||
 | 
					      action: 'SOME_FINAL_ACTION',
 | 
				
			||||||
 | 
					      payload: '[{"type":"ADD_TODO","text":"hi"},{"type":"SOME_FINAL_ACTION"}]',
 | 
				
			||||||
 | 
					      preloadedState:
 | 
				
			||||||
 | 
					        '{"todos":[{"text":"Use Redux","completed":false,"id":0}]}',
 | 
				
			||||||
 | 
					      userAgent:
 | 
				
			||||||
 | 
					        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) ' +
 | 
				
			||||||
 | 
					        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36',
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    it('should add a report', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000')
 | 
				
			||||||
 | 
					          .post('/')
 | 
				
			||||||
 | 
					          .send(report)
 | 
				
			||||||
 | 
					          .set('Accept', 'application/json')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /application\/json/)
 | 
				
			||||||
 | 
					          .expect(200)
 | 
				
			||||||
 | 
					          .then(function (res: { body: { id: string } }) {
 | 
				
			||||||
 | 
					            id = res.body.id;
 | 
				
			||||||
 | 
					            expect(id).toBeTruthy();
 | 
				
			||||||
 | 
					            done();
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should get the report', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000')
 | 
				
			||||||
 | 
					          .post('/')
 | 
				
			||||||
 | 
					          .send({
 | 
				
			||||||
 | 
					            op: 'get',
 | 
				
			||||||
 | 
					            id: id,
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .set('Accept', 'application/json')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /application\/json/)
 | 
				
			||||||
 | 
					          .expect(200)
 | 
				
			||||||
 | 
					          .then(function (res: { body: unknown }) {
 | 
				
			||||||
 | 
					            expect(res.body).toMatchObject(report);
 | 
				
			||||||
 | 
					            done();
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should list reports', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000')
 | 
				
			||||||
 | 
					          .post('/')
 | 
				
			||||||
 | 
					          .send({
 | 
				
			||||||
 | 
					            op: 'list',
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .set('Accept', 'application/json')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /application\/json/)
 | 
				
			||||||
 | 
					          .expect(200)
 | 
				
			||||||
 | 
					          .then(function (res: {
 | 
				
			||||||
 | 
					            body: { id: string; title: string | null; added: string | null }[];
 | 
				
			||||||
 | 
					          }) {
 | 
				
			||||||
 | 
					            expect(res.body).toHaveLength(1);
 | 
				
			||||||
 | 
					            expect(res.body[0].id).toBe(id);
 | 
				
			||||||
 | 
					            expect(res.body[0].title).toBe('Test report');
 | 
				
			||||||
 | 
					            expect(res.body[0].added).toBeTruthy();
 | 
				
			||||||
 | 
					            done();
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('GraphQL backend', function () {
 | 
				
			||||||
 | 
					    it('should get the report', function () {
 | 
				
			||||||
 | 
					      return new Promise((done) => {
 | 
				
			||||||
 | 
					        // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | 
				
			||||||
 | 
					        request('http://localhost:8000')
 | 
				
			||||||
 | 
					          .post('/graphql')
 | 
				
			||||||
 | 
					          .send({
 | 
				
			||||||
 | 
					            query: '{ reports { id, type, title } }',
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .set('Accept', 'application/json')
 | 
				
			||||||
 | 
					          .expect('Content-Type', /application\/json/)
 | 
				
			||||||
 | 
					          .expect(200)
 | 
				
			||||||
 | 
					          .then(function (res: {
 | 
				
			||||||
 | 
					            body: {
 | 
				
			||||||
 | 
					              data: {
 | 
				
			||||||
 | 
					                reports: {
 | 
				
			||||||
 | 
					                  id: string;
 | 
				
			||||||
 | 
					                  title: string | null;
 | 
				
			||||||
 | 
					                  type: string | null;
 | 
				
			||||||
 | 
					                }[];
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          }) {
 | 
				
			||||||
 | 
					            const reports = res.body.data.reports;
 | 
				
			||||||
 | 
					            expect(reports).toHaveLength(1);
 | 
				
			||||||
 | 
					            expect(reports[0].id).toBeTruthy();
 | 
				
			||||||
 | 
					            expect(reports[0].title).toBe('Test report');
 | 
				
			||||||
 | 
					            expect(reports[0].type).toBe('ACTIONS');
 | 
				
			||||||
 | 
					            done();
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										4
									
								
								packages/redux-devtools-cli/test/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/redux-devtools-cli/test/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": "../../../tsconfig.base.json",
 | 
				
			||||||
 | 
					  "include": ["../src", "."]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								packages/redux-devtools-cli/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/redux-devtools-cli/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": "../../tsconfig.base.json",
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "outDir": "dist"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "include": ["src"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								yarn.lock
									
									
									
									
									
								
							| 
						 | 
					@ -3493,6 +3493,11 @@
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96"
 | 
					  resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96"
 | 
				
			||||||
  integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==
 | 
					  integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/cookiejar@*":
 | 
				
			||||||
 | 
					  version "2.1.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8"
 | 
				
			||||||
 | 
					  integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/cookies@*":
 | 
					"@types/cookies@*":
 | 
				
			||||||
  version "0.7.4"
 | 
					  version "0.7.4"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.4.tgz#26dedf791701abc0e36b5b79a5722f40e455f87b"
 | 
					  resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.4.tgz#26dedf791701abc0e36b5b79a5722f40e455f87b"
 | 
				
			||||||
| 
						 | 
					@ -3510,6 +3515,13 @@
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@types/express" "*"
 | 
					    "@types/express" "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/cross-spawn@^6.0.2":
 | 
				
			||||||
 | 
					  version "6.0.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.2.tgz#168309de311cd30a2b8ae720de6475c2fbf33ac7"
 | 
				
			||||||
 | 
					  integrity sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@types/node" "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/d3@^3.5.43":
 | 
					"@types/d3@^3.5.43":
 | 
				
			||||||
  version "3.5.43"
 | 
					  version "3.5.43"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58"
 | 
					  resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58"
 | 
				
			||||||
| 
						 | 
					@ -3859,6 +3871,13 @@
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
 | 
					  resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
 | 
				
			||||||
  integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
 | 
					  integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/morgan@^1.9.1":
 | 
				
			||||||
 | 
					  version "1.9.1"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.1.tgz#6457872df95647c1dbc6b3741e8146b71ece74bf"
 | 
				
			||||||
 | 
					  integrity sha512-2j5IKrgJpEP6xw/uiVb2Xfga0W0sSVD9JP9t7EZLvpBENdB0OKgcnoKS8IsjNeNnZ/86robdZ61Orl0QCFGOXg==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@types/node" "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/ncom@*":
 | 
					"@types/ncom@*":
 | 
				
			||||||
  version "1.0.0"
 | 
					  version "1.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/ncom/-/ncom-1.0.0.tgz#8e33d06fc4914c941ba40ceca042081b947ba699"
 | 
					  resolved "https://registry.yarnpkg.com/@types/ncom/-/ncom-1.0.0.tgz#8e33d06fc4914c941ba40ceca042081b947ba699"
 | 
				
			||||||
| 
						 | 
					@ -4116,6 +4135,11 @@
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/sc-errors/-/sc-errors-1.4.0.tgz#dba1309b695ee8aafc3f574dfedfe4f3c5153419"
 | 
					  resolved "https://registry.yarnpkg.com/@types/sc-errors/-/sc-errors-1.4.0.tgz#dba1309b695ee8aafc3f574dfedfe4f3c5153419"
 | 
				
			||||||
  integrity sha512-WfBEiw/SVja1ZvJRdt37dOJFxp2llV35n9cPiDCDsFRSvTTYlO4iMFg+NyeEhiWBk1O4bvmyYpAEYzJx1DbHHQ==
 | 
					  integrity sha512-WfBEiw/SVja1ZvJRdt37dOJFxp2llV35n9cPiDCDsFRSvTTYlO4iMFg+NyeEhiWBk1O4bvmyYpAEYzJx1DbHHQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/semver@^7.3.4":
 | 
				
			||||||
 | 
					  version "7.3.4"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
 | 
				
			||||||
 | 
					  integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/serve-static@*":
 | 
					"@types/serve-static@*":
 | 
				
			||||||
  version "1.13.5"
 | 
					  version "1.13.5"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53"
 | 
					  resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53"
 | 
				
			||||||
| 
						 | 
					@ -4186,6 +4210,21 @@
 | 
				
			||||||
    "@types/react-native" "*"
 | 
					    "@types/react-native" "*"
 | 
				
			||||||
    csstype "^3.0.2"
 | 
					    csstype "^3.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/superagent@*":
 | 
				
			||||||
 | 
					  version "4.1.10"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.10.tgz#5e2cc721edf58f64fe9b819f326ee74803adee86"
 | 
				
			||||||
 | 
					  integrity sha512-xAgkb2CMWUMCyVc/3+7iQfOEBE75NvuZeezvmixbUw3nmENf2tCnQkW5yQLTYqvXUQ+R6EXxdqKKbal2zM5V/g==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@types/cookiejar" "*"
 | 
				
			||||||
 | 
					    "@types/node" "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/supertest@^2.0.10":
 | 
				
			||||||
 | 
					  version "2.0.10"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.10.tgz#630d79b4d82c73e043e43ff777a9ca98d457cab7"
 | 
				
			||||||
 | 
					  integrity sha512-Xt8TbEyZTnD5Xulw95GLMOkmjGICrOQyJ2jqgkSjAUR3mm7pAIzSR0NFBaMcwlzVvlpCjNwbATcWWwjNiZiFrQ==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    "@types/superagent" "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/tapable@*", "@types/tapable@^1.0.5":
 | 
					"@types/tapable@*", "@types/tapable@^1.0.5":
 | 
				
			||||||
  version "1.0.6"
 | 
					  version "1.0.6"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
 | 
					  resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
 | 
				
			||||||
| 
						 | 
					@ -4210,6 +4249,11 @@
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
 | 
					  resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
 | 
				
			||||||
  integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
 | 
					  integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"@types/uuid@^8.3.0":
 | 
				
			||||||
 | 
					  version "8.3.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
 | 
				
			||||||
 | 
					  integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"@types/warning@^3.0.0":
 | 
					"@types/warning@^3.0.0":
 | 
				
			||||||
  version "3.0.0"
 | 
					  version "3.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
 | 
					  resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
 | 
				
			||||||
| 
						 | 
					@ -9656,6 +9700,13 @@ graphql-upload@^8.0.2:
 | 
				
			||||||
    http-errors "^1.7.3"
 | 
					    http-errors "^1.7.3"
 | 
				
			||||||
    object-path "^0.11.4"
 | 
					    object-path "^0.11.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					graphql@^14.7.0:
 | 
				
			||||||
 | 
					  version "14.7.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72"
 | 
				
			||||||
 | 
					  integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    iterall "^1.2.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
graphql@^15.3.0:
 | 
					graphql@^15.3.0:
 | 
				
			||||||
  version "15.3.0"
 | 
					  version "15.3.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
 | 
					  resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
 | 
				
			||||||
| 
						 | 
					@ -11028,7 +11079,7 @@ istanbul-reports@^3.0.2:
 | 
				
			||||||
    html-escaper "^2.0.0"
 | 
					    html-escaper "^2.0.0"
 | 
				
			||||||
    istanbul-lib-report "^3.0.0"
 | 
					    istanbul-lib-report "^3.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
iterall@^1.1.3, iterall@^1.2.1:
 | 
					iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2:
 | 
				
			||||||
  version "1.3.0"
 | 
					  version "1.3.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
 | 
					  resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
 | 
				
			||||||
  integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
 | 
					  integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
 | 
				
			||||||
| 
						 | 
					@ -13074,6 +13125,11 @@ ncom@^1.0.2:
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    sc-formatter "~3.0.1"
 | 
					    sc-formatter "~3.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ncp@^2.0.0:
 | 
				
			||||||
 | 
					  version "2.0.0"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
 | 
				
			||||||
 | 
					  integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nearley@^2.7.10:
 | 
					nearley@^2.7.10:
 | 
				
			||||||
  version "2.19.5"
 | 
					  version "2.19.5"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.19.5.tgz#6be78e4942eeb9a043b17c563413111d4ad849b7"
 | 
					  resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.19.5.tgz#6be78e4942eeb9a043b17c563413111d4ad849b7"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user