diff --git a/.babelrc b/.babelrc index cf2b1db5..9cdc1bc8 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,5 @@ { + "comments": false, "env": { "development": { "presets": [ @@ -21,8 +22,7 @@ "presets": [ "lux" ], - "minified": true, - "comments": false + "minified": true } } } diff --git a/.eslintignore b/.eslintignore index e4d6d798..58f3cc9e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -10,4 +10,3 @@ decl/ examples/ flow-typed/ test/test-app/ -*interfaces.js diff --git a/.eslintrc.json b/.eslintrc.json index 8f19ce80..2cdc9a48 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,85 +4,52 @@ "jest", "flowtype" ], - "extends": "airbnb-base", + "extends": [ + "airbnb-base", + "plugin:flowtype/recommended", + "prettier", + "prettier/flowtype" + ], "env": { + "jest/globals": true, "node": true }, - "globals": { - "$PropertyType": true, - "afterAll": true, - "afterEach": true, - "beforeAll": true, - "beforeEach": true, - "Class": true, - "describe": true, - "expect": true, - "Generator": true, - "it": true, - "jasmine": true, - "jest": true, - "Knex$QueryBuilder": true, - "Knex$SchemaBuilder": true, - "Knex$Transaction": true, - "Process": true, - "test": true - }, "settings": { "flowtype": { "onlyFilesWithFlowAnnotation": true } }, - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module", - "ecmaFeatures": { - "impliedStrict": true, - "experimentalObjectRestSpread": true - } - }, "rules": { - "semi": ["error", "never"], - "strict": 0, - "max-len": ["error", 80], - "arrow-parens": 0, - "comma-dangle": [2, "only-multiline"], - "global-require": 0, - "no-underscore-dangle": 0, - "class-methods-use-this": 0, - "no-irregular-whitespace": 0, - "no-restricted-syntax": [ + "comma-dangle": [ + "error", + { + "arrays": "always-multiline", + "exports": "always-multiline", + "functions": "always-multiline", + "imports": "always-multiline", + "objects": "always-multiline" + } + ], + "max-len": [ + "error", + 80 + ], + "no-use-before-define": "off", + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "_", + "varsIgnorePattern": "_" + } + ], + "semi": [ "error", - "ForInStatement", - "LabeledStatement", - "WithStatement" + "never" ], - "import/order": ["warn", { - "groups": [ - "builtin", - "external", - "internal", - "parent", - "sibling", - "index" - ], - "newlines-between": "always" - }], - "import/extensions": 0, - "import/no-named-default": 0, - "import/no-dynamic-require": 0, - "import/prefer-default-export": 0, - "jest/no-focused-tests": "error", - "jest/no-disabled-tests": "warn", - "jest/no-identical-title": "error", - "flowtype/semi": ["error", "never"], - "flowtype/no-dupe-keys": 2, - "flowtype/boolean-style": [2, "boolean"], - "flowtype/generic-spacing": 2, - "flowtype/define-flow-type": 0, - "flowtype/space-after-type-colon": [2, "always"], - "flowtype/space-before-type-colon": [2, "never"], - "flowtype/union-intersection-spacing": [2, "always"], - "flowtype/space-before-generic-bracket": [2, "never"], - "flowtype/require-valid-file-annotation": [2, "always"] + "import/extensions": "off", + "import/first": "off", + "import/no-extraneous-dependencies": "off", + "import/no-unresolved": "off", + "import/prefer-default-export": "off" } } diff --git a/.flowconfig b/.flowconfig index 56952619..55867638 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,13 +1,16 @@ [ignore] -.*/bin/* -.*/dist/* -.*/examples/* -.*/guide/* -.*/lib/* -.*/node_modules/* -.*/scripts/* -.*/test/test-app/* -.*/__snapshots__/* +/__snapshots__/* +/bin/* +/dist/* +/examples/* +/guide/* +/lib/* +/node_modules/* +/scripts/* +/src/packages/cli/* +/test/test-app/* + +[include] [libs] flow-typed/ @@ -15,12 +18,13 @@ decl/ [options] emoji=true -suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore -module.name_mapper='LUX_LOCAL' -> '' +esproposal.class_static_fields=enable +esproposal.class_instance_fields=enable + +experimental.const_params=true + +module.name_mapper='^@lux\(.*\)' -> '/src\1' module.name_mapper='rollup-plugin-lux' -> '/node_modules/rollup-plugin-lux/src/index.js' unsafe.enable_getters_and_setters=true - -esproposal.class_static_fields=enable -esproposal.class_instance_fields=enable diff --git a/.gitignore b/.gitignore index 24585c47..20438ba2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ node_modules/ # misc *.sqlite *.DS_Store +.idea/ +.vscode/ # logs log/ diff --git a/bin/lux b/bin/lux index b88abb4e..6d732df9 100755 --- a/bin/lux +++ b/bin/lux @@ -1,27 +1,26 @@ #!/usr/bin/env node -'use strict'; +const { EOL } = require('os') +const path = require('path') -const { EOL } = require('os'); -const path = require('path'); +const cli = require('commander') +const { red, green } = require('chalk') -const cli = require('commander'); -const { red, green } = require('chalk'); - -const { version: VERSION } = require('../package.json'); +const { version: VERSION } = require('../package.json') function inLuxProject() { - const cwd = process.cwd(); + const cwd = process.cwd() if (cwd.indexOf(path.join('lux', 'test', 'test-app')) >= 0) { - return true; + return true } try { - const { dependencies } = require(path.join(cwd, 'package.json')); - return Boolean(dependencies['lux-framework']); + // eslint-disable-next-line global-require, import/no-dynamic-require + const { dependencies } = require(path.join(cwd, 'package.json')) + return Boolean(dependencies['lux-framework']) } catch (err) { - return false; + return false } } @@ -30,43 +29,44 @@ function commandNotFound(cmd) { console.log( `${EOL} ${red(cmd)} is not a valid command.${EOL.repeat(2)}`, ` Use ${green('lux --help')} for a full list of commands.${EOL}` - ); + ) } function setEnvVar(key, val, def) { if (val) { - Reflect.set(process.env, key, val); + Reflect.set(process.env, key, val) } else if (!Reflect.has(process.env, key)) { - Reflect.set(process.env, key, def); + Reflect.set(process.env, key, def) } } function exec(cmd, ...args) { - const handler = require('../dist')[cmd]; + // eslint-disable-next-line global-require + const handler = require('../dist/cli')[cmd] const needsProject = new RegExp( '^(?:db:.+|test|build|serve|console|generate|destroy)$' - ); + ) if (needsProject.test(cmd) && !inLuxProject()) { return Promise.reject(new Error( 'Directory does not contain a valid Lux application.' - )); + )) } - return handler(...args); + return handler(...args) } function exit(code) { - process.exit(typeof code === 'number' ? code : 0); + process.exit(typeof code === 'number' ? code : 0) } function rescue(err) { // eslint-disable-next-line - console.error(err.stack); - exit(1); + console.error(err.stack) + exit(1) } -cli.version(VERSION); +cli.version(VERSION) cli .command('n ') @@ -81,8 +81,8 @@ cli .action((name, { database }) => { exec('create', name, database) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('t') @@ -91,8 +91,8 @@ cli .action(() => { exec('test') .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('b') @@ -101,11 +101,11 @@ cli .option('-e, --environment [env]', '(Default: development)') .option('-w, --use-weak', 'Use weak mode') .action(({ environment, useWeak }) => { - setEnvVar('NODE_ENV', environment, 'development'); + setEnvVar('NODE_ENV', environment, 'development') exec('build', !useWeak) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('c') @@ -115,14 +115,18 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - setEnvVar('NODE_ENV', environment, 'development'); - process.env.LUX_CONSOLE = true; + setEnvVar('NODE_ENV', environment, 'development') + process.env.LUX_CONSOLE = true - (skipBuild ? Promise.resolve() : exec('build', !useWeak)) + if (skipBuild) { + return Promise.resolve() + } + + return exec('build', !useWeak) .then(() => exec('repl')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('s') @@ -139,25 +143,31 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ hot, port, cluster, environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak + + setEnvVar('PORT', port, 4000) + setEnvVar('NODE_ENV', environment, 'development') - setEnvVar('PORT', port, 4000); - setEnvVar('NODE_ENV', environment, 'development'); + if (skipBuild) { + return Promise.resolve() + } - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + return exec('build', useStrict) .then(() => exec('serve', { hot, cluster, useStrict })) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('g [attrs...]') .alias('generate') - .description('Example: lux generate model user name:string email:string admin:boolean') + .description( + 'Example: lux generate model user name:string email:string admin:boolean' + ) .action((type, name, attrs) => { exec('generate', { type, name, attrs }) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('d') @@ -166,8 +176,8 @@ cli .action((type, name) => { exec('destroy', { type, name }) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:create') @@ -176,15 +186,19 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak - setEnvVar('NODE_ENV', environment, 'development'); + setEnvVar('NODE_ENV', environment, 'development') - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + if (skipBuild) { + return Promise.resolve() + } + + return exec('build', useStrict) .then(() => exec('dbcreate')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:drop') @@ -193,15 +207,19 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak + + setEnvVar('NODE_ENV', environment, 'development') - setEnvVar('NODE_ENV', environment, 'development'); + if (skipBuild) { + return Promise.resolve() + } - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + return exec('build', useStrict) .then(() => exec('dbdrop')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:reset') @@ -210,16 +228,20 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak + + setEnvVar('NODE_ENV', environment, 'development') - setEnvVar('NODE_ENV', environment, 'development'); + if (skipBuild) { + return Promise.resolve() + } - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + return exec('build', useStrict) .then(() => exec('dbdrop')) .then(() => exec('dbcreate')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:migrate') @@ -228,15 +250,19 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak - setEnvVar('NODE_ENV', environment, 'development'); + setEnvVar('NODE_ENV', environment, 'development') - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + if (skipBuild) { + return Promise.resolve() + } + + return exec('build', useStrict) .then(() => exec('dbmigrate')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:rollback') @@ -245,15 +271,19 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak + + setEnvVar('NODE_ENV', environment, 'development') - setEnvVar('NODE_ENV', environment, 'development'); + if (skipBuild) { + return Promise.resolve() + } - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + return exec('build', useStrict) .then(() => exec('dbrollback')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .command('db:seed') @@ -262,20 +292,24 @@ cli .option('-w, --use-weak', 'Use weak mode') .option('--skip-build', 'Skip the application build process') .action(({ environment, useWeak, skipBuild }) => { - const useStrict = !useWeak; + const useStrict = !useWeak + + setEnvVar('NODE_ENV', environment, 'development') - setEnvVar('NODE_ENV', environment, 'development'); + if (skipBuild) { + return Promise.resolve() + } - (skipBuild ? Promise.resolve() : exec('build', useStrict)) + return exec('build', useStrict) .then(() => exec('dbseed')) .then(exit) - .catch(rescue); - }); + .catch(rescue) + }) cli .on('*', commandNotFound) - .parse(process.argv); + .parse(process.argv) if (!cli.args.length) { - cli.help(); + cli.help() } diff --git a/decl/repl.js b/decl/repl.js deleted file mode 100644 index 5d0efe10..00000000 --- a/decl/repl.js +++ /dev/null @@ -1,32 +0,0 @@ -/* @flow */ - -declare module 'repl' { - declare type REPL_MODE_MAGIC = Symbol; - declare type REPL_MODE_SLOPPY = Symbol; - declare type REPL_MODE_STRICT = Symbol; - - declare class REPLServer extends readline$Interface { - context: Object; - - displayPrompt(preserveCursor?: boolean): void; - defineCommand(command: string, options: { - help?: string; - action: (...args: Array) => void - }): void; - } - - declare function start(options: { - eval?: Function; - input?: stream$Readable; - output?: stream$Writable; - prompt?: string; - writer?: Function; - replMode?: Symbol; - terminal?: boolean; - completer?: Function; - useColors?: boolean; - useGlobal?: boolean; - ignoreUndefined?: boolean; - breakEvalOnSigint?: boolean; - }): REPLServer; -} diff --git a/flow-typed/npm/ansi-regex_vx.x.x.js b/flow-typed/npm/ansi-regex_vx.x.x.js index 5fd954d3..fe862f29 100644 --- a/flow-typed/npm/ansi-regex_vx.x.x.js +++ b/flow-typed/npm/ansi-regex_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 2cfcce160200116d7464b7ad59b251eb -// flow-typed version: <>/ansi-regex_v2.1.1/flow_v0.46.0 +// flow-typed signature: 523cc24194161740d1d95d439473f094 +// flow-typed version: <>/ansi-regex_v3.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-core_vx.x.x.js b/flow-typed/npm/babel-core_vx.x.x.js index c6eb35f7..1b508909 100644 --- a/flow-typed/npm/babel-core_vx.x.x.js +++ b/flow-typed/npm/babel-core_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: e0b5d045463211bda7f5a9dccdd21631 -// flow-typed version: <>/babel-core_v6.24.1/flow_v0.46.0 +// flow-typed signature: 8fddcb2f4c2d56c5c4fee48f56dcd76e +// flow-typed version: <>/babel-core_v6.25.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-eslint_vx.x.x.js b/flow-typed/npm/babel-eslint_vx.x.x.js index f4c3cd27..c7cddd4d 100644 --- a/flow-typed/npm/babel-eslint_vx.x.x.js +++ b/flow-typed/npm/babel-eslint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 7f4941edc27d3118a288add6a26e85b9 -// flow-typed version: <>/babel-eslint_v7.2.3/flow_v0.46.0 +// flow-typed signature: e595ec2c799fc7da4b7f702ea1351935 +// flow-typed version: <>/babel-eslint_v7.2.3/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-jest_vx.x.x.js b/flow-typed/npm/babel-jest_vx.x.x.js index 38b2648c..d9c980cd 100644 --- a/flow-typed/npm/babel-jest_vx.x.x.js +++ b/flow-typed/npm/babel-jest_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: f243d8f3ffc6276176cb114a850eb269 -// flow-typed version: <>/babel-jest_v20.0.3/flow_v0.46.0 +// flow-typed signature: f852a63234363e7169207376b341e211 +// flow-typed version: <>/babel-jest_v20.0.3/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-plugin-transform-es2015-modules-commonjs_vx.x.x.js b/flow-typed/npm/babel-plugin-transform-es2015-modules-commonjs_vx.x.x.js index 696e7774..c262c85f 100644 --- a/flow-typed/npm/babel-plugin-transform-es2015-modules-commonjs_vx.x.x.js +++ b/flow-typed/npm/babel-plugin-transform-es2015-modules-commonjs_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: d0c3579243c3f45da3b2bc686dcc31a8 -// flow-typed version: <>/babel-plugin-transform-es2015-modules-commonjs_v6.24.1/flow_v0.46.0 +// flow-typed signature: 8dfc1216009071213ce6c3735c5bce5b +// flow-typed version: <>/babel-plugin-transform-es2015-modules-commonjs_v6.24.1/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-preset-lux_vx.x.x.js b/flow-typed/npm/babel-preset-lux_vx.x.x.js index dde79746..f5bd983f 100644 --- a/flow-typed/npm/babel-preset-lux_vx.x.x.js +++ b/flow-typed/npm/babel-preset-lux_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: d7494fabdf5954ecc1b3c2c911b12e31 -// flow-typed version: <>/babel-preset-lux_v2.0.2/flow_v0.46.0 +// flow-typed signature: 5fa420848517d843f3e8aaf4f4719717 +// flow-typed version: <>/babel-preset-lux_v2.0.2/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/chalk_v1.x.x.js b/flow-typed/npm/chalk_v1.x.x.js index e115e1e3..a10a34ea 100644 --- a/flow-typed/npm/chalk_v1.x.x.js +++ b/flow-typed/npm/chalk_v1.x.x.js @@ -1,12 +1,12 @@ -// flow-typed signature: 7b4e29a4fd2be533e1822c1b0aade79b -// flow-typed version: 549b484575/chalk_v1.x.x/flow_>=v0.21.x +// flow-typed signature: 9d7ebf432fe5436b8912d014b367d934 +// flow-typed version: b059774d08/chalk_v1.x.x/flow_>=v0.21.x type $npm$chalk$StyleElement = { open: string; close: string; }; -type $npm$chalk$Chain = $npm$chalk$Style & (...text: string[]) => string; +type $npm$chalk$Chain = $npm$chalk$Style & (...text: any[]) => string; type $npm$chalk$Style = { // General diff --git a/flow-typed/npm/codecov_vx.x.x.js b/flow-typed/npm/codecov_vx.x.x.js index ad263ff2..3cd95219 100644 --- a/flow-typed/npm/codecov_vx.x.x.js +++ b/flow-typed/npm/codecov_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 6fc611692e0632777ba4b3f4cad5e280 -// flow-typed version: <>/codecov_v2.2.0/flow_v0.46.0 +// flow-typed signature: 8c12d1f7eb223c74ab19a5ff7c585392 +// flow-typed version: <>/codecov_v2.2.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-config-airbnb-base_vx.x.x.js b/flow-typed/npm/eslint-config-airbnb-base_vx.x.x.js index 910a3ccf..869acd2d 100644 --- a/flow-typed/npm/eslint-config-airbnb-base_vx.x.x.js +++ b/flow-typed/npm/eslint-config-airbnb-base_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 85a3ad529bf61fa0b32a0d1041384b69 -// flow-typed version: <>/eslint-config-airbnb-base_v11.2.0/flow_v0.46.0 +// flow-typed signature: d731cec790e8053f6e6bd3c6cc229877 +// flow-typed version: <>/eslint-config-airbnb-base_v11.2.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-config-prettier_vx.x.x.js b/flow-typed/npm/eslint-config-prettier_vx.x.x.js new file mode 100644 index 00000000..634e5090 --- /dev/null +++ b/flow-typed/npm/eslint-config-prettier_vx.x.x.js @@ -0,0 +1,59 @@ +// flow-typed signature: 892a388cdb6d8ed68bc844fbd381403e +// flow-typed version: <>/eslint-config-prettier_v2.2.0/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'eslint-config-prettier' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'eslint-config-prettier' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'eslint-config-prettier/bin/cli' { + declare module.exports: any; +} + +declare module 'eslint-config-prettier/bin/validators' { + declare module.exports: any; +} + +declare module 'eslint-config-prettier/flowtype' { + declare module.exports: any; +} + +declare module 'eslint-config-prettier/react' { + declare module.exports: any; +} + +// Filename aliases +declare module 'eslint-config-prettier/bin/cli.js' { + declare module.exports: $Exports<'eslint-config-prettier/bin/cli'>; +} +declare module 'eslint-config-prettier/bin/validators.js' { + declare module.exports: $Exports<'eslint-config-prettier/bin/validators'>; +} +declare module 'eslint-config-prettier/flowtype.js' { + declare module.exports: $Exports<'eslint-config-prettier/flowtype'>; +} +declare module 'eslint-config-prettier/index' { + declare module.exports: $Exports<'eslint-config-prettier'>; +} +declare module 'eslint-config-prettier/index.js' { + declare module.exports: $Exports<'eslint-config-prettier'>; +} +declare module 'eslint-config-prettier/react.js' { + declare module.exports: $Exports<'eslint-config-prettier/react'>; +} diff --git a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js b/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js index 7c54a51e..5f74314a 100644 --- a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 771ac283d3fd89f1b981555e4b615f09 -// flow-typed version: <>/eslint-plugin-flowtype_v2.33.0/flow_v0.46.0 +// flow-typed signature: 42ea966e13845f9b8d5b88fb1b30e5a7 +// flow-typed version: <>/eslint-plugin-flowtype_v2.34.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-import_vx.x.x.js b/flow-typed/npm/eslint-plugin-import_vx.x.x.js index f48d65a7..a96baefe 100644 --- a/flow-typed/npm/eslint-plugin-import_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-import_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 457adad52df6a2ab435814a0ec6960d7 -// flow-typed version: <>/eslint-plugin-import_v2.2.0/flow_v0.46.0 +// flow-typed signature: 6b428c3173e838b9127775795f352da5 +// flow-typed version: <>/eslint-plugin-import_v2.6.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: @@ -114,6 +114,10 @@ declare module 'eslint-plugin-import/lib/rules/no-amd' { declare module.exports: any; } +declare module 'eslint-plugin-import/lib/rules/no-anonymous-default-export' { + declare module.exports: any; +} + declare module 'eslint-plugin-import/lib/rules/no-commonjs' { declare module.exports: any; } @@ -264,6 +268,9 @@ declare module 'eslint-plugin-import/lib/rules/no-absolute-path.js' { declare module 'eslint-plugin-import/lib/rules/no-amd.js' { declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-amd'>; } +declare module 'eslint-plugin-import/lib/rules/no-anonymous-default-export.js' { + declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-anonymous-default-export'>; +} declare module 'eslint-plugin-import/lib/rules/no-commonjs.js' { declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-commonjs'>; } diff --git a/flow-typed/npm/eslint-plugin-jest_vx.x.x.js b/flow-typed/npm/eslint-plugin-jest_vx.x.x.js index 4b68737f..980265e0 100644 --- a/flow-typed/npm/eslint-plugin-jest_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-jest_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 561f8fb644b31ab1bdbbbba8aa36dd09 -// flow-typed version: <>/eslint-plugin-jest_v20.0.3/flow_v0.46.0 +// flow-typed signature: 1188c0d4ae2a77a9ed29ee9896c2b8d9 +// flow-typed version: <>/eslint-plugin-jest_v20.0.3/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint_vx.x.x.js b/flow-typed/npm/eslint_vx.x.x.js index 67ee9bdb..c9898661 100644 --- a/flow-typed/npm/eslint_vx.x.x.js +++ b/flow-typed/npm/eslint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 34e61917f309fb658542988a913e40e6 -// flow-typed version: <>/eslint_v3.19.0/flow_v0.46.0 +// flow-typed signature: 3bdde8b4c3132ddeee7f85b4a7ce3801 +// flow-typed version: <>/eslint_v4.1.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: @@ -26,7 +26,15 @@ declare module 'eslint/bin/eslint' { declare module.exports: any; } -declare module 'eslint/conf/cli-options' { +declare module 'eslint/conf/config-schema' { + declare module.exports: any; +} + +declare module 'eslint/conf/default-cli-options' { + declare module.exports: any; +} + +declare module 'eslint/conf/default-config-options' { declare module.exports: any; } @@ -94,6 +102,10 @@ declare module 'eslint/lib/config/autoconfig' { declare module.exports: any; } +declare module 'eslint/lib/config/config-cache' { + declare module.exports: any; +} + declare module 'eslint/lib/config/config-file' { declare module.exports: any; } @@ -122,10 +134,6 @@ declare module 'eslint/lib/config/plugins' { declare module.exports: any; } -declare module 'eslint/lib/eslint' { - declare module.exports: any; -} - declare module 'eslint/lib/file-finder' { declare module.exports: any; } @@ -190,6 +198,10 @@ declare module 'eslint/lib/internal-rules/internal-no-invalid-meta' { declare module.exports: any; } +declare module 'eslint/lib/linter' { + declare module.exports: any; +} + declare module 'eslint/lib/load-rules' { declare module.exports: any; } @@ -214,6 +226,10 @@ declare module 'eslint/lib/rules/accessor-pairs' { declare module.exports: any; } +declare module 'eslint/lib/rules/array-bracket-newline' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/array-bracket-spacing' { declare module.exports: any; } @@ -222,6 +238,10 @@ declare module 'eslint/lib/rules/array-callback-return' { declare module.exports: any; } +declare module 'eslint/lib/rules/array-element-newline' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/arrow-body-style' { declare module.exports: any; } @@ -318,6 +338,10 @@ declare module 'eslint/lib/rules/eqeqeq' { declare module.exports: any; } +declare module 'eslint/lib/rules/for-direction' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/func-call-spacing' { declare module.exports: any; } @@ -362,6 +386,10 @@ declare module 'eslint/lib/rules/id-match' { declare module.exports: any; } +declare module 'eslint/lib/rules/indent-legacy' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/indent' { declare module.exports: any; } @@ -466,6 +494,10 @@ declare module 'eslint/lib/rules/no-bitwise' { declare module.exports: any; } +declare module 'eslint/lib/rules/no-buffer-constructor' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/no-caller' { declare module.exports: any; } @@ -1026,6 +1058,10 @@ declare module 'eslint/lib/rules/padded-blocks' { declare module.exports: any; } +declare module 'eslint/lib/rules/padding-line-between-statements' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/prefer-arrow-callback' { declare module.exports: any; } @@ -1094,6 +1130,10 @@ declare module 'eslint/lib/rules/semi-spacing' { declare module.exports: any; } +declare module 'eslint/lib/rules/semi-style' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/semi' { declare module.exports: any; } @@ -1138,6 +1178,10 @@ declare module 'eslint/lib/rules/strict' { declare module.exports: any; } +declare module 'eslint/lib/rules/switch-colon-spacing' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/symbol-description' { declare module.exports: any; } @@ -1250,10 +1294,6 @@ declare module 'eslint/lib/token-store/utils' { declare module.exports: any; } -declare module 'eslint/lib/util/comment-event-generator' { - declare module.exports: any; -} - declare module 'eslint/lib/util/fix-tracker' { declare module.exports: any; } @@ -1322,8 +1362,14 @@ declare module 'eslint/lib/util/xml-escape' { declare module 'eslint/bin/eslint.js' { declare module.exports: $Exports<'eslint/bin/eslint'>; } -declare module 'eslint/conf/cli-options.js' { - declare module.exports: $Exports<'eslint/conf/cli-options'>; +declare module 'eslint/conf/config-schema.js' { + declare module.exports: $Exports<'eslint/conf/config-schema'>; +} +declare module 'eslint/conf/default-cli-options.js' { + declare module.exports: $Exports<'eslint/conf/default-cli-options'>; +} +declare module 'eslint/conf/default-config-options.js' { + declare module.exports: $Exports<'eslint/conf/default-config-options'>; } declare module 'eslint/conf/environments.js' { declare module.exports: $Exports<'eslint/conf/environments'>; @@ -1373,6 +1419,9 @@ declare module 'eslint/lib/config.js' { declare module 'eslint/lib/config/autoconfig.js' { declare module.exports: $Exports<'eslint/lib/config/autoconfig'>; } +declare module 'eslint/lib/config/config-cache.js' { + declare module.exports: $Exports<'eslint/lib/config/config-cache'>; +} declare module 'eslint/lib/config/config-file.js' { declare module.exports: $Exports<'eslint/lib/config/config-file'>; } @@ -1394,9 +1443,6 @@ declare module 'eslint/lib/config/environments.js' { declare module 'eslint/lib/config/plugins.js' { declare module.exports: $Exports<'eslint/lib/config/plugins'>; } -declare module 'eslint/lib/eslint.js' { - declare module.exports: $Exports<'eslint/lib/eslint'>; -} declare module 'eslint/lib/file-finder.js' { declare module.exports: $Exports<'eslint/lib/file-finder'>; } @@ -1445,6 +1491,9 @@ declare module 'eslint/lib/internal-rules/internal-consistent-docs-description.j declare module 'eslint/lib/internal-rules/internal-no-invalid-meta.js' { declare module.exports: $Exports<'eslint/lib/internal-rules/internal-no-invalid-meta'>; } +declare module 'eslint/lib/linter.js' { + declare module.exports: $Exports<'eslint/lib/linter'>; +} declare module 'eslint/lib/load-rules.js' { declare module.exports: $Exports<'eslint/lib/load-rules'>; } @@ -1463,12 +1512,18 @@ declare module 'eslint/lib/rules.js' { declare module 'eslint/lib/rules/accessor-pairs.js' { declare module.exports: $Exports<'eslint/lib/rules/accessor-pairs'>; } +declare module 'eslint/lib/rules/array-bracket-newline.js' { + declare module.exports: $Exports<'eslint/lib/rules/array-bracket-newline'>; +} declare module 'eslint/lib/rules/array-bracket-spacing.js' { declare module.exports: $Exports<'eslint/lib/rules/array-bracket-spacing'>; } declare module 'eslint/lib/rules/array-callback-return.js' { declare module.exports: $Exports<'eslint/lib/rules/array-callback-return'>; } +declare module 'eslint/lib/rules/array-element-newline.js' { + declare module.exports: $Exports<'eslint/lib/rules/array-element-newline'>; +} declare module 'eslint/lib/rules/arrow-body-style.js' { declare module.exports: $Exports<'eslint/lib/rules/arrow-body-style'>; } @@ -1541,6 +1596,9 @@ declare module 'eslint/lib/rules/eol-last.js' { declare module 'eslint/lib/rules/eqeqeq.js' { declare module.exports: $Exports<'eslint/lib/rules/eqeqeq'>; } +declare module 'eslint/lib/rules/for-direction.js' { + declare module.exports: $Exports<'eslint/lib/rules/for-direction'>; +} declare module 'eslint/lib/rules/func-call-spacing.js' { declare module.exports: $Exports<'eslint/lib/rules/func-call-spacing'>; } @@ -1574,6 +1632,9 @@ declare module 'eslint/lib/rules/id-length.js' { declare module 'eslint/lib/rules/id-match.js' { declare module.exports: $Exports<'eslint/lib/rules/id-match'>; } +declare module 'eslint/lib/rules/indent-legacy.js' { + declare module.exports: $Exports<'eslint/lib/rules/indent-legacy'>; +} declare module 'eslint/lib/rules/indent.js' { declare module.exports: $Exports<'eslint/lib/rules/indent'>; } @@ -1652,6 +1713,9 @@ declare module 'eslint/lib/rules/no-await-in-loop.js' { declare module 'eslint/lib/rules/no-bitwise.js' { declare module.exports: $Exports<'eslint/lib/rules/no-bitwise'>; } +declare module 'eslint/lib/rules/no-buffer-constructor.js' { + declare module.exports: $Exports<'eslint/lib/rules/no-buffer-constructor'>; +} declare module 'eslint/lib/rules/no-caller.js' { declare module.exports: $Exports<'eslint/lib/rules/no-caller'>; } @@ -2072,6 +2136,9 @@ declare module 'eslint/lib/rules/operator-linebreak.js' { declare module 'eslint/lib/rules/padded-blocks.js' { declare module.exports: $Exports<'eslint/lib/rules/padded-blocks'>; } +declare module 'eslint/lib/rules/padding-line-between-statements.js' { + declare module.exports: $Exports<'eslint/lib/rules/padding-line-between-statements'>; +} declare module 'eslint/lib/rules/prefer-arrow-callback.js' { declare module.exports: $Exports<'eslint/lib/rules/prefer-arrow-callback'>; } @@ -2123,6 +2190,9 @@ declare module 'eslint/lib/rules/rest-spread-spacing.js' { declare module 'eslint/lib/rules/semi-spacing.js' { declare module.exports: $Exports<'eslint/lib/rules/semi-spacing'>; } +declare module 'eslint/lib/rules/semi-style.js' { + declare module.exports: $Exports<'eslint/lib/rules/semi-style'>; +} declare module 'eslint/lib/rules/semi.js' { declare module.exports: $Exports<'eslint/lib/rules/semi'>; } @@ -2156,6 +2226,9 @@ declare module 'eslint/lib/rules/spaced-comment.js' { declare module 'eslint/lib/rules/strict.js' { declare module.exports: $Exports<'eslint/lib/rules/strict'>; } +declare module 'eslint/lib/rules/switch-colon-spacing.js' { + declare module.exports: $Exports<'eslint/lib/rules/switch-colon-spacing'>; +} declare module 'eslint/lib/rules/symbol-description.js' { declare module.exports: $Exports<'eslint/lib/rules/symbol-description'>; } @@ -2240,9 +2313,6 @@ declare module 'eslint/lib/token-store/skip-cursor.js' { declare module 'eslint/lib/token-store/utils.js' { declare module.exports: $Exports<'eslint/lib/token-store/utils'>; } -declare module 'eslint/lib/util/comment-event-generator.js' { - declare module.exports: $Exports<'eslint/lib/util/comment-event-generator'>; -} declare module 'eslint/lib/util/fix-tracker.js' { declare module.exports: $Exports<'eslint/lib/util/fix-tracker'>; } diff --git a/flow-typed/npm/faker_vx.x.x.js b/flow-typed/npm/faker_vx.x.x.js index b2e0cfa1..4f0334fe 100644 --- a/flow-typed/npm/faker_vx.x.x.js +++ b/flow-typed/npm/faker_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: e57fb264bdf23fd925970184e58f8d25 -// flow-typed version: <>/faker_v4.1.0/flow_v0.46.0 +// flow-typed signature: 7b4ee7f2dd77789ff580f24c495a2433 +// flow-typed version: <>/faker_v4.1.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/fb-watchman_vx.x.x.js b/flow-typed/npm/fb-watchman_vx.x.x.js index d75d4703..25b06f43 100644 --- a/flow-typed/npm/fb-watchman_vx.x.x.js +++ b/flow-typed/npm/fb-watchman_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: fefe3e7176829d5610e325a684f937bb -// flow-typed version: <>/fb-watchman_v2.0.0/flow_v0.46.0 +// flow-typed signature: e2ad71d9ae8a4c428f80d022db191699 +// flow-typed version: <>/fb-watchman_v2.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/flow-typed_vx.x.x.js b/flow-typed/npm/flow-typed_vx.x.x.js index f7515d20..561ff348 100644 --- a/flow-typed/npm/flow-typed_vx.x.x.js +++ b/flow-typed/npm/flow-typed_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: fe6193cea8c2348ac82d1b4c1b91f8d7 -// flow-typed version: <>/flow-typed_v2.1.2/flow_v0.46.0 +// flow-typed signature: cafa6f3ad70d243f80ad5cea7233815e +// flow-typed version: <>/flow-typed_v2.1.2/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/husky_vx.x.x.js b/flow-typed/npm/husky_vx.x.x.js new file mode 100644 index 00000000..07e97a46 --- /dev/null +++ b/flow-typed/npm/husky_vx.x.x.js @@ -0,0 +1,88 @@ +// flow-typed signature: 22b5636256912a22de66f02bfbb9bae6 +// flow-typed version: <>/husky_v0.14.1/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'husky' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'husky' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'husky/__tests__/index' { + declare module.exports: any; +} + +declare module 'husky/bin/install' { + declare module.exports: any; +} + +declare module 'husky/bin/uninstall' { + declare module.exports: any; +} + +declare module 'husky/src/install' { + declare module.exports: any; +} + +declare module 'husky/src/uninstall' { + declare module.exports: any; +} + +declare module 'husky/src/utils/find-hooks-dir' { + declare module.exports: any; +} + +declare module 'husky/src/utils/find-parent' { + declare module.exports: any; +} + +declare module 'husky/src/utils/get-hook-script' { + declare module.exports: any; +} + +declare module 'husky/src/utils/is-husky' { + declare module.exports: any; +} + +// Filename aliases +declare module 'husky/__tests__/index.js' { + declare module.exports: $Exports<'husky/__tests__/index'>; +} +declare module 'husky/bin/install.js' { + declare module.exports: $Exports<'husky/bin/install'>; +} +declare module 'husky/bin/uninstall.js' { + declare module.exports: $Exports<'husky/bin/uninstall'>; +} +declare module 'husky/src/install.js' { + declare module.exports: $Exports<'husky/src/install'>; +} +declare module 'husky/src/uninstall.js' { + declare module.exports: $Exports<'husky/src/uninstall'>; +} +declare module 'husky/src/utils/find-hooks-dir.js' { + declare module.exports: $Exports<'husky/src/utils/find-hooks-dir'>; +} +declare module 'husky/src/utils/find-parent.js' { + declare module.exports: $Exports<'husky/src/utils/find-parent'>; +} +declare module 'husky/src/utils/get-hook-script.js' { + declare module.exports: $Exports<'husky/src/utils/get-hook-script'>; +} +declare module 'husky/src/utils/is-husky.js' { + declare module.exports: $Exports<'husky/src/utils/is-husky'>; +} diff --git a/flow-typed/npm/inflection_vx.x.x.js b/flow-typed/npm/inflection_vx.x.x.js index 7dbfa3b7..1d115047 100644 --- a/flow-typed/npm/inflection_vx.x.x.js +++ b/flow-typed/npm/inflection_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: dccaa621238a70ced93fb1ec24f880a9 -// flow-typed version: <>/inflection_v1.12.0/flow_v0.46.0 +// flow-typed signature: 5eabb9d39c7bd8ce0a65b0e21b41d991 +// flow-typed version: <>/inflection_v1.12.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/jest-cli_vx.x.x.js b/flow-typed/npm/jest-cli_vx.x.x.js index b39a9aa8..c6f2de24 100644 --- a/flow-typed/npm/jest-cli_vx.x.x.js +++ b/flow-typed/npm/jest-cli_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c449174fb4ed4a224885798c6b311231 -// flow-typed version: <>/jest-cli_v20.0.3/flow_v0.46.0 +// flow-typed signature: 0f150bf2deeadc503005bb40b9fc8beb +// flow-typed version: <>/jest-cli_v20.0.4/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/jest_v20.x.x.js b/flow-typed/npm/jest_v20.x.x.js index a8f4aa16..0b01c0d7 100644 --- a/flow-typed/npm/jest_v20.x.x.js +++ b/flow-typed/npm/jest_v20.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: eb392bde0440325fce2421d18447acde -// flow-typed version: 0786be2fed/jest_v20.x.x/flow_>=v0.33.x +// flow-typed signature: 599948fccaf9881f9a36213f63311213 +// flow-typed version: 50ddf2f004/jest_v20.x.x/flow_>=v0.33.x type JestMockFn = { (...args: Array): any, @@ -30,6 +30,14 @@ type JestMockFn = { * completely restore a mock back to its initial state. */ mockReset(): Function, + /** + * Removes the mock and restores the initial implementation. This is useful + * when you want to mock functions in certain test cases and restore the + * original implementation in others. Beware that mockFn.mockRestore only + * works when mock was created with jest.spyOn. Thus you have to take care of + * restoration yourself when manually assigning jest.fn(). + */ + mockRestore(): Function, /** * Accepts a function that should be used as the implementation of the mock. * The mock itself will still record all calls that go into and instances @@ -77,7 +85,7 @@ type JestCallsType = { type JestClockType = { install(): void, mockDate(date: Date): void, - tick(): void, + tick(milliseconds?: number): void, uninstall(): void }; @@ -101,8 +109,31 @@ type JestPromiseType = { resolves: JestExpectType }; +/** + * Plugin: jest-enzyme + */ +type EnzymeMatchersType = { + toBeChecked(): void, + toBeDisabled(): void, + toBeEmpty(): void, + toBePresent(): void, + toContainReact(element: React$Element): void, + toHaveClassName(className: string): void, + toHaveHTML(html: string): void, + toHaveProp(propKey: string, propValue?: any): void, + toHaveRef(refName: string): void, + toHaveState(stateKey: string, stateValue?: any): void, + toHaveStyle(styleKey: string, styleValue?: any): void, + toHaveTagName(tagName: string): void, + toHaveText(text: string): void, + toIncludeText(text: string): void, + toHaveValue(value: any): void, + toMatchElement(element: React$Element): void, + toMatchSelector(selector: string): void, +}; + type JestExpectType = { - not: JestExpectType, + not: JestExpectType & EnzymeMatchersType, /** * If you have a mock function, you can use .lastCalledWith to test what * arguments it was last called with. @@ -202,6 +233,11 @@ type JestExpectType = { * specific arguments. */ toHaveBeenCalledWith(...args: Array): void, + /** + * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called + * with specific arguments. + */ + toHaveBeenLastCalledWith(...args: Array): void, /** * Check that an object has a .length property and it is set to a certain * numeric value. @@ -225,13 +261,13 @@ type JestExpectType = { toMatchSnapshot(name?: string): void, /** * Use .toThrow to test that a function throws when it is called. + * If you want to test that a specific error gets thrown, you can provide an + * argument to toThrow. The argument can be a string for the error message, + * a class for the error, or a regex that should match the error. + * + * Alias: .toThrowError */ - toThrow(message?: string | Error): void, - /** - * Use .toThrowError to test that a function throws a specific error when it - * is called. The argument can be a string for the error message, a class for - * the error, or a regex that should match the error. - */ + toThrow(message?: string | Error | RegExp): void, toThrowError(message?: string | Error | RegExp): void, /** * Use .toThrowErrorMatchingSnapshot to test that a function throws a error @@ -307,7 +343,11 @@ type JestObjectType = { * The third argument can be used to create virtual mocks -- mocks of modules * that don't exist anywhere in the system. */ - mock(moduleName: string, moduleFactory?: any): JestObjectType, + mock( + moduleName: string, + moduleFactory?: any, + options?: Object + ): JestObjectType, /** * Resets the module registry - the cache of all required modules. This is * useful to isolate modules where local state might conflict between tests. @@ -428,7 +468,7 @@ declare var xtest: typeof it; /** The expect function is used every time you want to test a value */ declare var expect: { /** The object that you want to make assertions against */ - (value: any): JestExpectType & JestPromiseType, + (value: any): JestExpectType & JestPromiseType & EnzymeMatchersType, /** Add additional Jasmine matchers to Jest's roster */ extend(matchers: { [name: string]: JestMatcher }): void, /** Add a module that formats application-specific data structures. */ diff --git a/flow-typed/npm/knex_vx.x.x.js b/flow-typed/npm/knex_vx.x.x.js index 4eeb55de..6c793598 100644 --- a/flow-typed/npm/knex_vx.x.x.js +++ b/flow-typed/npm/knex_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: a31697ad92b73e537dd49fdbb340d648 -// flow-typed version: <>/knex_v0.13.0/flow_v0.46.0 +// flow-typed signature: 12e69eb8e20488a489bee10fc63e7ff7 +// flow-typed version: <>/knex_v0.13.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/memory-fs_vx.x.x.js b/flow-typed/npm/memory-fs_vx.x.x.js new file mode 100644 index 00000000..57b082e9 --- /dev/null +++ b/flow-typed/npm/memory-fs_vx.x.x.js @@ -0,0 +1,46 @@ +// flow-typed signature: 8e7b5c7974ebae80da86f1e10773bf46 +// flow-typed version: <>/memory-fs_v0.4.1/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'memory-fs' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'memory-fs' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'memory-fs/lib/join' { + declare module.exports: any; +} + +declare module 'memory-fs/lib/MemoryFileSystem' { + declare module.exports: any; +} + +declare module 'memory-fs/lib/normalize' { + declare module.exports: any; +} + +// Filename aliases +declare module 'memory-fs/lib/join.js' { + declare module.exports: $Exports<'memory-fs/lib/join'>; +} +declare module 'memory-fs/lib/MemoryFileSystem.js' { + declare module.exports: $Exports<'memory-fs/lib/MemoryFileSystem'>; +} +declare module 'memory-fs/lib/normalize.js' { + declare module.exports: $Exports<'memory-fs/lib/normalize'>; +} diff --git a/flow-typed/npm/mz_vx.x.x.js b/flow-typed/npm/mz_vx.x.x.js new file mode 100644 index 00000000..dc22b121 --- /dev/null +++ b/flow-typed/npm/mz_vx.x.x.js @@ -0,0 +1,73 @@ +// flow-typed signature: 8bb651614917502ddb7611a203b02d84 +// flow-typed version: <>/mz_v2.6.0/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'mz' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'mz' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'mz/child_process' { + declare module.exports: any; +} + +declare module 'mz/crypto' { + declare module.exports: any; +} + +declare module 'mz/dns' { + declare module.exports: any; +} + +declare module 'mz/fs' { + declare module.exports: any; +} + +declare module 'mz/readline' { + declare module.exports: any; +} + +declare module 'mz/zlib' { + declare module.exports: any; +} + +// Filename aliases +declare module 'mz/child_process.js' { + declare module.exports: $Exports<'mz/child_process'>; +} +declare module 'mz/crypto.js' { + declare module.exports: $Exports<'mz/crypto'>; +} +declare module 'mz/dns.js' { + declare module.exports: $Exports<'mz/dns'>; +} +declare module 'mz/fs.js' { + declare module.exports: $Exports<'mz/fs'>; +} +declare module 'mz/index' { + declare module.exports: $Exports<'mz'>; +} +declare module 'mz/index.js' { + declare module.exports: $Exports<'mz'>; +} +declare module 'mz/readline.js' { + declare module.exports: $Exports<'mz/readline'>; +} +declare module 'mz/zlib.js' { + declare module.exports: $Exports<'mz/zlib'>; +} diff --git a/flow-typed/npm/object.entries_vx.x.x.js b/flow-typed/npm/object.entries_vx.x.x.js index 5446d823..c8bd362c 100644 --- a/flow-typed/npm/object.entries_vx.x.x.js +++ b/flow-typed/npm/object.entries_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c9b1df18ba7deb7cc91f30cac6203b90 -// flow-typed version: <>/object.entries_v1.0.4/flow_v0.46.0 +// flow-typed signature: f387f72fe08800e672f167d65146d3cf +// flow-typed version: <>/object.entries_v1.0.4/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/object.values_vx.x.x.js b/flow-typed/npm/object.values_vx.x.x.js new file mode 100644 index 00000000..8c27dae8 --- /dev/null +++ b/flow-typed/npm/object.values_vx.x.x.js @@ -0,0 +1,73 @@ +// flow-typed signature: 90417246066f88c25702115729260682 +// flow-typed version: <>/object.values_v1.0.4/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'object.values' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'object.values' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'object.values/implementation' { + declare module.exports: any; +} + +declare module 'object.values/polyfill' { + declare module.exports: any; +} + +declare module 'object.values/shim' { + declare module.exports: any; +} + +declare module 'object.values/test/index' { + declare module.exports: any; +} + +declare module 'object.values/test/shimmed' { + declare module.exports: any; +} + +declare module 'object.values/test/tests' { + declare module.exports: any; +} + +// Filename aliases +declare module 'object.values/implementation.js' { + declare module.exports: $Exports<'object.values/implementation'>; +} +declare module 'object.values/index' { + declare module.exports: $Exports<'object.values'>; +} +declare module 'object.values/index.js' { + declare module.exports: $Exports<'object.values'>; +} +declare module 'object.values/polyfill.js' { + declare module.exports: $Exports<'object.values/polyfill'>; +} +declare module 'object.values/shim.js' { + declare module.exports: $Exports<'object.values/shim'>; +} +declare module 'object.values/test/index.js' { + declare module.exports: $Exports<'object.values/test/index'>; +} +declare module 'object.values/test/shimmed.js' { + declare module.exports: $Exports<'object.values/test/shimmed'>; +} +declare module 'object.values/test/tests.js' { + declare module.exports: $Exports<'object.values/test/tests'>; +} diff --git a/flow-typed/npm/ora_vx.x.x.js b/flow-typed/npm/ora_vx.x.x.js index 94741f45..9a51ab4a 100644 --- a/flow-typed/npm/ora_vx.x.x.js +++ b/flow-typed/npm/ora_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 103b53410ea4fc00e5ad3c19715872a2 -// flow-typed version: <>/ora_v1.2.0/flow_v0.46.0 +// flow-typed signature: d3153d3246264eb13ee496846d27ba8e +// flow-typed version: <>/ora_v1.3.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/prettier_vx.x.x.js b/flow-typed/npm/prettier_vx.x.x.js new file mode 100644 index 00000000..b6cdae16 --- /dev/null +++ b/flow-typed/npm/prettier_vx.x.x.js @@ -0,0 +1,73 @@ +// flow-typed signature: 291c38d09bd3ed8eace0eefdb1d3fb13 +// flow-typed version: <>/prettier_v1.4.4/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'prettier' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'prettier' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'prettier/bin/prettier' { + declare module.exports: any; +} + +declare module 'prettier/parser-babylon' { + declare module.exports: any; +} + +declare module 'prettier/parser-flow' { + declare module.exports: any; +} + +declare module 'prettier/parser-graphql' { + declare module.exports: any; +} + +declare module 'prettier/parser-postcss' { + declare module.exports: any; +} + +declare module 'prettier/parser-typescript' { + declare module.exports: any; +} + +// Filename aliases +declare module 'prettier/bin/prettier.js' { + declare module.exports: $Exports<'prettier/bin/prettier'>; +} +declare module 'prettier/index' { + declare module.exports: $Exports<'prettier'>; +} +declare module 'prettier/index.js' { + declare module.exports: $Exports<'prettier'>; +} +declare module 'prettier/parser-babylon.js' { + declare module.exports: $Exports<'prettier/parser-babylon'>; +} +declare module 'prettier/parser-flow.js' { + declare module.exports: $Exports<'prettier/parser-flow'>; +} +declare module 'prettier/parser-graphql.js' { + declare module.exports: $Exports<'prettier/parser-graphql'>; +} +declare module 'prettier/parser-postcss.js' { + declare module.exports: $Exports<'prettier/parser-postcss'>; +} +declare module 'prettier/parser-typescript.js' { + declare module.exports: $Exports<'prettier/parser-typescript'>; +} diff --git a/flow-typed/npm/qs_vx.x.x.js b/flow-typed/npm/qs_vx.x.x.js index 423ed9a2..6975dd21 100644 --- a/flow-typed/npm/qs_vx.x.x.js +++ b/flow-typed/npm/qs_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: b99960b70adf287611a8695e96188d29 -// flow-typed version: <>/qs_v6.4.0/flow_v0.46.0 +// flow-typed signature: 22b91822b751617004500eb40c533b7e +// flow-typed version: <>/qs_v6.4.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/remark-cli_vx.x.x.js b/flow-typed/npm/remark-cli_vx.x.x.js index 4178f3b8..4db09791 100644 --- a/flow-typed/npm/remark-cli_vx.x.x.js +++ b/flow-typed/npm/remark-cli_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 065821e82444a79a1b28360ed9312883 -// flow-typed version: <>/remark-cli_v3.0.1/flow_v0.46.0 +// flow-typed signature: ea7ddb20943602fe1e755c51cc3a3a5b +// flow-typed version: <>/remark-cli_v3.0.1/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/remark-lint_vx.x.x.js b/flow-typed/npm/remark-lint_vx.x.x.js index b2b6e5d7..97ac1dda 100644 --- a/flow-typed/npm/remark-lint_vx.x.x.js +++ b/flow-typed/npm/remark-lint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 933cc59e23a9ac539270ea3d95b11703 -// flow-typed version: <>/remark-lint_v6.0.0/flow_v0.46.0 +// flow-typed signature: a2277cbac4103d8933d9d5af39e6b873 +// flow-typed version: <>/remark-lint_v6.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/remark-preset-lint-recommended_vx.x.x.js b/flow-typed/npm/remark-preset-lint-recommended_vx.x.x.js index 433beaf1..77f61484 100644 --- a/flow-typed/npm/remark-preset-lint-recommended_vx.x.x.js +++ b/flow-typed/npm/remark-preset-lint-recommended_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 27c01b365d249f224c837b3f5c184777 -// flow-typed version: <>/remark-preset-lint-recommended_v2.0.0/flow_v0.46.0 +// flow-typed signature: 418a0460fd320a16f663ae0f6b3f2a6a +// flow-typed version: <>/remark-preset-lint-recommended_v2.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-alias_vx.x.x.js b/flow-typed/npm/rollup-plugin-alias_vx.x.x.js index 48c3199b..f07d734d 100644 --- a/flow-typed/npm/rollup-plugin-alias_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-alias_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 81f65a8de578c83397b0f5c8d8266d05 -// flow-typed version: <>/rollup-plugin-alias_v1.3.1/flow_v0.46.0 +// flow-typed signature: 2b92e07b2a692347897142e2f758332a +// flow-typed version: <>/rollup-plugin-alias_vzacharygolba/rollup-plugin-alias#resolve-index-prebuilt/flow_v0.48.0 /** * This is an autogenerated libdef stub for: @@ -34,6 +34,38 @@ declare module 'rollup-plugin-alias/src/index' { declare module.exports: any; } +declare module 'rollup-plugin-alias/test/files/aliasMe' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/folder/anotherNumber' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/folder/hipster' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/folder/index' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/index' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/localAliasMe' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/files/nonAliased' { + declare module.exports: any; +} + +declare module 'rollup-plugin-alias/test/index' { + declare module.exports: any; +} + // Filename aliases declare module 'rollup-plugin-alias/dist/rollup-plugin-alias.es2015.js' { declare module.exports: $Exports<'rollup-plugin-alias/dist/rollup-plugin-alias.es2015'>; @@ -44,3 +76,27 @@ declare module 'rollup-plugin-alias/dist/rollup-plugin-alias.js' { declare module 'rollup-plugin-alias/src/index.js' { declare module.exports: $Exports<'rollup-plugin-alias/src/index'>; } +declare module 'rollup-plugin-alias/test/files/aliasMe.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/aliasMe'>; +} +declare module 'rollup-plugin-alias/test/files/folder/anotherNumber.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/folder/anotherNumber'>; +} +declare module 'rollup-plugin-alias/test/files/folder/hipster.jsx' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/folder/hipster'>; +} +declare module 'rollup-plugin-alias/test/files/folder/index.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/folder/index'>; +} +declare module 'rollup-plugin-alias/test/files/index.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/index'>; +} +declare module 'rollup-plugin-alias/test/files/localAliasMe.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/localAliasMe'>; +} +declare module 'rollup-plugin-alias/test/files/nonAliased.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/files/nonAliased'>; +} +declare module 'rollup-plugin-alias/test/index.js' { + declare module.exports: $Exports<'rollup-plugin-alias/test/index'>; +} diff --git a/flow-typed/npm/rollup-plugin-babel_vx.x.x.js b/flow-typed/npm/rollup-plugin-babel_vx.x.x.js index 85649bf4..782a31cb 100644 --- a/flow-typed/npm/rollup-plugin-babel_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-babel_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 8455c63cce651544db25522a722a5d27 -// flow-typed version: <>/rollup-plugin-babel_v2.7.1/flow_v0.46.0 +// flow-typed signature: 70c995ac0585be20bd9ac2ddd38f04ae +// flow-typed version: <>/rollup-plugin-babel_v2.7.1/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-cleanup_vx.x.x.js b/flow-typed/npm/rollup-plugin-cleanup_vx.x.x.js new file mode 100644 index 00000000..ede1e766 --- /dev/null +++ b/flow-typed/npm/rollup-plugin-cleanup_vx.x.x.js @@ -0,0 +1,81 @@ +// flow-typed signature: 1bf551e5f6fd16009f418a19ac551ca4 +// flow-typed version: <>/rollup-plugin-cleanup_v1.0.1/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'rollup-plugin-cleanup' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'rollup-plugin-cleanup' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'rollup-plugin-cleanup/dist/rollup-plugin-cleanup.es' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/dist/rollup-plugin-cleanup' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/blank-comments' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/cleanup' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/index' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/parse-options' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/remove-lines' { + declare module.exports: any; +} + +declare module 'rollup-plugin-cleanup/src/util/filter' { + declare module.exports: any; +} + +// Filename aliases +declare module 'rollup-plugin-cleanup/dist/rollup-plugin-cleanup.es.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/dist/rollup-plugin-cleanup.es'>; +} +declare module 'rollup-plugin-cleanup/dist/rollup-plugin-cleanup.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/dist/rollup-plugin-cleanup'>; +} +declare module 'rollup-plugin-cleanup/src/blank-comments.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/blank-comments'>; +} +declare module 'rollup-plugin-cleanup/src/cleanup.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/cleanup'>; +} +declare module 'rollup-plugin-cleanup/src/index.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/index'>; +} +declare module 'rollup-plugin-cleanup/src/parse-options.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/parse-options'>; +} +declare module 'rollup-plugin-cleanup/src/remove-lines.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/remove-lines'>; +} +declare module 'rollup-plugin-cleanup/src/util/filter.js' { + declare module.exports: $Exports<'rollup-plugin-cleanup/src/util/filter'>; +} diff --git a/flow-typed/npm/rollup-plugin-eslint_vx.x.x.js b/flow-typed/npm/rollup-plugin-eslint_vx.x.x.js index a7488302..b9225b85 100644 --- a/flow-typed/npm/rollup-plugin-eslint_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-eslint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: e7815e98acdc1589d968b0affd72b8dc -// flow-typed version: <>/rollup-plugin-eslint_v3.0.0/flow_v0.46.0 +// flow-typed signature: f179e558ae40d79b376699a491bfff7f +// flow-typed version: <>/rollup-plugin-eslint_v3.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-json_vx.x.x.js b/flow-typed/npm/rollup-plugin-json_vx.x.x.js index 4d0513a3..cb8fd199 100644 --- a/flow-typed/npm/rollup-plugin-json_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-json_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 4fa451751ed0f48585b4f26edf8398a3 -// flow-typed version: <>/rollup-plugin-json_v2.1.1/flow_v0.46.0 +// flow-typed signature: b4b154359450c77e6a9a7779b5367444 +// flow-typed version: <>/rollup-plugin-json_v2.3.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-lux_vx.x.x.js b/flow-typed/npm/rollup-plugin-lux_vx.x.x.js index 1a975658..cecc0106 100644 --- a/flow-typed/npm/rollup-plugin-lux_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-lux_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c737773f8669f0bed71675014d21efdb -// flow-typed version: <>/rollup-plugin-lux_v3.0.0/flow_v0.46.0 +// flow-typed signature: 2021ff78c45d4c6f0d7fbe519d92ef9f +// flow-typed version: <>/rollup-plugin-lux_v3.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js b/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js index 539b06ea..dec8d3c1 100644 --- a/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 2ef7f48018e4a4117b5a5d0da443e442 -// flow-typed version: <>/rollup-plugin-node-resolve_v3.0.0/flow_v0.46.0 +// flow-typed signature: 2b1d4762ddff3d629db7db3106dbdb00 +// flow-typed version: <>/rollup-plugin-node-resolve_v3.0.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup_vx.x.x.js b/flow-typed/npm/rollup_vx.x.x.js index 66039dc7..eae75ba7 100644 --- a/flow-typed/npm/rollup_vx.x.x.js +++ b/flow-typed/npm/rollup_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 531ffdb8d996f02680ffe4a71be37169 -// flow-typed version: <>/rollup_v0.41.6/flow_v0.46.0 +// flow-typed signature: 7ea8da31de61326535fc8ebaedc42d13 +// flow-typed version: <>/rollup_v0.43.0/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/shx_vx.x.x.js b/flow-typed/npm/shx_vx.x.x.js index 3994b710..25a2d3e2 100644 --- a/flow-typed/npm/shx_vx.x.x.js +++ b/flow-typed/npm/shx_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: a79191f487ed1cd5d88d436999ab5516 -// flow-typed version: <>/shx_v0.2.2/flow_v0.46.0 +// flow-typed signature: fe195fbb15079619e6383a9e944b9503 +// flow-typed version: <>/shx_v0.2.2/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/slash_vx.x.x.js b/flow-typed/npm/slash_vx.x.x.js new file mode 100644 index 00000000..54492696 --- /dev/null +++ b/flow-typed/npm/slash_vx.x.x.js @@ -0,0 +1,33 @@ +// flow-typed signature: e0f39136c90a54fc43a8277e35dcffeb +// flow-typed version: <>/slash_v1.0.0/flow_v0.48.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'slash' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'slash' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ + + +// Filename aliases +declare module 'slash/index' { + declare module.exports: $Exports<'slash'>; +} +declare module 'slash/index.js' { + declare module.exports: $Exports<'slash'>; +} diff --git a/flow-typed/npm/source-map-support_vx.x.x.js b/flow-typed/npm/source-map-support_vx.x.x.js index f2f0c326..c586914c 100644 --- a/flow-typed/npm/source-map-support_vx.x.x.js +++ b/flow-typed/npm/source-map-support_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 341dcdb6776f1a3010285462ad32e68e -// flow-typed version: <>/source-map-support_v0.4.15/flow_v0.46.0 +// flow-typed signature: deba8f2ca5fc243a7578a7a3e85ae5cd +// flow-typed version: <>/source-map-support_v0.4.15/flow_v0.48.0 /** * This is an autogenerated libdef stub for: diff --git a/package.json b/package.json index 6f68b23b..9b708d17 100644 --- a/package.json +++ b/package.json @@ -12,20 +12,23 @@ "rest", "framework" ], - "main": "src/index.js", + "main": "dist/index.js", "bin": { "lux": "bin/lux" }, "scripts": { - "build": "rollup -c", - "build:debugger": "rollup -c test/utils/debugger/rollup.config.js", + "build": "rollup -c -i src/index.js -o dist/index.js && rollup -c -i src/packages/cli/commands/index.js -o dist/cli.js", + "build:debugger": "rollup -c -i test/utils/debugger/src/debug.js -o test/utils/debugger/dist/debug.js", "clean": "shx rm -rf coverage dist test/test-app/dist", "codecov": "codecov", "debugger": "node test/utils/debugger/dist/debug.js", "flow": "flow check", - "types": "shx rm -rf flow-typed && flow-typed install", "lint": "remark . && eslint --cache .", - "test": "jest" + "lint:fix": "remark . && eslint --cache --fix .", + "precommit": "lint-staged", + "prettier": "prettier --write --single-quote --trailing-comma all --no-semi --parser flow src/**/*.js", + "test": "jest", + "types": "shx rm -rf flow-typed && flow-typed install" }, "author": "Zachary Golba", "license": "MIT", @@ -37,54 +40,76 @@ "node": ">= 6.0" }, "dependencies": { - "ansi-regex": "2.1.1", + "ansi-regex": "3.0.0", "babel-eslint": "7.2.3", - "chalk": "1.1.3", - "commander": "2.9.0", - "eslint": "3.19.0", + "chalk": "2.0.1", + "commander": "2.11.0", + "eslint": "4.2.0", "fb-watchman": "2.0.0", "inflection": "1.12.0", "knex": "0.13.0", - "ora": "1.2.0", - "qs": "6.4.0", - "rollup": "0.41.6", - "rollup-plugin-alias": "1.3.1", + "mz": "2.6.0", + "object.entries": "1.0.4", + "object.values": "1.0.4", + "ora": "1.3.0", + "qs": "6.5.0", + "rollup": "0.45.2", + "rollup-plugin-alias": "zacharygolba/rollup-plugin-alias#resolve-index-prebuilt", "rollup-plugin-babel": "2.7.1", - "rollup-plugin-eslint": "3.0.0", - "rollup-plugin-json": "2.1.1", + "rollup-plugin-cleanup": "1.0.1", + "rollup-plugin-eslint": "4.0.0", + "rollup-plugin-json": "2.3.0", "rollup-plugin-lux": "3.0.0", "rollup-plugin-node-resolve": "3.0.0", + "slash": "1.0.0", "source-map-support": "0.4.15" }, "devDependencies": { - "babel-core": "6.24.1", + "babel-core": "6.25.0", "babel-jest": "20.0.3", "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", "babel-preset-lux": "2.0.2", "codecov": "2.2.0", "eslint-config-airbnb-base": "11.2.0", - "eslint-plugin-flowtype": "2.33.0", - "eslint-plugin-import": "2.2.0", + "eslint-config-prettier": "2.3.0", + "eslint-plugin-flowtype": "2.35.0", + "eslint-plugin-import": "2.7.0", "eslint-plugin-jest": "20.0.3", + "eslint-plugin-prettier": "2.1.2", "faker": "4.1.0", - "flow-bin": "0.46.0", + "flow-bin": "0.50.0", "flow-typed": "2.1.2", - "jest": "20.0.3", - "jest-cli": "20.0.3", - "object.entries": "1.0.4", + "husky": "0.14.3", + "jest": "20.0.4", + "jest-cli": "20.0.4", + "lint-staged": "4.0.1", + "memory-fs": "0.4.1", + "prettier": "1.5.3", "remark-cli": "3.0.1", "remark-lint": "6.0.0", "remark-preset-lint-recommended": "2.0.0", "shx": "0.2.2" }, "jest": { - "testRegex": "\\.test\\.js$", - "testEnvironment": "node", "cacheDirectory": "./.jest-cache", "coveragePathIgnorePatterns": [ "/test/", "/__tests__/", "/node_modules/" + ], + "moduleNameMapper": { + "@lux(.*)": "/src$1" + }, + "setupFiles": [ + "./test/setup.js" + ], + "testRegex": "\\.test\\.js$" + }, + "lint-staged": { + "src/**/*.js": [ + "yarn prettier", + "yarn lint:fix", + "git add" ] } } diff --git a/rollup.config.js b/rollup.config.js index a15c9145..0ffdc84f 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,38 +1,87 @@ -import path from 'path' +import * as path from 'path' +import alias from 'rollup-plugin-alias' +import cleanup from 'rollup-plugin-cleanup' import json from 'rollup-plugin-json' import babel from 'rollup-plugin-babel' import resolve from 'rollup-plugin-node-resolve' +import { dependencies } from './package.json' + +const BANNER = `\ +'use strict'; + +const srcmap = require('source-map-support').install({ + environment: 'node', +}); + +if (Object.entries === undefined) { + require('object.entries').shim(); +} + +if (Object.values === undefined) { + require('object.values').shim(); +} +` + export default { - dest: 'dist/index.js', - entry: 'src/packages/cli/commands/index.js', + banner: BANNER, + external: Object.keys(dependencies).concat([ + 'assert', + 'async_hooks', + 'buffer', + 'child_process', + 'cluster', + 'console', + 'constants', + 'crypto', + 'dgram', + 'dns', + 'domain', + 'events', + 'fs', + 'http', + 'https', + 'inspector', + 'module', + 'net', + 'os', + 'path', + 'process', + 'punycode', + 'querystring', + 'readline', + 'repl', + 'stream', + 'string_decoder', + 'sys', + 'timers', + 'tls', + 'tty', + 'url', + 'util', + 'v8', + 'vm', + 'zlib', + + 'mz/child_process', + 'mz/crypto', + 'mz/dns', + 'mz/fs', + 'mz/readline', + 'mz/zlib', + ]), format: 'cjs', - banner: ( - 'require(\'source-map-support\').install({\n' - + ' environment: \'node\'\n' - + '});\n' - ), - onwarn: ({ code, message }) => { - if (code === 'UNUSED_EXTERNAL_IMPORT') { - return - } - // eslint-disable-next-line no-console - console.warn(message) - }, plugins: [ + alias({ + '@lux': path.join(__dirname, 'src'), + }), json(), babel(), - resolve() + resolve(), + cleanup(), ], - external: id => !( - id.startsWith('.') - || id.startsWith('/') // Absolute path on Unix - || /^[A-Z]:[\\/]/.test(id) // Absolute path on Windows - || id.startsWith('src') - || id.startsWith(path.join(__dirname, 'src')) - || id === 'babelHelpers' - || id === '\u0000babelHelpers' - ), - sourceMap: true + preferConst: true, + sourceMap: true, + useStrict: false, } diff --git a/src/constants.js b/src/constants.js index fa274caa..b28dce56 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,7 +3,8 @@ import * as os from 'os' import { worker, isWorker } from 'cluster' -import normalizePort from './utils/normalize-port' +import normalizePort from '@lux/utils/normalize-port' +import type { Method } from '@lux/packages/request' const { env: ENV } = process @@ -28,7 +29,7 @@ export const CIRCLECI: boolean = Boolean(ENV.CIRCLECI) export const APPVEYOR: boolean = Boolean(ENV.APPVEYOR) export const HAS_BODY: RegExp = /^(?:POST|PATCH)$/ -export const METHODS: Set = new Set([ +export const METHODS: Set = new Set([ 'GET', 'HEAD', 'POST', @@ -37,69 +38,67 @@ export const METHODS: Set = new Set([ 'OPTIONS', ]) -export const STATUS_CODES: Map = ( - new Map([ - [100, 'Continue'], - [101, 'Switching Protocols'], - [102, 'Processing'], - [200, 'OK'], - [201, 'Created'], - [202, 'Accepted'], - [203, 'Non-Authoritative Information'], - [204, 'No Content'], - [205, 'Reset Content'], - [206, 'Partial Content'], - [207, 'Multi-Status'], - [208, 'Already Reported'], - [226, 'IM Used'], - [300, 'Multiple Choices'], - [301, 'Moved Permanently'], - [302, 'Found'], - [303, 'See Other'], - [304, 'Not Modified'], - [305, 'Use Proxy'], - [307, 'Temporary Redirect'], - [308, 'Permanent Redirect'], - [400, 'Bad Request'], - [401, 'Unauthorized'], - [402, 'Payment Required'], - [403, 'Forbidden'], - [404, 'Not Found'], - [405, 'Method Not Allowed'], - [406, 'Not Acceptable'], - [407, 'Proxy Authentication Required'], - [408, 'Request Timeout'], - [409, 'Conflict'], - [410, 'Gone'], - [411, 'Length Required'], - [412, 'Precondition Failed'], - [413, 'Payload Too Large'], - [414, 'URI Too Long'], - [415, 'Unsupported Media Type'], - [416, 'Range Not Satisfiable'], - [417, 'Expectation Failed'], - [418, 'I\'m a teapot'], - [421, 'Misdirected Request'], - [422, 'Unprocessable Entity'], - [423, 'Locked'], - [424, 'Failed Dependency'], - [425, 'Unordered Collection'], - [426, 'Upgrade Required'], - [428, 'Precondition Required'], - [429, 'Too Many Requests'], - [431, 'Request Header Fields Too Large'], - [451, 'Unavailable For Legal Reasons'], - [500, 'Internal Server Error'], - [501, 'Not Implemented'], - [502, 'Bad Gateway'], - [503, 'Service Unavailable'], - [504, 'Gateway Timeout'], - [505, 'HTTP Version Not Supported'], - [506, 'Variant Also Negotiates'], - [507, 'Insufficient Storage'], - [508, 'Loop Detected'], - [509, 'Bandwidth Limit Exceeded'], - [510, 'Not Extended'], - [511, 'Network Authentication Required'], - ]) -) +export const STATUS_CODES: Map = new Map([ + [100, 'Continue'], + [101, 'Switching Protocols'], + [102, 'Processing'], + [200, 'OK'], + [201, 'Created'], + [202, 'Accepted'], + [203, 'Non-Authoritative Information'], + [204, 'No Content'], + [205, 'Reset Content'], + [206, 'Partial Content'], + [207, 'Multi-Status'], + [208, 'Already Reported'], + [226, 'IM Used'], + [300, 'Multiple Choices'], + [301, 'Moved Permanently'], + [302, 'Found'], + [303, 'See Other'], + [304, 'Not Modified'], + [305, 'Use Proxy'], + [307, 'Temporary Redirect'], + [308, 'Permanent Redirect'], + [400, 'Bad Request'], + [401, 'Unauthorized'], + [402, 'Payment Required'], + [403, 'Forbidden'], + [404, 'Not Found'], + [405, 'Method Not Allowed'], + [406, 'Not Acceptable'], + [407, 'Proxy Authentication Required'], + [408, 'Request Timeout'], + [409, 'Conflict'], + [410, 'Gone'], + [411, 'Length Required'], + [412, 'Precondition Failed'], + [413, 'Payload Too Large'], + [414, 'URI Too Long'], + [415, 'Unsupported Media Type'], + [416, 'Range Not Satisfiable'], + [417, 'Expectation Failed'], + [418, "I'm a teapot"], + [421, 'Misdirected Request'], + [422, 'Unprocessable Entity'], + [423, 'Locked'], + [424, 'Failed Dependency'], + [425, 'Unordered Collection'], + [426, 'Upgrade Required'], + [428, 'Precondition Required'], + [429, 'Too Many Requests'], + [431, 'Request Header Fields Too Large'], + [451, 'Unavailable For Legal Reasons'], + [500, 'Internal Server Error'], + [501, 'Not Implemented'], + [502, 'Bad Gateway'], + [503, 'Service Unavailable'], + [504, 'Gateway Timeout'], + [505, 'HTTP Version Not Supported'], + [506, 'Variant Also Negotiates'], + [507, 'Insufficient Storage'], + [508, 'Loop Detected'], + [509, 'Bandwidth Limit Exceeded'], + [510, 'Not Extended'], + [511, 'Network Authentication Required'], +]) diff --git a/src/errors/utils/create-server-error.js b/src/errors/utils/create-server-error.js index fe97ce3e..bc814e96 100644 --- a/src/errors/utils/create-server-error.js +++ b/src/errors/utils/create-server-error.js @@ -1,7 +1,7 @@ /* @flow */ type ServerError = T & { - statusCode: number; + statusCode: number, } /** @@ -9,10 +9,10 @@ type ServerError = T & { */ export default function createServerError( Source: Class, - statusCode: number + statusCode: number, ): Class> { const Target = class extends Source { - statusCode: number; + statusCode: number } Object.defineProperty(Target, 'name', { @@ -23,6 +23,6 @@ export default function createServerError( value: statusCode, }) - // $FlowIgnore + // $FlowFixMe return Target } diff --git a/src/index.js b/src/index.js index 4e011b7c..8f758abf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,12 @@ /* @flow */ -import * as Adapters from './packages/adapter' -import * as Testing from './packages/testing' +import * as Adapters from '@lux/packages/adapter' +import * as Testing from '@lux/packages/testing' export { Adapters, Testing } -export { Model } from './packages/database' -export { default as Logger } from './packages/logger' -export { default as Controller } from './packages/controller' -export { default as Serializer } from './packages/serializer' -export { default as Application } from './packages/application' -export { default as luxify } from './packages/luxify' +export { Model } from '@lux/packages/database' +export { default as Logger } from '@lux/packages/logger' +export { default as Controller } from '@lux/packages/controller' +export { default as Serializer } from '@lux/packages/serializer' +export { default as Application } from '@lux/packages/application' +export { default as luxify } from '@lux/packages/luxify' diff --git a/src/interfaces.js b/src/interfaces.js index 412b4929..f7e7328b 100644 --- a/src/interfaces.js +++ b/src/interfaces.js @@ -1,20 +1,17 @@ /* @flow */ -export type ObjectMap = { - [key: string]: T; -}; +export type { ObjectMap } from './types' export interface Lux$Collection { - size: number; - - has(key: T): boolean; - clear(): void; - delete(key: T): boolean; - values(): Iterator; + size: number, + has(key: T): boolean, + clear(): void, + delete(key: T): boolean, + values(): Iterator, } export interface Chain { - pipe(handler: (value: T) => U): Chain; - value(): T; - construct>(constructor: V): Chain; + pipe(handler: (value: T) => U): Chain, + value(): T, + construct>(constructor: V): Chain, } diff --git a/src/packages/adapter/__tests__/__snapshots__/http.test.js.snap b/src/packages/adapter/__tests__/__snapshots__/http.test.js.snap index 43e7e10c..be41bd28 100644 --- a/src/packages/adapter/__tests__/__snapshots__/http.test.js.snap +++ b/src/packages/adapter/__tests__/__snapshots__/http.test.js.snap @@ -61,7 +61,7 @@ Request { "encrypted": false, "headers": Map { "content-type" => "application/vnd.api+json", - "content-length" => 87, + "content-length" => "87", }, "logger": Logger { "enabled": false, diff --git a/src/packages/adapter/__tests__/headers.test.js b/src/packages/adapter/__tests__/headers.test.js index 76e3948c..e4292bdd 100644 --- a/src/packages/adapter/__tests__/headers.test.js +++ b/src/packages/adapter/__tests__/headers.test.js @@ -1,6 +1,6 @@ /* @flow */ -import { MIME_TYPE } from '../../jsonapi' +import { MIME_TYPE } from '@lux/packages/jsonapi' import { Headers, ResponseHeaders } from '../utils/headers' describe('module "adapters/headers"', () => { @@ -22,9 +22,8 @@ describe('module "adapters/headers"', () => { test('creates an instance of Headers', () => { expect(subject).toMatchSnapshot() }) - }); - - ['get', 'has'].forEach(method => { + }) + ;['get', 'has'].forEach(method => { describe(`#${method}()`, () => { const key = 'Accept' const value = method === 'get' ? MIME_TYPE : true @@ -34,12 +33,12 @@ describe('module "adapters/headers"', () => { }) test('returns the correct value for the given key', () => { - // $FlowIgnore + // $FlowFixMe expect(subject[method](key)).toBe(value) }) test('is not case sensitive', () => { - // $FlowIgnore + // $FlowFixMe expect(subject[method](key.toUpperCase())).toBe(value) }) }) diff --git a/src/packages/adapter/__tests__/http.test.js b/src/packages/adapter/__tests__/http.test.js index 05e6a7ca..266ab2c8 100644 --- a/src/packages/adapter/__tests__/http.test.js +++ b/src/packages/adapter/__tests__/http.test.js @@ -2,8 +2,8 @@ import { IncomingMessage, ServerResponse } from 'http' -import { MIME_TYPE } from '../../jsonapi' -import Logger from '../../logger' +import { MIME_TYPE } from '@lux/packages/jsonapi' +import Logger from '@lux/packages/logger' import createAdapter, { request, response } from '../http' import { getTestApp } from '../../../../test/utils/test-app' @@ -156,7 +156,7 @@ describe('module "adapter/http"', () => { }) describe('=> Response', () => { - ['end', 'send'].forEach(method => { + ;['end', 'send'].forEach(method => { beforeAll(() => { Reflect.set(res, 'end', jest.fn()) }) diff --git a/src/packages/adapter/__tests__/method.test.js b/src/packages/adapter/__tests__/method.test.js index 96663b4c..d2e934f2 100644 --- a/src/packages/adapter/__tests__/method.test.js +++ b/src/packages/adapter/__tests__/method.test.js @@ -1,6 +1,6 @@ /* @flow */ -import { METHODS } from '../../request' +import { METHODS } from '@lux/packages/request' import { Headers } from '../utils/headers' import { resolve } from '../utils/method' @@ -14,9 +14,12 @@ describe('module "adapters/method"', () => { test('supports using an x-http-method-override header', () => { METHODS.forEach(method => { - const result = resolve('POST', new Headers({ - 'X-HTTP-Method-Override': method, - })) + const result = resolve( + 'POST', + new Headers({ + 'X-HTTP-Method-Override': method, + }), + ) expect(result).toBe(method) }) diff --git a/src/packages/adapter/__tests__/mock.test.js b/src/packages/adapter/__tests__/mock.test.js index eaf2c197..9f817164 100644 --- a/src/packages/adapter/__tests__/mock.test.js +++ b/src/packages/adapter/__tests__/mock.test.js @@ -1,7 +1,7 @@ /* @flow */ -import { MIME_TYPE } from '../../jsonapi' -import Logger from '../../logger' +import { MIME_TYPE } from '@lux/packages/jsonapi' +import Logger from '@lux/packages/logger' import createAdapter, { request, response } from '../mock' import { getTestApp } from '../../../../test/utils/test-app' @@ -116,7 +116,7 @@ describe('module "adapter/mock"', () => { }) describe('=> Response', () => { - ['end', 'send'].forEach(method => { + ;['end', 'send'].forEach(method => { describe(`#${method}()`, () => { test('calls the resolver function', () => { const body = 'Test' @@ -137,7 +137,7 @@ describe('module "adapter/mock"', () => { describe('- without a resolver function', () => { beforeEach(() => { subject = response.create({ - logger + logger, }) }) diff --git a/src/packages/adapter/__tests__/query.test.js b/src/packages/adapter/__tests__/query.test.js index 98eaa2b9..252deff4 100644 --- a/src/packages/adapter/__tests__/query.test.js +++ b/src/packages/adapter/__tests__/query.test.js @@ -71,7 +71,7 @@ describe('module "adapters/query"', () => { }) test('always coerces `include` to an array', () => { - [ + ;[ { include: '1' }, { include: '1,2,3' }, { include: 'test-include,include-test' }, diff --git a/src/packages/adapter/http/index.js b/src/packages/adapter/http/index.js index 69647b17..bf400d84 100644 --- a/src/packages/adapter/http/index.js +++ b/src/packages/adapter/http/index.js @@ -3,7 +3,7 @@ import type { IncomingMessage, ServerResponse } from 'http' import type { Adapter } from '../index' -import type Application from '../../application' +import type Application from '@lux/packages/application' import * as request from './request' import * as response from './response' diff --git a/src/packages/adapter/http/request/index.js b/src/packages/adapter/http/request/index.js index a2e0204c..7674f5af 100644 --- a/src/packages/adapter/http/request/index.js +++ b/src/packages/adapter/http/request/index.js @@ -5,9 +5,9 @@ import type { IncomingMessage } from 'http' import qs from 'qs' -import { HAS_BODY } from '../../../../constants' -import Request from '../../../request' -import type Logger from '../../../logger' +import { HAS_BODY } from '@lux/constants' +import Request from '@lux/packages/request' +import type Logger from '@lux/packages/logger' import * as query from '../../utils/query' import * as method from '../../utils/method' import { Headers } from '../../utils/headers' @@ -22,7 +22,7 @@ export function create(req: IncomingMessage, logger: Logger): Promise { url: { ...url, params: [] }, params: query.fromObject(qs.parse(url.query)), method: method.resolve(req.method, headers), - // $FlowIgnore + // $FlowFixMe encrypted: Boolean(req.connection.encrypted), defaultParams: {}, }) @@ -32,7 +32,7 @@ export function create(req: IncomingMessage, logger: Logger): Promise { if (HAS_BODY.test(request.method)) { let offset = 0 const body = Buffer.allocUnsafe( - Number.parseInt(request.headers.get('content-length') || '0', 10) || 0 + Number.parseInt(request.headers.get('content-length') || '0', 10) || 0, ) req diff --git a/src/packages/adapter/http/response/index.js b/src/packages/adapter/http/response/index.js index 214d0018..862971b1 100644 --- a/src/packages/adapter/http/response/index.js +++ b/src/packages/adapter/http/response/index.js @@ -2,9 +2,9 @@ import type { ServerResponse } from 'http' -import Response from '../../../response' +import Response from '@lux/packages/response' import { ResponseHeaders } from '../../utils/headers' -import type Logger from '../../../logger' +import type Logger from '@lux/packages/logger' export function create(res: ServerResponse, logger: Logger): Response { return new Response({ diff --git a/src/packages/adapter/index.js b/src/packages/adapter/index.js index 89e9644d..4ff85f3a 100644 --- a/src/packages/adapter/index.js +++ b/src/packages/adapter/index.js @@ -1,8 +1,8 @@ /* @flow */ -import type Application from '../application' -import type Request from '../request' -import type Response from '../response' +import type Application from '@lux/packages/application' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' export type Adapter = (...args: Array) => Promise<[Request, Response]> export type AdapterFactory = (application: Application) => Adapter diff --git a/src/packages/adapter/mock/index.js b/src/packages/adapter/mock/index.js index a7210dd0..5bf217fb 100644 --- a/src/packages/adapter/mock/index.js +++ b/src/packages/adapter/mock/index.js @@ -1,18 +1,18 @@ /* @flow */ import type { Adapter } from '../index' -import type Application from '../../application' +import type Application from '@lux/packages/application' import type { ObjectMap } from '../../../interfaces' import * as request from './request' import * as response from './response' type Options = { - url: string; - body?: Object; - method: string; - headers: ObjectMap; - resolve?: (data: any) => void; + url: string, + body?: Object, + method: string, + headers: ObjectMap, + resolve?: (data: any) => void, } function createAdapter({ logger }: Application): Adapter { diff --git a/src/packages/adapter/mock/request/index.js b/src/packages/adapter/mock/request/index.js index c60fdf2a..566ebf9c 100644 --- a/src/packages/adapter/mock/request/index.js +++ b/src/packages/adapter/mock/request/index.js @@ -4,19 +4,19 @@ import * as url from 'url' import qs from 'qs' -import Request from '../../../request' -import type Logger from '../../../logger' +import Request from '@lux/packages/request' +import type Logger from '@lux/packages/logger' import * as query from '../../utils/query' import * as method from '../../utils/method' import { Headers } from '../../utils/headers' import type { ObjectMap } from '../../../../interfaces' type Options = { - url: string; - body?: Object; - method: string; - logger: Logger; - headers: ObjectMap; + url: string, + body?: Object, + method: string, + logger: Logger, + headers: ObjectMap, } export function create(options: Options): Request { diff --git a/src/packages/adapter/mock/response/index.js b/src/packages/adapter/mock/response/index.js index 6d5e781b..81be0a3a 100644 --- a/src/packages/adapter/mock/response/index.js +++ b/src/packages/adapter/mock/response/index.js @@ -1,13 +1,13 @@ /* @flow */ -import Response from '../../../response' +import Response from '@lux/packages/response' import { ResponseHeaders } from '../../utils/headers' -import noop from '../../../../utils/noop' -import type Logger from '../../../logger' +import noop from '@lux/utils/noop' +import type Logger from '@lux/packages/logger' type Options = { - logger: Logger; - resolve?: (data: any) => void; + logger: Logger, + resolve?: (data: any) => void, } export function create(options: Options): Response { @@ -24,11 +24,7 @@ export function create(options: Options): Response { send(body: string): void { if (options.resolve) { - const { - headers, - statusCode, - statusMessage, - } = this + const { headers, statusCode, statusMessage } = this options.resolve({ body, diff --git a/src/packages/adapter/utils/headers.js b/src/packages/adapter/utils/headers.js index 4f2851f6..54ea1d99 100644 --- a/src/packages/adapter/utils/headers.js +++ b/src/packages/adapter/utils/headers.js @@ -1,14 +1,13 @@ /* @flow */ -import entries from '../../../utils/entries' -import { FreezeableMap } from '../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import type { ObjectMap } from '../../../interfaces' type HandleChange = (type: 'SET' | 'DELETE', data: [string, ?string]) => void export class Headers extends FreezeableMap { constructor(value: ObjectMap = {}) { - super(entries(value)) + super(Object.entries(value).map(([a, b]) => [a, String(b)])) } get(key: string): void | string { @@ -30,7 +29,7 @@ export class Headers extends FreezeableMap { } export class ResponseHeaders extends Headers { - handleChange: HandleChange; + handleChange: HandleChange constructor(handleChange: HandleChange) { super() diff --git a/src/packages/adapter/utils/method.js b/src/packages/adapter/utils/method.js index 35b2cbef..b3274013 100644 --- a/src/packages/adapter/utils/method.js +++ b/src/packages/adapter/utils/method.js @@ -1,6 +1,6 @@ /* @flow */ -import type Request, { Method } from '../../request' +import type Request, { Method } from '@lux/packages/request' type Headers = $PropertyType diff --git a/src/packages/adapter/utils/query.js b/src/packages/adapter/utils/query.js index 0aedb977..5de4cebf 100644 --- a/src/packages/adapter/utils/query.js +++ b/src/packages/adapter/utils/query.js @@ -1,7 +1,6 @@ /* @flow */ -import entries from '../../../utils/entries' -import isObject from '../../../utils/is-object' +import { isNil, isObject, isString } from '@lux/utils/is-type' import type { ObjectMap } from '../../../interfaces' const INT = /^\d+$/ @@ -12,25 +11,22 @@ const DATE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}(Z|\+\d{4})$/ const TRUE = /^true$/ const DELIMITER = /[_-\s]+/ -export function camelize(source: string): string { - return source - .split(DELIMITER) - .reduce((result, part, idx) => { - if (part[0]) { - const [first] = part +export const camelize = (source: string): string => + source.split(DELIMITER).reduce((result, part, idx) => { + if (part[0]) { + const [first] = part - return ( - result - + (idx === 0 ? first.toLowerCase() : first.toUpperCase()) - + part.slice(1).toLowerCase() - ) - } + return ( + result + + (idx === 0 ? first.toLowerCase() : first.toUpperCase()) + + part.slice(1).toLowerCase() + ) + } - return result - }, '') -} + return result + }, '') -export function fromString(source: string): any { +const fromString = (source: string): any => { if (INT.test(source)) { return Number.parseInt(source, 10) } else if (BOOL.test(source)) { @@ -45,46 +41,36 @@ export function fromString(source: string): any { return source } -export function fromObject(source: ObjectMap): ObjectMap { - return entries(source).reduce((target, [k, v]) => { - const key = camelize(k) - let value = v +const wrapValue = source => { + if (Array.isArray(source)) { + return source.map(item => (isString(item) ? camelize(item) : item)) + } + + if (isNil(source)) { + return [] + } + + return [isString(source) ? camelize(source) : source] +} + +export const fromObject = (source: ObjectMap): ObjectMap => + Object.entries(source).reduce((prev, entry) => { + const next = prev + let [key, value] = entry - if (typeof value === 'string') { + key = camelize(key) + + if (isString(value)) { value = fromString(value) } else if (isObject(value)) { value = fromObject(value) } if (key === 'include') { - if (value && !Array.isArray(value)) { - value = [value] - } - - value = value.map(item => { - if (typeof item === 'string') { - return camelize(item) - } - return item - }) - } else if (key === 'fields' && isObject(value)) { - value = entries(value).reduce((fields, [resource, names]) => { - // eslint-disable-next-line no-param-reassign - fields[resource] = ( - Array.isArray(names) ? names : [names] - ).map(item => { - if (typeof item === 'string') { - return camelize(item) - } - return item - }) - return fields - }, {}) + value = wrapValue(value) } - // eslint-disable-next-line no-param-reassign - target[key] = value + next[key] = value - return target + return next }, {}) -} diff --git a/src/packages/application/index.js b/src/packages/application/index.js index 2447d76f..a2db6467 100644 --- a/src/packages/application/index.js +++ b/src/packages/application/index.js @@ -2,26 +2,21 @@ import EventEmitter from 'events' -import { createDefaultConfig } from '../config' -import * as responder from '../responder' -import merge from '../../utils/merge' -import tryCatch from '../../utils/try-catch' -import type Logger from '../logger' -import type Router from '../router' -import type Controller from '../controller' -import type Serializer from '../serializer' -import type { Config } from '../config' -import type { Adapter } from '../adapter' -import type { FreezeableMap } from '../freezeable' -import type Database, { Model, Config as DatabaseConfig } from '../database' +import { createDefaultConfig } from '@lux/packages/config' +import * as responder from '@lux/packages/responder' +import merge from '@lux/utils/merge' +import tryCatch from '@lux/utils/try-catch' +import type Logger from '@lux/packages/logger' +import type Router from '@lux/packages/router' +import type Controller from '@lux/packages/controller' +import type Serializer from '@lux/packages/serializer' +import type { Config } from '@lux/packages/config' +import type { Adapter } from '@lux/packages/adapter' +import type { FreezeableMap } from '@lux/packages/freezeable' +import type Database, { Model } from '@lux/packages/database' import initialize from './initialize' -export type Options = Config & { - path: string; - database: DatabaseConfig; -} - /** * @class Application * @public @@ -34,14 +29,14 @@ class Application extends EventEmitter { * @type {String} * @public */ - path: string; + path: string /** * @property adapter * @type {Adapter} * @private */ - adapter: Adapter; + adapter: Adapter /** * A reference to the `Database` instance. @@ -50,7 +45,7 @@ class Application extends EventEmitter { * @type {Database} * @private */ - store: Database; + store: Database /** * A reference to the `Logger` instance. @@ -59,7 +54,7 @@ class Application extends EventEmitter { * @type {Logger} * @private */ - logger: Logger; + logger: Logger /** * A reference to the `Router` instance. @@ -68,7 +63,7 @@ class Application extends EventEmitter { * @type {Router} * @private */ - router: Router; + router: Router /** * A map containing each `Model` class. @@ -77,7 +72,7 @@ class Application extends EventEmitter { * @type {Map} * @private */ - models: FreezeableMap>; + models: FreezeableMap> /** * A map containing each `Controller` instance. @@ -86,7 +81,7 @@ class Application extends EventEmitter { * @type {Map} * @private */ - controllers: FreezeableMap; + controllers: FreezeableMap /** * A map containing each `Serializer` instance. @@ -95,7 +90,7 @@ class Application extends EventEmitter { * @type {Map} * @private */ - serializers: FreezeableMap>; + serializers: FreezeableMap> /** * @method constructor @@ -103,9 +98,9 @@ class Application extends EventEmitter { * @return {Promise} * @public */ - constructor(options: Options): Promise { + constructor(config: Config): Promise { super() - return initialize(this, merge(createDefaultConfig(), options)) + return initialize(this, merge(createDefaultConfig(), config)) } /** @@ -113,32 +108,33 @@ class Application extends EventEmitter { * @private */ exec(...args: Array): Promise { - return tryCatch(async () => { - const [request, response] = await this.adapter(...args) + return tryCatch( + async () => { + const [request, response] = await this.adapter(...args) - this.emit('request:start', request, response) + this.emit('request:start', request, response) - const respond = responder.create(request, response) - const route = this.router.match(request) + const respond = responder.create(request, response) + const route = this.router.match(request) - if (route) { - this.emit('request:match', request, response, route) + if (route) { + this.emit('request:match', request, response, route) - const data = await route - .visit(request, response) - .catch(err => { + const data = await route.visit(request, response).catch(err => { this.emit('request:error', request, response, err) }) - respond(data) - this.emit('request:complete', request, response) - } else { - respond(404) - this.emit('request:complete', request, response) - } - }, err => { - this.emit('error', err) - }) + respond(data) + this.emit('request:complete', request, response) + } else { + respond(404) + this.emit('request:complete', request, response) + } + }, + err => { + this.emit('error', err) + }, + ) } /** diff --git a/src/packages/application/initialize.js b/src/packages/application/initialize.js index 5a5a5db5..1bddea0a 100644 --- a/src/packages/application/initialize.js +++ b/src/packages/application/initialize.js @@ -1,27 +1,24 @@ /* @flow */ -import Database from '../database' -import Logger from '../logger' -import Router from '../router' -import { build, createLoader, closestChild } from '../loader' -import { freezeProps, deepFreezeProps } from '../freezeable' -import ControllerMissingError from '../../errors/controller-missing-error' +import Database from '@lux/packages/database' +import Logger from '@lux/packages/logger' +import Router from '@lux/packages/router' +import { build, createLoader, closestChild } from '@lux/packages/loader' +import { freezeProps, deepFreezeProps } from '@lux/packages/freezeable' +import ControllerMissingError from '@lux/errors/controller-missing-error' +import type Application from '@lux/packages/application' +import type { Config } from '@lux/packages/config' import createController from './utils/create-controller' import createSerializer from './utils/create-serializer' - // eslint-disable-next-line no-unused-vars -import type Application, { Options } from './index' - /** * @private */ -export default async function initialize(app: T, { - path, - adapter, - logging, - database, -}: Options): Promise { +export default (async function initialize( + app: T, + { path, adapter, logging, database }: Config, +): Promise { const load = createLoader(path) const routes = load('routes') const models = load('models') @@ -32,16 +29,15 @@ export default async function initialize(app: T, { models, logger, config: database, - checkMigrations: true + checkMigrations: true, }) - const serializers = build( - load('serializers'), - (key, value, parent) => createSerializer(value, { + const serializers = build(load('serializers'), (key, value, parent) => + createSerializer(value, { key, store, - parent - }) + parent, + }), ) models.forEach(model => { @@ -49,18 +45,17 @@ export default async function initialize(app: T, { value: closestChild(serializers, model.resourceName), writable: false, enumerable: false, - configurable: false + configurable: false, }) }) - const controllers = build( - load('controllers'), - (key, value, parent) => createController(value, { + const controllers = build(load('controllers'), (key, value, parent) => + createController(value, { key, store, parent, - serializers - }) + serializers, + }), ) controllers.forEach(controller => { @@ -68,7 +63,7 @@ export default async function initialize(app: T, { value: controllers, writable: true, enumerable: false, - configurable: false + configurable: false, }) }) @@ -81,7 +76,7 @@ export default async function initialize(app: T, { const router = new Router({ routes, controllers, - controller: ApplicationController + controller: ApplicationController, }) Object.assign(app, { @@ -91,12 +86,7 @@ export default async function initialize(app: T, { serializers, }) - deepFreezeProps(app, true, - 'logger', - 'models', - 'controllers', - 'serializers' - ) + deepFreezeProps(app, true, 'logger', 'models', 'controllers', 'serializers') Object.assign(app, { path, @@ -104,14 +94,10 @@ export default async function initialize(app: T, { router, }) - freezeProps(app, false, - 'path', - 'store', - 'router' - ) + freezeProps(app, false, 'path', 'store', 'router') Object.assign(app, { adapter: adapter(app) }) freezeProps(app, false, 'adapter') return app -} +}) diff --git a/src/packages/application/interfaces.js b/src/packages/application/interfaces.js index 4a559150..222d689c 100644 --- a/src/packages/application/interfaces.js +++ b/src/packages/application/interfaces.js @@ -1,18 +1,18 @@ /* @flow */ -import type { Config } from '../config'; -import type Database, { Config as DatabaseConfig } from '../database'; -import type Controller from '../controller'; -import type Serializer from '../serializer'; +import type { Config } from '@lux/packages/config' +import type Database, { Config as DatabaseConfig } from '@lux/packages/database' +import type Controller from '@lux/packages/controller' +import type Serializer from '@lux/packages/serializer' export type Application$opts = Config & { - path: string; - port: string | number; - database: DatabaseConfig; -}; + path: string, + port: string | number, + database: DatabaseConfig, +} export type Application$factoryOpts> = { - key: string; - store: Database; - parent: ?T; -}; + key: string, + store: Database, + parent: ?T, +} diff --git a/src/packages/application/utils/create-controller.js b/src/packages/application/utils/create-controller.js index 76703e45..fb4fa019 100644 --- a/src/packages/application/utils/create-controller.js +++ b/src/packages/application/utils/create-controller.js @@ -2,22 +2,22 @@ import { posix } from 'path' -import { deepFreezeProps } from '../../freezeable' -import { closestAncestor } from '../../loader' -import { tryCatchSync } from '../../../utils/try-catch' -import type Database from '../../database' -import type Controller from '../../controller' -import type Serializer from '../../serializer' -import type { Bundle$Namespace } from '../../loader' // eslint-disable-line max-len, no-duplicate-imports +import { deepFreezeProps } from '@lux/packages/freezeable' +import { closestAncestor } from '@lux/packages/loader' +import { tryCatchSync } from '@lux/utils/try-catch' +import type Database from '@lux/packages/database' +import type Controller from '@lux/packages/controller' +import type Serializer from '@lux/packages/serializer' +import type { Bundle$Namespace } from '@lux/packages/loader' // eslint-disable-line max-len, no-duplicate-imports export default function createController( constructor: Class, opts: { - key: string; - store: Database; - parent: ?Controller; - serializers: Bundle$Namespace>; - } + key: string, + store: Database, + parent: ?Controller, + serializers: Bundle$Namespace>, + }, ): T { const { key, store, serializers } = opts const namespace = posix.dirname(key).replace('.', '') @@ -37,11 +37,13 @@ export default function createController( serializer = closestAncestor(serializers, key) } - const instance: T = Reflect.construct(constructor, [{ - model, - namespace, - serializer - }]) + const instance: T = Reflect.construct(constructor, [ + { + model, + namespace, + serializer, + }, + ]) if (serializer) { if (!instance.filter.length) { @@ -56,12 +58,12 @@ export default function createController( if (parent) { instance.beforeAction = [ ...parent.beforeAction.map(fn => fn.bind(parent)), - ...instance.beforeAction.map(fn => fn.bind(instance)) + ...instance.beforeAction.map(fn => fn.bind(instance)), ] instance.afterAction = [ ...instance.afterAction.map(fn => fn.bind(instance)), - ...parent.afterAction.map(fn => fn.bind(parent)) + ...parent.afterAction.map(fn => fn.bind(parent)), ] } @@ -69,15 +71,17 @@ export default function createController( value: parent, writable: false, enumerable: true, - configurable: false + configurable: false, }) - return deepFreezeProps(instance, true, + return deepFreezeProps( + instance, + true, 'query', 'sort', 'filter', 'params', 'beforeAction', - 'afterAction' + 'afterAction', ) } diff --git a/src/packages/application/utils/create-serializer.js b/src/packages/application/utils/create-serializer.js index 1dc9ed4a..b68afade 100644 --- a/src/packages/application/utils/create-serializer.js +++ b/src/packages/application/utils/create-serializer.js @@ -2,14 +2,14 @@ import { posix } from 'path' -import { deepFreezeProps } from '../../freezeable' -import { tryCatchSync } from '../../../utils/try-catch' -import type Serializer from '../../serializer' // eslint-disable-line max-len, no-unused-vars +import { deepFreezeProps } from '@lux/packages/freezeable' +import { tryCatchSync } from '@lux/utils/try-catch' +import type Serializer from '@lux/packages/serializer' // eslint-disable-line max-len, no-unused-vars import type { Application$factoryOpts } from '../index' export default function createSerializer>( constructor: Class, - opts: Application$factoryOpts + opts: Application$factoryOpts, ): T { const { key, store } = opts const namespace = posix.dirname(key).replace('.', '') @@ -24,22 +24,20 @@ export default function createSerializer>( parent = null } - const instance: T = Reflect.construct(constructor, [{ - model, - parent, - namespace - }]) + const instance: T = Reflect.construct(constructor, [ + { + model, + parent, + namespace, + }, + ]) Reflect.defineProperty(instance, 'parent', { value: parent, writable: false, enumerable: true, - configurable: false + configurable: false, }) - return deepFreezeProps(instance, true, - 'hasOne', - 'hasMany', - 'attributes' - ) + return deepFreezeProps(instance, true, 'hasOne', 'hasMany', 'attributes') } diff --git a/src/packages/cli/commands/build.js b/src/packages/cli/commands/build.js index fbc892a6..f16f7615 100644 --- a/src/packages/cli/commands/build.js +++ b/src/packages/cli/commands/build.js @@ -1,18 +1,22 @@ +/* @flow */ + import Ora from 'ora' -import { CWD, NODE_ENV } from '../../../constants' -import { compile } from '../../compiler' +import { compile } from '@lux/packages/compiler' +import * as env from '@lux/utils/env' export async function build(useStrict: boolean = false): Promise { const spinner = new Ora({ text: 'Building your application...', - spinner: 'dots' + spinner: 'dots', }) spinner.start() - await compile(CWD, NODE_ENV, { - useStrict + await compile({ + directory: process.cwd(), + environment: env.name(), + useStrict, }) spinner.stop() diff --git a/src/packages/cli/commands/create.js b/src/packages/cli/commands/create.js index d9121d47..898d51c8 100644 --- a/src/packages/cli/commands/create.js +++ b/src/packages/cli/commands/create.js @@ -2,11 +2,11 @@ import { EOL } from 'os' import Ora from 'ora' import { green } from 'chalk' +import { mkdir, writeFile } from 'mz/fs' -import { CWD } from '../../../constants' -import { mkdir, writeFile } from '../../fs' -import template from '../../template' -import exec from '../../../utils/exec' +import { CWD } from '@lux/constants' +import template from '@lux/packages/template' +import exec from '@lux/utils/exec' import driverFor from '../utils/driver-for' import appTemplate from '../templates/application' import configTemplate from '../templates/config' @@ -34,7 +34,7 @@ export async function create(name, database) { await Promise.all([ mkdir(`${project}/app`), mkdir(`${project}/config`), - mkdir(`${project}/db`) + mkdir(`${project}/db`), ]) await Promise.all([ @@ -44,74 +44,44 @@ export async function create(name, database) { mkdir(`${project}/app/middleware`), mkdir(`${project}/app/utils`), mkdir(`${project}/config/environments`), - mkdir(`${project}/db/migrate`) + mkdir(`${project}/db/migrate`), ]) await Promise.all([ - writeFile( - `${project}/app/index.js`, - appTemplate(name) - ), + writeFile(`${project}/app/index.js`, appTemplate(name)), - writeFile( - `${project}/app/routes.js`, - routesTemplate() - ), + writeFile(`${project}/app/routes.js`, routesTemplate()), writeFile( `${project}/config/environments/development.js`, - configTemplate(name, 'development') + configTemplate(name, 'development'), ), writeFile( `${project}/config/environments/test.js`, - configTemplate(name, 'test') + configTemplate(name, 'test'), ), writeFile( `${project}/config/environments/production.js`, - configTemplate(name, 'production') + configTemplate(name, 'production'), ), - writeFile( - `${project}/config/database.js`, - dbTemplate(name, driver) - ), + writeFile(`${project}/config/database.js`, dbTemplate(name, driver)), - writeFile( - `${project}/db/seed.js`, - seedTemplate() - ), + writeFile(`${project}/db/seed.js`, seedTemplate()), - writeFile( - `${project}/README.md`, - readmeTemplate(name) - ), + writeFile(`${project}/README.md`, readmeTemplate(name)), - writeFile( - `${project}/LICENSE`, - licenseTemplate() - ), + writeFile(`${project}/LICENSE`, licenseTemplate()), - writeFile( - `${project}/package.json`, - pkgJSONTemplate(name, database) - ), + writeFile(`${project}/package.json`, pkgJSONTemplate(name, database)), - writeFile( - `${project}/.babelrc`, - babelrcTemplate() - ), + writeFile(`${project}/.babelrc`, babelrcTemplate()), - writeFile( - `${project}/.eslintrc.json`, - eslintrcTemplate() - ), + writeFile(`${project}/.eslintrc.json`, eslintrcTemplate()), - writeFile( - `${project}/.gitignore`, - gitignoreTemplate() - ) + writeFile(`${project}/.gitignore`, gitignoreTemplate()), ]) const logOutput = template` @@ -139,18 +109,18 @@ export async function create(name, database) { generate({ cwd: project, type: 'serializer', - name: 'application' + name: 'application', }), generate({ cwd: project, type: 'controller', - name: 'application' - }) + name: 'application', + }), ]) await exec('git init && git add .', { - cwd: project + cwd: project, }) process.stdout.write(`${green('initialize')} git`) @@ -158,17 +128,17 @@ export async function create(name, database) { const spinner = new Ora({ text: 'Installing dependencies from npm...', - spinner: 'dots' + spinner: 'dots', }) spinner.start() await exec('npm install', { - cwd: project + cwd: project, }) await exec(`npm install --save --save-exact ${driver}`, { - cwd: project + cwd: project, }) spinner.stop() diff --git a/src/packages/cli/commands/dbcreate.js b/src/packages/cli/commands/dbcreate.js index f8df1e8c..5c214aa3 100644 --- a/src/packages/cli/commands/dbcreate.js +++ b/src/packages/cli/commands/dbcreate.js @@ -2,12 +2,13 @@ import { EOL } from 'os' -import { CWD, NODE_ENV, DATABASE_URL } from '../../../constants' +import { writeFile } from 'mz/fs' + +import { CWD, NODE_ENV, DATABASE_URL } from '@lux/constants' import { CONNECTION_STRING_MESSAGE } from '../constants' import DatabaseConfigMissingError from '../errors/database-config-missing' -import { connect } from '../../database' -import { writeFile } from '../../fs' -import { createLoader } from '../../loader' +import { connect } from '@lux/packages/database' +import { createLoader } from '@lux/packages/loader' /** * @private @@ -23,7 +24,7 @@ export function dbcreate() { if (config.driver === 'sqlite3') { return writeFile( `${CWD}/db/${config.database}_${NODE_ENV}.sqlite`, - Buffer.from('') + Buffer.from(''), ) } diff --git a/src/packages/cli/commands/dbdrop.js b/src/packages/cli/commands/dbdrop.js index 6f85f359..21993198 100644 --- a/src/packages/cli/commands/dbdrop.js +++ b/src/packages/cli/commands/dbdrop.js @@ -2,12 +2,13 @@ import { EOL } from 'os' -import { CWD, NODE_ENV, DATABASE_URL } from '../../../constants' +import { unlink } from 'mz/fs' + +import { CWD, NODE_ENV, DATABASE_URL } from '@lux/constants' import { CONNECTION_STRING_MESSAGE } from '../constants' import DatabaseConfigMissingError from '../errors/database-config-missing' -import { rmrf } from '../../fs' -import { connect } from '../../database' -import { createLoader } from '../../loader' +import { connect } from '@lux/packages/database' +import { createLoader } from '@lux/packages/loader' /** * @private @@ -21,7 +22,7 @@ export function dbdrop() { } if (config.driver === 'sqlite3') { - return rmrf(`${CWD}/db/${config.database}_${NODE_ENV}.sqlite`) + return unlink(`${CWD}/db/${config.database}_${NODE_ENV}.sqlite`).catch() } if (DATABASE_URL || config.url) { diff --git a/src/packages/cli/commands/dbmigrate.js b/src/packages/cli/commands/dbmigrate.js index 2ef314cf..903f2107 100644 --- a/src/packages/cli/commands/dbmigrate.js +++ b/src/packages/cli/commands/dbmigrate.js @@ -1,10 +1,10 @@ import { EOL } from 'os' -import { CWD } from '../../../constants' -import Database, { pendingMigrations } from '../../database' -import Logger, { sql } from '../../logger' -import { createLoader } from '../../loader' -import { composeAsync } from '../../../utils/compose' +import { CWD } from '@lux/constants' +import Database, { pendingMigrations } from '@lux/packages/database' +import Logger, { sql } from '@lux/packages/logger' +import { createLoader } from '@lux/packages/loader' +import { composeAsync } from '@lux/utils/compose' /** * @private @@ -23,8 +23,8 @@ export async function dbmigrate() { checkMigrations: false, logger: new Logger({ - enabled: false - }) + enabled: false, + }), }) const pending = await pendingMigrations(CWD, () => connection('migrations')) @@ -47,11 +47,11 @@ export async function dbmigrate() { process.stdout.write(sql`${query.toString()}`) process.stdout.write(EOL) }) - .then(() => ( + .then(() => connection('migrations').insert({ - version - }) - )) + version, + }), + ) }) await composeAsync(...runners)() diff --git a/src/packages/cli/commands/dbrollback.js b/src/packages/cli/commands/dbrollback.js index b8f5a5d2..6048ea5c 100644 --- a/src/packages/cli/commands/dbrollback.js +++ b/src/packages/cli/commands/dbrollback.js @@ -1,10 +1,11 @@ import { EOL } from 'os' -import { CWD } from '../../../constants' -import Database from '../../database' -import Logger, { sql } from '../../logger' -import { readdir } from '../../fs' -import { createLoader } from '../../loader' +import { readdir } from 'mz/fs' + +import { CWD } from '@lux/constants' +import Database from '@lux/packages/database' +import Logger, { sql } from '@lux/packages/logger' +import { createLoader } from '@lux/packages/loader' /** * @private @@ -23,8 +24,8 @@ export async function dbrollback() { checkMigrations: false, logger: new Logger({ - enabled: false - }) + enabled: false, + }), }) const migrationFiles = await readdir(`${CWD}/db/migrate`) @@ -53,9 +54,11 @@ export async function dbrollback() { process.stdout.write(EOL) }) - await connection('migrations').where({ - version - }).del() + await connection('migrations') + .where({ + version, + }) + .del() } } } diff --git a/src/packages/cli/commands/dbseed.js b/src/packages/cli/commands/dbseed.js index f04e93bd..f3e56761 100644 --- a/src/packages/cli/commands/dbseed.js +++ b/src/packages/cli/commands/dbseed.js @@ -1,7 +1,7 @@ -import { CWD } from '../../../constants' -import Logger from '../../logger' -import Database from '../../database' -import { createLoader } from '../../loader' +import { CWD } from '@lux/constants' +import Logger from '@lux/packages/logger' +import Database from '@lux/packages/database' +import { createLoader } from '@lux/packages/loader' /** * @private @@ -17,9 +17,9 @@ export function dbseed() { models, path: CWD, logger: new Logger({ - enabled: false - }) - }).then(store => ( - store.connection.transaction(trx => seed(trx, store.connection)) - )) + enabled: false, + }), + }).then(store => + store.connection.transaction(trx => seed(trx, store.connection)), + ) } diff --git a/src/packages/cli/commands/destroy.js b/src/packages/cli/commands/destroy.js index 383f9218..9fda7dad 100644 --- a/src/packages/cli/commands/destroy.js +++ b/src/packages/cli/commands/destroy.js @@ -1,15 +1,17 @@ +/* @flow */ + import { EOL } from 'os' +import * as fs from 'mz/fs' import { red, green } from 'chalk' import { pluralize, singularize } from 'inflection' -import { CWD } from '../../../constants' -import { rmrf, exists, readdir, readFile, writeFile } from '../../fs' +import { CWD } from '@lux/constants' /** * @private */ -export async function destroyType(type, name) { +export async function destroyType(type: string, name: string): Promise { const normalizedType = type.toLowerCase() let normalizedName = name let path @@ -22,13 +24,13 @@ export async function destroyType(type, name) { break case 'migration': - migrations = await readdir(`${CWD}/db/migrate`) + migrations = await fs.readdir(`${CWD}/db/migrate`) normalizedName = migrations.find( - file => `${normalizedName}.js` === file.substr(17) + file => `${String(normalizedName)}.js` === file.substr(17), ) - path = `db/migrate/${normalizedName}` + path = `db/migrate/${String(normalizedName)}` break case 'controller': @@ -49,8 +51,8 @@ export async function destroyType(type, name) { return } - if (await exists(`${CWD}/${path}`)) { - await rmrf(`${CWD}/${path}`) + if (await fs.exists(`${CWD}/${path}`)) { + await fs.rmrf(`${CWD}/${path}`) process.stdout.write(`${red('remove')} ${path}`) process.stdout.write(EOL) @@ -60,38 +62,37 @@ export async function destroyType(type, name) { /** * @private */ -export async function destroy({ type, name }: { - type: string; - name: string; -}) { +export async function destroy({ type, name }: { type: string, name: string }) { if (type === 'resource') { - const routes = (await readFile(`${CWD}/app/routes.js`)) + let routes = await fs.readFile(`${CWD}/app/routes.js`) + + routes = routes .toString('utf8') .split('\n') .reduce((lines, line) => { const pattern = new RegExp( - `\\s*this.resource\\(('|"|\`)${pluralize(name)}('|"|\`)\\);?` + `\\s*this.resource\\(('|"|\`)${pluralize(name)}('|"|\`)\\);?`, ) return pattern.test(line) ? lines : [...lines, line] - }, '') + }, []) .join('\n') await Promise.all([ destroyType('model', name), destroyType('migration', `create-${pluralize(name)}`), destroyType('serializer', name), - destroyType('controller', name) + destroyType('controller', name), ]) - await writeFile(`${CWD}/app/routes.js`, routes) + await fs.writeFile(`${CWD}/app/routes.js`, routes) process.stdout.write(`${green('update')} app/routes.js`) process.stdout.write(EOL) } else if (type === 'model') { await Promise.all([ destroyType(type, name), - destroyType('migration', `create-${pluralize(name)}`) + destroyType('migration', `create-${pluralize(name)}`), ]) } else { await destroyType(type, name) diff --git a/src/packages/cli/commands/generate.js b/src/packages/cli/commands/generate.js index 7780467c..536f1502 100644 --- a/src/packages/cli/commands/generate.js +++ b/src/packages/cli/commands/generate.js @@ -1,6 +1,6 @@ /* @flow */ -import { CWD } from '../../../constants' +import { CWD } from '@lux/constants' import { runGenerator } from '../generator' import type { Generator$opts } from '../generator' // eslint-disable-line max-len, no-duplicate-imports @@ -11,12 +11,12 @@ export function generate({ cwd = CWD, name, type, - attrs = [] + attrs = [], }: Generator$opts): Promise { return runGenerator({ cwd, name, type, - attrs + attrs, }) } diff --git a/src/packages/cli/commands/repl.js b/src/packages/cli/commands/repl.js index f9df0b7d..4f33022b 100644 --- a/src/packages/cli/commands/repl.js +++ b/src/packages/cli/commands/repl.js @@ -3,17 +3,17 @@ import * as path from 'path' import { start as startRepl } from 'repl' -import { CWD } from '../../../constants' -import type Application from '../../application' +import { CWD } from '@lux/constants' +import type Application from '@lux/packages/application' export function repl(): Promise { - return new Promise(async (resolve) => { + return new Promise(async resolve => { const app: Application = await Reflect.apply(require, null, [ - path.join(CWD, 'dist', 'boot') + path.join(CWD, 'dist', 'boot'), ]) const instance = startRepl({ - prompt: '> ' + prompt: '> ', }) instance.once('exit', resolve) @@ -24,26 +24,29 @@ export function repl(): Promise { routes: app.router, [app.constructor.name]: app, - ...Array - .from(app.models) - .reduce((context, [, model]) => ({ + ...Array.from(app.models).reduce( + (context, [, model]) => ({ ...context, - [model.name]: model - }), {}), + [model.name]: model, + }), + {}, + ), - ...Array - .from(app.controllers) - .reduce((context, [, controller]) => ({ + ...Array.from(app.controllers).reduce( + (context, [, controller]) => ({ ...context, - [controller.constructor.name]: controller - }), {}), + [controller.constructor.name]: controller, + }), + {}, + ), - ...Array - .from(app.serializers) - .reduce((context, [, serializer]) => ({ + ...Array.from(app.serializers).reduce( + (context, [, serializer]) => ({ ...context, - [serializer.constructor.name]: serializer - }), {}) + [serializer.constructor.name]: serializer, + }), + {}, + ), }) }) } diff --git a/src/packages/cli/commands/serve.js b/src/packages/cli/commands/serve.js index 473605c8..8b766741 100644 --- a/src/packages/cli/commands/serve.js +++ b/src/packages/cli/commands/serve.js @@ -2,11 +2,11 @@ import { cyan } from 'chalk' -import { CWD, PORT, NODE_ENV } from '../../../constants' -import Logger from '../../logger' -import { createLoader } from '../../loader' -import { createCluster } from '../../pm' -import { watch } from '../../fs' +import { CWD, PORT, NODE_ENV } from '@lux/constants' +import Logger from '@lux/packages/logger' +import { createLoader } from '@lux/packages/loader' +import { createCluster } from '@lux/packages/pm' +import Watcher from '@lux/packages/cli/watcher' import { build } from './build' @@ -14,22 +14,22 @@ import { build } from './build' * @private */ export async function serve({ - hot = (NODE_ENV === 'development'), + hot = NODE_ENV === 'development', cluster = false, - useStrict = false + useStrict = false, }: { - hot: boolean; - cluster: boolean; - useStrict: boolean; + hot: boolean, + cluster: boolean, + useStrict: boolean, }): Promise { const load = createLoader(CWD) const { logging } = load('config') const logger = new Logger(logging) if (hot) { - const watcher = await watch(CWD) + const watcher = await new Watcher(CWD) - watcher.on('change', async (changed) => { + watcher.on('change', async changed => { await build(useStrict) process.emit('update', changed) }) @@ -39,7 +39,7 @@ export async function serve({ logger, path: CWD, port: PORT, - maxWorkers: cluster ? undefined : 1 + maxWorkers: cluster ? undefined : 1, }).once('ready', () => { logger.info(`Lux Server listening on port: ${cyan(`${PORT}`)}`) }) diff --git a/src/packages/cli/constants.js b/src/packages/cli/constants.js index adf23f6b..b718e8b1 100644 --- a/src/packages/cli/constants.js +++ b/src/packages/cli/constants.js @@ -1,18 +1,18 @@ /* @flow */ -import template from '../template' -import { fileLink } from '../../utils/github' +import template from '@lux/packages/template' +import { fileLink } from '@lux/utils/github' export const VALID_DATABASES = [ 'postgres', 'sqlite', 'mysql', 'mariadb', - 'oracle' + 'oracle', ] const DB_INTERFACE_URL = fileLink('src/packages/database/interfaces.js', { - line: 17 + line: 17, }) export const CONNECTION_STRING_MESSAGE = template` diff --git a/src/packages/cli/generator/constants.js b/src/packages/cli/generator/constants.js index 4cc6309c..7eb98e96 100644 --- a/src/packages/cli/generator/constants.js +++ b/src/packages/cli/generator/constants.js @@ -2,7 +2,7 @@ import { dim } from 'chalk' -import template from '../../template' +import template from '@lux/packages/template' /** * TODO: Update the 'routes.js' file when generating a resource within a diff --git a/src/packages/cli/generator/index.js b/src/packages/cli/generator/index.js index 0661be5e..92d8e463 100644 --- a/src/packages/cli/generator/index.js +++ b/src/packages/cli/generator/index.js @@ -10,11 +10,16 @@ import type { Generator$opts } from './interfaces' /** * @private */ -export async function runGenerator({ cwd, type, name, attrs }: { - cwd: $PropertyType; - type: $PropertyType; - name: $PropertyType; - attrs: $PropertyType; +export async function runGenerator({ + cwd, + type, + name, + attrs, +}: { + cwd: $PropertyType, + type: $PropertyType, + name: $PropertyType, + attrs: $PropertyType, }): Promise { const generator = generatorFor(type) const prompt = createPrompt() @@ -24,9 +29,8 @@ export async function runGenerator({ cwd, type, name, attrs }: { type, name, attrs, - onConflict: path => prompt.question( - `${green('?')} ${red('Overwrite')} ${path}? (Y/n)\r` - ) + onConflict: path => + prompt.question(`${green('?')} ${red('Overwrite')} ${path}? (Y/n)\r`), }) prompt.close() @@ -35,5 +39,5 @@ export async function runGenerator({ cwd, type, name, attrs }: { export type { Generator, Generator$opts, - Generator$template + Generator$template, } from './interfaces' diff --git a/src/packages/cli/generator/interfaces.js b/src/packages/cli/generator/interfaces.js index 5e03721f..8b205398 100644 --- a/src/packages/cli/generator/interfaces.js +++ b/src/packages/cli/generator/interfaces.js @@ -1,12 +1,12 @@ /* @flow */ export type Generator$opts = { - cwd: string; - type: string; - name: string; - attrs: Array; - onConflict(text: string): Promise; -}; + cwd: string, + type: string, + name: string, + attrs: Array, + onConflict(text: string): Promise, +} -export type Generator = (opts: Generator$opts) => Promise; -export type Generator$template = (name: string, attrs: Array) => string; +export type Generator = (opts: Generator$opts) => Promise +export type Generator$template = (name: string, attrs: Array) => string diff --git a/src/packages/cli/generator/utils/create-generator.js b/src/packages/cli/generator/utils/create-generator.js index 7d59408b..7103f954 100644 --- a/src/packages/cli/generator/utils/create-generator.js +++ b/src/packages/cli/generator/utils/create-generator.js @@ -1,51 +1,59 @@ /* @flow */ -import { join as joinPath } from 'path' +import * as path from 'path' +import * as fs from 'mz/fs' import { red, green, yellow } from 'chalk' -import { rmrf, exists, mkdirRec, writeFile, parsePath } from '../../../fs' +import * as fse from '@lux/utils/fs-extras' import type { Generator, Generator$template } from '../index' import log from './log' const FORWARD_SLASH = /\//g +const pathsFor = absolute => [ + absolute, + path.relative(path.dirname(path.dirname(absolute)), absolute), +] + /** * @private */ export default function createGenerator({ dir, template, - hasConflict = exists + hasConflict = fs.exists, }: { - dir: string; - template: Generator$template; - hasConflict?: (path: string) => Promise; + dir: string, + template: Generator$template, + hasConflict?: (path: string) => Promise, }): Generator { return async ({ cwd, attrs, onConflict, ...opts }) => { - const path = parsePath(cwd, dir, `${opts.name}.js`) - const name = opts.name.replace(FORWARD_SLASH, '-') + let { name } = opts let action = green('create') + const [absolute, relative] = pathsFor(path.join(cwd, dir, `${name}.js`)) + + name = opts.name.replace(FORWARD_SLASH, '-') - await mkdirRec(path.dir) + await fse.mkdirRec(path.dirname(absolute)) - if (await hasConflict(path.absolute)) { - const shouldContinue = await onConflict(path.relative) + if (await hasConflict(absolute)) { + const shouldContinue = await onConflict(relative) if (shouldContinue && typeof shouldContinue === 'string') { - await rmrf(joinPath(path.dir, shouldContinue)) - log(`${red('remove')} ${joinPath(dir, shouldContinue)}`) + await fse.rmrf(path.join(path.dirname(absolute), shouldContinue)) + log(`${red('remove')} ${path.join(dir, shouldContinue)}`) } else if (shouldContinue && typeof shouldContinue === 'boolean') { action = yellow('overwrite') - await rmrf(path.absolute) + await fse.rmrf(absolute) } else { - log(`${yellow('skip')} ${path.relative}`) + log(`${yellow('skip')} ${relative}`) return } } - await writeFile(path.absolute, Buffer.from(template(name, attrs))) - log(`${action} ${path.relative}`) + await fs.writeFile(absolute, Buffer.from(template(name, attrs))) + log(`${action} ${relative}`) } } diff --git a/src/packages/cli/generator/utils/generate-type.js b/src/packages/cli/generator/utils/generate-type.js index 81b7edd1..78acb42c 100644 --- a/src/packages/cli/generator/utils/generate-type.js +++ b/src/packages/cli/generator/utils/generate-type.js @@ -2,12 +2,12 @@ import { posix, join as joinPath } from 'path' +import * as fs from 'mz/fs' import { green } from 'chalk' import { pluralize, singularize } from 'inflection' import { NAMESPACED_RESOURCE_MESSAGE } from '../constants' -import { generateTimestamp } from '../../../database' -import { exists, readFile, writeFile } from '../../../fs' +import { generateTimestamp } from '@lux/packages/database' import modelTemplate from '../../templates/model' import serializerTemplate from '../../templates/serializer' import controllerTemplate from '../../templates/controller' @@ -15,7 +15,7 @@ import emptyMigrationTemplate from '../../templates/empty-migration' import modelMigrationTemplate from '../../templates/model-migration' import middlewareTemplate from '../../templates/middleware' import utilTemplate from '../../templates/util' -import chain from '../../../../utils/chain' +import chain from '@lux/utils/chain' import type { Generator$opts } from '../index' import log from './log' @@ -32,7 +32,7 @@ export async function controller(opts: Generator$opts): Promise { const dir = joinPath('app', 'controllers') const generate = createGenerator({ dir, - template: controllerTemplate + template: controllerTemplate, }) if (!name.endsWith('application')) { @@ -42,14 +42,14 @@ export async function controller(opts: Generator$opts): Promise { await generate({ ...opts, cwd, - name + name, }) const namespace = posix.dirname(name) if (namespace !== '.') { - const hasParent = await exists( - joinPath(cwd, dir, ...[...namespace.split('/'), 'application.js']) + const hasParent = await fs.exists( + joinPath(cwd, dir, ...[...namespace.split('/'), 'application.js']), ) if (!hasParent) { @@ -57,7 +57,7 @@ export async function controller(opts: Generator$opts): Promise { ...opts, cwd, name: `${namespace}/application`, - attrs: [] + attrs: [], }) } } @@ -73,7 +73,7 @@ export async function serializer(opts: Generator$opts): Promise { const dir = joinPath('app', 'serializers') const generate = createGenerator({ dir, - template: serializerTemplate + template: serializerTemplate, }) if (!name.endsWith('application')) { @@ -83,14 +83,14 @@ export async function serializer(opts: Generator$opts): Promise { await generate({ ...opts, cwd, - name + name, }) const namespace = posix.dirname(name) if (namespace !== '.') { - const hasParent = await exists( - joinPath(cwd, dir, ...[...namespace.split('/'), 'application.js']) + const hasParent = await fs.exists( + joinPath(cwd, dir, ...[...namespace.split('/'), 'application.js']), ) if (!hasParent) { @@ -98,7 +98,7 @@ export async function serializer(opts: Generator$opts): Promise { ...opts, cwd, name: `${namespace}/application`, - attrs: [] + attrs: [], }) } } @@ -115,7 +115,7 @@ export function migration(opts: Generator$opts) { const generate = createGenerator({ dir, template: emptyMigrationTemplate, - hasConflict: detectConflict + hasConflict: detectConflict, }) name = chain(name) @@ -129,8 +129,8 @@ export function migration(opts: Generator$opts) { name, onConflict: createConflictResolver({ cwd, - onConflict - }) + onConflict, + }), }) } @@ -145,7 +145,7 @@ export function modelMigration(opts: Generator$opts) { const generate = createGenerator({ dir, template: modelMigrationTemplate, - hasConflict: detectConflict + hasConflict: detectConflict, }) name = chain(name) @@ -160,8 +160,8 @@ export function modelMigration(opts: Generator$opts) { name, onConflict: createConflictResolver({ cwd, - onConflict - }) + onConflict, + }), }) } @@ -172,19 +172,16 @@ export async function model(opts: Generator$opts): Promise { let { name } = opts const generate = createGenerator({ dir: joinPath('app', 'models'), - template: modelTemplate + template: modelTemplate, }) await modelMigration({ name, ...opts }) - name = chain(name) - .pipe(posix.basename) - .pipe(singularize) - .value() + name = chain(name).pipe(posix.basename).pipe(singularize).value() return generate({ ...opts, - name + name, }) } @@ -199,12 +196,12 @@ export function middleware(opts: Generator$opts) { const generate = createGenerator({ dir: joinPath('app', 'middleware', ...parts), - template: middlewareTemplate + template: middlewareTemplate, }) return generate({ ...opts, - name + name, }) } @@ -219,12 +216,12 @@ export function util(opts: Generator$opts) { const generate = createGenerator({ dir: joinPath('app', 'utils', ...parts), - template: utilTemplate + template: utilTemplate, }) return generate({ ...opts, - name + name, }) } @@ -242,25 +239,27 @@ export async function resource(opts: Generator$opts) { } const path = joinPath(opts.cwd, 'app', 'routes.js') - const routes = chain(await readFile(path)) + const routes = chain(await fs.readFile(path)) .pipe(buf => buf.toString('utf8')) .pipe(str => str.split('\n')) - .pipe(lines => lines.reduce((result, line, index, arr) => { - const closeIndex = arr.lastIndexOf('}') - let str = result + .pipe(lines => + lines.reduce((result, line, index, arr) => { + const closeIndex = arr.lastIndexOf('}') + let str = result - if (line && index <= closeIndex) { - str += `${line}\n` - } + if (line && index <= closeIndex) { + str += `${line}\n` + } - if (index + 1 === closeIndex) { - str += ` this.resource('${pluralize(opts.name)}');\n` - } + if (index + 1 === closeIndex) { + str += ` this.resource('${pluralize(opts.name)}');\n` + } - return str - }, '')) + return str + }, ''), + ) .value() - await writeFile(path, Buffer.from(routes)) + await fs.writeFile(path, Buffer.from(routes)) log(`${green('update')} app/routes.js`) } diff --git a/src/packages/cli/generator/utils/migration-conflict.js b/src/packages/cli/generator/utils/migration-conflict.js index e3cd4950..8e6ded1f 100644 --- a/src/packages/cli/generator/utils/migration-conflict.js +++ b/src/packages/cli/generator/utils/migration-conflict.js @@ -1,27 +1,35 @@ /* @flow */ -import { exists, readdir, parsePath } from '../../../fs' +import * as path from 'path' + +import * as fs from 'mz/fs' + +import * as fse from '@lux/utils/fs-extras' import type { Generator$opts } from '../index' -export function detectConflict(path: string): Promise { - const { dir, base } = parsePath(path) +export function detectConflict(target: string): Promise { + const { dir, base } = path.parse(target) const pattern = new RegExp(`^\\d+-${base.substr(17)}$`) - return exists(pattern, dir) + return fse.existsInDir(dir, pattern) } -export function createConflictResolver({ cwd, onConflict }: { - cwd: $PropertyType; - onConflict: $PropertyType; +export function createConflictResolver({ + cwd, + onConflict, +}: { + cwd: $PropertyType, + onConflict: $PropertyType, }): $PropertyType { - return async path => { - if (await onConflict(path)) { - const parsed = parsePath(cwd, path) - const migrations = await readdir(parsed.dir) - - return migrations.find( - file => file.substr(17) === parsed.base.substr(17) - ) || false + return async target => { + if (await onConflict(target)) { + const parsed = path.parse(path.join(cwd, target)) + const migrations = await fs.readdir(parsed.dir) + + return ( + migrations.find(file => file.substr(17) === parsed.base.substr(17)) || + false + ) } return false diff --git a/src/packages/cli/templates/application.js b/src/packages/cli/templates/application.js index d7e46a56..d70e5235 100644 --- a/src/packages/cli/templates/application.js +++ b/src/packages/cli/templates/application.js @@ -2,18 +2,15 @@ import { classify } from 'inflection' -import template from '../../template' -import chain from '../../../utils/chain' -import underscore from '../../../utils/underscore' +import template from '@lux/packages/template' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' /** * @private */ export default (name: string): string => { - const normalized = chain(name) - .pipe(underscore) - .pipe(classify) - .value() + const normalized = chain(name).pipe(underscore).pipe(classify).value() return template` import { Application } from 'lux-framework'; diff --git a/src/packages/cli/templates/babelrc.js b/src/packages/cli/templates/babelrc.js index 819f5808..847c970b 100644 --- a/src/packages/cli/templates/babelrc.js +++ b/src/packages/cli/templates/babelrc.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/config.js b/src/packages/cli/templates/config.js index 05407f40..b02493f5 100644 --- a/src/packages/cli/templates/config.js +++ b/src/packages/cli/templates/config.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private @@ -12,8 +12,8 @@ export default (name: string, env: string): string => { return template` export default { logging: { - level: ${isProdENV ? '\'INFO\'' : '\'DEBUG\''}, - format: ${isProdENV ? '\'json\'' : '\'text\''}, + level: ${isProdENV ? "'INFO'" : "'DEBUG'"}, + format: ${isProdENV ? "'json'" : "'text'"}, enabled: ${(!isTestENV).toString()}, filter: { diff --git a/src/packages/cli/templates/controller.js b/src/packages/cli/templates/controller.js index 911fe7d0..db5ffc91 100644 --- a/src/packages/cli/templates/controller.js +++ b/src/packages/cli/templates/controller.js @@ -1,50 +1,44 @@ /* @flow */ -import { classify, camelize, pluralize } from 'inflection' +import { pluralize } from 'inflection' + +import template from '@lux/packages/template' +import { classify, camelize } from '@lux/packages/inflector' -import template from '../../template' -import entries from '../../../utils/entries' import indent from '../utils/indent' -import chain from '../../../utils/chain' -import underscore from '../../../utils/underscore' + +const parseAttrs = attrs => + attrs + .filter(attr => /^(\w|-)+:(\w|-)+$/g.test(attr)) + .map(attr => attr.split(':')[0]) + .map(camelize) /** * @private */ export default (name: string, attrs: Array): string => { - let normalized = chain(name) - .pipe(underscore) - .pipe(classify) - .value() + let normalized = classify(name) if (!normalized.endsWith('Application')) { normalized = pluralize(normalized) } - const body = entries( - attrs - .filter(attr => /^(\w|-)+:(\w|-)+$/g.test(attr)) - .map(attr => attr.split(':')[0]) - .reduce((obj, attr) => ({ - ...obj, - params: [ - ...obj.params, - `${indent(8)}'${camelize(underscore(attr), true)}'` - ] - }), { params: [] }) + const body = Object.entries( + parseAttrs(attrs), ).reduce((result, group, index) => { const [key] = group let [, value] = group let str = result - if (value.length) { + if (Array.isArray(value) && value.length) { value = value.join(',\n') if (index && str.length) { str += '\n\n' } - str += `${indent(index === 0 ? 2 : 6)}${key} = ` + + str += + `${indent(index === 0 ? 2 : 6)}${key} = ` + `[\n${value}\n${indent(6)}];` } diff --git a/src/packages/cli/templates/database.js b/src/packages/cli/templates/database.js index e6e9f96a..7162228f 100644 --- a/src/packages/cli/templates/database.js +++ b/src/packages/cli/templates/database.js @@ -1,7 +1,7 @@ /* @flow */ import indent from '../utils/indent' -import underscore from '../../../utils/underscore' +import underscore from '@lux/utils/underscore' /** * @private @@ -22,38 +22,38 @@ export default (name: string, driver: string): string => { username = 'root' } - ['development', 'test', 'production'].forEach(environment => { - template += (`${indent(2)}${environment}: {\n`) + ;['development', 'test', 'production'].forEach(environment => { + template += `${indent(2)}${environment}: {\n` if (driverName !== 'sqlite3') { - template += (`${indent(4)}pool: 5,\n`) + template += `${indent(4)}pool: 5,\n` } - template += (`${indent(4)}driver: '${driverName}',\n`) + template += `${indent(4)}driver: '${driverName}',\n` if (username) { - template += (`${indent(4)}username: '${username}',\n`) + template += `${indent(4)}username: '${username}',\n` } switch (environment) { case 'development': - template += (`${indent(4)}database: '${schemaName}_dev'\n`) + template += `${indent(4)}database: '${schemaName}_dev'\n` break case 'test': - template += (`${indent(4)}database: '${schemaName}_test'\n`) + template += `${indent(4)}database: '${schemaName}_test'\n` break case 'production': - template += (`${indent(4)}database: '${schemaName}_prod'\n`) + template += `${indent(4)}database: '${schemaName}_prod'\n` break default: - template += (`${indent(4)}database: '${schemaName}_${environment}'\n`) + template += `${indent(4)}database: '${schemaName}_${environment}'\n` break } - template += (`${indent(2)}}`) + template += `${indent(2)}}` if (environment !== 'production') { template += ',\n\n' diff --git a/src/packages/cli/templates/empty-migration.js b/src/packages/cli/templates/empty-migration.js index 3f516811..738b4e4e 100644 --- a/src/packages/cli/templates/empty-migration.js +++ b/src/packages/cli/templates/empty-migration.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/eslintrc.js b/src/packages/cli/templates/eslintrc.js index d1a645e8..91f5f24b 100644 --- a/src/packages/cli/templates/eslintrc.js +++ b/src/packages/cli/templates/eslintrc.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/gitignore.js b/src/packages/cli/templates/gitignore.js index e8283b87..a0cd300a 100644 --- a/src/packages/cli/templates/gitignore.js +++ b/src/packages/cli/templates/gitignore.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/license.js b/src/packages/cli/templates/license.js index 877367c2..5f0d0be3 100644 --- a/src/packages/cli/templates/license.js +++ b/src/packages/cli/templates/license.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/middleware.js b/src/packages/cli/templates/middleware.js index c814e1aa..ff729bb2 100644 --- a/src/packages/cli/templates/middleware.js +++ b/src/packages/cli/templates/middleware.js @@ -2,9 +2,9 @@ import { camelize } from 'inflection' -import chain from '../../../utils/chain' -import underscore from '../../../utils/underscore' -import template from '../../template' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/model-migration.js b/src/packages/cli/templates/model-migration.js index 9f7ca37e..e70fab53 100644 --- a/src/packages/cli/templates/model-migration.js +++ b/src/packages/cli/templates/model-migration.js @@ -2,10 +2,10 @@ import { pluralize } from 'inflection' -import template from '../../template' -import chain from '../../../utils/chain' +import template from '@lux/packages/template' +import chain from '@lux/utils/chain' import indent from '../utils/indent' -import underscore from '../../../utils/underscore' +import underscore from '@lux/utils/underscore' /** * @private diff --git a/src/packages/cli/templates/model.js b/src/packages/cli/templates/model.js index c313ec77..466baa8a 100644 --- a/src/packages/cli/templates/model.js +++ b/src/packages/cli/templates/model.js @@ -4,11 +4,10 @@ import { EOL } from 'os' import { classify, camelize } from 'inflection' -import template from '../../template' +import template from '@lux/packages/template' import indent from '../utils/indent' -import chain from '../../../utils/chain' -import entries from '../../../utils/entries' -import underscore from '../../../utils/underscore' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' const VALID_ATTR = /^(\w|-)+:(\w|-)+$/ const RELATIONSHIP = /^belongs-to|has-(one|many)$/ @@ -17,69 +16,74 @@ const RELATIONSHIP = /^belongs-to|has-(one|many)$/ * @private */ export default (name: string, attrs: Array) => { - const normalized = chain(name) - .pipe(underscore) - .pipe(classify) - .value() + const normalized = chain(name).pipe(underscore).pipe(classify).value() return template` import { Model } from 'lux-framework'; class ${normalized} extends Model { - ${entries((attrs || []) - .filter(attr => VALID_ATTR.test(attr)) - .map(attr => attr.split(':')) - .filter(([, type]) => RELATIONSHIP.test(type)) - .reduce((types, [related, type]) => { - const key = chain(type) - .pipe(underscore) - .pipe(str => camelize(str, true)) - .value() + ${Object.entries( + (attrs || []) + .filter(attr => VALID_ATTR.test(attr)) + .map(attr => attr.split(':')) + .filter(([, type]) => RELATIONSHIP.test(type)) + .reduce( + (types, [related, type]) => { + const key = chain(type) + .pipe(underscore) + .pipe(str => camelize(str, true)) + .value() - const value = Reflect.get(types, key) + const value = Reflect.get(types, key) - if (value) { - const inverse = camelize(normalized, true) - const relatedKey = chain(related) - .pipe(underscore) - .pipe(str => camelize(str, true)) - .value() + if (value) { + const inverse = camelize(normalized, true) + const relatedKey = chain(related) + .pipe(underscore) + .pipe(str => camelize(str, true)) + .value() - return { - ...types, - [key]: [ - ...value, - `${indent(8)}${relatedKey}: {${EOL}` - + `${indent(10)}inverse: '${inverse}'${EOL}` - + `${indent(8)}}` - ] - } - } + return { + ...types, + [key]: [ + ...value, + `${indent(8)}${relatedKey}: {${EOL}` + + `${indent(10)}inverse: '${inverse}'${EOL}` + + `${indent(8)}}`, + ], + } + } - return types - }, { - hasOne: [], - hasMany: [], - belongsTo: [] - })) + return types + }, + { + hasOne: [], + hasMany: [], + belongsTo: [], + }, + ), + ) .filter(([, value]) => value.length) - .reduce((result, [key, value], index) => ( - chain(result) - .pipe(str => { - if (index && str.length) { - return `${str}${EOL.repeat(2)}` - } + .reduce( + (result, [key, value], index) => + chain(result) + .pipe(str => { + if (index && str.length) { + return `${str}${EOL.repeat(2)}` + } - return str - }) - .pipe(str => ( - str // eslint-disable-line prefer-template - + `${indent(index === 0 ? 2 : 6)}static ${key} = {${EOL}` - + `${value.join(`,${EOL.repeat(2)}`)}${EOL}` // eslint-disable-line max-len, comma-spacing - + `${indent(6)}};` - )) - .value() - ), '')} + return str + }) + .pipe( + str => + str + // eslint-disable-line prefer-template + `${indent(index === 0 ? 2 : 6)}static ${key} = {${EOL}` + + `${value.join(`,${EOL.repeat(2)}`)}${EOL}` + // eslint-disable-line max-len, comma-spacing + `${indent(6)}};`, + ) + .value(), + '', + )} } export default ${normalized}; diff --git a/src/packages/cli/templates/package-json.js b/src/packages/cli/templates/package-json.js index ad0108f8..3583c8a6 100644 --- a/src/packages/cli/templates/package-json.js +++ b/src/packages/cli/templates/package-json.js @@ -1,7 +1,7 @@ /* @flow */ import { version, devDependencies } from '../../../../package.json' -import template from '../../template' +import template from '@lux/packages/template' const LUX_VERSION: string = version const BABEL_PRESET_VERSION: string = devDependencies['babel-preset-lux'] diff --git a/src/packages/cli/templates/readme.js b/src/packages/cli/templates/readme.js index a24be66f..c0111d09 100644 --- a/src/packages/cli/templates/readme.js +++ b/src/packages/cli/templates/readme.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/routes.js b/src/packages/cli/templates/routes.js index 38df96f7..98bac1d5 100644 --- a/src/packages/cli/templates/routes.js +++ b/src/packages/cli/templates/routes.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/seed.js b/src/packages/cli/templates/seed.js index 3efe307a..0cb5caa1 100644 --- a/src/packages/cli/templates/seed.js +++ b/src/packages/cli/templates/seed.js @@ -1,6 +1,6 @@ /* @flow */ -import template from '../../template' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/templates/serializer.js b/src/packages/cli/templates/serializer.js index 984a647f..9c9568e7 100644 --- a/src/packages/cli/templates/serializer.js +++ b/src/packages/cli/templates/serializer.js @@ -2,65 +2,60 @@ import { classify, camelize, pluralize } from 'inflection' -import chain from '../../../utils/chain' -import entries from '../../../utils/entries' -import underscore from '../../../utils/underscore' -import template from '../../template' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' +import template from '@lux/packages/template' import indent from '../utils/indent' /** * @private */ export default (name: string, attrs: Array): string => { - let normalized = chain(name) - .pipe(underscore) - .pipe(classify) - .value() + let normalized = chain(name).pipe(underscore).pipe(classify).value() if (!normalized.endsWith('Application')) { normalized = pluralize(normalized) } - const body = entries( + const body = Object.entries( attrs .filter(attr => /^(\w|-)+:(\w|-)+$/g.test(attr)) .map(attr => attr.split(':')) - .reduce((obj, parts) => { - const [, type] = parts - let [attr] = parts - let { - hasOne, - hasMany, - attributes - } = obj - - attr = `${indent(8)}'${camelize(underscore(attr), true)}'` - - switch (type) { - case 'belongs-to': - case 'has-one': - hasOne = [...hasOne, attr] - break - - case 'has-many': - hasMany = [...hasMany, attr] - break - - default: - attributes = [...attributes, attr] - } - - return { - attributes, - hasOne, - hasMany - } - }, { - attributes: [], - belongsTo: [], - hasOne: [], - hasMany: [] - }) + .reduce( + (obj, parts) => { + const [, type] = parts + let [attr] = parts + let { hasOne, hasMany, attributes } = obj + + attr = `${indent(8)}'${camelize(underscore(attr), true)}'` + + switch (type) { + case 'belongs-to': + case 'has-one': + hasOne = [...hasOne, attr] + break + + case 'has-many': + hasMany = [...hasMany, attr] + break + + default: + attributes = [...attributes, attr] + } + + return { + attributes, + hasOne, + hasMany, + } + }, + { + attributes: [], + belongsTo: [], + hasOne: [], + hasMany: [], + }, + ), ).reduce((result, group, index) => { const [key] = group let [, value] = group @@ -73,7 +68,8 @@ export default (name: string, attrs: Array): string => { str += '\n\n' } - str += `${indent(index === 0 ? 2 : 6)}${key} = ` + + str += + `${indent(index === 0 ? 2 : 6)}${key} = ` + `[\n${value}\n${indent(6)}];` } diff --git a/src/packages/cli/templates/util.js b/src/packages/cli/templates/util.js index 97a90a22..2c2be9eb 100644 --- a/src/packages/cli/templates/util.js +++ b/src/packages/cli/templates/util.js @@ -2,9 +2,9 @@ import { camelize } from 'inflection' -import chain from '../../../utils/chain' -import underscore from '../../../utils/underscore' -import template from '../../template' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' +import template from '@lux/packages/template' /** * @private diff --git a/src/packages/cli/utils/create-prompt.js b/src/packages/cli/utils/create-prompt.js index 09b3916d..74a1e10e 100644 --- a/src/packages/cli/utils/create-prompt.js +++ b/src/packages/cli/utils/create-prompt.js @@ -7,7 +7,7 @@ const YES = /^y(es)?$/i export default function createPrompt() { const prompt = createInterface({ input: process.stdin, - output: process.stdout + output: process.stdout, }) prompt.setPrompt('') @@ -23,6 +23,6 @@ export default function createPrompt() { close(): void { prompt.close() - } + }, } } diff --git a/src/packages/cli/utils/driver-for.js b/src/packages/cli/utils/driver-for.js index 75714507..a706cbcc 100644 --- a/src/packages/cli/utils/driver-for.js +++ b/src/packages/cli/utils/driver-for.js @@ -3,7 +3,7 @@ const drivers = new Map([ ['sqlite', 'sqlite3'], ['mysql', 'mysql2'], ['mariadb', 'mariasql'], - ['oracle', 'oracle'] + ['oracle', 'oracle'], ]) export default function driverFor(database = 'sqlite') { diff --git a/src/packages/fs/watcher/index.js b/src/packages/cli/watcher/index.js similarity index 86% rename from src/packages/fs/watcher/index.js rename to src/packages/cli/watcher/index.js index 8a79eaec..d707475e 100644 --- a/src/packages/fs/watcher/index.js +++ b/src/packages/cli/watcher/index.js @@ -7,17 +7,15 @@ import { Client as Watchman } from 'fb-watchman' import initialize from './initialize' -export type Client = - | FSWatcher - | Watchman +export type Client = FSWatcher | Watchman /** * @private */ class Watcher extends EventEmitter { - path: string; + path: string - client: Client; + client: Client constructor(path: string, useWatchman: boolean = true): Promise { super() diff --git a/src/packages/cli/watcher/initialize.js b/src/packages/cli/watcher/initialize.js new file mode 100644 index 00000000..301dc044 --- /dev/null +++ b/src/packages/cli/watcher/initialize.js @@ -0,0 +1,79 @@ +/* @flow */ + +import * as path from 'path' + +import * as fs from 'mz/fs' +import { exec } from 'mz/child_process' +import { Client as Watchman } from 'fb-watchman' + +import noop from '@lux/utils/noop' +import promisify from '@lux/utils/promisify' +import { freezeProps } from '@lux/packages/freezeable' + +import type Watcher from './index' + +const SUBSCRIPTION_NAME = 'lux-watcher' + +const fallback = (instance, target) => + fs.watch(target, { recursive: true }, (type, name) => { + if (path.extname('.js')) { + instance.emit('change', [{ name, type }]) + } + }) + +const subscribeConfig = data => ({ + since: data.since, + relative_root: data.relative_path, + fields: ['name', 'size', 'exists', 'type'], + expression: ['allof', ['match', '*.js']], +}) + +const setupWatchmen = (instance, target) => { + const client = new Watchman() + const command = promisify(client.command, client) + const capabilityCheck = promisify(client.capabilityCheck, client) + + capabilityCheck({}) + .then(() => command(['watch-project', target])) + .then(data => + command(['clock', data.watch]).then(({ clock: since }) => ({ + ...data, + since, + })), + ) + .then(data => [data.watch, subscribeConfig(data)]) + .then(([watch, config]) => + command(['subscribe', watch, SUBSCRIPTION_NAME, config]), + ) + .then(() => + client.on('subscription', ({ files, subscription }) => { + if (subscription === SUBSCRIPTION_NAME) { + instance.emit('change', files) + } + }), + ) +} + +export default (async function initialize( + instance: Watcher, + target: string, + useWatchman: boolean, +): Promise { + const appPath = path.join(target, 'app') + let client + + if (useWatchman) { + await exec('which watchman') + .then(() => setupWatchmen(instance, appPath)) + .catch(noop) + } + + Object.assign(instance, { + path: appPath, + client: client || fallback(instance, appPath), + }) + + freezeProps(instance, true, 'path', 'client') + + return instance +}) diff --git a/src/packages/compiler/__tests__/__snapshots__/compiler.test.js.snap b/src/packages/compiler/__tests__/__snapshots__/compiler.test.js.snap index 24bbd2ac..9c4d0f42 100644 --- a/src/packages/compiler/__tests__/__snapshots__/compiler.test.js.snap +++ b/src/packages/compiler/__tests__/__snapshots__/compiler.test.js.snap @@ -1,8 +1,266 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`module "compiler" #compile() - with strict mode creates an instance with the correct config 1`] = `undefined`; +exports[`module "compiler" #compile() - with strict mode creates an instance with the correct config 1`] = ` +Array [ + Array [ + Object { + "cache": undefined, + "entry": "/Users/zacharygolba/src/lux/test/test-app/dist/index.js", + "external": Array [ + "babel-core", + "babel-preset-lux", + "bcryptjs", + "faker", + "knex", + "lux-framework", + "mssql", + "mysql2", + "pg", + "source-map-support", + "sqlite3", + "assert", + "async_hooks", + "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "dns", + "domain", + "events", + "fs", + "http", + "https", + "inspector", + "module", + "net", + "os", + "path", + "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "string_decoder", + "sys", + "timers", + "tls", + "tty", + "url", + "util", + "v8", + "vm", + "zlib", + ], + "onwarn": [Function], + "plugins": Array [ + Object { + "resolveId": [Function], + }, + Object { + "name": "json", + "transform": [Function], + }, + Object { + "name": "node-resolve", + "resolveId": [Function], + }, + Object { + "load": [Function], + "name": "babel", + "options": [Function], + "resolveId": [Function], + "transform": [Function], + }, + Object { + "transform": [Function], + }, + Object { + "name": "cleanup", + "transform": [Function], + }, + ], + "preferConst": true, + }, + ], +] +`; -exports[`module "compiler" #compile() - without strict mode creates an instance with the correct config 1`] = `undefined`; +exports[`module "compiler" #compile() - without strict mode creates an instance with the correct config 1`] = ` +Array [ + Array [ + Object { + "cache": undefined, + "entry": "/Users/zacharygolba/src/lux/test/test-app/dist/index.js", + "external": Array [ + "babel-core", + "babel-preset-lux", + "bcryptjs", + "faker", + "knex", + "lux-framework", + "mssql", + "mysql2", + "pg", + "source-map-support", + "sqlite3", + "assert", + "async_hooks", + "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "dns", + "domain", + "events", + "fs", + "http", + "https", + "inspector", + "module", + "net", + "os", + "path", + "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "string_decoder", + "sys", + "timers", + "tls", + "tty", + "url", + "util", + "v8", + "vm", + "zlib", + ], + "onwarn": [Function], + "plugins": Array [ + Object { + "resolveId": [Function], + }, + Object { + "name": "json", + "transform": [Function], + }, + Object { + "name": "node-resolve", + "resolveId": [Function], + }, + Object { + "load": [Function], + "name": "babel", + "options": [Function], + "resolveId": [Function], + "transform": [Function], + }, + Object { + "transform": [Function], + }, + Object { + "name": "cleanup", + "transform": [Function], + }, + ], + "preferConst": true, + }, + ], + Array [ + Object { + "cache": undefined, + "entry": "/Users/zacharygolba/src/lux/test/test-app/dist/index.js", + "external": Array [ + "babel-core", + "babel-preset-lux", + "bcryptjs", + "faker", + "knex", + "lux-framework", + "mssql", + "mysql2", + "pg", + "source-map-support", + "sqlite3", + "assert", + "async_hooks", + "buffer", + "child_process", + "cluster", + "console", + "constants", + "crypto", + "dgram", + "dns", + "domain", + "events", + "fs", + "http", + "https", + "inspector", + "module", + "net", + "os", + "path", + "process", + "punycode", + "querystring", + "readline", + "repl", + "stream", + "string_decoder", + "sys", + "timers", + "tls", + "tty", + "url", + "util", + "v8", + "vm", + "zlib", + ], + "onwarn": [Function], + "plugins": Array [ + Object { + "resolveId": [Function], + }, + Object { + "name": "json", + "transform": [Function], + }, + Object { + "name": "node-resolve", + "resolveId": [Function], + }, + Object { + "load": [Function], + "name": "babel", + "options": [Function], + "resolveId": [Function], + "transform": [Function], + }, + Object { + "transform": [Function], + }, + Object { + "name": "cleanup", + "transform": [Function], + }, + ], + "preferConst": true, + }, + ], +] +`; exports[`module "compiler" #onwarn() outputs valid warning types to stderr 1`] = ` Array [ diff --git a/src/packages/compiler/__tests__/compiler.test.js b/src/packages/compiler/__tests__/compiler.test.js index d313c916..7c940139 100644 --- a/src/packages/compiler/__tests__/compiler.test.js +++ b/src/packages/compiler/__tests__/compiler.test.js @@ -2,13 +2,9 @@ import * as path from 'path' -const LOCAL = path.join( - __dirname, - '..', - '..', - '..', - 'index.js', -) +import { rollup } from 'rollup' + +import { compile, onwarn } from '../index' const APP_PATH = path.join( __dirname, @@ -20,24 +16,15 @@ const APP_PATH = path.join( 'test-app', ) +jest.mock('rollup') + describe('module "compiler"', () => { describe('#compile()', () => { - let rollup - let compile - - beforeAll(async () => { - rollup = jest.mock('rollup'); - ({ compile } = require('../index')) - }) - - afterAll(async () => { - jest.unmock('rollup') - }) - describe('- with strict mode', () => { test('creates an instance with the correct config', async () => { - await compile(APP_PATH, 'test', { - local: LOCAL, + await compile({ + directory: APP_PATH, + environment: 'test', useStrict: true, }) @@ -47,9 +34,9 @@ describe('module "compiler"', () => { describe('- without strict mode', () => { test('creates an instance with the correct config', async () => { - await compile(APP_PATH, 'test', { - local: LOCAL, - useStrict: false, + await compile({ + directory: APP_PATH, + environment: 'test', }) expect(rollup.mock.calls).toMatchSnapshot() @@ -61,16 +48,14 @@ describe('module "compiler"', () => { describe('#onwarn()', () => { const { warn } = console - let onwarn beforeAll(() => { - // $FlowIgnore - console.warn = jest.fn(); - ({ onwarn } = require('../index')) + // $FlowFixMe + console.warn = jest.fn() }) afterAll(() => { - // $FlowIgnore + // $FlowFixMe console.warn = warn jest.resetModules() }) diff --git a/src/packages/compiler/__tests__/is-external.test.js b/src/packages/compiler/__tests__/is-external.test.js deleted file mode 100644 index a5dac7b6..00000000 --- a/src/packages/compiler/__tests__/is-external.test.js +++ /dev/null @@ -1,55 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -import isExternal from '../utils/is-external' - -const SRC = path.join(__dirname, '..', '..', '..') - -describe('module "compiler"', () => { - describe('util isExternal()', () => { - test('returns a function that accepts a single argument', () => { - expect(isExternal(SRC)).toEqual(expect.any(Function)) - }) - - describe('external()', () => { - let external: (id: string) => boolean - - beforeEach(() => { - external = isExternal(SRC) - }) - - test('returns `true` for external modules', () => { - expect(external('knex')).toBe(true) - }) - - test('returns `false` for aliased file paths', () => { - expect(external('app/models/user')).toBe(false) - }) - - test('returns `false` for absolute file paths', () => { - expect(external('/absolute/path/to/app/models/user')).toBe(false) - expect(external('C:/absolute/path/to/app/models/user')).toBe(false) - expect(external( - 'C:\\absolute\\path\\to\\app\\models\\user' - )).toBe(false) - }) - - test('returns `false` for relative file paths', () => { - expect(external('./app/models/user')).toBe(false) - }) - - test('returns `false` for "LUX_LOCAL"', () => { - expect(external('LUX_LOCAL')).toBe(false) - }) - - test('returns `false` for "lux-framework"', () => { - expect(external('lux-framework')).toBe(false) - }) - - test('returns `false` for "babelHelpers"', () => { - expect(external('babelHelpers')).toBe(false) - }) - }) - }) -}) diff --git a/src/packages/compiler/constants.js b/src/packages/compiler/constants.js new file mode 100644 index 00000000..c5f2c97b --- /dev/null +++ b/src/packages/compiler/constants.js @@ -0,0 +1,56 @@ +/* @flow */ + +import template from '@lux/packages/template' + +export const BANNER: string = template` + const srcmap = require('source-map-support').install({ + environment: 'node', + }); + + if (Object.entries === undefined) { + require('object.entries').shim(); + } + + if (Object.values === undefined) { + require('object.values').shim(); + } +` + +export const STD_LIB: Array = [ + 'assert', + 'async_hooks', + 'buffer', + 'child_process', + 'cluster', + 'console', + 'constants', + 'crypto', + 'dgram', + 'dns', + 'domain', + 'events', + 'fs', + 'http', + 'https', + 'inspector', + 'module', + 'net', + 'os', + 'path', + 'process', + 'punycode', + 'querystring', + 'readline', + 'repl', + 'stream', + 'string_decoder', + 'sys', + 'timers', + 'tls', + 'tty', + 'url', + 'util', + 'v8', + 'vm', + 'zlib', +] diff --git a/src/packages/compiler/index.js b/src/packages/compiler/index.js index 3827005c..1215ee39 100644 --- a/src/packages/compiler/index.js +++ b/src/packages/compiler/index.js @@ -1,148 +1,114 @@ /* @flow */ -import * as os from 'os' import * as path from 'path' +import * as fs from 'mz/fs' import lux from 'rollup-plugin-lux' import json from 'rollup-plugin-json' import alias from 'rollup-plugin-alias' import babel from 'rollup-plugin-babel' -import eslint from 'rollup-plugin-eslint' import resolve from 'rollup-plugin-node-resolve' +import cleanup from 'rollup-plugin-cleanup' import { rollup } from 'rollup' -import { rmrf, readdir, readdirRec, isJSFile } from '../fs' -import template from '../template' -import { NODE_ENV } from '../../constants' +import { NODE_ENV } from '@lux/constants' +import * as fse from '@lux/utils/fs-extras' +import type { Environment } from '@lux/types' +import { BANNER, STD_LIB } from './constants' import onwarn from './utils/handle-warning' -import isExternal from './utils/is-external' import createManifest from './utils/create-manifest' -import readBabelConfig from './utils/read-babel-config' import createBootScript from './utils/create-boot-script' -/** - * @private - */ -type Options = { - local?: string; - useStrict?: boolean; +export type Options = { + directory: string, + environment: Environment, + useStrict?: boolean, } let cache -/** - * @private - */ -export async function compile( - dir: string, - env: string, - opts: Options = {} -): Promise { - const { useStrict = false } = opts - const local = opts.local || path.join(__dirname, '..', 'src', 'index.js') - const entry = path.join(dir, 'dist', 'index.js') - const external = isExternal(dir) +export const compile = async (options: Options): Promise => { + const { directory, environment, useStrict = false } = options + const entry = path.join(directory, 'dist', 'index.js') + let external = STD_LIB let banner + const babelConfig = { + babelrc: false, + } + const assets = await Promise.all([ - readdir(path.join(dir, 'app', 'models')), - readdir(path.join(dir, 'db', 'migrate')), - readdirRec(path.join(dir, 'app', 'controllers')), - readdirRec(path.join(dir, 'app', 'serializers')) + fs.readdir(path.join(directory, 'app', 'models')), + fs.readdir(path.join(directory, 'db', 'migrate')), + fse.readdirRec(path.join(directory, 'app', 'controllers')), + fse.readdirRec(path.join(directory, 'app', 'serializers')), + fs.readFile(path.join(directory, 'package.json')).then(JSON.parse), + fs.readFile(path.join(directory, '.babelrc')).then(JSON.parse), ]).then(types => { - let [ - models, - migrations, - controllers, - serializers - ] = types - - models = models.filter(isJSFile) - migrations = migrations.filter(isJSFile) - controllers = controllers.filter(isJSFile) - serializers = serializers.filter(isJSFile) + let [models, migrations, controllers, serializers] = types + + models = models.filter(fse.isExt('.js')) + migrations = migrations.filter(fse.isExt('.js')) + controllers = controllers.filter(fse.isExt('.js')) + serializers = serializers.filter(fse.isExt('.js')) + + const [, , , , packageInfo, babelRc] = types + + if (packageInfo.dependencies) { + external = Object.keys(packageInfo.dependencies).concat(external) + } + + Object.assign(babelConfig, babelRc) return new Map([ ['Application', path.join('app', 'index.js')], - ['config', path.join('config', 'environments', `${env}.js`)], + ['config', path.join('config', 'environments', `${environment}.js`)], ['controllers', controllers], ['database', path.join('config', 'database.js')], ['migrations', migrations], ['models', models], ['routes', path.join('app', 'routes.js')], ['seed', path.join('db', 'seed.js')], - ['serializers', serializers] + ['serializers', serializers], ]) }) await Promise.all([ - createManifest(dir, assets, { - useStrict + createManifest(directory, assets, { + useStrict, + }), + createBootScript(directory, { + useStrict, }), - createBootScript(dir, { - useStrict - }) ]) - const aliases = { - app: path.posix.join('/', ...dir.split(path.sep), 'app'), - LUX_LOCAL: path.posix.join('/', ...local.split(path.sep)) - } - - if (os.platform() === 'win32') { - const [volume] = dir - const prefix = `${volume}:/` - - Object.assign(aliases, { - app: aliases.app.replace(prefix, ''), - LUX_LOCAL: aliases.LUX_LOCAL.replace(prefix, '') - }) - } - const bundle = await rollup({ + cache, entry, - onwarn, external, - cache, + onwarn, plugins: [ alias({ + app: path.posix.join('/', ...directory.split(path.sep).concat('app')), resolve: ['.js'], - ...aliases }), json(), resolve(), - eslint({ - cwd: dir, - parser: 'babel-eslint', - useEslintrc: false, - include: [ - path.join(dir, 'app', '**'), - ], - exclude: [ - path.join(dir, 'package.json'), - path.join(local, '..', '**') - ] - }), - babel({ - ...(await readBabelConfig(dir)), - babelrc: false, - }), - lux(path.resolve(path.sep, dir, 'app')) - ] + babel(babelConfig), + lux(path.resolve(path.sep, directory, 'app')), + cleanup(), + ], + preferConst: true, }) if (NODE_ENV === 'development') { cache = bundle } - await rmrf(entry) + await fse.rmrf(entry) - banner = template` - const srcmap = require('source-map-support').install({ - environment: 'node' - }); - ` + banner = BANNER if (useStrict) { banner = `'use strict';\n\n${banner}` @@ -150,10 +116,10 @@ export async function compile( return bundle.write({ banner, - dest: path.join(dir, 'dist', 'bundle.js'), + dest: path.join(directory, 'dist', 'bundle.js'), format: 'cjs', sourceMap: true, - useStrict: false + useStrict: false, }) } diff --git a/src/packages/compiler/interfaces.js b/src/packages/compiler/interfaces.js deleted file mode 100644 index 46beb529..00000000 --- a/src/packages/compiler/interfaces.js +++ /dev/null @@ -1,7 +0,0 @@ -/* @flow */ - -declare export function Compiler$manifestWriter( - value: string | Array, - resolveName?: (value: string) => string, - resolveExport?: (value: string) => string -): Promise; diff --git a/src/packages/compiler/utils/create-boot-script.js b/src/packages/compiler/utils/create-boot-script.js index c13bce55..764e7e16 100644 --- a/src/packages/compiler/utils/create-boot-script.js +++ b/src/packages/compiler/utils/create-boot-script.js @@ -2,17 +2,21 @@ import * as path from 'path' -import template from '../../template' -import { writeFile } from '../../fs' +import * as fs from 'mz/fs' + +import template from '@lux/packages/template' /** * @private */ -export default async function createBootScript(dir: string, { - useStrict -}: { - useStrict: boolean; -}): Promise { +export default (async function createBootScript( + dir: string, + { + useStrict, + }: { + useStrict: boolean, + }, +): Promise { let data = template` const http = require('http'); @@ -75,5 +79,5 @@ export default async function createBootScript(dir: string, { data = `'use strict';\n\n${data}` } - await writeFile(path.join(dir, 'dist', 'boot.js'), Buffer.from(data)) -} + await fs.writeFile(path.join(dir, 'dist', 'boot.js'), Buffer.from(data)) +}) diff --git a/src/packages/compiler/utils/create-manifest.js b/src/packages/compiler/utils/create-manifest.js index 4695d672..02954c8b 100644 --- a/src/packages/compiler/utils/create-manifest.js +++ b/src/packages/compiler/utils/create-manifest.js @@ -1,124 +1,99 @@ /* @flow */ -import { sep, posix, basename, join as joinPath } from 'path' +import * as path from 'path' +import slash from 'slash' +import * as fs from 'mz/fs' import { camelize, capitalize, pluralize } from 'inflection' -import { mkdir, writeFile, appendFile } from '../../fs' -import chain from '../../../utils/chain' -import tryCatch from '../../../utils/try-catch' -import underscore from '../../../utils/underscore' -import { compose } from '../../../utils/compose' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' +import { compose } from '@lux/utils/compose' +import noop from '@lux/utils/noop' import formatName from './format-name' -/** - * @private - */ -function createExportStatement( - name: string, - path: string, - isDefault: boolean = true -): Buffer { - const normalized = posix.join(...path.split(sep)) - let data - - if (isDefault) { - data = `export {\n default as ${name}\n} from '../${normalized}';\n\n` - } else { - data = `export {\n ${name}\n} from '../${normalized}';\n\n` +const createExporter = dist => (name, absolute, isNamedExport) => { + const relative = path.relative(dist, absolute) + const normalized = slash(relative) + + if (isNamedExport) { + return Buffer.from(`export {\n ${name}\n} from '${normalized}';\n\n`) } - return Buffer.from(data) + return Buffer.from( + `export {\n default as ${name}\n} from '${normalized}';\n\n`, + ) } -/** - * @private - */ -function createWriter(file: string) { - const writerFor = ( - type: string, - handleWrite: void | (value: string) => Promise - ) => (value: Array) => { - const formatSymbol = compose(str => str + capitalize(type), formatName) - - return Promise.all( - value.map(item => { - if (handleWrite) { - return handleWrite(item) - } - - const path = joinPath('app', pluralize(type), item) - const symbol = formatSymbol(item) - - return appendFile(file, createExportStatement(symbol, path)) - }) - ) - } +const writerForType = (type, file, exporter, handleWrite) => value => { + const formatIdentifier = compose(str => str + capitalize(type), formatName) - return { - controllers: writerFor('controller'), - serializers: writerFor('serializer'), + return Promise.all( + value.map(item => { + if (handleWrite) { + return handleWrite(item) + } - models: writerFor('model', async item => { - const path = joinPath('app', 'models', item) - const name = formatName(item) + const data = exporter( + formatIdentifier(item), + path.join('app', pluralize(type), item), + ) - return appendFile(file, createExportStatement(name, path)) + return fs.appendFile(file, data) }), - - migrations: writerFor('migration', async (item) => { - const path = joinPath('db', 'migrate', item) - const name = chain(item) - .pipe(str => basename(str, '.js')) - .pipe(underscore) - .pipe(str => str.substr(17)) - .pipe(str => camelize(str, true)) - .value() - - await appendFile(file, createExportStatement( - `up as ${name}Up`, - path, - false - )) - - await appendFile(file, createExportStatement( - `down as ${name}Down`, - path, - false - )) - }) - } + ) } -/** - * @private - */ -export default async function createManifest( +const createWriter = (file, exporter) => ({ + controllers: writerForType('controller', file, exporter), + serializers: writerForType('serializer', file, exporter), + models: writerForType('model', file, exporter, item => { + const id = path.join('app', 'models', item) + const name = formatName(item) + + return fs.appendFile(file, exporter(name, id)) + }), + migrations: writerForType('migration', file, exporter, item => { + const id = path.join('db', 'migrate', item) + const name = chain(item) + .pipe(str => path.basename(str, '.js')) + .pipe(underscore) + .pipe(str => str.substr(17)) + .pipe(str => camelize(str, true)) + .value() + + return Promise.all([ + fs.appendFile(file, exporter(`up as ${name}Up`, id, true)), + fs.appendFile(file, exporter(`down as ${name}Down`, id, true)), + ]) + }), +}) + +export default (async function createManifest( dir: string, assets: Map | string>, - { useStrict }: { useStrict: boolean } + { useStrict }: { useStrict: boolean }, ): Promise { - const dist = joinPath(dir, 'dist') - const file = joinPath(dist, 'index.js') - const writer = createWriter(file) - - await tryCatch(() => mkdir(dist)) - await writeFile(file, Buffer.from(useStrict ? '\'use strict\';\n\n' : '')) - - await Promise.all( - Array - .from(assets) - .map(([key, value]) => { - const write = Reflect.get(writer, key) - - if (write) { - return write(value) - } else if (!write && typeof value === 'string') { - return appendFile(file, createExportStatement(key, value)) - } - - return Promise.resolve() - }) - ) -} + const dist = path.join(dir, 'dist') + const file = path.join(dist, 'index.js') + const exporter = createExporter(dist) + const writer = createWriter(file, exporter) + + await fs.mkdir(dist).catch(noop) + await fs.writeFile(file, Buffer.from(useStrict ? "'use strict';\n\n" : '')) + + const promises = Array.from(assets).map(([key, value]) => { + const write = Reflect.get(writer, key) + + if (write) { + return write(value) + } else if (!write && typeof value === 'string') { + return fs.appendFile(file, exporter(key, value)) + } + + return Promise.resolve() + }) + + await Promise.all(promises) +}) diff --git a/src/packages/compiler/utils/format-name.js b/src/packages/compiler/utils/format-name.js index 7fe9365c..0818a03d 100644 --- a/src/packages/compiler/utils/format-name.js +++ b/src/packages/compiler/utils/format-name.js @@ -4,8 +4,8 @@ import { posix, dirname, basename } from 'path' import { camelize } from 'inflection' -import underscore from '../../../utils/underscore' -import { compose } from '../../../utils/compose' +import underscore from '@lux/utils/underscore' +import { compose } from '@lux/utils/compose' const DOUBLE_COLON = /::/g @@ -16,10 +16,7 @@ const formatName: (source: string) => string = compose( (name: string) => name.replace(DOUBLE_COLON, '$'), camelize, underscore, - (name: string) => posix.join( - dirname(name), - basename(name, '.js') - ) + (name: string) => posix.join(dirname(name), basename(name, '.js')), ) export default formatName diff --git a/src/packages/compiler/utils/handle-warning.js b/src/packages/compiler/utils/handle-warning.js index b3f38ac9..9d00f248 100644 --- a/src/packages/compiler/utils/handle-warning.js +++ b/src/packages/compiler/utils/handle-warning.js @@ -4,8 +4,8 @@ * @private */ type CompilerWarning = { - code: string; - message: string; + code: string, + message: string, } /** diff --git a/src/packages/compiler/utils/is-external.js b/src/packages/compiler/utils/is-external.js deleted file mode 100644 index bd248188..00000000 --- a/src/packages/compiler/utils/is-external.js +++ /dev/null @@ -1,21 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -/** - * @private - */ -export default function isExternal(dir: string): (id: string) => boolean { - return (id: string): boolean => !( - id.startsWith('.') - || id.endsWith('lux-framework') - || id.startsWith('/') // Absolute path on Unix - || /^[A-Z]:[\\/]/.test(id) // Absolute path on Windows - || id.startsWith('app') - || id.startsWith(path.join(dir, 'app')) - || id.startsWith(path.join(dir, 'dist')) - || id === 'LUX_LOCAL' - || id === 'babelHelpers' - || id === '\u0000babelHelpers' - ) -} diff --git a/src/packages/compiler/utils/read-babel-config.js b/src/packages/compiler/utils/read-babel-config.js deleted file mode 100644 index dd3509e4..00000000 --- a/src/packages/compiler/utils/read-babel-config.js +++ /dev/null @@ -1,19 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -import { readFile } from '../../fs' - -type BabelConfig = { - presets?: Array; - plugins?: Array; -} - -async function readBabelConfig(root: string): Promise { - let data = await readFile(path.join(root, '.babelrc')) - - data = data.toString('utf8') - return JSON.parse(data) -} - -export default readBabelConfig diff --git a/src/packages/config/__tests__/__snapshots__/config.test.js.snap b/src/packages/config/__tests__/__snapshots__/config.test.js.snap index 6cc7b767..568001e5 100644 --- a/src/packages/config/__tests__/__snapshots__/config.test.js.snap +++ b/src/packages/config/__tests__/__snapshots__/config.test.js.snap @@ -3,6 +3,17 @@ exports[`module "config" #createDefaultConfig() creates a default config object in the context of NODE_ENV 1`] = ` Object { "adapter": [Function], + "database": Object { + "development": Object { + "driver": "sqlite3", + }, + "production": Object { + "driver": "sqlite3", + }, + "test": Object { + "driver": "sqlite3", + }, + }, "logging": Object { "enabled": false, "filter": Object { @@ -11,6 +22,7 @@ Object { "format": "text", "level": "DEBUG", }, + "path": "/Users/zacharygolba/src/lux", "server": Object { "cors": Object { "enabled": false, diff --git a/src/packages/config/__tests__/fixtures/results.js b/src/packages/config/__tests__/fixtures/results.js index 09233da1..ba6b7e57 100644 --- a/src/packages/config/__tests__/fixtures/results.js +++ b/src/packages/config/__tests__/fixtures/results.js @@ -1,6 +1,6 @@ /* @flow */ -import { NODE_ENV } from '../../../../constants' +import { NODE_ENV } from '@lux/constants' const isTestENV = NODE_ENV === 'test' const isProdENV = NODE_ENV === 'production' @@ -8,8 +8,8 @@ const isProdENV = NODE_ENV === 'production' export const CREATE_DEFAULT_CONFIG_RESULT = { server: { cors: { - enabled: false - } + enabled: false, + }, }, logging: { level: isProdENV ? 'INFO' : 'DEBUG', @@ -17,7 +17,7 @@ export const CREATE_DEFAULT_CONFIG_RESULT = { enabled: !isTestENV, filter: { - params: [] - } - } + params: [], + }, + }, } diff --git a/src/packages/config/index.js b/src/packages/config/index.js index 9526f5f1..d198f314 100644 --- a/src/packages/config/index.js +++ b/src/packages/config/index.js @@ -1,39 +1,49 @@ /* @flow */ -import { NODE_ENV } from '../../constants' -import { mock, http } from '../adapter' -// eslint-disable-next-line no-duplicate-imports -import type { AdapterFactory } from '../adapter' -import type { Config as LoggerConfig } from '../logger' +import { NODE_ENV } from '@lux/constants' +import { mock, http } from '@lux/packages/adapter' +import * as env from '@lux/utils/env' +import type { AdapterFactory } from '@lux/packages/adapter' +import type { Config as LoggerConfig } from '@lux/packages/logger' +import type { Config as DatabaseConfig } from '@lux/packages/database' export type Config = { + adapter: AdapterFactory, + database: DatabaseConfig, + logging: LoggerConfig, + path: string, server: { cors: { - enabled: boolean; - }; - }; - adapter: AdapterFactory; - logging: LoggerConfig; + enabled: boolean, + }, + }, } -export function createDefaultConfig(): Config { - const isTestENV = NODE_ENV === 'test' - const isProdENV = NODE_ENV === 'production' - - return { - server: { - cors: { - enabled: false, - }, +export const createDefaultConfig = (): Config => ({ + adapter: env.isTest() ? mock : http, + database: { + development: { + driver: 'sqlite3', }, - adapter: isTestENV ? mock : http, - logging: { - level: isProdENV ? 'INFO' : 'DEBUG', - format: isProdENV ? 'json' : 'text', - enabled: !isTestENV, - filter: { - params: [], - }, + production: { + driver: 'sqlite3', }, - } -} + test: { + driver: 'sqlite3', + }, + }, + logging: { + level: env.isProduction() ? 'INFO' : 'DEBUG', + format: env.isProduction() ? 'json' : 'text', + enabled: !env.isTest(), + filter: { + params: [], + }, + }, + path: process.cwd(), + server: { + cors: { + enabled: false, + }, + }, +}) diff --git a/src/packages/controller/__tests__/__snapshots__/controller.test.js.snap b/src/packages/controller/__tests__/__snapshots__/controller.test.js.snap new file mode 100644 index 00000000..0872a1e5 --- /dev/null +++ b/src/packages/controller/__tests__/__snapshots__/controller.test.js.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`module "controller" class Controller #update() returns a record if relationships(s) change 1`] = ` +Object { + "body": null, + "comments": Array [], + "createdAt": 2017-06-25T16:44:06.744Z, + "id": 105, + "isPublic": false, + "title": "#update() Test", + "updatedAt": 2017-06-25T16:44:07.470Z, + "user": Object { + "createdAt": 2017-06-25T16:44:07.454Z, + "email": "Carmelo76@yahoo.com", + "id": 101, + "name": "Jessy Stroman", + "password": "$2a$10$lI3eGqw7UvuwZYiFqPasteItwKTLYJK2RhnrjyKeiPgnstBR8OZ9a", + "posts": Array [ + [Circular], + ], + "updatedAt": 2017-06-25T16:44:07.454Z, + }, + "userId": 101, +} +`; diff --git a/src/packages/controller/__tests__/controller.test.js b/src/packages/controller/__tests__/controller.test.js index 03b94dae..6f05524c 100644 --- a/src/packages/controller/__tests__/controller.test.js +++ b/src/packages/controller/__tests__/controller.test.js @@ -2,36 +2,21 @@ import faker from 'faker' -import { MIME_TYPE } from '../../jsonapi' +import { MIME_TYPE } from '@lux/packages/jsonapi' import Controller from '../index' -import Serializer from '../../serializer' -import * as Adapters from '../../adapter' -import noop from '../../../utils/noop' +import Serializer from '@lux/packages/serializer' +import * as Adapters from '@lux/packages/adapter' +import noop from '@lux/utils/noop' import { getTestApp } from '../../../../test/utils/test-app' const HOST = 'localhost:4000' const DEFAULT_FIELDS = { - posts: [ - 'body', - 'title', - 'createdAt', - 'updatedAt', - ], - users: [ - 'id', - ], - images: [ - 'id', - ], - comments: [ - 'id', - ], - reactions: [ - 'id', - ], - tags: [ - 'id', - ], + posts: ['body', 'title', 'createdAt', 'updatedAt'], + users: ['id'], + images: ['id'], + comments: ['id'], + reactions: ['id'], + tags: ['id'], } describe('module "controller"', () => { @@ -53,9 +38,7 @@ describe('module "controller"', () => { expect(item).toBeInstanceOf(Post) if (item instanceof Post) { - expect(item.toObject()).toEqual( - expect.objectContaining(props) - ) + expect(item.toObject()).toEqual(expect.objectContaining(props)) } } @@ -69,8 +52,8 @@ describe('module "controller"', () => { serializer: new Serializer({ model: Post, parent: null, - namespace: '' - }) + namespace: '', + }), }) subject.controllers = app.controllers @@ -198,19 +181,14 @@ describe('module "controller"', () => { test('throws an error if the record is not found', async () => { const [request, response] = await mockArgs(10000) - await subject - .show(request, response) - .catch(err => { - expect(err).toEqual(expect.any(Error)) - }) + await subject.show(request, response).catch(err => { + expect(err).toEqual(expect.any(Error)) + }) }) test('supports sparse field sets', async () => { const { id, title } = getDefaultProps() - const [request, response] = await mockArgs( - 1, - '?fields[posts]=id,title' - ) + const [request, response] = await mockArgs(1, '?fields[posts]=id,title') assertRecord(await subject.show(request, response), { id, @@ -270,9 +248,7 @@ describe('module "controller"', () => { isPublic, }, }, - include: [ - 'user', - ], + include: ['user'], }) result = await subject.create(request, response) @@ -311,9 +287,9 @@ describe('module "controller"', () => { result = await subject.create(request, response) - expect( - response.headers.get('location') - ).toBe(`http://${HOST}/posts/${result.getPrimaryKey()}`) + expect(response.headers.get('location')).toBe( + `http://${HOST}/posts/${result.getPrimaryKey()}`, + ) }) }) @@ -356,9 +332,9 @@ describe('module "controller"', () => { beforeEach(async () => { User = app.store.modelFor('user') Comment = app.store.modelFor('comment') - record = await Post - .create({ title: '#update() Test' }) - .then(post => post.unwrap()) + record = await Post.create({ title: '#update() Test' }).then(post => + post.unwrap(), + ) }) afterEach(async () => { @@ -377,7 +353,7 @@ describe('module "controller"', () => { }, }) - // $FlowIgnore + // $FlowFixMe expect(record.isPublic).toBe(!isPublic) assertRecord(await subject.update(request, response), { ...getDefaultProps(), @@ -430,9 +406,9 @@ describe('module "controller"', () => { }) const [user, comments] = await Promise.all([ - // $FlowIgnore + // $FlowFixMe record.user, - // $FlowIgnore + // $FlowFixMe record.comments, ]) @@ -441,33 +417,25 @@ describe('module "controller"', () => { await subject.update(request, response) - record = await Post - .find(id) - .include('user', 'comments') + record = await Post.find(id).include('user', 'comments') assertRecord(record, { ...getDefaultProps(), id, user: expect.objectContaining( - newUser.getAttributes('id', 'name', 'email') + newUser.getAttributes('id', 'name', 'email'), ), comments: expect.arrayContaining([ - expect.objectContaining( - newComment.getAttributes('id', 'message') - ), + expect.objectContaining(newComment.getAttributes('id', 'message')), ]), }) - await Post.transaction(trx => ( + await Post.transaction(trx => Promise.all([ - newUser - .transacting(trx) - .destroy(), - newComment - .transacting(trx) - .destroy(), - ]) - )) + newUser.transacting(trx).destroy(), + newComment.transacting(trx).destroy(), + ]), + ) }) test('returns the number `204` if no changes occur', async () => { @@ -479,11 +447,9 @@ describe('module "controller"', () => { test('throws an error if the record is not found', async () => { const [request, response] = await mockArgs(10000) - await subject - .update(request, response) - .catch(err => { - expect(err).toEqual(expect.any(Error)) - }) + await subject.update(request, response).catch(err => { + expect(err).toEqual(expect.any(Error)) + }) }) test('supports sparse field sets', async () => { @@ -512,21 +478,15 @@ describe('module "controller"', () => { }, }, fields: { - users: [ - 'id', - 'name', - 'email', - ], + users: ['id', 'name', 'email'], }, - include: [ - 'user', - ], + include: ['user'], }) const [user, comments] = await Promise.all([ - // $FlowIgnore + // $FlowFixMe record.user, - // $FlowIgnore + // $FlowFixMe record.comments, ]) @@ -537,11 +497,7 @@ describe('module "controller"', () => { ...getDefaultProps(), id, user: expect.objectContaining( - newUser.getAttributes( - 'id', - 'name', - 'email' - ) + newUser.getAttributes('id', 'name', 'email'), ), }) @@ -575,7 +531,7 @@ describe('module "controller"', () => { beforeAll(async () => { record = await Post.create({ - title: '#destroy() Test' + title: '#destroy() Test', }) }) @@ -588,11 +544,9 @@ describe('module "controller"', () => { test('throws an error if the record is not found', async () => { const [request, response] = await mockArgs(10000) - await subject - .destroy(request, response) - .catch(err => { - expect(err).toEqual(expect.any(Error)) - }) + await subject.destroy(request, response).catch(err => { + expect(err).toEqual(expect.any(Error)) + }) }) }) diff --git a/src/packages/controller/__tests__/params-to-query.test.js b/src/packages/controller/__tests__/params-to-query.test.js index b9c0ca47..df4da628 100644 --- a/src/packages/controller/__tests__/params-to-query.test.js +++ b/src/packages/controller/__tests__/params-to-query.test.js @@ -1,8 +1,8 @@ /* @flow */ -import type { Model } from '../../database' -import type Request from '../../request' -import merge from '../../../utils/merge' +import type { Model } from '@lux/packages/database' +import type Request from '@lux/packages/request' +import merge from '@lux/utils/merge' import paramsToQuery from '../utils/params-to-query' import { getTestApp } from '../../../../test/utils/test-app' @@ -10,20 +10,17 @@ describe('module "controller"', () => { describe('util paramsToQuery()', () => { let app let Post: Class - const createParams = (obj: Object): $PropertyType => ( - merge({ - sort: 'createdAt', - filter: {}, - fields: { - posts: [ - 'body', - 'title', - 'createdAt', - 'updatedAt' - ] - } - }, obj) - ) + const createParams = (obj: Object): $PropertyType => + merge( + { + sort: 'createdAt', + filter: {}, + fields: { + posts: ['body', 'title', 'createdAt', 'updatedAt'], + }, + }, + obj, + ) beforeAll(async () => { app = await getTestApp() @@ -40,17 +37,14 @@ describe('module "controller"', () => { sort: 'title', page: { size: 10, - number: 5 + number: 5, }, filter: { - title: 'New Post' + title: 'New Post', }, fields: { - posts: [ - 'body', - 'title' - ] - } + posts: ['body', 'title'], + }, }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() @@ -63,8 +57,8 @@ describe('module "controller"', () => { subject = createParams({ page: { size: 10, - number: 2 - } + number: 2, + }, }) }) @@ -76,7 +70,7 @@ describe('module "controller"', () => { describe('- sort', () => { test('converts asc parameters', () => { const subject = createParams({ - sort: 'title' + sort: 'title', }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() @@ -84,7 +78,7 @@ describe('module "controller"', () => { test('converts desc parameters', () => { const subject = createParams({ - sort: '-title' + sort: '-title', }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() @@ -95,13 +89,9 @@ describe('module "controller"', () => { test('can properly build included fields', () => { const subject = createParams({ fields: { - users: [ - 'name', - ], + users: ['name'], }, - include: [ - 'user', - ], + include: ['user'], }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() @@ -110,13 +100,9 @@ describe('module "controller"', () => { test('ignores invalid field sets', () => { const subject = createParams({ fields: { - authors: [ - 'name' - ] + authors: ['name'], }, - include: [ - 'author' - ] + include: ['author'], }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() @@ -125,11 +111,8 @@ describe('module "controller"', () => { test('only adds `id` when the include array is `undefined`', () => { const subject = createParams({ fields: { - images: [ - 'id', - 'url' - ] - } + images: ['id', 'url'], + }, }) expect(paramsToQuery(Post, subject)).toMatchSnapshot() diff --git a/src/packages/controller/constants.js b/src/packages/controller/constants.js index b27e068d..0ad361c1 100644 --- a/src/packages/controller/constants.js +++ b/src/packages/controller/constants.js @@ -2,12 +2,10 @@ import type { BuiltInAction } from './index' -export const BUILT_IN_ACTIONS: Array = ( - Object.freeze([ - 'show', - 'index', - 'create', - 'update', - 'destroy', - ]) -) +export const BUILT_IN_ACTIONS: Array = Object.freeze([ + 'show', + 'index', + 'create', + 'update', + 'destroy', +]) diff --git a/src/packages/controller/index.js b/src/packages/controller/index.js index 1136cbe4..11d204e2 100644 --- a/src/packages/controller/index.js +++ b/src/packages/controller/index.js @@ -1,24 +1,18 @@ /* @flow */ -import { Model } from '../database' -import { freezeProps } from '../freezeable' -import getDomain from '../../utils/get-domain' -import type Serializer from '../serializer' -// eslint-disable-next-line no-duplicate-imports -import type { Query } from '../database' -import type Request from '../request' -import type Response from '../response' +import { Model } from '@lux/packages/database' +import { freezeProps } from '@lux/packages/freezeable' +import getDomain from '@lux/utils/get-domain' +import type Serializer from '@lux/packages/serializer' +import type { Query } from '@lux/packages/database' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import findOne from './utils/find-one' import findMany from './utils/find-many' import resolveRelationships from './utils/resolve-relationships' -export type BuiltInAction = - | 'show' - | 'index' - | 'create' - | 'update' - | 'destroy' +export type BuiltInAction = 'show' | 'index' | 'create' | 'update' | 'destroy' export type BeforeAction = ( request: Request, @@ -37,6 +31,8 @@ export type Options = { serializer?: Serializer, } +export { BUILT_IN_ACTIONS } from './constants' + /** * ## Overview * @@ -103,17 +99,17 @@ export type Options = { * * ```javascript * // app/controllers/posts.js - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * class PostsController extends Controller { * index(request, response) { * return super.index(request, response).where({ * isPublic: true - * }); + * }) * } * } * - * export default PostsController; + * export default PostsController * ``` * * **Custom Actions** @@ -126,15 +122,15 @@ export type Options = { * * ```javascript * // app/controllers/health.js - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * class HealthController extends Controller { * async check() { - * return 204; + * return 204 * } * } * - * export default HealthController; + * export default HealthController * ``` * * The example above is nice but we can make the code a bit more concise with an @@ -142,13 +138,13 @@ export type Options = { * * ```javascript * // app/controllers/health.js - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * class HealthController extends Controller { - * check = async () => 204; + * check = async () => 204 * } * - * export default HealthController; + * export default HealthController * ``` * * Using an Arrow Function instead of a traditional method Controller can be @@ -163,18 +159,18 @@ export type Options = { * * ```javascript * // app/controllers/posts.js - * import { Controller } from 'lux-framework'; - * import Post from 'app/models/posts'; + * import { Controller } from 'lux-framework' + * import Post from 'app/models/posts' * * class PostsController extends Controller { * drafts() { * return Post.where({ * isPublic: false - * }); + * }) * } * } * - * export default PostsController; + * export default PostsController * ``` * * While the example above works, we would have to implement all the custom @@ -184,17 +180,17 @@ export type Options = { * * ```javascript * // app/controllers/posts.js - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * class PostsController extends Controller { * drafts(request, response) { * return this.index(request, response).where({ * isPublic: false - * }); + * }) * } * } * - * export default PostsController; + * export default PostsController * ``` * * Now we can sort, filter, and paginate our custom `drafts` route! @@ -232,20 +228,20 @@ export type Options = { * * ```javascript * // app/controllers/application.js - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * class ApplicationController extends Controller { * beforeAction = [ * async function authenticate(request) { * if (!request.currentUser) { * // 401 Unauthorized - * return false; + * return false * } * } - * ]; + * ] * } * - * export default ApplicationController; + * export default ApplicationController * ``` * * **Execuation Order** @@ -272,7 +268,7 @@ export type Options = { * export default async function authenticate(request) { * if (!request.currentUser) { * // 401 Unauthorized - * return false; + * return false * } * } * ``` @@ -281,22 +277,22 @@ export type Options = { * * ```javascript * // app/controllers/application.js - * import { Controller } from 'lux-framework'; - * import authenticate from 'app/middleware/authenticate'; + * import { Controller } from 'lux-framework' + * import authenticate from 'app/middleware/authenticate' * * class ApplicationController extends Controller { * beforeAction = [ * authenticate - * ]; + * ] * } * - * export default ApplicationController; + * export default ApplicationController * ``` * * @class Controller * @public */ -class Controller { +export default class Controller { /** * An array of custom query parameter keys that are allowed to reach a * Controller instance from an incoming `HTTP` request. @@ -311,7 +307,7 @@ class Controller { * // Controller's actions. * query = [ * 'cache' - * ]; + * ] * } * ``` * @@ -320,7 +316,7 @@ class Controller { * @default [] * @public */ - query: Array = []; + query: Array = [] /** * An array of sort query parameter values that are allowed to reach a @@ -335,7 +331,7 @@ class Controller { * @default [] * @public */ - sort: Array = []; + sort: Array = [] /** * An array of filter query parameter keys that are allowed to reach a @@ -350,7 +346,7 @@ class Controller { * @default [] * @public */ - filter: Array = []; + filter: Array = [] /** * An array of parameter keys that are allowed to reach a Controller instance @@ -365,7 +361,7 @@ class Controller { * @default [] * @public */ - params: Array = []; + params: Array = [] /** * Functions to execute on each request handled by a `Controller` before the @@ -384,34 +380,34 @@ class Controller { * **Example:** * * ```javascript - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * - * const UNSAFE_METHODS = /(?:POST|PATCH|DELETE)/i; + * const UNSAFE_METHODS = /(?:POST|PATCH|DELETE)/i * * function isAdmin(user) { * if (user) { - * return user.isAdmin; + * return user.isAdmin * } * - * return false; + * return false * } * * async function authentication(request) { - * const { method, currentUser } = request; - * const isUnsafe = UNSAFE_METHODS.test(method); + * const { method, currentUser } = request + * const isUnsafe = UNSAFE_METHODS.test(method) * * if (isUnsafe && !isAdmin(currentUser)) { - * return false; // 401 Unauthorized if the current user is not an admin. + * return false // 401 Unauthorized if the current user is not an admin. * } * } * * class PostsController extends Controller { * beforeAction = [ * authentication - * ]; + * ] * } * - * export default PostsController; + * export default PostsController * ``` * * @property beforeAction @@ -419,7 +415,7 @@ class Controller { * @default [] * @public */ - beforeAction: Array = []; + beforeAction: Array = [] /** * Functions to execute on each request handled by a `Controller` after the @@ -440,10 +436,10 @@ class Controller { * **Example:** * * ```javascript - * import { Controller } from 'lux-framework'; + * import { Controller } from 'lux-framework' * * async function addCopyright(request, response, payload) { - * const { action } = request; + * const { action } = request * * if (payload && action !== preflight) { * return { @@ -451,19 +447,19 @@ class Controller { * meta: { * copyright: '2016 (c) Postlight' * } - * }; + * } * } * - * return payload; + * return payload * } * * class ApplicationController extends Controller { * afterAction = [ * addCopyright - * ]; + * ] * } * - * export default ApplicationController; + * export default ApplicationController * ``` * * @property afterAction @@ -471,7 +467,7 @@ class Controller { * @default [] * @public */ - afterAction: Array> = []; + afterAction: Array> = [] /** * The default amount of items to include per each response of the index @@ -482,7 +478,7 @@ class Controller { * @default 25 * @public */ - defaultPerPage: number = 25; + defaultPerPage: number = 25 /** * The resolved Model for a Controller instance. @@ -491,7 +487,7 @@ class Controller { * @type {Model} * @private */ - model: Class; + model: Class /** * A reference to the root Controller for the namespace that a Controller @@ -501,7 +497,7 @@ class Controller { * @type {?Controller} * @private */ - parent: ?Controller; + parent: ?Controller /** * The namespace that a Controller instance is a member of. @@ -510,7 +506,7 @@ class Controller { * @type {String} * @private */ - namespace: string; + namespace: string /** * The resolved Serializer for a Controller instance. @@ -519,7 +515,7 @@ class Controller { * @type {Serializer} * @private */ - serializer: Serializer<*>; + serializer: Serializer<*> /** * A Map instance containing a reference to all the Controller within an @@ -529,7 +525,7 @@ class Controller { * @type {Map} * @private */ - controllers: Map; + controllers: Map /** * A boolean value representing whether or not a Controller instance has a @@ -539,7 +535,7 @@ class Controller { * @type {Boolean} * @private */ - hasModel: boolean; + hasModel: boolean /** * A boolean value representing whether or not a Controller instance is within @@ -549,7 +545,7 @@ class Controller { * @type {Boolean} * @private */ - hasNamespace: boolean; + hasNamespace: boolean /** * A boolean value representing whether or not a Controller instance has a @@ -559,7 +555,7 @@ class Controller { * @type {Boolean} * @private */ - hasSerializer: boolean; + hasSerializer: boolean constructor(options: Options<*> = {}) { const { model, serializer } = options @@ -575,20 +571,12 @@ class Controller { serializer, hasModel: Boolean(model), hasNamespace: Boolean(namespace), - hasSerializer: Boolean(serializer) + hasSerializer: Boolean(serializer), }) - freezeProps(this, true, - 'model', - 'namespace', - 'serializer' - ) + freezeProps(this, true, 'model', 'namespace', 'serializer') - freezeProps(this, false, - 'hasModel', - 'hasNamespace', - 'hasSerializer' - ) + freezeProps(this, false, 'hasModel', 'hasNamespace', 'hasSerializer') } /** @@ -638,25 +626,18 @@ class Controller { const { model } = this const { - url: { - pathname - }, - params: { - data: { - attributes, - relationships - } - } + url: { pathname }, + params: { data: { attributes, relationships } }, } = req const record = await model.create({ ...attributes, - ...resolveRelationships(model, relationships) + ...resolveRelationships(model, relationships), }) res.setHeader( 'Location', - `${getDomain(req) + (pathname || '')}/${record.getPrimaryKey()}` + `${getDomain(req) + (pathname || '')}/${record.getPrimaryKey()}`, ) Reflect.set(res, 'statusCode', 201) @@ -680,19 +661,12 @@ class Controller { const { model } = this const record = await findOne(this.model, request) - const { - params: { - data: { - attributes, - relationships, - }, - }, - } = request + const { params: { data: { attributes, relationships } } } = request Object.assign( record, attributes, - resolveRelationships(model, relationships) + resolveRelationships(model, relationships), ) if (record.isDirty) { @@ -720,6 +694,8 @@ class Controller { .then(() => 204) } + /* eslint-disable class-methods-use-this */ + /** * Respond to HEAD or OPTIONS requests. * @@ -732,7 +708,6 @@ class Controller { preflight(): Promise { return Promise.resolve(204) } -} -export default Controller -export { BUILT_IN_ACTIONS } from './constants' + /* eslint-enable class-methods-use-this */ +} diff --git a/src/packages/controller/interfaces.js b/src/packages/controller/interfaces.js index c7a2eaf5..9b717011 100644 --- a/src/packages/controller/interfaces.js +++ b/src/packages/controller/interfaces.js @@ -1,39 +1,36 @@ /* @flow */ -import type Database, { Model, Query } from '../database'; -import type Serializer from '../serializer'; -import type Controller from './index'; -import type Request from '../request'; -import type Response from '../response'; +import type { Model, Query } from '@lux/packages/database' +import type Serializer from '@lux/packages/serializer' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' export type Controller$opts = { - model?: Class; - namespace?: string; - serializer?: Serializer<*>; -}; + model?: Class, + namespace?: string, + serializer?: Serializer<*>, +} export type Controller$builtIn = | 'show' | 'index' | 'create' | 'update' - | 'destroy'; + | 'destroy' export type Controller$beforeAction = ( request: Request, - response: Response -) => Promise; + response: Response, +) => Promise export type Controller$afterAction = ( request: Request, response: Response, - responseData: any -) => Promise; + responseData: any, +) => Promise -export type Controller$findOne = ( - request: Request -) => Query; +export type Controller$findOne = (request: Request) => Query export type Controller$findMany = ( - request: Request -) => Query>; + request: Request, +) => Query> diff --git a/src/packages/controller/utils/find-many.js b/src/packages/controller/utils/find-many.js index 0ebfe949..078c56cc 100644 --- a/src/packages/controller/utils/find-many.js +++ b/src/packages/controller/utils/find-many.js @@ -1,8 +1,8 @@ /* @flow */ -import merge from '../../../utils/merge' -import type { Model, Query } from '../../database' -import type Request from '../../request' +import merge from '@lux/utils/merge' +import type { Model, Query } from '@lux/packages/database' +import type Request from '@lux/packages/request' import paramsToQuery from './params-to-query' @@ -11,19 +11,16 @@ import paramsToQuery from './params-to-query' */ export default function findMany( model: Class, - req: Request + req: Request, ): Query> { const params = merge(req.defaultParams, req.params) - const { - sort, - page, - limit, - select, - filter, - include - } = paramsToQuery(model, params) + const { sort, page, limit, select, filter, include } = paramsToQuery( + model, + params, + ) - return model.select(...select) + return model + .select(...select) .include(include) .limit(limit) .page(page) diff --git a/src/packages/controller/utils/find-one.js b/src/packages/controller/utils/find-one.js index e34290aa..96a4cde3 100644 --- a/src/packages/controller/utils/find-one.js +++ b/src/packages/controller/utils/find-one.js @@ -1,9 +1,8 @@ /* @flow */ -import merge from '../../../utils/merge' -// eslint-disable-next-line no-unused-vars -import type { Model, Query } from '../../database' -import type Request from '../../request' +import merge from '@lux/utils/merge' +import type { Model, Query } from '@lux/packages/database' +import type Request from '@lux/packages/request' import paramsToQuery from './params-to-query' @@ -14,9 +13,7 @@ function findOne(model: Class, request: Request): Query { const params = merge(request.defaultParams, request.params) const { id, select, include } = paramsToQuery(model, params) - return model.find(id) - .select(...select) - .include(include) + return model.find(id).select(...select).include(include) } export default findOne diff --git a/src/packages/controller/utils/params-to-query.js b/src/packages/controller/utils/params-to-query.js index 11ebdc3f..158c127e 100644 --- a/src/packages/controller/utils/params-to-query.js +++ b/src/packages/controller/utils/params-to-query.js @@ -1,35 +1,28 @@ /* @flow */ -import omit from '../../../utils/omit' -import entries from '../../../utils/entries' -import type { Model } from '../../database' -import type Request from '../../request' +import omit from '@lux/utils/omit' +import { isUndefined } from '@lux/utils/is-type' +import type { Model, Relationship } from '@lux/packages/database' -/** - * @private - */ -export default function paramsToQuery(model: Class, { - id, - page, - sort, - filter, - fields, - include -}: $PropertyType): Object { - const relationships = entries(model.relationships) - let includedFields = omit(fields, model.resourceName) +const paramsToQuery = (model: Class, params: Object): Object => { + const { id, page, sort, filter, fields, include } = params + // $FlowFixMe + const relationships: Array<[string, Relationship]> = Object.entries( + model.relationships, + ) let query = { id, filter, - select: [model.primaryKey, ...Reflect.get(fields, model.resourceName)] + include: {}, + select: [model.primaryKey, ...Reflect.get(fields, model.resourceName)], } if (page) { query = { ...query, page: page.number, - limit: page.size + limit: page.size, } } @@ -37,29 +30,34 @@ export default function paramsToQuery(model: Class, { if (sort.startsWith('-')) { query = { ...query, - sort: [sort.substr(1), 'DESC'] + sort: [sort.substr(1), 'DESC'], } } else { query = { ...query, - sort: [sort, 'ASC'] + sort: [sort, 'ASC'], } } } - includedFields = entries(includedFields).reduce((result, field) => { + query.include = Object.entries( + omit(fields, model.resourceName), + ).reduce((prev, field) => { + const next = prev const [key] = field let [, value] = field - const [ - name, - relationship - ] = relationships.find(([, { model: related }]) => ( - key === related.resourceName - )) || [] + const [name, relationship] = + relationships.find( + ([, { model: related }]) => key === related.resourceName, + ) || [] - if (!name || !relationship) { - return result + if ( + isUndefined(name) || + isUndefined(relationship) || + !Array.isArray(value) + ) { + return next } if (!value.includes(relationship.model.primaryKey)) { @@ -72,14 +70,11 @@ export default function paramsToQuery(model: Class, { value = value.slice(0, 1) } - return { - ...result, - [name]: value - } + next[name] = value + return next }, {}) - return { - ...query, - include: includedFields - } + return query } + +export default paramsToQuery diff --git a/src/packages/controller/utils/resolve-relationships.js b/src/packages/controller/utils/resolve-relationships.js index a03c5809..6108e717 100644 --- a/src/packages/controller/utils/resolve-relationships.js +++ b/src/packages/controller/utils/resolve-relationships.js @@ -1,34 +1,27 @@ /* @flow */ -import entries from '../../../utils/entries' -// eslint-disable-next-line no-unused-vars -import type { Model } from '../../database' +import { isObject } from '@lux/utils/is-type' +import type { Model } from '@lux/packages/database' -/** - * @private - */ -export default function resolveRelationships( - model: Class, - relationships: Object = {} -): Object { - return entries(relationships).reduce((obj, [key, value]) => { - let { data = null } = value || {} +const resolve = (model: Class, objMap?: Object = {}): Object => + Object.entries(objMap).reduce((prev, [key, value]) => { + const next = prev - if (data) { + if (isObject(value) && isObject(value.data)) { const opts = model.relationshipFor(key) if (opts) { - if (Array.isArray(data)) { - data = data.map(item => Reflect.construct(opts.model, [item])) + if (Array.isArray(value.data)) { + next[key] = value.data.map(item => + Reflect.construct(opts.model, [item]), + ) } else { - data = Reflect.construct(opts.model, [data]) + next[key] = Reflect.construct(opts.model, [value.data]) } } } - return { - ...obj, - [key]: data - } + return next }, {}) -} + +export default resolve diff --git a/src/packages/database/__tests__/database.test.js b/src/packages/database/__tests__/database.test.js index 8c2e9b81..a99c0248 100644 --- a/src/packages/database/__tests__/database.test.js +++ b/src/packages/database/__tests__/database.test.js @@ -11,20 +11,20 @@ const DEFAULT_CONFIG = { development: { pool: 5, driver: 'sqlite3', - database: 'lux_test' + database: 'lux_test', }, test: { pool: 5, driver: DATABASE_DRIVER || 'sqlite3', database: 'lux_test', username: DATABASE_USERNAME, - password: DATABASE_PASSWORD + password: DATABASE_PASSWORD, }, production: { pool: 5, driver: 'sqlite3', - database: 'lux_test' - } + database: 'lux_test', + }, } describe('module "database"', () => { @@ -37,17 +37,16 @@ describe('module "database"', () => { const { path, models, logger } = app - createDatabase = (config = DEFAULT_CONFIG) => ( + createDatabase = (config = DEFAULT_CONFIG) => Promise.resolve( new Database({ path, models, logger, config, - checkMigrations: false - }) + checkMigrations: false, + }), ) - ) }) afterAll(async () => { @@ -66,16 +65,16 @@ describe('module "database"', () => { const store = await createDatabase({ development: { ...DEFAULT_CONFIG.development, - driver: 'invalid-driver' + driver: 'invalid-driver', }, test: { ...DEFAULT_CONFIG.test, - driver: 'invalid-driver' + driver: 'invalid-driver', }, production: { ...DEFAULT_CONFIG.production, - driver: 'invalid-driver' - } + driver: 'invalid-driver', + }, }).catch(err => { expect(err.constructor.name).toBe('InvalidDriverError') }) diff --git a/src/packages/database/__tests__/migration.test.js b/src/packages/database/__tests__/migration.test.js index da2527f3..ef4c8318 100644 --- a/src/packages/database/__tests__/migration.test.js +++ b/src/packages/database/__tests__/migration.test.js @@ -2,10 +2,7 @@ import Migration from '../migration' import { getTestApp } from '../../../../test/utils/test-app' -import { - default as generateTimestamp, - padding -} from '../migration/utils/generate-timestamp' +import * as timestamp from '@lux/packages/database/migration/timestamp' describe('module "database/migration"', () => { describe('class Migration', () => { @@ -13,8 +10,8 @@ describe('module "database/migration"', () => { let store beforeAll(async () => { - app = await getTestApp(); - ({ store } = app) + app = await getTestApp() + store = app.store }) afterAll(async () => { @@ -26,31 +23,24 @@ describe('module "database/migration"', () => { let subject beforeEach(() => { - subject = new Migration(schema => ( + subject = new Migration(schema => schema.createTable(tableName, table => { table.increments() - table - .boolean('success') - .index() - .notNullable() - .defaultTo(false) + table.boolean('success').index().notNullable().defaultTo(false) table.timestamps() table.index(['created_at', 'updated_at']) - }) - )) + }), + ) }) - afterEach(() => ( - store.schema().dropTable(tableName) - )) + afterEach(() => store.schema().dropTable(tableName)) - test('runs a migration function', () => subject - .run(store.schema()) - .then(result => { - expect(result).toEqual(expect.anything()) - })) + test('runs a migration function', () => + subject.run(store.schema()).then(result => { + expect(result).toEqual(expect.anything()) + })) }) }) }) @@ -58,13 +48,13 @@ describe('module "database/migration"', () => { describe('module "database/migration/utils/generate-timestamp"', () => { describe('.generateTimestamp()', () => { test('generates a timestamp string', () => { - expect(generateTimestamp()).toMatch(/^\d{16}$/g) + expect(timestamp.generate()).toMatch(/^\d{16}$/g) }) }) describe('.padding()', () => { test('yields the specified char for the specified amount', () => { - const iter = padding('w', 3) + const iter = timestamp.padding('w', 3) let next = iter.next() expect(next.value).toBe('w') diff --git a/src/packages/database/__tests__/model.test.js b/src/packages/database/__tests__/model.test.js index 5a631315..878d979e 100644 --- a/src/packages/database/__tests__/model.test.js +++ b/src/packages/database/__tests__/model.test.js @@ -14,8 +14,8 @@ describe('module "database/model"', () => { let Comment: Class beforeAll(async () => { - app = await getTestApp(); - ({ store } = app) + app = await getTestApp() + store = app.store User = store.modelFor('user') Image = store.modelFor('image') Comment = store.modelFor('comment') @@ -27,29 +27,29 @@ describe('module "database/model"', () => { describe('.initialize()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } static hasMany = { comments: { - inverse: 'post' + inverse: 'post', }, reactions: { inverse: 'post', - model: 'reaction' + model: 'reaction', }, tags: { inverse: 'posts', - through: 'categorization' - } - }; + through: 'categorization', + }, + } static hooks = [ 'afterCreate', @@ -59,33 +59,32 @@ describe('module "database/model"', () => { // eslint-disable-next-line no-param-reassign hooks[key] = jest.fn().mockImplementation(() => Promise.resolve()) return hooks - }, {}); + }, {}) static scopes = { isPublic() { return this.where({ - isPublic: true + isPublic: true, }) }, isDraft() { return this.where({ - isPublic: false + isPublic: false, }) - } - }; + }, + } static validates = { title: str => Boolean(str), notAFunction: {}, notAnAttribute: () => false, - }; + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -116,14 +115,13 @@ describe('module "database/model"', () => { }) test('adds an `attributes` property to the `Model`', () => { - const metaFor = (columnName, docName = columnName) => ( + const metaFor = (columnName, docName = columnName) => expect.objectContaining({ columnName, docName, type: expect.any(String), nullable: expect.any(Boolean), }) - ) expect(Subject.attributes).toEqual({ id: metaFor('id'), @@ -141,17 +139,12 @@ describe('module "database/model"', () => { }) test('adds attribute accessors on the `prototype`', () => { - Object - .keys(Subject.attributes) - .forEach(key => { - const desc = Reflect.getOwnPropertyDescriptor( - Subject.prototype, - key - ) - - expect(typeof desc.get).toBe('function') - expect(typeof desc.set).toBe('function') - }) + Object.keys(Subject.attributes).forEach(key => { + const desc = Reflect.getOwnPropertyDescriptor(Subject.prototype, key) + + expect(typeof desc.get).toBe('function') + expect(typeof desc.set).toBe('function') + }) }) test('adds a `hasOne` property to the `Model`', () => { @@ -182,7 +175,7 @@ describe('module "database/model"', () => { expect.objectContaining({ get: expect.any(Function), set: expect.any(Function), - }) + }), ) }) }) @@ -240,26 +233,25 @@ describe('module "database/model"', () => { let result class Subject extends Model { - id: number; - body: ?string; - title: ?string; - isPublic: boolean; - createdAt: Date; - updatedAt: Date; + id: number + body: ?string + title: ?string + isPublic: boolean + createdAt: Date + updatedAt: Date - static tableName = 'posts'; + static tableName = 'posts' static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -277,10 +269,10 @@ describe('module "database/model"', () => { user, body, title, - isPublic: true + isPublic: true, }) - // $FlowIgnore + // $FlowFixMe result = result.unwrap() expect(result).toBeInstanceOf(Subject) @@ -312,13 +304,12 @@ describe('module "database/model"', () => { describe('.transacting()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -335,13 +326,12 @@ describe('module "database/model"', () => { describe('.all()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -354,13 +344,12 @@ describe('module "database/model"', () => { describe('.find()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -373,13 +362,12 @@ describe('module "database/model"', () => { describe('.page()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -392,13 +380,12 @@ describe('module "database/model"', () => { describe('.limit()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -411,13 +398,12 @@ describe('module "database/model"', () => { describe('.offset()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -430,13 +416,12 @@ describe('module "database/model"', () => { describe('.count()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -449,13 +434,12 @@ describe('module "database/model"', () => { describe('.order()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -468,19 +452,18 @@ describe('module "database/model"', () => { describe('.where()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) test('returns an instance of `Query`', () => { const result = Subject.where({ - isPublic: true + isPublic: true, }) expect(result instanceof Query).toBe(true) @@ -489,19 +472,18 @@ describe('module "database/model"', () => { describe('.not()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) test('returns an instance of `Query`', () => { const result = Subject.not({ - isPublic: true + isPublic: true, }) expect(result instanceof Query).toBe(true) @@ -510,18 +492,18 @@ describe('module "database/model"', () => { describe('.whereBetween()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { await Subject.initialize(store, () => - store.connection(Subject.tableName) + store.connection(Subject.tableName), ) }) it('returns an instance of `Query`', () => { const result = Subject.whereBetween({ - userId: [1, 10] + userId: [1, 10], }) expect(result instanceof Query).toBe(true) @@ -530,20 +512,17 @@ describe('module "database/model"', () => { describe('.whereRaw()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { await Subject.initialize(store, () => - store.connection(Subject.tableName) + store.connection(Subject.tableName), ) }) it('returns an instance of `Query`', () => { - const result = Subject.whereRaw( - '"title" LIKE ?', - ['%Test%'] - ) + const result = Subject.whereRaw('"title" LIKE ?', ['%Test%']) expect(result instanceof Query).toBe(true) }) @@ -551,12 +530,12 @@ describe('module "database/model"', () => { describe('.first()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { await Subject.initialize(store, () => - store.connection(Subject.tableName) + store.connection(Subject.tableName), ) }) @@ -569,13 +548,12 @@ describe('module "database/model"', () => { describe('.last()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -588,13 +566,12 @@ describe('module "database/model"', () => { describe('.select()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -607,13 +584,12 @@ describe('module "database/model"', () => { describe('.distinct()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -626,25 +602,24 @@ describe('module "database/model"', () => { describe('.include()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' static hasMany = { comments: { - inverse: 'post' - } - }; + inverse: 'post', + }, + } static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -657,21 +632,20 @@ describe('module "database/model"', () => { describe('.unscope()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' static scopes = { isPublic() { return this.where({ - isPublic: true + isPublic: true, }) - } - }; + }, + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -687,8 +661,8 @@ describe('module "database/model"', () => { static scopes = { mostRecent() { return this.order('createdAt', 'DESC') - } - }; + }, + } } test('returns true if a `Model` has a scope', () => { @@ -706,21 +680,19 @@ describe('module "database/model"', () => { describe('.isInstance()', () => { class SubjectA extends Model { - static tableName = 'posts'; + static tableName = 'posts' } class SubjectB extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await SubjectA.initialize( - store, - () => store.connection(SubjectA.tableName) + await SubjectA.initialize(store, () => + store.connection(SubjectA.tableName), ) - await SubjectB.initialize( - store, - () => store.connection(SubjectB.tableName) + await SubjectB.initialize(store, () => + store.connection(SubjectB.tableName), ) }) @@ -741,13 +713,12 @@ describe('module "database/model"', () => { describe('.columnFor()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -758,20 +729,19 @@ describe('module "database/model"', () => { docName: 'is-public', type: expect.any(String), nullable: expect.any(Boolean), - }) + }), ) }) }) describe('.columnNameFor()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -784,19 +754,18 @@ describe('module "database/model"', () => { describe('.relationshipFor()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -806,8 +775,8 @@ describe('module "database/model"', () => { }) describe('.hooks', () => { - ['after', 'before'].forEach(prefix => { - ['Save', 'Create', 'Destroy', 'Validation'].forEach(suffix => { + ;['after', 'before'].forEach(prefix => { + ;['Save', 'Create', 'Destroy', 'Validation'].forEach(suffix => { const name = prefix + suffix const tableName = 'posts' let Subject @@ -820,15 +789,12 @@ describe('module "database/model"', () => { hook = jest.fn().mockReturnValue(Promise.resolve()) Subject = class extends Model { - isPublic: boolean; - static hooks = { [name]: hook }; - static tableName = tableName; + isPublic: boolean + static hooks = { [name]: hook } + static tableName = tableName } - await Subject.initialize( - store, - () => store.connection(tableName) - ) + await Subject.initialize(store, () => store.connection(tableName)) if (store.hasPool) { trx = expect.any(Function) @@ -836,14 +802,10 @@ describe('module "database/model"', () => { }) beforeEach(async () => { - instance = await Subject - .create({ - title: 'Test Hook', - isPublic: false, - }) - .then(result => ( - result.unwrap() - )) + instance = await Subject.create({ + title: 'Test Hook', + isPublic: false, + }).then(result => result.unwrap()) }) afterEach(async () => { @@ -893,16 +855,15 @@ describe('module "database/model"', () => { describe('.attributes', () => { class Subject extends Model { - body: void | ?string; - title: ?string; + body: void | ?string + title: ?string - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) @@ -912,7 +873,7 @@ describe('module "database/model"', () => { beforeEach(() => { instance = new Subject({ - title: ogTitle + title: ogTitle, }) }) @@ -947,9 +908,8 @@ describe('module "database/model"', () => { }) }) }) - }); - - ['save', 'update'].forEach(method => { + }) + ;['save', 'update'].forEach(method => { describe(`#${method}()`, () => { let user let image @@ -957,47 +917,46 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - id: number; - body: string; - title: string; - isPublic: boolean; + id: number + body: string + title: string + isPublic: boolean - static tableName = 'posts'; + static tableName = 'posts' static hasOne = { image: { - inverse: 'post' - } - }; + inverse: 'post', + }, + } static hasMany = { comments: { - inverse: 'post' - } - }; + inverse: 'post', + }, + } static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } static validates = { - title: str => str.split(' ').length > 1 - }; + title: str => str.split(' ').length > 1, + } } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) beforeEach(async () => { instance = await Subject.create({ title: 'Test Post', - isPublic: false + isPublic: false, }) }) @@ -1039,21 +998,17 @@ describe('module "database/model"', () => { body, user, image, - comments: [ - comment, - ], - isPublic: true + comments: [comment], + isPublic: true, }) } else { - // $FlowIgnore + // $FlowFixMe Object.assign(instance, { body, user, image, - comments: [ - comment, - ], - isPublic: true + comments: [comment], + isPublic: true, }) await instance.save() @@ -1062,13 +1017,11 @@ describe('module "database/model"', () => { expect(instance.body).toBe(body) expect(instance.isPublic).toBe(true) - let result = await Subject - .find(instance.getPrimaryKey()) - .include( - 'user', - 'image', - 'comments' - ) + let result = await Subject.find(instance.getPrimaryKey()).include( + 'user', + 'image', + 'comments', + ) result = result.toObject() @@ -1078,13 +1031,13 @@ describe('module "database/model"', () => { expect(result.user).toEqual( expect.objectContaining({ id: user.getPrimaryKey(), - }) + }), ) expect(result.image).toEqual( expect.objectContaining({ id: image.getPrimaryKey(), - }) + }), ) expect(result.comments).toEqual(expect.any(Array)) @@ -1115,19 +1068,18 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - id: number; + id: number - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) instance = await Subject.create({ - title: 'Test Post' + title: 'Test Post', }) }) @@ -1147,21 +1099,20 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - title: string; + title: string - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) instance = await Subject.create({ body: 'Lots of content...', title: 'Test Post', - isPublic: true + isPublic: true, }) }) @@ -1199,21 +1150,20 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - title: string; + title: string - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) instance = await Subject.create({ body: 'Lots of content...', title: 'Test Post', - isPublic: true + isPublic: true, }) }) @@ -1240,19 +1190,18 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) instance = await Subject.create({ body: 'Lots of content...', title: 'Test Post', - isPublic: true + isPublic: true, }) }) @@ -1265,7 +1214,7 @@ describe('module "database/model"', () => { expect(result).toEqual({ body: 'Lots of content...', - title: 'Test Post' + title: 'Test Post', }) }) }) @@ -1274,17 +1223,16 @@ describe('module "database/model"', () => { let instance class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) instance = await Subject.create({ - title: 'Test Post' + title: 'Test Post', }) }) @@ -1301,13 +1249,12 @@ describe('module "database/model"', () => { describe('get #persisted()', () => { class Subject extends Model { - static tableName = 'posts'; + static tableName = 'posts' } beforeAll(async () => { - await Subject.initialize( - store, - () => store.connection(Subject.tableName) + await Subject.initialize(store, () => + store.connection(Subject.tableName), ) }) diff --git a/src/packages/database/__tests__/query.test.js b/src/packages/database/__tests__/query.test.js index 39f5120c..ca361234 100644 --- a/src/packages/database/__tests__/query.test.js +++ b/src/packages/database/__tests__/query.test.js @@ -2,7 +2,7 @@ import Query from '../query' import Model from '../model' -import range from '../../../utils/range' +import range from '@lux/utils/range' import { getTestApp } from '../../../../test/utils/test-app' describe('module "database/query"', () => { @@ -11,47 +11,47 @@ describe('module "database/query"', () => { let app class TestModel extends Model { - id: number; - body: string; - user: Class; - tags: Array>; - title: string; - comments: Array>; - isPublic: boolean; - reactions: Array>; - createdAt: Date; - updatedAt: Date; - - static tableName = 'posts'; + id: number + body: string + user: Class + tags: Array> + title: string + comments: Array> + isPublic: boolean + reactions: Array> + createdAt: Date + updatedAt: Date + + static tableName = 'posts' static belongsTo = { user: { - inverse: 'posts' - } - }; + inverse: 'posts', + }, + } static hasMany = { comments: { - inverse: 'post' + inverse: 'post', }, reactions: { - inverse: 'post' + inverse: 'post', }, tags: { inverse: 'posts', - through: 'categorization' - } - }; + through: 'categorization', + }, + } static scopes = { isPublic() { return this.where({ - isPublic: true + isPublic: true, }) - } - }; + }, + } } const assertItem = item => { @@ -65,9 +65,8 @@ describe('module "database/query"', () => { Test = store.modelFor('test') - await TestModel.initialize( - store, - () => store.connection(TestModel.tableName), + await TestModel.initialize(store, () => + store.connection(TestModel.tableName), ) await Test.store.connection.batchInsert( @@ -88,14 +87,9 @@ describe('module "database/query"', () => { source = new Query(TestModel) .limit(10) .order('title', 'DESC') - .include( - 'user', - 'tags', - 'comments', - 'reactions' - ) + .include('user', 'tags', 'comments', 'reactions') .where({ - isPublic: true + isPublic: true, }) }) @@ -135,7 +129,7 @@ describe('module "database/query"', () => { test('properly handles null conditions', () => { const result = subject.where({ - isPublic: null + isPublic: null, }) expect(result.snapshots).toMatchSnapshot() @@ -151,7 +145,7 @@ describe('module "database/query"', () => { test('returns `this`', () => { const result = subject.not({ - isPublic: true + isPublic: true, }) expect(result).toBe(subject) @@ -159,55 +153,58 @@ describe('module "database/query"', () => { test('properly modifies #snapshots', () => { const result = subject.not({ - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ - ['whereNot', { 'posts.is_public': true }] + ['whereNot', { 'posts.is_public': true }], ]) }) test('properly handles array conditions', () => { const result = subject.not({ id: [1, 2, 3], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ ['whereNotIn', ['posts.id', [1, 2, 3]]], - ['whereNot', { 'posts.is_public': true }] + ['whereNot', { 'posts.is_public': true }], ]) }) test('properly handles array conditions with single value', () => { const result = subject.not({ id: [1], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ - ['whereNot', { - 'posts.is_public': true, - 'posts.id': 1 - }] + [ + 'whereNot', + { + 'posts.is_public': true, + 'posts.id': 1, + }, + ], ]) }) test('properly handles empty array conditions', () => { const result = subject.not({ id: [], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ ['whereNotIn', ['posts.id', []]], - ['whereNot', { 'posts.is_public': true }] + ['whereNot', { 'posts.is_public': true }], ]) }) test('resolves with the correct array of `Model` instances', async () => { const result = await subject.not({ - isPublic: true + isPublic: true, }) expect(result).toEqual(expect.any(Array)) @@ -239,7 +236,7 @@ describe('module "database/query"', () => { expect(result.snapshots).toEqual([ ['where', { 'posts.id': 1 }], - ['limit', 1] + ['limit', 1], ]) }) @@ -260,9 +257,7 @@ describe('module "database/query"', () => { const result = subject.find(1) - expect(result.snapshots).toEqual([ - ['where', { 'posts.id': 1 }] - ]) + expect(result.snapshots).toEqual([['where', { 'posts.id': 1 }]]) }) test('resolves with the correct `Model` instance', async () => { @@ -272,7 +267,7 @@ describe('module "database/query"', () => { expect(result).toEqual( expect.objectContaining({ id: 1, - }) + }), ) }) }) @@ -293,10 +288,7 @@ describe('module "database/query"', () => { test('properly modifies #snapshots', () => { const result = subject.page(2) - expect(result.snapshots).toEqual([ - ['limit', 25], - ['offset', 25] - ]) + expect(result.snapshots).toEqual([['limit', 25], ['offset', 25]]) }) test('does not modify #snapshots if #shouldCount', () => { @@ -332,9 +324,7 @@ describe('module "database/query"', () => { test('properly modifies #snapshots', () => { const result = subject.limit(5) - expect(result.snapshots).toEqual([ - ['limit', 5] - ]) + expect(result.snapshots).toEqual([['limit', 5]]) }) test('does not modify #snapshots if #shouldCount', () => { @@ -394,7 +384,7 @@ describe('module "database/query"', () => { test('returns `this`', () => { const result = subject.where({ - isPublic: true + isPublic: true, }) expect(result).toBe(subject) @@ -402,55 +392,58 @@ describe('module "database/query"', () => { test('properly modifies #snapshots', () => { const result = subject.where({ - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ - ['where', { 'posts.is_public': true }] + ['where', { 'posts.is_public': true }], ]) }) test('properly handles array conditions', () => { const result = subject.where({ id: [1, 2, 3], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ ['whereIn', ['posts.id', [1, 2, 3]]], - ['where', { 'posts.is_public': true }] + ['where', { 'posts.is_public': true }], ]) }) test('properly handles array conditions with single value', () => { const result = subject.where({ id: [1], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ - ['where', { - 'posts.is_public': true, - 'posts.id': 1 - }] + [ + 'where', + { + 'posts.is_public': true, + 'posts.id': 1, + }, + ], ]) }) test('properly handles empty array conditions', () => { const result = subject.where({ id: [], - isPublic: true + isPublic: true, }) expect(result.snapshots).toEqual([ ['whereIn', ['posts.id', []]], - ['where', { 'posts.is_public': true }] + ['where', { 'posts.is_public': true }], ]) }) test('resolves with the correct array of `Model` instances', async () => { const result = await subject.where({ - isPublic: true + isPublic: true, }) expect(result).toEqual(expect.any(Array)) @@ -473,7 +466,7 @@ describe('module "database/query"', () => { test('returns `this`', () => { const result = subject.whereBetween({ - userId: [1, 10] + userId: [1, 10], }) expect(result).toBe(subject) @@ -481,7 +474,7 @@ describe('module "database/query"', () => { test('properly modifies #snapshots', () => { const result = subject.whereBetween({ - userId: [1, 10] + userId: [1, 10], }) expect(result.snapshots).toMatchSnapshot() @@ -489,7 +482,7 @@ describe('module "database/query"', () => { test('resolves with the correct array of `Model` instances', async () => { const result = await subject.whereBetween({ - userId: [1, 10] + userId: [1, 10], }) expect(result).toEqual(expect.any(Array)) @@ -511,28 +504,19 @@ describe('module "database/query"', () => { }) test('returns `this`', () => { - const result = subject.whereRaw( - '"title" LIKE ?', - ['%Test%'] - ) + const result = subject.whereRaw('"title" LIKE ?', ['%Test%']) expect(result).toBe(subject) }) test('properly modifies #snapshots', () => { - const result = subject.whereRaw( - '"title" LIKE ?', - ['%Test%'] - ) + const result = subject.whereRaw('"title" LIKE ?', ['%Test%']) expect(result.snapshots).toMatchSnapshot() }) test('resolves with the correct array of `Model` instances', async () => { - const result = await subject.whereRaw( - '"title" LIKE ?', - ['%Test%'] - ) + const result = await subject.whereRaw('"title" LIKE ?', ['%Test%']) expect(result).toEqual(expect.any(Array)) @@ -563,7 +547,7 @@ describe('module "database/query"', () => { expect(result.snapshots).toEqual([ ['orderByRaw', 'posts.id ASC'], - ['limit', 1] + ['limit', 1], ]) }) @@ -578,7 +562,7 @@ describe('module "database/query"', () => { expect(result.snapshots).toEqual([ ['orderByRaw', 'posts.created_at DESC, posts.id DESC'], - ['limit', 1] + ['limit', 1], ]) }) @@ -597,7 +581,7 @@ describe('module "database/query"', () => { expect(result).toEqual( expect.objectContaining({ id: 1, - }) + }), ) }) }) @@ -622,9 +606,7 @@ describe('module "database/query"', () => { }) test('respects order if one already exists', () => { - const result = subject - .order('createdAt', 'DESC') - .last() + const result = subject.order('createdAt', 'DESC').last() expect(result.snapshots).toMatchSnapshot() }) @@ -780,30 +762,16 @@ describe('module "database/query"', () => { test('it works when using an array of strings', () => { const result = subject.include('user', 'comments') - expect([ - result.snapshots, - result.relationships, - ]).toMatchSnapshot() + expect([result.snapshots, result.relationships]).toMatchSnapshot() }) test('properly modifies #snapshots when using an object', () => { const result = subject.include({ - user: [ - 'id', - 'name' - ], - comments: [ - 'id', - 'name', - 'edited', - 'updatedAt' - ] + user: ['id', 'name'], + comments: ['id', 'name', 'edited', 'updatedAt'], }) - expect([ - result.snapshots, - result.relationships, - ]).toMatchSnapshot() + expect([result.snapshots, result.relationships]).toMatchSnapshot() }) test('resolves with the correct array of `Model` instances', async () => { @@ -832,20 +800,13 @@ describe('module "database/query"', () => { }) test('can be chained to other query methods', () => { - const result = subject - .isPublic() - .select('id', 'title') - .limit(10) + const result = subject.isPublic().select('id', 'title').limit(10) expect(result.snapshots).toMatchSnapshot() }) test('can be chained from other query methods', () => { - const result = subject - .all() - .select('id', 'title') - .limit(10) - .isPublic() + const result = subject.all().select('id', 'title').limit(10).isPublic() expect(result.snapshots).toMatchSnapshot() }) diff --git a/src/packages/database/__tests__/relationship.test.js b/src/packages/database/__tests__/relationship.test.js index 8e9d1e8a..963c55d0 100644 --- a/src/packages/database/__tests__/relationship.test.js +++ b/src/packages/database/__tests__/relationship.test.js @@ -5,11 +5,19 @@ import * as faker from 'faker' import { get, set } from '../relationship' import { getTestApp } from '../../../../test/utils/test-app' +const del = (store, table) => store.connection(table).del(store) + +const insert = (store, table, data) => + store.connection(table).insert(data).returning('id').then(([id]) => id) + +const timestamps = () => ({ + created_at: new Date(), + updated_at: new Date(), +}) + describe('module "database/relationship"', () => { let app - let del let store - let insert let record let postId let userId @@ -18,69 +26,59 @@ describe('module "database/relationship"', () => { let commentIds let categorizationIds - const timestamps = () => ({ - created_at: new Date(), - updated_at: new Date(), - }) - beforeAll(async () => { - app = await getTestApp(); - ({ store } = app) + app = await getTestApp() + store = app.store - del = table => store.connection(table).del() - insert = (table, data) => ( - store.connection(table).insert(data).returning('id') - ); - - [userId] = await insert('users', { + userId = await insert(store, 'users', { name: 'Test User', email: 'hello@postlight.com', password: 'password', ...timestamps(), - }); + }) - [postId] = await insert('posts', { + postId = await insert(store, 'posts', { title: '#get() test', user_id: userId, ...timestamps(), }) let tagsResult - let commentsResult; + let commentsResult // eslint-disable-next-line prefer-const - [imageId, tagsResult, commentsResult] = await Promise.all([ - insert('images', { + ;[imageId, tagsResult, commentsResult] = await Promise.all([ + insert(store, 'images', { url: 'https://postlight.com', post_id: postId, ...timestamps(), }), Promise.all([ - insert('tags', { + insert(store, 'tags', { name: '#get() test 1', ...timestamps(), }), - insert('tags', { + insert(store, 'tags', { name: '#get() test 2', ...timestamps(), }), - insert('tags', { + insert(store, 'tags', { name: '#get() test 3', ...timestamps(), }), ]), Promise.all([ - insert('comments', { + insert(store, 'comments', { message: '#get() test 1', post_id: postId, ...timestamps(), }), - insert('comments', { + insert(store, 'comments', { message: '#get() test 2', post_id: postId, ...timestamps(), }), - insert('comments', { + insert(store, 'comments', { message: '#get() test 3', post_id: postId, ...timestamps(), @@ -92,17 +90,17 @@ describe('module "database/relationship"', () => { commentIds = [].concat(...commentsResult) const categorizationsResult = await Promise.all([ - insert('categorizations', { + insert(store, 'categorizations', { tag_id: tagIds[0], post_id: postId, ...timestamps(), }), - insert('categorizations', { + insert(store, 'categorizations', { tag_id: tagIds[1], post_id: postId, ...timestamps(), }), - insert('categorizations', { + insert(store, 'categorizations', { tag_id: tagIds[2], post_id: postId, ...timestamps(), @@ -114,20 +112,17 @@ describe('module "database/relationship"', () => { afterAll(async () => { await Promise.all([ - del('posts').where('id', postId), - del('users').where('id', userId), - del('images').where('id', imageId), - del('tags').whereIn('id', tagIds), - del('comments').whereIn('id', commentIds), - del('categorizations').whereIn('id', categorizationIds), + del(store, 'posts').where('id', postId), + del(store, 'users').where('id', userId), + del(store, 'images').where('id', imageId), + del(store, 'tags').whereIn('id', tagIds), + del(store, 'comments').whereIn('id', commentIds), + del(store, 'categorizations').whereIn('id', categorizationIds), ]) - await app.destroy() }) beforeEach(async () => { - record = await store - .modelFor('post') - .find(postId) + record = await store.modelFor('post').find(postId) }) describe('#get()', () => { @@ -141,7 +136,7 @@ describe('module "database/relationship"', () => { expect(result.toObject()).toEqual( expect.objectContaining({ post: expect.objectContaining(record.getAttributes()), - }) + }), ) } }) @@ -158,8 +153,8 @@ describe('module "database/relationship"', () => { expect.objectContaining({ posts: expect.arrayContaining([ expect.objectContaining(record.getAttributes()), - ]) - }) + ]), + }), ) } }) @@ -175,10 +170,8 @@ describe('module "database/relationship"', () => { result.forEach(comment => { expect(comment.toObject()).toEqual( expect.objectContaining({ - post: expect.objectContaining( - record.getAttributes() - ), - }) + post: expect.objectContaining(record.getAttributes()), + }), ) }) } @@ -195,10 +188,8 @@ describe('module "database/relationship"', () => { result.forEach(tag => { expect(tag.toObject()).toEqual( expect.objectContaining({ - post: expect.objectContaining( - record.getAttributes() - ), - }) + post: expect.objectContaining(record.getAttributes()), + }), ) }) } @@ -211,18 +202,16 @@ describe('module "database/relationship"', () => { let image beforeAll(async () => { - const [newImageId] = await insert('images', { + const newImageId = await insert(store, 'images', { url: faker.image.imageUrl(), ...timestamps(), }) - image = await store - .modelFor('image') - .find(newImageId) + image = await store.modelFor('image').find(newImageId) }) afterAll(async () => { - await del('images').where('id', image.getPrimaryKey()) + await del(store, 'images').where('id', image.getPrimaryKey()) }) test('can add a record to the relationship', () => { @@ -230,9 +219,7 @@ describe('module "database/relationship"', () => { expect(image.toObject()).toEqual( expect.objectContaining({ - post: expect.objectContaining( - record.getAttributes() - ), + post: expect.objectContaining(record.getAttributes()), }), ) @@ -245,20 +232,18 @@ describe('module "database/relationship"', () => { let user beforeAll(async () => { - const [newUserId] = await insert('users', { + const newUserId = await insert(store, 'users', { name: `${faker.name.firstName()} ${faker.name.lastName()}`, email: faker.internet.email(), password: faker.internet.password(8), ...timestamps(), }) - user = await store - .modelFor('user') - .find(newUserId) + user = await store.modelFor('user').find(newUserId) }) afterAll(async () => { - await del('users').where('id', user.getPrimaryKey()) + await del(store, 'users').where('id', user.getPrimaryKey()) }) test('can add a record to the relationship', () => { @@ -269,10 +254,8 @@ describe('module "database/relationship"', () => { posts: expect.arrayContaining([ expect.objectContaining({ ...record.getAttributes(), - user: expect.objectContaining( - user.getAttributes() - ), - }) + user: expect.objectContaining(user.getAttributes()), + }), ]), }), ) @@ -285,18 +268,16 @@ describe('module "database/relationship"', () => { let comment beforeEach(async () => { - const [newCommentId] = await insert('comments', { + const newCommentId = await insert(store, 'comments', { message: faker.lorem.sentence(), ...timestamps(), }) - comment = await store - .modelFor('comment') - .find(newCommentId) + comment = await store.modelFor('comment').find(newCommentId) }) afterEach(async () => { - await del('comments').where('id', comment.getPrimaryKey()) + await del(store, 'comments').where('id', comment.getPrimaryKey()) }) test('can add records to the relationship', () => { @@ -312,12 +293,10 @@ describe('module "database/relationship"', () => { post: expect.objectContaining({ ...record.getAttributes(), comments: expect.arrayContaining([ - expect.objectContaining( - comment.getAttributes() - ), + expect.objectContaining(comment.getAttributes()), ]), }), - }) + }), ) }) @@ -328,7 +307,7 @@ describe('module "database/relationship"', () => { expect(record.toObject()).toEqual( expect.objectContaining({ comments: [], - }) + }), ) }) }) diff --git a/src/packages/database/__tests__/transaction.test.js b/src/packages/database/__tests__/transaction.test.js index 4e0aa868..c84b6340 100644 --- a/src/packages/database/__tests__/transaction.test.js +++ b/src/packages/database/__tests__/transaction.test.js @@ -4,7 +4,7 @@ import Model from '../model' import { createTransactionResultProxy, createStaticTransactionProxy, - createInstanceTransactionProxy + createInstanceTransactionProxy, } from '../transaction' import { getTestApp } from '../../../../test/utils/test-app' @@ -12,9 +12,9 @@ describe('module "database/transaction"', () => { const tableName = 'posts' let app - // $FlowIgnore + // $FlowFixMe class Subject extends Model { - static tableName = tableName; + static tableName = tableName } beforeAll(async () => { @@ -22,10 +22,7 @@ describe('module "database/transaction"', () => { const { store } = app - await Subject.initialize( - store, - () => store.connection(tableName) - ) + await Subject.initialize(store, () => store.connection(tableName)) }) afterAll(async () => { @@ -47,9 +44,9 @@ describe('module "database/transaction"', () => { let instance beforeAll(async () => { - mockCreate = jest.fn().mockImplementation((...args) => ( - create.apply(Subject, args) - )) + mockCreate = jest + .fn() + .mockImplementation((...args) => create.apply(Subject, args)) Subject.create = mockCreate }) @@ -80,7 +77,7 @@ describe('module "database/transaction"', () => { }) describe('.createInstanceTransactionProxy()', () => { - ['save', 'update', 'destroy'].forEach(method => { + ;['save', 'update', 'destroy'].forEach(method => { describe(`#${method}()`, () => { let instance let ogMethod @@ -88,13 +85,13 @@ describe('module "database/transaction"', () => { beforeAll(async () => { await Subject.create().then(proxy => { - // $FlowIgnore + // $FlowFixMe instance = proxy.unwrap() ogMethod = instance[method] - mockMethod = jest.fn().mockImplementation((...args) => ( - ogMethod.apply(instance, args) - )) + mockMethod = jest + .fn() + .mockImplementation((...args) => ogMethod.apply(instance, args)) instance[method] = mockMethod }) diff --git a/src/packages/database/__tests__/validation.test.js b/src/packages/database/__tests__/validation.test.js index fd84227f..17244f19 100644 --- a/src/packages/database/__tests__/validation.test.js +++ b/src/packages/database/__tests__/validation.test.js @@ -11,7 +11,7 @@ describe('module "database/validation"', () => { const subject = new Validation({ validator, key: 'password', - value: 'super-secret-password' + value: 'super-secret-password', }) expect(subject.isValid()).toBe(true) @@ -21,7 +21,7 @@ describe('module "database/validation"', () => { const subject = new Validation({ validator, key: 'password', - value: 'pwd' + value: 'pwd', }) expect(subject.isValid()).toBe(false) diff --git a/src/packages/database/attribute/index.js b/src/packages/database/attribute/index.js index 953365e3..c79fd5db 100644 --- a/src/packages/database/attribute/index.js +++ b/src/packages/database/attribute/index.js @@ -13,12 +13,12 @@ export function createAttribute(opts: Attribute$meta): Object { const meta = { ...opts, normalize, - defaultValue: normalize(opts.defaultValue) + defaultValue: normalize(opts.defaultValue), } return { get: createGetter(meta), - set: createSetter(meta) + set: createSetter(meta), } } diff --git a/src/packages/database/attribute/interfaces.js b/src/packages/database/attribute/interfaces.js index 82ce91e7..ca1f20f3 100644 --- a/src/packages/database/attribute/interfaces.js +++ b/src/packages/database/attribute/interfaces.js @@ -1,8 +1,8 @@ /* @flow */ export type Attribute$meta = { - key: string; - type: string; - nullable: boolean; - defaultValue: any; -}; + key: string, + type: string, + nullable: boolean, + defaultValue: any, +} diff --git a/src/packages/database/attribute/utils/create-attribute.js b/src/packages/database/attribute/utils/create-attribute.js index 614d79a5..03185cb9 100644 --- a/src/packages/database/attribute/utils/create-attribute.js +++ b/src/packages/database/attribute/utils/create-attribute.js @@ -14,11 +14,11 @@ export default function createAttribute(opts: Attribute$meta): Object { const meta = { ...opts, normalize, - defaultValue: normalize(opts.defaultValue) + defaultValue: normalize(opts.defaultValue), } return { get: createGetter(meta), - set: createSetter(meta) + set: createSetter(meta), } } diff --git a/src/packages/database/attribute/utils/create-getter.js b/src/packages/database/attribute/utils/create-getter.js index 87ce6439..d3cd3007 100644 --- a/src/packages/database/attribute/utils/create-getter.js +++ b/src/packages/database/attribute/utils/create-getter.js @@ -1,17 +1,16 @@ /* @flow */ import type { Attribute$meta } from '../index' -import isNull from '../../../../utils/is-null' -import isUndefined from '../../../../utils/is-undefined' +import { isNil } from '@lux/utils/is-type' export default function createGetter({ key, - defaultValue + defaultValue, }: Attribute$meta): () => any { return function getter() { let value = this.currentChangeSet.get(key) - if (isNull(value) || isUndefined(value)) { + if (isNil(value)) { value = defaultValue } diff --git a/src/packages/database/attribute/utils/create-setter.js b/src/packages/database/attribute/utils/create-setter.js index 337c52be..06eb15c5 100644 --- a/src/packages/database/attribute/utils/create-setter.js +++ b/src/packages/database/attribute/utils/create-setter.js @@ -1,7 +1,6 @@ /* @flow */ -import isNull from '../../../../utils/is-null' -import isUndefined from '../../../../utils/is-undefined' +import { isNil } from '@lux/utils/is-type' import type { Attribute$meta } from '../index' /** @@ -11,13 +10,13 @@ export default function createSetter({ key, nullable, normalize, - defaultValue + defaultValue, }: Attribute$meta & { - normalize: (value: any) => any + normalize: (value: any) => any, }): (value?: any) => void { return function setter(nextValue) { if (!nullable) { - if (isNull(nextValue) || isUndefined(nextValue)) { + if (isNil(nextValue)) { return } } diff --git a/src/packages/database/change-set/index.js b/src/packages/database/change-set/index.js index fb717c05..8ac04ccc 100644 --- a/src/packages/database/change-set/index.js +++ b/src/packages/database/change-set/index.js @@ -1,17 +1,15 @@ /* @flow */ import type { Model } from '../index' -import entries from '../../../utils/entries' -import mapToObject from '../../../utils/map-to-object' +import mapToObject from '@lux/utils/map-to-object' class ChangeSet extends Map { - isPersisted: boolean; + isPersisted: boolean constructor(data?: Object = {}): this { - super(entries(data)) + super(Object.entries(data)) this.isPersisted = false - return this } @@ -29,7 +27,6 @@ class ChangeSet extends Map { } this.isPersisted = true - return this } @@ -42,7 +39,6 @@ class ChangeSet extends Map { const instance = new ChangeSet(mapToObject(this)) target.changeSets.unshift(instance) - return instance } } diff --git a/src/packages/database/constants.js b/src/packages/database/constants.js index 979fb4cd..6b551b5b 100644 --- a/src/packages/database/constants.js +++ b/src/packages/database/constants.js @@ -1,6 +1,6 @@ /* @flow */ -export const UNIQUE_CONSTRAINT = /UNIQUE\sCONSTRAINT/ig +export const UNIQUE_CONSTRAINT = /UNIQUE\sCONSTRAINT/gi export const VALID_DRIVERS = [ 'pg', @@ -10,7 +10,7 @@ export const VALID_DRIVERS = [ 'mysql2', 'mariasql', 'strong-oracle', - 'oracle' + 'oracle', ] export const TYPE_ALIASES = new Map([ @@ -39,5 +39,5 @@ export const TYPE_ALIASES = new Map([ ['integer', 'number'], ['decimal', 'number'], ['floating', 'number'], - ['bigInteger', 'number'] + ['bigInteger', 'number'], ]) diff --git a/src/packages/database/errors/invalid-driver-error.js b/src/packages/database/errors/invalid-driver-error.js index b4eec492..e498fa1f 100644 --- a/src/packages/database/errors/invalid-driver-error.js +++ b/src/packages/database/errors/invalid-driver-error.js @@ -3,7 +3,7 @@ import { green, yellow } from 'chalk' import { VALID_DRIVERS } from '../constants' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' /** * @private diff --git a/src/packages/database/errors/migrations-pending-error.js b/src/packages/database/errors/migrations-pending-error.js index 3567a889..c5cf87e5 100644 --- a/src/packages/database/errors/migrations-pending-error.js +++ b/src/packages/database/errors/migrations-pending-error.js @@ -2,7 +2,7 @@ import { green, yellow } from 'chalk' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' /** * @private diff --git a/src/packages/database/errors/unique-constraint-error.js b/src/packages/database/errors/unique-constraint-error.js index c3f389f9..684ffb1d 100644 --- a/src/packages/database/errors/unique-constraint-error.js +++ b/src/packages/database/errors/unique-constraint-error.js @@ -4,5 +4,5 @@ import createServerError from '../../../errors/utils/create-server-error' export default createServerError( class UniqueConstraintError extends Error {}, - 409 + 409, ) diff --git a/src/packages/database/index.js b/src/packages/database/index.js index 074babb1..c1c99f65 100644 --- a/src/packages/database/index.js +++ b/src/packages/database/index.js @@ -2,7 +2,7 @@ import type Knex from 'knex' -import type Logger from '../logger' +import type Logger from '@lux/packages/logger' import { ModelMissingError } from './errors' import Model from './model' @@ -14,33 +14,33 @@ import type { Database$opts } from './interfaces' * @private */ class Database { - path: string; + path: string - debug: boolean; + debug: boolean - logger: Logger; + logger: Logger - config: Object; + config: Object - schema: () => $PropertyType; + schema: () => $PropertyType - connection: Knex; + connection: Knex - models: Map>; + models: Map> constructor({ path, models, config, logger, - checkMigrations + checkMigrations, }: Database$opts): Promise { return initialize(this, { path, models, config, logger, - checkMigrations + checkMigrations, }) } @@ -77,3 +77,4 @@ export { default as createMigrations } from './utils/create-migrations' export { default as pendingMigrations } from './utils/pending-migrations' export type { Database$opts, Config } from './interfaces' +export type { Relationship } from './relationship' diff --git a/src/packages/database/initialize.js b/src/packages/database/initialize.js index cf6ecb3c..28aa5cfa 100644 --- a/src/packages/database/initialize.js +++ b/src/packages/database/initialize.js @@ -2,24 +2,23 @@ import { worker, isMaster } from 'cluster' -import { NODE_ENV } from '../../constants' -import { createLoader } from '../loader' -import { composeAsync } from '../../utils/compose' +import { NODE_ENV } from '@lux/constants' +import { createLoader } from '@lux/packages/loader' +import { composeAsync } from '@lux/utils/compose' import { ConfigMissingError, MigrationsPendingError } from './errors' import connect from './utils/connect' import createMigrations from './utils/create-migrations' import pendingMigrations from './utils/pending-migrations' -// eslint-disable-next-line no-unused-vars import type Database, { Database$opts } from './index' /** * @private */ -export default async function initialize( +export default (async function initialize( instance: T, - opts: Database$opts + opts: Database$opts, ): Promise { const { path, models, logger, checkMigrations } = opts let { config } = opts @@ -31,9 +30,9 @@ export default async function initialize( } const { - debug = (NODE_ENV === 'development') + debug = NODE_ENV === 'development', }: { - debug: boolean + debug: boolean, } = config Object.defineProperties(instance, { @@ -41,44 +40,44 @@ export default async function initialize( value: path, writable: false, enumerable: false, - configurable: false + configurable: false, }, debug: { value: debug, writable: false, enumerable: false, - configurable: false + configurable: false, }, models: { value: models, writable: false, enumerable: false, - configurable: false + configurable: false, }, logger: { value: logger, writable: false, enumerable: false, - configurable: false + configurable: false, }, config: { value: config, writable: false, enumerable: true, - configurable: false + configurable: false, }, schema: { value: () => instance.connection.schema, writable: false, enumerable: false, - configurable: false + configurable: false, }, connection: { value: connect(path, config), writable: false, enumerable: false, - configurable: false - } + configurable: false, + }, }) if (config.memory && config.driver === 'sqlite3') { @@ -88,9 +87,9 @@ export default async function initialize( await createMigrations(instance.schema) - const pending = await pendingMigrations(path, () => ( - instance.connection('migrations') - )) + const pending = await pendingMigrations(path, () => + instance.connection('migrations'), + ) const runners = pending .map(name => { @@ -104,24 +103,22 @@ export default async function initialize( .map(([version, migration]) => () => { const query = migration.run(instance.schema()) - return query.then(() => ( + return query.then(() => instance.connection('migrations').insert({ - version - }) - )) + version, + }), + ) }) await composeAsync(...runners)() - await instance.connection.transaction(trx => ( - seed(trx, instance.connection) - )) + await instance.connection.transaction(trx => seed(trx, instance.connection)) } else if (isMaster || (worker && worker.id === 1)) { await createMigrations(instance.schema) if (checkMigrations) { - const pending = await pendingMigrations(path, () => ( - instance.connection('migrations') - )) + const pending = await pendingMigrations(path, () => + instance.connection('migrations'), + ) if (pending.length) { throw new MigrationsPendingError(pending) @@ -130,12 +127,10 @@ export default async function initialize( } await Promise.all( - Array - .from(models.values()) - .map(model => ( - model.initialize(instance, () => instance.connection(model.tableName)) - )) + Array.from(models.values()).map(model => + model.initialize(instance, () => instance.connection(model.tableName)), + ), ) return instance -} +}) diff --git a/src/packages/database/interfaces.js b/src/packages/database/interfaces.js index 9a68703b..d8c7fe50 100644 --- a/src/packages/database/interfaces.js +++ b/src/packages/database/interfaces.js @@ -1,53 +1,55 @@ /* @flow */ -import type Logger from '../logger'; -import type { Model } from './index'; +import type Logger from '@lux/packages/logger' +import type { Model } from './index' -type Database$pool = number | { - min: number; - max: number; -}; +type Database$pool = + | number + | { + min: number, + max: number, + } type Database$columnType = | 'floating' | 'enu' | 'bool' | 'varchar' - | 'bigInteger'; + | 'bigInteger' export type Database$environment = { - host?: string; - pool?: Database$pool; - debug?: boolean; - driver: string; - socket?: string; - memory?: boolean; - database?: string; - username?: string; - password?: string; - port?: number; - ssl?: boolean; - url?: string; -}; + host?: string, + pool?: Database$pool, + debug?: boolean, + driver: string, + socket?: string, + memory?: boolean, + database?: string, + username?: string, + password?: string, + port?: number, + ssl?: boolean, + url?: string, +} export type Config = { - development: Database$environment; - test: Database$environment; - production: Database$environment; -}; + development: Database$environment, + test: Database$environment, + production: Database$environment, +} export type Database$opts = { - path: string; - models: Map>; - config: Config; - logger: Logger; - checkMigrations: boolean; -}; + path: string, + models: Map>, + config: Config, + logger: Logger, + checkMigrations: boolean, +} export type Database$column = { - type: Database$columnType; - nullable: boolean; - maxLength: string; - columnName: string; - defaultValue: ?mixed; -}; + type: Database$columnType, + nullable: boolean, + maxLength: string, + columnName: string, + defaultValue: ?mixed, +} diff --git a/src/packages/database/migration/index.js b/src/packages/database/migration/index.js index ca0fd69d..5b05214c 100644 --- a/src/packages/database/migration/index.js +++ b/src/packages/database/migration/index.js @@ -1,22 +1,17 @@ /* @flow */ -import type { Migration$Fn } from './interfaces' +export type Migratator = (schema: T) => Promise -/** - * @private - */ -class Migration { - fn: Migration$Fn; +export { generate as generateTimestamp } from './timestamp' - constructor(fn: Migration$Fn) { +export default class Migration { + fn: Migratator + + constructor(fn: Migratator) { this.fn = fn } - run(schema: T): T { + run(schema: T): Promise { return this.fn(schema) } } - -export default Migration -export { default as generateTimestamp } from './utils/generate-timestamp' -export type { Migration$Fn } from './interfaces' diff --git a/src/packages/database/migration/interfaces.js b/src/packages/database/migration/interfaces.js index 593040a5..e24e9be8 100644 --- a/src/packages/database/migration/interfaces.js +++ b/src/packages/database/migration/interfaces.js @@ -3,4 +3,4 @@ /** * @private */ -export type Migration$Fn = (schema: T) => T; +export type Migration$Fn = (schema: T) => T diff --git a/src/packages/database/migration/timestamp.js b/src/packages/database/migration/timestamp.js new file mode 100644 index 00000000..fb0b37f3 --- /dev/null +++ b/src/packages/database/migration/timestamp.js @@ -0,0 +1,25 @@ +/* @flow */ + +const format = (value: number): string => + String(value / 10).replace('.', '').substr(0, 2) + +export function* padding( + char: string, + amount: number, +): Generator { + for (let i = 0; i < amount; i += 1) { + yield char + } +} + +export const generate = (): string => { + const now = new Date() + const timestamp = + now.toISOString().substr(0, 10).split('-').join('') + + format(now.getHours()) + + format(now.getMinutes()) + + format(now.getSeconds()) + + format(now.getMilliseconds()) + + return timestamp + [...padding('0', 16 - timestamp.length)].join('') +} diff --git a/src/packages/database/migration/utils/generate-timestamp.js b/src/packages/database/migration/utils/generate-timestamp.js deleted file mode 100644 index 0b572465..00000000 --- a/src/packages/database/migration/utils/generate-timestamp.js +++ /dev/null @@ -1,28 +0,0 @@ -/* @flow */ - -function formatInt(int: number): string { - return (int / 10).toString().replace('.', '').substr(0, 2) -} - -export function* padding( - char: string, - amount: number -): Generator { - for (let i = 0; i < amount; i += 1) { - yield char - } -} - -export default function generateTimestamp(): string { - const now = new Date() - const timestamp = now.toISOString() - .substr(0, 10) - .split('-') - .join('') - + formatInt(now.getHours()) - + formatInt(now.getMinutes()) - + formatInt(now.getSeconds()) - + formatInt(now.getMilliseconds()) - - return timestamp + [...padding('0', 16 - timestamp.length)].join('') -} diff --git a/src/packages/database/model/index.js b/src/packages/database/model/index.js index 916270cf..744a8d90 100644 --- a/src/packages/database/model/index.js +++ b/src/packages/database/model/index.js @@ -8,21 +8,21 @@ import { updateRelationship } from '../relationship' import { createTransactionResultProxy, createStaticTransactionProxy, - createInstanceTransactionProxy + createInstanceTransactionProxy, } from '../transaction' -import pick from '../../../utils/pick' -import entries from '../../../utils/entries' -import underscore from '../../../utils/underscore' -import { compose } from '../../../utils/compose' -import { map as diffMap } from '../../../utils/diff' -import mapToObject from '../../../utils/map-to-object' -import type Logger from '../../logger' -import type Database from '../../database' -import type Serializer from '../../serializer' -/* eslint-disable no-duplicate-imports */ -import type { Relationship$opts } from '../relationship' +import pick from '@lux/utils/pick' +import underscore from '@lux/utils/underscore' +import { compose } from '@lux/utils/compose' +import { map as diffMap } from '@lux/utils/diff' +import mapToObject from '@lux/utils/map-to-object' +import { isObject } from '@lux/utils/is-type' +import type Logger from '@lux/packages/logger' +import type Database from '@lux/packages/database' +import type Serializer from '@lux/packages/serializer' +import type { ObjectMap } from '@lux/types' + +import type { Relationship } from '../relationship' import type { Transaction$ResultProxy } from '../transaction' -/* eslint-enable no-duplicate-imports */ import { create, update, destroy, createRunner } from './utils/persistence' import initializeClass from './initialize-class' @@ -34,7 +34,7 @@ import type { Model$Hooks } from './interfaces' * @class Model * @public */ -class Model { +export default class Model { /** * The name of the corresponding database table for a `Model` instance's * constructor. @@ -43,7 +43,7 @@ class Model { * @type {String} * @public */ - tableName: string; + tableName: string /** * The canonical name of a `Model`'s constructor. @@ -52,7 +52,7 @@ class Model { * @type {String} * @public */ - modelName: string; + modelName: string /** * The name of the API resource a `Model` instance's constructor represents. @@ -61,7 +61,7 @@ class Model { * @type {String} * @public */ - resourceName: string; + resourceName: string /** * A timestamp representing when the Model instance was created. @@ -70,7 +70,7 @@ class Model { * @type {Date} * @public */ - createdAt: Date; + createdAt: Date /** * A timestamp representing the last time the Model instance was updated. @@ -79,42 +79,42 @@ class Model { * @type {Date} * @public */ - updatedAt: Date; + updatedAt: Date /** * @property initialized * @type {Boolean} * @private */ - initialized: boolean; + initialized: boolean /** * @property rawColumnData * @type {Object} * @private */ - rawColumnData: Object; + rawColumnData: Object /** * @property isModelInstance * @type {Boolean} * @private */ - isModelInstance: boolean; + isModelInstance: boolean /** * @property prevAssociations * @type {Set} * @private */ - prevAssociations: Set; + prevAssociations: Set /** * @property changeSets * @type {Array} * @private */ - changeSets: Array; + changeSets: Array /** * An object where you declare `hasOne` relationships. @@ -130,7 +130,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on profile instances via `profile.user`. * } - * }; + * } * } * * class Profile extends Model { @@ -140,7 +140,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on user instances via `user.profile`. * } - * }; + * } * } * ``` * @@ -156,7 +156,7 @@ class Model { * // The line above lets Lux know that this is a relationship with the * // `User` model and not a non-existent `Owner` model. * } - * }; + * } * } * ``` * @@ -166,7 +166,7 @@ class Model { * @static * @public */ - static hasOne: Object; + static hasOne: Object /** * An object where you declare `hasMany` relationships. @@ -182,7 +182,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on book instances via `book.author`. * } - * }; + * } * } * * class Book extends Model { @@ -192,7 +192,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on author instances via `author.books`. * } - * }; + * } * } * ``` * @@ -208,7 +208,7 @@ class Model { * // The line above lets Lux know that this is a relationship with the * // `Book` model and not a non-existent `Publication` model. * } - * }; + * } * } * ``` * @@ -237,7 +237,7 @@ class Model { * inverse: 'tags', * through: 'categorizations' * } - * }; + * } * } * * class Post extends Model { @@ -246,7 +246,7 @@ class Model { * inverse: 'posts', * through: 'categorizations' * } - * }; + * } * } * ``` * @@ -256,7 +256,7 @@ class Model { * @static * @public */ - static hasMany: Object; + static hasMany: Object /** * An object where you declare `belongsTo` relationships. @@ -272,7 +272,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on author instances via `author.books`. * } - * }; + * } * } * * class Author extends Model { @@ -282,7 +282,7 @@ class Model { * // The line above lets Lux know that this relationship is accessible * // on book instances via `book.author`. * } - * }; + * } * } * ``` * @@ -298,7 +298,7 @@ class Model { * // The line above lets Lux know that this is a relationship with the * // `Author` model and not a non-existent `Writer` model. * } - * }; + * } * } * ``` * @@ -313,7 +313,7 @@ class Model { * inverse: 'books', * foreignKey: 'SoMe_UnCoNvEnTiOnAl_FoReIgN_KeY' * } - * }; + * } * } * ``` * @@ -323,7 +323,7 @@ class Model { * @static * @public */ - static belongsTo: Object; + static belongsTo: Object /** * An object where you declare validations for an instance's attributes. @@ -340,7 +340,7 @@ class Model { * static validates { * username: value => /^\w{2,30}$/.test(value), * password: value => String(value).length >= 8 - * }; + * } * } * ``` * @@ -349,12 +349,12 @@ class Model { * excellent validation libraries like [validator](https://goo.gl/LWaHBB). * * ```javascript - * import { isEmail } from 'validator'; + * import { isEmail } from 'validator' * * class User extends Model { * static validates { * email: isEmail - * }; + * } * } * ``` * @@ -364,7 +364,7 @@ class Model { * @static * @public */ - static validates: Object; + static validates: Object /** * An object where you declare custom query scopes for the model. @@ -382,31 +382,31 @@ class Model { * comments: { * inverse: 'post' * } - * }; + * } * * static belongsTo = { * user: { * inverse: 'posts' * } - * }; + * } * * static scopes = { * isPublic() { * return this.where({ * isPublic: true - * }); + * }) * }, * * byUser(user) { * return this.where({ * userId: user.id - * }); + * }) * }, * * withEverything() { - * return this.includes('tags', 'user', 'comments'); + * return this.includes('tags', 'user', 'comments') * } - * }; + * } * } * ``` * @@ -415,25 +415,25 @@ class Model { * id of 1. * * ```javascript - * const user = await User.find(1); + * const user = await User.find(1) * * return Post * .byUser(user) * .isPublic() - * .withEverything(); + * .withEverything() * ``` * * Since scopes can be chained with built-in query methods, we can easily * paginate this collection. * * ```javascript - * const user = await User.find(1); + * const user = await User.find(1) * * return Post * .byUser(user) * .isPublic() * .withEverything() - * .page(1); + * .page(1) * ``` * * @property scopes @@ -442,7 +442,7 @@ class Model { * @static * @public */ - static scopes: Object; + static scopes: Object /** * An object where you declare hooks to execute at certain times in a model @@ -492,7 +492,7 @@ class Model { * that initiated the transaction fails. * * ```javascript - * import Notification from 'app/models/notification'; + * import Notification from 'app/models/notification' * * class Comment extends Model { * static belongsTo = { @@ -502,19 +502,19 @@ class Model { * user: { * inverse: 'comments' * } - * }; + * } * * static hooks = { * async afterCreate(comment, trx) { * let [post, commenter] = await Promise.all([ * comment.post, * comment.user - * ]); + * ]) * - * const commentee = await post.user; + * const commentee = await post.user * - * post = post.title; - * commenter = commenter.name; + * post = post.title + * commenter = commenter.name * * // Calling .transacting(trx) prevents the commentee from getting a * // notification if the comment fails to be persisted in the database. @@ -523,14 +523,14 @@ class Model { * .create({ * user: commentee, * message: `${commenter} commented on your post "${post}"` - * }); + * }) * }, * * async afterSave() { * // Good thing you called transacting in afterCreate. - * throw new Error('Fatal Error'); + * throw new Error('Fatal Error') * } - * }; + * } * } * ``` * @@ -540,7 +540,7 @@ class Model { * @static * @public */ - static hooks: Model$Hooks; + static hooks: Model$Hooks /** * A reference to the application's logger. @@ -550,7 +550,7 @@ class Model { * @static * @public */ - static logger: Logger; + static logger: Logger /** * The name of the corresponding database table for the model. @@ -560,7 +560,7 @@ class Model { * @static * @public */ - static tableName: string; + static tableName: string /** * The canonical name of the model. @@ -570,7 +570,7 @@ class Model { * @static * @public */ - static modelName: string; + static modelName: string /** * The name of the resource the model represents. @@ -580,7 +580,7 @@ class Model { * @static * @public */ - static resourceName: string; + static resourceName: string /** * The column name to use for a model's primary key. @@ -591,7 +591,7 @@ class Model { * @static * @public */ - static primaryKey: string = 'id'; + static primaryKey: string = 'id' /** * @property table @@ -599,7 +599,7 @@ class Model { * @static * @private */ - static table: () => Object; + static table: () => Object /** * @property store @@ -607,7 +607,7 @@ class Model { * @static * @private */ - static store: Database; + static store: Database /** * @property initialized @@ -615,7 +615,7 @@ class Model { * @static * @private */ - static initialized: boolean; + static initialized: boolean /** * @property serializer @@ -623,7 +623,7 @@ class Model { * @static * @private */ - static serializer: Serializer; + static serializer: Serializer /** * @property attributes @@ -631,15 +631,17 @@ class Model { * @static * @private */ - static attributes: Object; + static attributes: Object /** + * $FlowFixMe + * * @property attributeNames * @type {Array} * @static * @private */ - static attributeNames: Array; + static attributeNames: Array /** * @property relationships @@ -647,7 +649,7 @@ class Model { * @static * @private */ - static relationships: Object; + static relationships: ObjectMap /** * @property relationshipNames @@ -655,28 +657,28 @@ class Model { * @static * @private */ - static relationshipNames: Array; + static relationshipNames: Array - constructor(attrs: Object = {}, initialize: boolean = true): this { + constructor(attrs: Object = {}, initialize: boolean = true) { Object.defineProperties(this, { changeSets: { value: [new ChangeSet()], writable: false, enumerable: false, - configurable: false + configurable: false, }, rawColumnData: { value: attrs, writable: false, enumerable: false, - configurable: false + configurable: false, }, prevAssociations: { value: new Set(), writable: false, enumerable: false, - configurable: false - } + configurable: false, + }, }) const { constructor: { attributeNames, relationshipNames } } = this @@ -685,30 +687,28 @@ class Model { Object.assign(this, props) if (initialize) { - Reflect.defineProperty(this, 'initialized', { + Object.defineProperty(this, 'initialized', { value: true, writable: false, enumerable: false, - configurable: false + configurable: false, }) } - - return this } /** * Indicates if the model is new. * * ```javascript - * import Post from 'app/models/post'; + * import Post from 'app/models/post' * * let post = new Post({ * body: '', * title: 'New Post', * isPublic: false - * }); + * }) * - * post.isNew; + * post.isNew * // => true * * Post.create({ @@ -716,9 +716,9 @@ class Model { * title: 'New Post', * isPublic: false * }).then(post => { - * post.isNew; - * // => false; - * }); + * post.isNew + * // => false + * }) * ``` * * @property isNew @@ -733,25 +733,25 @@ class Model { * Indicates if the model is dirty. * * ```javascript - * import Post from 'app/models/post'; + * import Post from 'app/models/post' * * Post * .find(1) * .then(post => { - * post.isDirty; + * post.isDirty * // => false * - * post.isPublic = true; + * post.isPublic = true * - * post.isDirty; + * post.isDirty * // => true * - * return post.save(); + * return post.save() * }) * .then(post => { - * post.isDirty; + * post.isDirty * // => false - * }); + * }) * ``` * * @property isDirty @@ -766,25 +766,25 @@ class Model { * Indicates if the model is persisted. * * ```javascript - * import Post from 'app/models/post'; + * import Post from 'app/models/post' * * Post * .find(1) * .then(post => { - * post.persisted; + * post.persisted * // => true * - * post.isPublic = true; + * post.isPublic = true * - * post.persisted; + * post.persisted * // => false * - * return post.save(); + * return post.save() * }) * .then(post => { - * post.persisted; + * post.persisted * // => true - * }); + * }) * ``` * * @property persisted @@ -801,12 +801,7 @@ class Model { * @public */ get dirtyAttributes(): Map { - const { - dirtyProperties, - constructor: { - relationshipNames - } - } = this + const { dirtyProperties, constructor: { relationshipNames } } = this dirtyProperties.forEach((prop, key) => { if (relationshipNames.indexOf(key) >= 0) { @@ -823,20 +818,13 @@ class Model { * @public */ get dirtyRelationships(): Map { - const { - dirtyProperties, - constructor: { - attributeNames - } - } = this + const { dirtyProperties, constructor: { attributeNames } } = this - Array - .from(dirtyProperties.keys()) - .forEach(key => { - if (attributeNames.indexOf(key) >= 0) { - dirtyProperties.delete(key) - } - }) + Array.from(dirtyProperties.keys()).forEach(key => { + if (attributeNames.indexOf(key) >= 0) { + dirtyProperties.delete(key) + } + }) return dirtyProperties } @@ -889,12 +877,12 @@ class Model { * method is called. * * ```javascript - * const post = await Post.first(); + * const post = await Post.first() * * // This call to update uses the transaction that lux will initiate. * await post.update({ * // updates to post... - * }); + * }) * * await post.transaction(trx => { * // This call to update uses the transaction that we created with the @@ -903,8 +891,8 @@ class Model { * .transacting(trx) * .update({ * // updates to post... - * }); - * }); + * }) + * }) * ``` * * @method transacting @@ -926,8 +914,8 @@ class Model { * the transaction method can be useful. * * ```javascript - * const post = await Post.first().include('user'); - * const user = await post.user; + * const post = await Post.first().include('user') + * const user = await post.user * * await post.transaction(trx => { * return Promise.all([ @@ -937,8 +925,8 @@ class Model { * user.transacting(trx).update({ * // updates to user... * }) - * ]); - * }); + * ]) + * }) * ``` * * @method transaction @@ -956,19 +944,19 @@ class Model { * Persist any unsaved changes to the database. * * ```javascript - * const post = await Post.first(); + * const post = await Post.first() * - * console.log(post.title, post.isDirty); + * console.log(post.title, post.isDirty) * // => 'New Post' false * - * post.title = 'How to Save a Lux Model'; + * post.title = 'How to Save a Lux Model' * - * console.log(post.title, post.isDirty); + * console.log(post.title, post.isDirty) * // => 'How to Update a Lux Model' true * - * await post.save(); + * await post.save() * - * console.log(post.title, post.isDirty); + * console.log(post.title, post.isDirty) * // => 'How to Save a Lux Model' false * ``` * @@ -984,17 +972,17 @@ class Model { * Assign values to the instance and persist any changes to the database. * * ```javascript - * const post = await Post.first(); + * const post = await Post.first() * - * console.log(post.title, post.isPublic, post.isDirty); + * console.log(post.title, post.isPublic, post.isDirty) * // => 'New Post' false false * * await post.update({ * title: 'How to Update a Lux Model', * isPublic: true - * }); + * }) * - * console.log(post.title, post.isPublic, post.isDirty); + * console.log(post.title, post.isPublic, post.isDirty) * // => 'How to Update a Lux Model' true false * ``` * @@ -1006,7 +994,7 @@ class Model { */ update( props: Object = {}, - transaction?: Object + transaction?: Object, ): Promise> { const run = async (trx: Object) => { const { constructor: { hooks, logger } } = this @@ -1015,20 +1003,18 @@ class Model { let hadDirtyAttrs = false let hadDirtyAssoc = false - const associations = Object - .keys(props) - .filter(key => ( - Boolean(this.constructor.relationshipFor(key)) - )) + const associations = Object.keys(props).filter(key => + Boolean(this.constructor.relationshipFor(key)), + ) Object.assign(this, props) if (associations.length) { hadDirtyAssoc = true - statements = associations.reduce((arr, key) => [ - ...arr, - ...updateRelationship(this, key, trx) - ], []) + statements = associations.reduce( + (arr, key) => [...arr, ...updateRelationship(this, key, trx)], + [], + ) } if (this.isDirty) { @@ -1038,10 +1024,12 @@ class Model { validate(this) - await runHooks(this, trx, + await runHooks( + this, + trx, hooks.afterValidation, hooks.beforeUpdate, - hooks.beforeSave + hooks.beforeSave, ) promise = update(this, trx) @@ -1053,10 +1041,7 @@ class Model { this.currentChangeSet.persist(this.changeSets) if (hadDirtyAttrs) { - await runHooks(this, trx, - hooks.afterUpdate, - hooks.afterSave - ) + await runHooks(this, trx, hooks.afterUpdate, hooks.afterSave) } return createTransactionResultProxy(this, hadDirtyAttrs || hadDirtyAssoc) @@ -1103,16 +1088,13 @@ class Model { */ reload(): Query { if (this.isNew) { - // $FlowIgnore + // $FlowFixMe return Promise.resolve(this) } const { persistedChangeSet, - constructor: { - attributeNames, - relationshipNames, - }, + constructor: { attributeNames, relationshipNames }, } = this let filterKey = key => attributeNames.includes(key) @@ -1139,9 +1121,7 @@ class Model { const { persistedChangeSet } = this if (persistedChangeSet && !this.currentChangeSet.isPersisted) { - persistedChangeSet - .applyTo(this) - .persist(this.changeSets) + persistedChangeSet.applyTo(this).persist(this.changeSets) } return this @@ -1173,29 +1153,33 @@ class Model { return Reflect.get(this, this.constructor.primaryKey) } - toObject(callee?: Model, prev?: Object): Object { + toObject(callee?: Model, accumulator?: Object): Object { const { currentChangeSet, constructor: { relationships } } = this + const attributes = this.getAttributes() - return entries(relationships).reduce((obj, [key, { type }]) => { - const value = currentChangeSet.get(key) + return Object.entries(relationships).reduce((prev, [key, data]) => { + const next = prev - /* eslint-disable no-param-reassign */ + if (isObject(data)) { + const { type } = data + const value = currentChangeSet.get(key) - if (type === 'hasMany' && Array.isArray(value)) { - obj[key] = value.map(item => { - if (item === callee) { - return prev - } - return item.toObject(this, obj) - }) - } else if (value && typeof value.toObject === 'function') { - obj[key] = value === callee ? prev : value.toObject(this, obj) + if (type === 'hasMany' && Array.isArray(value)) { + next[key] = value.map(item => { + if (item === callee) { + return accumulator + } + return item.toObject(this, next, accumulator) + }) + } else if (value && typeof value.toObject === 'function') { + next[key] = value === callee + ? accumulator + : value.toObject(this, next, accumulator) + } } - /* eslint-enable no-param-reassign */ - - return obj - }, this.getAttributes()) + return next + }, attributes) } /** @@ -1210,34 +1194,34 @@ class Model { */ static create( props: Object = {}, - transaction?: Object + transaction?: Object, ): Promise> { const run = async (trx: Object) => { const { hooks, logger, primaryKey } = this const instance = Reflect.construct(this, [props, false]) let statements = [] - const associations = Object - .keys(props) - .filter(key => ( - Boolean(this.relationshipFor(key)) - )) + const associations = Object.keys(props).filter(key => + Boolean(this.relationshipFor(key)), + ) if (associations.length) { - statements = associations.reduce((arr, key) => [ - ...arr, - ...updateRelationship(instance, key, trx) - ], []) + statements = associations.reduce( + (arr, key) => [...arr, ...updateRelationship(instance, key, trx)], + [], + ) } await runHooks(instance, trx, hooks.beforeValidation) validate(instance) - await runHooks(instance, trx, + await runHooks( + instance, + trx, hooks.afterValidation, hooks.beforeCreate, - hooks.beforeSave + hooks.beforeSave, ) const runner = createRunner(logger, statements) @@ -1250,15 +1234,12 @@ class Model { value: true, writable: false, enumerable: false, - configurable: false + configurable: false, }) instance.currentChangeSet.persist(instance.changeSets) - await runHooks(instance, trx, - hooks.afterCreate, - hooks.afterSave - ) + await runHooks(instance, trx, hooks.afterCreate, hooks.afterSave) return createTransactionResultProxy(instance, true) } @@ -1285,15 +1266,15 @@ class Model { * * ```javascript * // This call to create uses the transaction that lux will initiate. - * await Post.create(); + * await Post.create() * * await Post.transaction(trx => { * // This call to create uses the transaction that we created with the * // call to the transaction method. * return Post * .transacting(trx) - * .create(); - * }); + * .create() + * }) * ``` * * @method transacting @@ -1324,8 +1305,8 @@ class Model { * Post.transacting(trx).create({ * // ...props * }) - * ]); - * }); + * ]) + * }) * ``` * * @method transaction @@ -1401,7 +1382,8 @@ class Model { static whereRaw( query: string, - bindings: Array = []): Query> { + bindings: Array = [], + ): Query> { return new Query(this).whereRaw(query, bindings) } @@ -1455,7 +1437,20 @@ class Model { * @static * @public */ - static isInstance(value: any): boolean { + static isInstance(value: mixed): boolean /* %checks */ { + return this.isModel(value) + } + + /** + * Check if a value is an instance of a model. + * + * @method isModel + * @param {any} value - The value in question. + * @return {Boolean} + * @static + * @public + */ + static isModel(value: mixed): boolean { return value instanceof this } @@ -1481,25 +1476,20 @@ class Model { const getTableName = compose(pluralize, underscore) const tableName = getTableName(this.name) - Reflect.defineProperty(this, 'tableName', { + Object.defineProperty(this, 'tableName', { value: tableName, - writable: false, enumerable: true, - configurable: false }) - Reflect.defineProperty(this.prototype, 'tableName', { + Object.defineProperty(this.prototype, 'tableName', { value: tableName, - writable: false, - enumerable: false, - configurable: false }) } return initializeClass({ store, table, - model: this + model: this, }) } @@ -1537,11 +1527,10 @@ class Model { * @static * @private */ - static relationshipFor(key: string): void | Relationship$opts { + static relationshipFor(key: string): void | Relationship { return Reflect.get(this.relationships, key) } } -export default Model export { default as tableFor } from './utils/table-for' export type { Model$Hook, Model$Hooks } from './interfaces' diff --git a/src/packages/database/model/initialize-class.js b/src/packages/database/model/initialize-class.js index eeb7f596..cbf8b07a 100644 --- a/src/packages/database/model/initialize-class.js +++ b/src/packages/database/model/initialize-class.js @@ -1,16 +1,13 @@ /* @flow */ -import { camelize, dasherize, pluralize, singularize } from 'inflection' +import { pluralize, singularize } from 'inflection' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' +import { camelize, dasherize, underscore } from '@lux/packages/inflector' +import { isFunction, isObject, isString } from '@lux/utils/is-type' import { createAttribute } from '../attribute' -import { - get as getRelationship, - set as setRelationship -} from '../relationship' -import entries from '../../../utils/entries' -import underscore from '../../../utils/underscore' -import type Database, { Model } from '../index' // eslint-disable-line no-unused-vars, max-len +import { get as getRelationship, set as setRelationship } from '../relationship' +import type Database, { Model } from '../index' const VALID_HOOKS = new Set([ 'afterCreate', @@ -22,7 +19,7 @@ const VALID_HOOKS = new Set([ 'beforeDestroy', 'beforeSave', 'beforeUpdate', - 'beforeValidation' + 'beforeValidation', ]) /** @@ -30,52 +27,63 @@ const VALID_HOOKS = new Set([ */ function initializeProps(prototype, attributes, relationships) { Object.defineProperties(prototype, { - ...entries(attributes).reduce((obj, [key, value]) => ({ - ...obj, - [key]: createAttribute({ - key, - ...value - }) - }), {}), - - ...Object.keys(relationships).reduce((obj, key) => ({ - ...obj, - [key]: { - get() { - return getRelationship(this, key) + ...Object.entries(attributes).reduce( + (obj, [key, value]) => ({ + ...obj, + [key]: createAttribute({ + key, + ...value, + }), + }), + {}, + ), + ...Object.keys(relationships).reduce( + (obj, key) => ({ + ...obj, + [key]: { + get() { + return getRelationship(this, key) + }, + set(val) { + setRelationship(this, key, val) + }, }, - set(val) { - setRelationship(this, key, val) - } - } - }), {}) + }), + {}, + ), }) } /** * @private */ -function initializeHooks({ model, hooks, logger }) { - return Object.freeze( - entries(hooks).reduce((obj, [key, value]) => { +const initHooks = ({ model, hooks, logger }) => + Object.freeze( + Object.entries(hooks).reduce((prev, [key, value]) => { + const next = prev + if (!VALID_HOOKS.has(key)) { logger.warn(line` Invalid hook '${key}' will not be added to Model '${model.name}'. Valid hooks are ${[...VALID_HOOKS].map(h => `'${h}'`).join(', ')}. `) - return obj + return next } - return { - ...obj, - [key]: async (instance, transaction) => { - await Reflect.apply(value, model, [instance, transaction]) - } + if (isFunction(value)) { + next[key] = (...args) => + Promise.resolve(Reflect.apply(value, model, args)) + } else { + logger.warn(line` + Invalid hook '${key}' will not be added to Model '${model.name}'. + '${key}' must be a function. + `) } - }, {}) + + return next + }, {}), ) -} /** * @private @@ -85,7 +93,7 @@ function initializeValidations(opts) { const attributeNames = Object.keys(attributes) let { validates } = opts - validates = entries(validates) + validates = Object.entries(validates) .filter(([key, value]) => { let isValid = attributeNames.indexOf(key) >= 0 @@ -108,10 +116,13 @@ function initializeValidations(opts) { return isValid }) - .reduce((obj, [key, value]) => ({ - ...obj, - [key]: value - }), {}) + .reduce( + (obj, [key, value]) => ({ + ...obj, + [key]: value, + }), + {}, + ) return Object.freeze(validates) } @@ -119,124 +130,111 @@ function initializeValidations(opts) { /** * @private */ -export default async function initializeClass>({ +export default (async function initializeClass>({ store, table, - model + model, }: { store: Database, table: $PropertyType, - model: T + model: T, }): Promise { let { hooks, scopes, validates } = model const { logger } = store - const modelName = dasherize(underscore(model.name)) + const modelName = dasherize(model.name) const resourceName = pluralize(modelName) - const attributes = entries(await table().columnInfo()) - .reduce((obj, [columnName, value]) => ({ - ...obj, - [camelize(columnName, true)]: { + const attributes = Object.entries( + await table().columnInfo(), + ).reduce((prev, [columnName, value]) => { + const next = prev + + if (isObject(value)) { + next[camelize(columnName)] = { ...value, columnName, - docName: dasherize(columnName) + docName: dasherize(columnName), } - }), {}) + } - const belongsTo = entries(model.belongsTo || {}) - .reduce((obj, [relatedName, { inverse, model: relatedModel }]) => { - const relationship = {} + return next + }, {}) + const belongsTo = Object.entries( + model.belongsTo || {}, + ).reduce((prev, [key, value]) => { + const next = prev + const relationship = {} + + if (isObject(value)) { Object.defineProperties(relationship, { model: { - value: store.modelFor(relatedModel || relatedName), - writable: false, + value: store.modelFor(isString(value.model) ? value.model : key), enumerable: true, - configurable: false }, - inverse: { - value: inverse, - writable: false, + value: value.inverse, enumerable: true, - configurable: false }, - type: { value: 'belongsTo', - writable: false, enumerable: false, - configurable: false }, - foreignKey: { - value: `${underscore(relatedName)}_id`, - writable: false, - enumerable: false, - configurable: false - } + value: `${underscore(key)}_id`, + }, }) - return { - ...obj, - [relatedName]: relationship - } - }, {}) + next[key] = relationship + } - const hasOne = entries(model.hasOne || {}) - .reduce((obj, [relatedName, { inverse, model: relatedModel }]) => { - const relationship = {} + return next + }, {}) + + const hasOne = Object.entries( + model.hasOne || {}, + ).reduce((prev, [key, value]) => { + const next = prev + const relationship = {} + + if (isObject(value) && isString(value.inverse)) { + const inverse = value.inverse Object.defineProperties(relationship, { model: { - value: store.modelFor(relatedModel || relatedName), - writable: false, + value: store.modelFor(isString(value.model) ? value.model : key), enumerable: true, - configurable: false }, - inverse: { value: inverse, - writable: false, enumerable: true, - configurable: false }, - type: { value: 'hasOne', - writable: false, - enumerable: false, - configurable: false }, - foreignKey: { value: `${underscore(inverse)}_id`, - writable: false, - enumerable: false, - configurable: false - } + }, }) - return { - ...obj, - [relatedName]: relationship - } - }, {}) + next[key] = relationship + } - const hasMany = entries(model.hasMany || {}) - .reduce((hash, [relatedName, opts]) => { - const { inverse } = opts - const relationship = {} - let { through, model: relatedModel } = opts - let foreignKey + return next + }, {}) - if (typeof relatedModel === 'string') { - relatedModel = store.modelFor(relatedModel) - } else { - relatedModel = store.modelFor(relatedName) - } + const hasMany = Object.entries( + model.hasMany || {}, + ).reduce((prev, [key, value]) => { + const next = prev + const relationship = {} + + if (isObject(value) && isString(value.inverse)) { + const { inverse } = value + let { through } = value + let foreignKey - if (typeof through === 'string') { + if (isString(through)) { through = store.modelFor(through) foreignKey = `${singularize(underscore(inverse))}_id` } else { @@ -245,46 +243,30 @@ export default async function initializeClass>({ Object.defineProperties(relationship, { model: { - value: relatedModel, - writable: false, + value: store.modelFor(isString(value.model) ? value.model : key), enumerable: true, - configurable: false }, - inverse: { value: inverse, - writable: false, enumerable: true, - configurable: false }, - through: { value: through, - writable: false, enumerable: Boolean(through), - configurable: false }, - type: { value: 'hasMany', - writable: false, - enumerable: false, - configurable: false }, - foreignKey: { value: foreignKey, - writable: false, - enumerable: false, - configurable: false - } + }, }) - return { - ...hash, - [relatedName]: relationship - } - }, {}) + next[key] = relationship + } + + return next + }, {}) Object.freeze(hasOne) Object.freeze(hasMany) @@ -293,7 +275,7 @@ export default async function initializeClass>({ const relationships = Object.freeze({ ...hasOne, ...hasMany, - ...belongsTo + ...belongsTo, }) if (!hooks) { @@ -311,164 +293,98 @@ export default async function initializeClass>({ Object.defineProperties(model, { store: { value: store, - writable: false, - enumerable: false, - configurable: false }, - table: { value: table, - writable: false, - enumerable: false, - configurable: false }, - logger: { value: logger, - writable: false, - enumerable: false, - configurable: false }, - attributes: { value: Object.freeze(attributes), - writable: false, - enumerable: false, - configurable: false }, - attributeNames: { value: Object.freeze(Object.keys(attributes)), - writable: false, - enumerable: false, - configurable: false }, - hasOne: { value: hasOne, - writable: false, enumerable: Boolean(Object.keys(hasOne).length), - configurable: false }, - hasMany: { value: hasMany, - writable: false, enumerable: Boolean(Object.keys(hasMany).length), - configurable: false }, - belongsTo: { value: belongsTo, - writable: false, enumerable: Boolean(Object.keys(belongsTo).length), - configurable: false }, - relationships: { value: relationships, - writable: false, - enumerable: false, - configurable: false }, - relationshipNames: { value: Object.freeze(Object.keys(relationships)), - writable: false, - enumerable: false, - configurable: false }, - hooks: { - value: initializeHooks({ + value: initHooks({ model, hooks, - logger + logger, }), - writable: false, enumerable: Boolean(Object.keys(hooks).length), - configurable: false }, - scopes: { value: scopes, - writable: false, enumerable: Boolean(Object.keys(scopes).length), - configurable: false }, - validates: { value: initializeValidations({ model, logger, validates, - attributes + attributes, }), - writable: false, enumerable: Boolean(Object.keys(validates).length), - configurable: false }, - modelName: { value: modelName, - writable: false, enumerable: true, - configurable: false }, - resourceName: { value: resourceName, - writable: false, enumerable: true, - configurable: false }, - initialized: { value: true, - writable: false, - enumerable: false, - configurable: false }, - ...Object.freeze( - entries(scopes).reduce((obj, [name, scope]) => ({ - ...obj, - [name]: { - value: scope, - writable: false, - enumerable: false, - configurable: false - } - }), {}) - ) + Object.entries(scopes).reduce((prev, [key, value]) => { + const next = prev + + next[key] = { value } + return next + }, {}), + ), }) initializeProps(model.prototype, attributes, { ...hasOne, ...hasMany, - ...belongsTo + ...belongsTo, }) Object.defineProperties(model.prototype, { modelName: { value: modelName, - writable: false, enumerable: true, - configurable: false }, resourceName: { value: resourceName, - writable: false, enumerable: true, - configurable: false }, isModelInstance: { value: true, - writable: false, - enumerable: false, - configurable: false - } + }, }) return model -} +}) diff --git a/src/packages/database/model/interfaces.js b/src/packages/database/model/interfaces.js index 101ae1d7..16e8d651 100644 --- a/src/packages/database/model/interfaces.js +++ b/src/packages/database/model/interfaces.js @@ -1,18 +1,18 @@ /* @flow */ -import type Model from './index'; +import type Model from './index' -export type Model$Hook = (instance: Model, trx: Object) => Promise; +export type Model$Hook = (instance: Model, trx: Object) => Promise export interface Model$Hooks { - +afterCreate?: Model$Hook; - +afterDestroy?: Model$Hook; - +afterSave?: Model$Hook; - +afterUpdate?: Model$Hook; - +afterValidation?: Model$Hook; - +beforeCreate?: Model$Hook; - +beforeDestroy?: Model$Hook; - +beforeSave?: Model$Hook; - +beforeUpdate?: Model$Hook; - +beforeValidation?: Model$Hook; + +afterCreate?: Model$Hook, + +afterDestroy?: Model$Hook, + +afterSave?: Model$Hook, + +afterUpdate?: Model$Hook, + +afterValidation?: Model$Hook, + +beforeCreate?: Model$Hook, + +beforeDestroy?: Model$Hook, + +beforeSave?: Model$Hook, + +beforeUpdate?: Model$Hook, + +beforeValidation?: Model$Hook, } diff --git a/src/packages/database/model/utils/get-columns.js b/src/packages/database/model/utils/get-columns.js index c33fabe9..7a1dbdec 100644 --- a/src/packages/database/model/utils/get-columns.js +++ b/src/packages/database/model/utils/get-columns.js @@ -1,7 +1,6 @@ /* @flow */ -import pick from '../../../../utils/pick' -import entries from '../../../../utils/entries' +import pick from '@lux/utils/pick' import type Model from '../index' /** @@ -14,8 +13,19 @@ export default function getColumns(record: Model, only?: Array) { columns = pick(columns, ...only) } - return entries(columns).reduce((obj, [key, { columnName }]) => ({ - ...obj, - [columnName]: Reflect.get(record, key) - }), {}) + return Object.entries(columns) + .map(([key, value]) => { + if (value && typeof value.columnName === 'string') { + return [key, value.columnName] + } + + return [key, 'undefined'] + }) + .reduce( + (obj, [key, columnName]) => ({ + ...obj, + [columnName]: Reflect.get(record, key), + }), + {}, + ) } diff --git a/src/packages/database/model/utils/persistence.js b/src/packages/database/model/utils/persistence.js index 5d92ea83..d4aa813c 100644 --- a/src/packages/database/model/utils/persistence.js +++ b/src/packages/database/model/utils/persistence.js @@ -1,9 +1,8 @@ /* @flow */ -import { sql } from '../../../logger' -import omit from '../../../../utils/omit' -// eslint-disable-next-line no-duplicate-imports -import type Logger from '../../../logger' +import { sql } from '@lux/packages/logger' +import omit from '@lux/utils/omit' +import type Logger from '@lux/packages/logger' import type Model from '../index' import tableFor from './table-for' @@ -17,12 +16,12 @@ export function create(record: Model, trx: Object): Array { Object.assign(record, { createdAt: timestamp, - updatedAt: timestamp + updatedAt: timestamp, }) Object.assign(record.rawColumnData, { createdAt: timestamp, - updatedAt: timestamp + updatedAt: timestamp, }) const { constructor: { primaryKey } } = record @@ -35,7 +34,7 @@ export function create(record: Model, trx: Object): Array { return [ tableFor(record, trx) .returning(record.constructor.primaryKey) - .insert(columns) + .insert(columns), ] } @@ -48,9 +47,7 @@ export function update(record: Model, trx: Object): Array { return [ tableFor(record, trx) .where(record.constructor.primaryKey, record.getPrimaryKey()) - .update(getColumns(record, [ - ...record.dirtyAttributes.keys() - ])) + .update(getColumns(record, [...record.dirtyAttributes.keys()])), ] } @@ -61,7 +58,7 @@ export function destroy(record: Model, trx: Object): Array { return [ tableFor(record, trx) .where(record.constructor.primaryKey, record.getPrimaryKey()) - .del() + .del(), ] } @@ -70,7 +67,7 @@ export function destroy(record: Model, trx: Object): Array { */ export function createRunner( logger: Logger, - statements: Array + statements: Array, ): (query: Array) => Promise> { return query => { const promises = query.concat(statements) diff --git a/src/packages/database/model/utils/run-hooks.js b/src/packages/database/model/utils/run-hooks.js index d4080c1d..2bf95e77 100644 --- a/src/packages/database/model/utils/run-hooks.js +++ b/src/packages/database/model/utils/run-hooks.js @@ -12,7 +12,8 @@ export default function runHooks( ): Promise { return hooks .filter(Boolean) - .reduce((prev, next) => ( - prev.then(() => next(record, trx)) - ), Promise.resolve()) + .reduce( + (prev, next) => prev.then(() => next(record, trx)), + Promise.resolve(), + ) } diff --git a/src/packages/database/model/utils/table-for.js b/src/packages/database/model/utils/table-for.js index 462939a6..6f847baf 100644 --- a/src/packages/database/model/utils/table-for.js +++ b/src/packages/database/model/utils/table-for.js @@ -7,9 +7,11 @@ type Table = $PropertyType, 'table'> function tableFor>(model: T, trx?: Object): Table { let table - if (model instanceof Model) { + if (Model.isModel(model)) { + // $FlowFixMe table = model.constructor.table() } else { + // $FlowFixMe table = model.table() } diff --git a/src/packages/database/model/utils/validate.js b/src/packages/database/model/utils/validate.js index 23941dbe..b66cc764 100644 --- a/src/packages/database/model/utils/validate.js +++ b/src/packages/database/model/utils/validate.js @@ -7,12 +7,11 @@ import type { Model } from '../../index' * @private */ export default function validate(instance: Model): true { - return Array - .from(instance.dirtyAttributes) + return Array.from(instance.dirtyAttributes) .map(([key, value]) => ({ key, value, - validator: Reflect.get(instance.constructor.validates, key) + validator: Reflect.get(instance.constructor.validates, key), })) .filter(({ validator }) => validator) .map(props => new Validation(props)) diff --git a/src/packages/database/query/errors/record-not-found-error.js b/src/packages/database/query/errors/record-not-found-error.js index de47976c..ba416a7f 100644 --- a/src/packages/database/query/errors/record-not-found-error.js +++ b/src/packages/database/query/errors/record-not-found-error.js @@ -1,14 +1,14 @@ /* @flow */ import createServerError from '../../../../errors/utils/create-server-error' -import stringify from '../../../../utils/stringify' -import typeof { Model } from '../../../database' +import stringify from '@lux/utils/stringify' +import typeof { Model } from '@lux/packages/database' class RecordNotFoundError extends Error { constructor({ name, primaryKey }: Model, primaryKeyValue: mixed) { - super( - `Could not find ${name} with ${primaryKey} ${stringify(primaryKeyValue)}.` - ) + const value = stringify(primaryKeyValue) + + super(`Could not find ${name} with ${primaryKey} ${value}.`) } } diff --git a/src/packages/database/query/index.js b/src/packages/database/query/index.js index 0293ab07..3798e527 100644 --- a/src/packages/database/query/index.js +++ b/src/packages/database/query/index.js @@ -2,8 +2,7 @@ import { camelize } from 'inflection' -import entries from '../../../utils/entries' -import uniq from '../../../utils/uniq' +import uniq from '@lux/utils/uniq' import type Model from '../model' import scopesFor from './utils/scopes-for' @@ -19,32 +18,32 @@ class Query<+T: any> extends Promise { /** * @private */ - model: Class; + model: Class /** * @private */ - isFind: boolean; + isFind: boolean /** * @private */ - snapshots: Array>; + snapshots: Array> /** * @private */ - collection: boolean; + collection: boolean /** * @private */ - shouldCount: boolean; + shouldCount: boolean /** * @private */ - relationships: Object; + relationships: Object constructor(model: Class) { let resolve @@ -57,7 +56,7 @@ class Query<+T: any> extends Promise { createRunner(this, { resolve, - reject + reject, }) Object.defineProperties(this, { @@ -65,42 +64,42 @@ class Query<+T: any> extends Promise { value: model, writable: false, enumerable: false, - configurable: false + configurable: false, }, collection: { value: true, writable: true, enumerable: false, - configurable: false + configurable: false, }, snapshots: { value: [], writable: true, enumerable: false, - configurable: false + configurable: false, }, shouldCount: { value: false, writable: true, enumerable: false, - configurable: false + configurable: false, }, relationships: { value: {}, writable: true, enumerable: false, - configurable: false - } + configurable: false, + }, }) Object.defineProperties(this, scopesFor(this)) } - // $FlowIgnore + // $FlowFixMe static get [Symbol.species]() { return Promise } @@ -116,11 +115,11 @@ class Query<+T: any> extends Promise { find(primaryKey: any): this { Object.assign(this, { isFind: true, - collection: false + collection: false, }) this.where({ - [this.model.primaryKey]: primaryKey + [this.model.primaryKey]: primaryKey, }) if (!this.shouldCount) { @@ -138,7 +137,7 @@ class Query<+T: any> extends Promise { let limit = this.snapshots.find(([name]) => name === 'limit') if (limit) { - [, limit] = limit + ;[, limit] = limit } if (typeof limit !== 'number') { @@ -168,10 +167,12 @@ class Query<+T: any> extends Promise { this.snapshots = this.snapshots .filter(([method]) => method !== 'orderByRaw') .concat([ - ['orderByRaw', uniq([columnName, this.model.primaryKey]) - .map(key => `${this.model.tableName}.${key} ${dirUpcase}`) - .join(', ') - ] + [ + 'orderByRaw', + uniq([columnName, this.model.primaryKey]) + .map(key => `${this.model.tableName}.${key} ${dirUpcase}`) + .join(', '), + ], ]) } } @@ -180,13 +181,9 @@ class Query<+T: any> extends Promise { } where(conditions: Object = {}, not: boolean = false): this { - const { - model: { - tableName - } - } = this + const { model: { tableName } } = this - const where = entries(conditions).reduce((obj, condition) => { + const where = Object.entries(conditions).reduce((obj, condition) => { let [key, value] = condition const columnName = this.model.columnNameFor(key) @@ -201,23 +198,17 @@ class Query<+T: any> extends Promise { if (value.length === 1) { return { ...obj, - [key]: value[0] + [key]: value[0], } } - this.snapshots.push([ - not ? 'whereNotIn' : 'whereIn', - [key, value] - ]) + this.snapshots.push([not ? 'whereNotIn' : 'whereIn', [key, value]]) } else if (value === null) { - this.snapshots.push([ - not ? 'whereNotNull' : 'whereNull', - [key] - ]) + this.snapshots.push([not ? 'whereNotNull' : 'whereNull', [key]]) } else { return { ...obj, - [key]: value + [key]: value, } } } @@ -233,13 +224,9 @@ class Query<+T: any> extends Promise { } whereBetween(conditions: Object, not: boolean = false): this { - const { - model: { - tableName - } - } = this + const { model: { tableName } } = this - entries(conditions).forEach((condition) => { + Object.entries(conditions).forEach(condition => { let [key] = condition const [, value] = condition const columnName = this.model.columnNameFor(key) @@ -250,7 +237,7 @@ class Query<+T: any> extends Promise { if (Array.isArray(value)) { this.snapshots.push([ `where${not ? 'NotBetween' : 'Between'}`, - [key, value] + [key, value], ]) } } @@ -267,7 +254,7 @@ class Query<+T: any> extends Promise { first(): this { if (!this.shouldCount) { const willSort = this.snapshots.some( - ([method]) => method === 'orderByRaw' + ([method]) => method === 'orderByRaw', ) this.collection = false @@ -285,7 +272,7 @@ class Query<+T: any> extends Promise { last(): this { if (!this.shouldCount) { const willSort = this.snapshots.some( - ([method]) => method === 'orderByRaw' + ([method]) => method === 'orderByRaw', ) this.collection = false @@ -308,8 +295,8 @@ class Query<+T: any> extends Promise { snapshots: [ ['count', '* as countAll'], - ...this.snapshots.filter(([name]) => validName.test(name)) - ] + ...this.snapshots.filter(([name]) => validName.test(name)), + ], }) return this @@ -344,21 +331,26 @@ class Query<+T: any> extends Promise { if (!this.shouldCount) { if (relationships.length === 1 && typeof relationships[0] === 'object') { - included = entries(relationships[0]).reduce((arr, relationship) => { + included = Object.entries( + relationships[0], + ).reduce((arr, relationship) => { const [name] = relationship const opts = this.model.relationshipFor(name) let [, attrs] = relationship - if (opts) { + if (opts && Array.isArray(attrs)) { if (!attrs.length) { attrs = opts.model.attributeNames } - return [...arr, { - name, - attrs, - relationship: opts - }] + return [ + ...arr, + { + name, + attrs, + relationship: opts, + }, + ] } return arr @@ -376,11 +368,14 @@ class Query<+T: any> extends Promise { if (opts) { const attrs = opts.model.attributeNames - return [...arr, { - attrs, - name: str, - relationship: opts - }] + return [ + ...arr, + { + attrs, + name: str, + relationship: opts, + }, + ] } return arr @@ -393,17 +388,16 @@ class Query<+T: any> extends Promise { let { attrs } = opts if (relationship.type === 'hasMany') { - attrs = relationship.through ? attrs : [ - ...attrs, - camelize(relationship.foreignKey, true) - ] + attrs = relationship.through + ? attrs + : [...attrs, camelize(relationship.foreignKey, true)] this.relationships[name] = { attrs, type: 'hasMany', model: relationship.model, through: relationship.through, - foreignKey: relationship.foreignKey + foreignKey: relationship.foreignKey, } return false @@ -411,27 +405,37 @@ class Query<+T: any> extends Promise { return true }) - .reduce((arr, { name, attrs, relationship }) => { + .reduce((arr, { attrs, name, relationship }) => { arr.push([ 'includeSelect', - formatSelect(relationship.model, attrs, `${name}.`) + formatSelect( + relationship.model, + Array.isArray(attrs) ? attrs.map(String) : [], + `${name}.`, + ), ]) if (relationship.type === 'belongsTo') { - arr.push(['leftOuterJoin', [ - relationship.model.tableName, - `${this.model.tableName}.${relationship.foreignKey}`, - '=', - `${relationship.model.tableName}.` + - `${relationship.model.primaryKey}` - ]]) + arr.push([ + 'leftOuterJoin', + [ + relationship.model.tableName, + `${this.model.tableName}.${relationship.foreignKey}`, + '=', + `${relationship.model.tableName}.` + + `${relationship.model.primaryKey}`, + ], + ]) } else if (relationship.type === 'hasOne') { - arr.push(['leftOuterJoin', [ - relationship.model.tableName, - `${this.model.tableName}.${this.model.primaryKey}`, - '=', - `${relationship.model.tableName}.${relationship.foreignKey}` - ]]) + arr.push([ + 'leftOuterJoin', + [ + relationship.model.tableName, + `${this.model.tableName}.${this.model.primaryKey}`, + '=', + `${relationship.model.tableName}.${relationship.foreignKey}`, + ], + ]) } return arr @@ -469,26 +473,20 @@ class Query<+T: any> extends Promise { then( onFulfilled?: (value: T) => Promise | U, - onRejected?: (error: Error) => Promise | U + onRejected?: (error: Error) => Promise | U, ): Promise { runQuery(this) return super.then(onFulfilled, onRejected) } // eslint-disable-line brace-style - // $FlowIgnore + // $FlowFixMe catch(onRejected?: (error: Error) => ?Promise | U): Promise { runQuery(this) return super.catch(onRejected) } static from(src: any): Query { - const { - model, - snapshots, - collection, - shouldCount, - relationships - } = src + const { model, snapshots, collection, shouldCount, relationships } = src const dest = Reflect.construct(this, [model]) @@ -496,7 +494,7 @@ class Query<+T: any> extends Promise { snapshots, collection, shouldCount, - relationships + relationships, }) return dest diff --git a/src/packages/database/query/runner/index.js b/src/packages/database/query/runner/index.js index b1b307d1..f47313d4 100644 --- a/src/packages/database/query/runner/index.js +++ b/src/packages/database/query/runner/index.js @@ -1,7 +1,7 @@ /* @flow */ import { RecordNotFoundError } from '../errors' -import { sql } from '../../../logger' +import { sql } from '@lux/packages/logger' import type Query from '../index' import { RUNNERS } from './constants' @@ -11,10 +11,13 @@ import buildResults from './utils/build-results' /** * @private */ -export function createRunner(target: Query<*>, opts: { - resolve?: (value: any) => void; - reject?: (error: Error) => void; -}): void { +export function createRunner( + target: Query<*>, + opts: { + resolve?: (value: any) => void, + reject?: (error: Error) => void, + }, +): void { if (opts.resolve && opts.reject) { const { resolve, reject } = opts let didRun = false @@ -27,7 +30,7 @@ export function createRunner(target: Query<*>, opts: { snapshots, collection, shouldCount, - relationships + relationships, } = target if (didRun) { @@ -40,10 +43,7 @@ export function createRunner(target: Query<*>, opts: { target.select(...target.model.attributeNames) } - const records: any = snapshots.reduce(( - query, - snapshot - ) => { + const records: any = snapshots.reduce((query, snapshot) => { let [name, params] = snapshot if (!shouldCount && name === 'includeSelect') { @@ -74,7 +74,7 @@ export function createRunner(target: Query<*>, opts: { results = await buildResults({ model, records, - relationships + relationships, }) if (collection) { diff --git a/src/packages/database/query/runner/utils/build-results.js b/src/packages/database/query/runner/utils/build-results.js index 4db4e4c7..c1b02e24 100644 --- a/src/packages/database/query/runner/utils/build-results.js +++ b/src/packages/database/query/runner/utils/build-results.js @@ -1,24 +1,20 @@ /* @flow */ -import { camelize, singularize } from 'inflection' - -import Model from '../../../model' -import entries from '../../../../../utils/entries' -import underscore from '../../../../../utils/underscore' -import promiseHash from '../../../../../utils/promise-hash' - -/** - * @private - */ -export default async function buildResults({ - model, - records, - relationships -}: { +import { singularize } from 'inflection' + +import { Model } from '@lux/packages/database' +import { camelize, underscore } from '@lux/packages/inflector' +import { isObject, isString } from '@lux/utils/is-type' +import promiseHash from '@lux/utils/promise-hash' + +type Options = { model: Class, records: Promise>, - relationships: Object -}): Promise> { + relationships: Object, +} + +async function buildResults(options: Options): Promise> { + const { model, records, relationships } = options const results = await records const pkPattern = new RegExp(`^.+\\.${model.primaryKey}$`) let related @@ -28,109 +24,111 @@ export default async function buildResults({ } if (Object.keys(relationships).length) { - related = entries(relationships) - .reduce((obj, entry) => { - const [name, relationship] = entry - let foreignKey = camelize(relationship.foreignKey, true) + related = Object.entries(relationships).reduce((prev, [key, value]) => { + const next = prev + + if (isObject(value) && isString(value.foreignKey)) { + // $FlowFixMe + const relatedModel: Class = value.model + const foreignKeyString = value.foreignKey + let foreignKey = camelize(foreignKeyString) - if (relationship.through) { - const query = relationship.model.select(...relationship.attrs) + if (value.through) { + // $FlowFixMe + const throughModel: Class = value.through + const query = relatedModel.select(...value.attrs) - const baseKey = `${relationship.through.tableName}.` + - `${singularize(underscore(name))}_id` + const baseKey = `${throughModel.tableName}.${singularize( + underscore(key), + )}_id` - foreignKey = `${relationship.through.tableName}.` + - `${relationship.foreignKey}` + foreignKey = `${throughModel.tableName}.${foreignKeyString}` query.snapshots.push( - ['select', [ - `${baseKey} as ${camelize(baseKey.split('.').pop(), true)}`, - `${foreignKey} as ${camelize(foreignKey.split('.').pop(), true)}` - ]], - - ['innerJoin', [ - relationship.through.tableName, - `${relationship.model.tableName}.` + - `${relationship.model.primaryKey}`, - '=', - baseKey - ]], - - ['whereIn', [ - foreignKey, - results.map(({ id }) => id) - ]] + [ + 'select', + [ + `${baseKey} as ${camelize(baseKey.split('.').pop())}`, + `${foreignKey} as ${camelize(foreignKey.split('.').pop())}`, + ], + ], + [ + 'innerJoin', + [ + throughModel.tableName, + `${relatedModel.tableName}.${relatedModel.primaryKey}`, + '=', + baseKey, + ], + ], + ['whereIn', [foreignKey, results.map(({ id }) => id)]], ) - return { - ...obj, - [name]: query - } + next[key] = query + return next } - return { - ...obj, - [name]: relationship.model - .select(...relationship.attrs) - .where({ - [foreignKey]: results.map(({ id }) => id) - }) - } - }, {}) + // $FlowFixMe + next[key] = relatedModel.select(...value.attrs).where({ + [foreignKey]: results.map(({ id }) => id), + }) + } + + return next + }, {}) related = await promiseHash(related) } return results.map(record => { if (related) { - entries(related) - .forEach(([name, relatedResults]: [string, Array]) => { - const relationship = model.relationshipFor(name) - - if (relationship) { - let { foreignKey } = relationship + Object.entries(related).forEach(([key, value]) => { + const relationship = model.relationshipFor(key) + + if (relationship && Array.isArray(value)) { + const foreignKey = camelize(relationship.foreignKey) + + Reflect.set( + record, + key, + value.filter( + item => + isObject(item) && + isObject(item.rawColumnData) && + Reflect.get(item.rawColumnData, foreignKey) === + Reflect.get(record, model.primaryKey), + ), + ) + } + }) + } - foreignKey = camelize(foreignKey, true) + const instance = Reflect.construct(model, [ + Object.entries(record).reduce((r, entry) => { + let [key, value] = entry - Reflect.set(record, name, relatedResults.filter(({ - rawColumnData - }) => { - const fk = Reflect.get(rawColumnData, foreignKey) - const pk = Reflect.get(record, model.primaryKey) + if (!value && pkPattern.test(key)) { + return r + } else if (key.indexOf('.') >= 0) { + const [a, b] = key.split('.') + let parent: ?Object = r[a] - return fk === pk - })) + if (!parent) { + parent = {} } - }) - } - const instance = Reflect.construct(model, [ - entries(record) - .reduce((r, entry) => { - let [key, value] = entry - - if (!value && pkPattern.test(key)) { - return r - } else if (key.indexOf('.') >= 0) { - const [a, b] = key.split('.') - let parent: ?Object = r[a] - - if (!parent) { - parent = {} - } - - key = a - value = { - ...parent, - [b]: value - } + key = a + value = { + ...parent, + [b]: value, } + } - return { - ...r, - [key]: value - } - }, {}) + return { + ...r, + [key]: value, + } + }, {}), ]) instance.currentChangeSet.persist() @@ -138,3 +136,5 @@ export default async function buildResults({ return instance }) } + +export default buildResults diff --git a/src/packages/database/query/runner/utils/get-find-param.js b/src/packages/database/query/runner/utils/get-find-param.js index a0df807e..ec50fe0b 100644 --- a/src/packages/database/query/runner/utils/get-find-param.js +++ b/src/packages/database/query/runner/utils/get-find-param.js @@ -1,15 +1,12 @@ /* @flow */ -import isObject from '../../../../../utils/is-object' +import { isObject } from '@lux/utils/is-type' import type Query from '../../index' export default function getFindParam({ isFind, snapshots, - model: { - tableName, - primaryKey - } + model: { tableName, primaryKey }, }: Query<*>) { if (isFind) { const snapshot = snapshots.find(([method]) => method === 'where') diff --git a/src/packages/database/query/utils/format-select.js b/src/packages/database/query/utils/format-select.js index 91211f50..e34fe07d 100644 --- a/src/packages/database/query/utils/format-select.js +++ b/src/packages/database/query/utils/format-select.js @@ -1,20 +1,17 @@ /* @flow */ -import { camelize } from 'inflection' +import { camelize } from '@lux/packages/inflector' import Model from '../../model' -/** - * @private - */ export default function formatSelect( model: Class, - attrs: Array = [], - prefix: string = '' + attrs?: Array = [], + prefix?: string = '', ) { return attrs.map(attr => { const name = model.columnNameFor(attr) || 'undefined' - return `${model.tableName}.${name} AS ${prefix}${camelize(name, true)}` + return `${model.tableName}.${name} AS ${prefix}${camelize(name)}` }) } diff --git a/src/packages/database/query/utils/scopes-for.js b/src/packages/database/query/utils/scopes-for.js index c3bbfe03..ad27d119 100644 --- a/src/packages/database/query/utils/scopes-for.js +++ b/src/packages/database/query/utils/scopes-for.js @@ -2,40 +2,39 @@ import type Query from '../index' -export default function scopesFor(target: Query): { - [key: string]: () => Query -} { - return Object.keys(target.model.scopes).reduce((scopes, name) => ({ - ...scopes, - [name]: { - get() { - // eslint-disable-next-line func-names - const scope = function (...args: Array) { - const fn = Reflect.get(target.model, name) - const { snapshots } = Reflect.apply(fn, target.model, args) - - Object.assign(target, { - snapshots: [ - ...target.snapshots, - ...snapshots.map(snapshot => [ - ...snapshot, - name - ]) - ] - }) +type Scopes = { + [key: string]: () => Query, +} - return target - } +const scopesFor = (target: Query): Scopes => + Object.keys(target.model.scopes).reduce( + (scopes, name) => ({ + ...scopes, + [name]: { + get() { + const scope = function _(...args: Array) { + const fn = Reflect.get(target.model, name) + const { snapshots } = fn.apply(target.model, args) - Reflect.defineProperty(scope, 'name', { - value: name, - writable: false, - enumerable: false, - configurable: false - }) + Object.assign(target, { + snapshots: [ + ...target.snapshots, + ...snapshots.map(snapshot => [...snapshot, name]), + ], + }) - return scope - } - } - }), {}) -} + return target + } + + Object.defineProperty(scope, 'name', { + value: name, + }) + + return scope + }, + }, + }), + {}, + ) + +export default scopesFor diff --git a/src/packages/database/relationship/index.js b/src/packages/database/relationship/index.js index 0da62e3f..707c9dbc 100644 --- a/src/packages/database/relationship/index.js +++ b/src/packages/database/relationship/index.js @@ -23,18 +23,18 @@ function set(owner: Model, key: string, value?: Array | ?Model): void { if (type === 'hasMany') { setHasMany(owner, key, value, { ...opts, - foreignKey + foreignKey, }) } } else if (type === 'hasOne') { setHasOne(owner, key, value, { ...opts, - foreignKey + foreignKey, }) } else if (type === 'belongsTo') { setBelongsTo(owner, key, value, { ...opts, - foreignKey + foreignKey, }) } } @@ -59,21 +59,21 @@ async function get(owner: Model, key: string): Promise | ?Model> { case 'hasOne': value = await getHasOne(owner, { ...opts, - foreignKey + foreignKey, }) break case 'hasMany': value = await getHasMany(owner, { ...opts, - foreignKey + foreignKey, }) break default: value = await getBelongsTo(owner, { ...opts, - foreignKey + foreignKey, }) break } @@ -87,4 +87,4 @@ async function get(owner: Model, key: string): Promise | ?Model> { export { get, set } export { default as updateRelationship } from './utils/update-relationship' -export type { Relationship$opts } from './interfaces' +export type { Relationship } from './interfaces' diff --git a/src/packages/database/relationship/interfaces.js b/src/packages/database/relationship/interfaces.js index ae65931d..a4b1ebba 100644 --- a/src/packages/database/relationship/interfaces.js +++ b/src/packages/database/relationship/interfaces.js @@ -1,15 +1,16 @@ /* @flow */ -import type { Model } from '../index'; +import type { Model } from '../index' -type Relationship$ref = Model | Array; +type Type = 'belongsTo' | 'hasMany' | 'hasOne' +type Reference = Model | Array -export type Relationship$refs = WeakMap>; +export type References = WeakMap> -export type Relationship$opts = { - type: 'hasOne' | 'hasMany' | 'belongsTo'; - model: Class; - inverse: string; - through?: Class; - foreignKey: string; -}; +export type Relationship = { + type: Type, + model: Class, + inverse: string, + through?: Class, + foreignKey: string, +} diff --git a/src/packages/database/relationship/utils/getters.js b/src/packages/database/relationship/utils/getters.js index a2fae1cf..454597e6 100644 --- a/src/packages/database/relationship/utils/getters.js +++ b/src/packages/database/relationship/utils/getters.js @@ -3,33 +3,29 @@ import { camelize } from 'inflection' import type { Model } from '../../index' -import type { Relationship$opts } from '../index' +import type { Relationship } from '../index' /** * @private */ -async function getHasManyThrough(owner: Model, { - model, - inverse, - through, - foreignKey: baseKey -}: Relationship$opts): Promise> { +async function getHasManyThrough( + owner: Model, + { model, inverse, through, foreignKey: baseKey }: Relationship, +): Promise> { const inverseOpts = model.relationshipFor(inverse) let value = [] if (through && inverseOpts) { const foreignKey = camelize(inverseOpts.foreignKey, true) - const records = await through - .select(baseKey, foreignKey) - .where({ - [baseKey]: owner.getPrimaryKey() - }) + const records = await through.select(baseKey, foreignKey).where({ + [baseKey]: owner.getPrimaryKey(), + }) if (records.length) { value = await model.where({ [model.primaryKey]: records .map(record => Reflect.get(record, foreignKey)) - .filter(Boolean) + .filter(Boolean), }) } } @@ -40,33 +36,32 @@ async function getHasManyThrough(owner: Model, { /** * @private */ -export function getHasOne(owner: Model, { - model, - foreignKey -}: Relationship$opts) { +export function getHasOne(owner: Model, { model, foreignKey }: Relationship) { return model.first().where({ - [foreignKey]: owner.getPrimaryKey() + [foreignKey]: owner.getPrimaryKey(), }) } /** * @private */ -export function getHasMany(owner: Model, opts: Relationship$opts) { +export function getHasMany(owner: Model, opts: Relationship) { const { model, through, foreignKey } = opts - return through ? getHasManyThrough(owner, opts) : model.where({ - [foreignKey]: owner.getPrimaryKey() - }) + return through + ? getHasManyThrough(owner, opts) + : model.where({ + [foreignKey]: owner.getPrimaryKey(), + }) } /** * @private */ -export function getBelongsTo(owner: Model, { - model, - foreignKey -}: Relationship$opts) { +export function getBelongsTo( + owner: Model, + { model, foreignKey }: Relationship, +) { const foreignValue = Reflect.get(owner, foreignKey) return foreignValue ? model.find(foreignValue) : Promise.resolve(null) diff --git a/src/packages/database/relationship/utils/inverse-setters.js b/src/packages/database/relationship/utils/inverse-setters.js index f7a0e77a..c99c2ee2 100644 --- a/src/packages/database/relationship/utils/inverse-setters.js +++ b/src/packages/database/relationship/utils/inverse-setters.js @@ -1,22 +1,26 @@ /* @flow */ import type { Model } from '../../index' -import type { Relationship$opts } from '../index' +import type { Relationship } from '../index' /** * @private */ -export function setHasManyInverse(owner: Model, value: Array, { - inverse, - foreignKey, - inverseModel -}: Relationship$opts & { - inverseModel: Class; -}) { +export function setHasManyInverse( + owner: Model, + value: Array, + { + inverse, + foreignKey, + inverseModel, + }: Relationship & { + inverseModel: Class, + }, +) { const primaryKey = Reflect.get(owner, owner.constructor.primaryKey) const { type: inverseType } = inverseModel.relationshipFor(inverse) - for (const record of value) { + value.forEach(record => { let { currentChangeSet: changeSet } = record if (owner !== changeSet.get(inverse)) { @@ -30,19 +34,23 @@ export function setHasManyInverse(owner: Model, value: Array, { Reflect.set(record, foreignKey, primaryKey) } } - } + }) } /** * @private */ -export function setHasOneInverse(owner: Model, value?: ?Model, { - inverse, - foreignKey, - inverseModel -}: Relationship$opts & { - inverseModel: Class; -}) { +export function setHasOneInverse( + owner: Model, + value?: ?Model, + { + inverse, + foreignKey, + inverseModel, + }: Relationship & { + inverseModel: Class, + }, +) { if (value) { const { type: inverseType } = inverseModel.relationshipFor(inverse) let inverseValue = value.currentChangeSet.get(inverse) diff --git a/src/packages/database/relationship/utils/setters.js b/src/packages/database/relationship/utils/setters.js index 68297737..4d47173a 100644 --- a/src/packages/database/relationship/utils/setters.js +++ b/src/packages/database/relationship/utils/setters.js @@ -1,21 +1,19 @@ /* @flow */ import type { Model } from '../../index' -import type { Relationship$opts } from '../index' +import type { Relationship } from '../index' import unassociate from './unassociate' import validateType from './validate-type' import { setHasOneInverse, setHasManyInverse } from './inverse-setters' -/** - * @private - */ -export function setHasMany(owner: Model, key: string, value: Array, { - type, - model, - inverse, - foreignKey -}: Relationship$opts) { +export const setHasMany = ( + owner: Model, + key: string, + value: Array, + relationship: Relationship, +): void => { + const { type, model, inverse, foreignKey } = relationship let { currentChangeSet: changeSet } = owner if (validateType(model, value)) { @@ -26,9 +24,12 @@ export function setHasMany(owner: Model, key: string, value: Array, { if (Array.isArray(prevValue)) { prevValue - .filter(prev => ( - !value.find(next => prev.getPrimaryKey() === next.getPrimaryKey()) - )) + .filter( + prev => + !value.find( + next => prev.getPrimaryKey() === next.getPrimaryKey(), + ), + ) .forEach(record => owner.prevAssociations.add(record)) } } @@ -44,20 +45,18 @@ export function setHasMany(owner: Model, key: string, value: Array, { model, inverse, foreignKey, - inverseModel: model + inverseModel: model, }) } } -/** - * @private - */ -export function setHasOne(owner: Model, key: string, value?: ?Model, { - type, - model, - inverse, - foreignKey -}: Relationship$opts) { +export const setHasOne = ( + owner: Model, + key: string, + value?: ?Model, + relationship: Relationship, +): void => { + const { type, model, inverse, foreignKey } = relationship let valueToSet = value if (value && typeof value === 'object' && !model.isInstance(value)) { @@ -87,24 +86,22 @@ export function setHasOne(owner: Model, key: string, value?: ?Model, { model, inverse, foreignKey, - inverseModel: model + inverseModel: model, }) } -/** - * @private - */ -export function setBelongsTo(owner: Model, key: string, value?: ?Model, { - type, - model, - inverse, - foreignKey -}: Relationship$opts) { +export const setBelongsTo = ( + owner: Model, + key: string, + value?: ?Model, + relationship: Relationship, +): void => { + const { type, model, inverse, foreignKey } = relationship setHasOne(owner, key, value, { type, model, inverse, - foreignKey + foreignKey, }) if (value) { diff --git a/src/packages/database/relationship/utils/unassociate.js b/src/packages/database/relationship/utils/unassociate.js index 00a08fab..7f1cba7e 100644 --- a/src/packages/database/relationship/utils/unassociate.js +++ b/src/packages/database/relationship/utils/unassociate.js @@ -18,7 +18,7 @@ function unassociateOne(value: T, foreignKey: string): T { */ export default function unassociate>( value: U, - foreignKey: string + foreignKey: string, ): U | Array { return value.map(record => unassociateOne(record, foreignKey)) } diff --git a/src/packages/database/relationship/utils/update-relationship.js b/src/packages/database/relationship/utils/update-relationship.js index c9a9718e..d97945d0 100644 --- a/src/packages/database/relationship/utils/update-relationship.js +++ b/src/packages/database/relationship/utils/update-relationship.js @@ -1,23 +1,17 @@ /* @flow */ -// eslint-disable-next-line no-duplicate-imports import { tableFor } from '../../index' import type { Model } from '../../index' -import type { Relationship$opts } from '../interfaces' +import type { Relationship } from '../interfaces' type Params = { - record: Model; - value: ?Model | Array; - opts: Relationship$opts; - trx: Object; + record: Model, + value: ?Model | Array, + opts: Relationship, + trx: Object, } -function updateHasOne({ - record, - value, - opts, - trx -}: Params): Array { +function updateHasOne({ record, value, opts, trx }: Params): Array { const recordPrimaryKey = record.getPrimaryKey() if (value) { @@ -25,81 +19,59 @@ function updateHasOne({ return [ tableFor(opts.model, trx) .update(opts.foreignKey, null) - .where( - `${opts.model.tableName}.${opts.foreignKey}`, - recordPrimaryKey - ) + .where(`${opts.model.tableName}.${opts.foreignKey}`, recordPrimaryKey) .whereNot( `${opts.model.tableName}.${opts.model.primaryKey}`, - value.getPrimaryKey() + value.getPrimaryKey(), ), tableFor(opts.model, trx) .update(opts.foreignKey, recordPrimaryKey) .where( `${opts.model.tableName}.${opts.model.primaryKey}`, - value.getPrimaryKey() - ) + value.getPrimaryKey(), + ), ] } } else { return [ tableFor(opts.model, trx) .update(opts.foreignKey, null) - .where( - `${opts.model.tableName}.${opts.foreignKey}`, - recordPrimaryKey - ) + .where(`${opts.model.tableName}.${opts.foreignKey}`, recordPrimaryKey), ] } return [] } -function updateHasMany({ - record, - value, - opts, - trx -}: Params): Array { +function updateHasMany({ record, value, opts, trx }: Params): Array { const recordPrimaryKey = record.getPrimaryKey() if (Array.isArray(value) && value.length) { return [ tableFor(opts.model, trx) .update(opts.foreignKey, null) - .where( - `${opts.model.tableName}.${opts.foreignKey}`, - recordPrimaryKey - ) + .where(`${opts.model.tableName}.${opts.foreignKey}`, recordPrimaryKey) .whereNotIn( `${opts.model.tableName}.${opts.model.primaryKey}`, - value.map(item => item.getPrimaryKey()) + value.map(item => item.getPrimaryKey()), ), tableFor(opts.model, trx) .update(opts.foreignKey, recordPrimaryKey) .whereIn( `${opts.model.tableName}.${opts.model.primaryKey}`, - value.map(item => item.getPrimaryKey()) - ) + value.map(item => item.getPrimaryKey()), + ), ] } return [ tableFor(opts.model, trx) .update(opts.foreignKey, null) - .where( - `${opts.model.tableName}.${opts.foreignKey}`, - recordPrimaryKey - ) + .where(`${opts.model.tableName}.${opts.foreignKey}`, recordPrimaryKey), ] } -function updateBelongsTo({ - record, - value, - opts, - trx -}: Params): Array { +function updateBelongsTo({ record, value, opts, trx }: Params): Array { if (value instanceof opts.model) { const inverseOpts = opts.model.relationshipFor(opts.inverse) const foreignKeyValue = value.getPrimaryKey() @@ -113,8 +85,8 @@ function updateBelongsTo({ .where(opts.foreignKey, foreignKeyValue) .whereNot( `${record.constructor.tableName}.${record.constructor.primaryKey}`, - record.getPrimaryKey() - ) + record.getPrimaryKey(), + ), ] } } @@ -128,16 +100,12 @@ function updateBelongsTo({ export default function updateRelationship( record: Model, name: string, - trx: Object + trx: Object, ): Array { const opts = record.constructor.relationshipFor(name) if (!opts) { - const { - constructor: { - name: className - } - } = record + const { constructor: { name: className } } = record throw new Error(`Could not find relationship '${name} on '${className}`) } @@ -156,7 +124,7 @@ export default function updateRelationship( record, value, opts, - trx + trx, }) case 'hasMany': @@ -164,7 +132,7 @@ export default function updateRelationship( record, value, opts, - trx + trx, }) default: @@ -172,7 +140,7 @@ export default function updateRelationship( record, value, opts, - trx + trx, }) } } diff --git a/src/packages/database/relationship/utils/validate-type.js b/src/packages/database/relationship/utils/validate-type.js index 9ccdb53b..ac7eafe6 100644 --- a/src/packages/database/relationship/utils/validate-type.js +++ b/src/packages/database/relationship/utils/validate-type.js @@ -1,6 +1,6 @@ /* @flow */ -import isNull from '../../../../utils/is-null' +import { isNull } from '@lux/utils/is-type' import type { Model } from '../../index' function validateOne(model: Class, value: void | ?mixed) { diff --git a/src/packages/database/transaction/index.js b/src/packages/database/transaction/index.js index 3af6edbd..66a43aac 100644 --- a/src/packages/database/transaction/index.js +++ b/src/packages/database/transaction/index.js @@ -1,6 +1,6 @@ /* @flow */ -import { trapGet } from '../../../utils/proxy' +import { trapGet } from '@lux/utils/proxy' import type { Model } from '../index' // eslint-disable-line no-unused-vars import type { Transaction$ResultProxy } from './interfaces' @@ -10,14 +10,14 @@ import type { Transaction$ResultProxy } from './interfaces' */ export function createStaticTransactionProxy>( target: T, - trx: Object + trx: Object, ): T { return new Proxy(target, { get: trapGet({ create(model: T, props: Object = {}) { return model.create(props, trx) - } - }) + }, + }), }) } @@ -26,7 +26,7 @@ export function createStaticTransactionProxy>( */ export function createInstanceTransactionProxy( target: T, - trx: Object + trx: Object, ): T { return new Proxy(target, { get: trapGet({ @@ -40,8 +40,8 @@ export function createInstanceTransactionProxy( destroy(model: T) { return model.destroy(trx) - } - }) + }, + }), }) } @@ -50,12 +50,12 @@ export function createInstanceTransactionProxy( */ export function createTransactionResultProxy( record: T, - didPersist: U + didPersist: U, ): Transaction$ResultProxy { return new Proxy(record, { get: trapGet({ - didPersist - }) + didPersist, + }), }) } diff --git a/src/packages/database/transaction/interfaces.js b/src/packages/database/transaction/interfaces.js index 991cba77..6dcc28f8 100644 --- a/src/packages/database/transaction/interfaces.js +++ b/src/packages/database/transaction/interfaces.js @@ -1,9 +1,9 @@ /* @flow */ -import type { Model } from '../index'; // eslint-disable-line no-unused-vars +import type { Model } from '../index' -// $FlowIgnore +// $FlowFixMe export type Transaction$ResultProxy<+T: Model, U: boolean> = T & { - didPersist: U; - unwrap(): T; -}; + didPersist: U, + unwrap(): T, +} diff --git a/src/packages/database/utils/connect.js b/src/packages/database/utils/connect.js index f60fcbf6..d2fe4ddb 100644 --- a/src/packages/database/utils/connect.js +++ b/src/packages/database/utils/connect.js @@ -1,8 +1,10 @@ +/* @flow */ + import { join as joinPath } from 'path' import type Knex from 'knex' -import { NODE_ENV, DATABASE_URL } from '../../../constants' +import { NODE_ENV, DATABASE_URL } from '@lux/constants' import { VALID_DRIVERS } from '../constants' import { InvalidDriverError } from '../errors' @@ -22,7 +24,7 @@ export default function connect(path: string, config: Object = {}): Knex { password, port, ssl, - url + url, } = config if (VALID_DRIVERS.indexOf(driver) < 0) { @@ -32,10 +34,12 @@ export default function connect(path: string, config: Object = {}): Knex { if (pool && typeof pool === 'number') { pool = { min: pool > 1 ? 2 : 1, - max: pool + max: pool, } } + /* eslint-disable global-require, import/no-dynamic-require */ + // $FlowFixMe const knex: Class = require(joinPath(path, 'node_modules', 'knex')) const usingSQLite = driver === 'sqlite3' let filename @@ -48,14 +52,15 @@ export default function connect(path: string, config: Object = {}): Knex { filename = joinPath( path, 'db', - `${database || 'default'}_${NODE_ENV}.sqlite` + `${database || 'default'}_${NODE_ENV}.sqlite`, ) } } return knex({ pool, - connection: DATABASE_URL || url || { + connection: DATABASE_URL || + url || { ssl, host, port, diff --git a/src/packages/database/utils/create-migrations.js b/src/packages/database/utils/create-migrations.js index 48c7a710..3fb7cbc6 100644 --- a/src/packages/database/utils/create-migrations.js +++ b/src/packages/database/utils/create-migrations.js @@ -5,8 +5,8 @@ import type Database from '../index' /** * @private */ -export default async function createMigrations( - schema: $PropertyType +export default (async function createMigrations( + schema: $PropertyType, ): Promise { const hasTable: boolean = await schema().hasTable('migrations') @@ -17,4 +17,4 @@ export default async function createMigrations( } return true -} +}) diff --git a/src/packages/database/utils/normalize-model-name.js b/src/packages/database/utils/normalize-model-name.js index ece0def6..2d449cb4 100644 --- a/src/packages/database/utils/normalize-model-name.js +++ b/src/packages/database/utils/normalize-model-name.js @@ -2,8 +2,8 @@ import { dasherize, singularize } from 'inflection' -import { compose } from '../../../utils/compose' -import underscore from '../../../utils/underscore' +import { compose } from '@lux/utils/compose' +import underscore from '@lux/utils/underscore' /** * @private diff --git a/src/packages/database/utils/pending-migrations.js b/src/packages/database/utils/pending-migrations.js index d86e51ef..9c6e188a 100644 --- a/src/packages/database/utils/pending-migrations.js +++ b/src/packages/database/utils/pending-migrations.js @@ -1,20 +1,21 @@ /* @flow */ -import { readdir } from '../../fs' +import { readdir } from 'mz/fs' /** * @private */ -export default async function pendingMigrations( +export default (async function pendingMigrations( appPath: string, - table: () => Object + table: () => Object, ): Promise> { const migrations: Array = await readdir(`${appPath}/db/migrate`) const versions: Array = await table() - .select() - .then(data => data.map(({ version }) => version)) + .select() + .then(data => data.map(({ version }) => version)) - return migrations.filter(migration => versions.indexOf( - migration.replace(/^(\d{16})-.+$/g, '$1') - ) < 0) -} + return migrations.filter( + migration => + versions.indexOf(migration.replace(/^(\d{16})-.+$/g, '$1')) < 0, + ) +}) diff --git a/src/packages/database/validation/index.js b/src/packages/database/validation/index.js index 3ebe436a..eab9dc48 100644 --- a/src/packages/database/validation/index.js +++ b/src/packages/database/validation/index.js @@ -6,11 +6,11 @@ import type { Validation$opts } from './interfaces' * @private */ class Validation { - key: string; + key: string - value: T; + value: T - validator: (value?: T) => boolean; + validator: (value?: T) => boolean constructor(opts: Validation$opts) { Object.defineProperties(this, { @@ -18,22 +18,22 @@ class Validation { value: opts.key, writable: false, enumerable: true, - configurable: false + configurable: false, }, value: { value: opts.value, writable: false, enumerable: true, - configurable: false + configurable: false, }, validator: { value: opts.validator, writable: false, enumerable: false, - configurable: false - } + configurable: false, + }, }) } diff --git a/src/packages/database/validation/interfaces.js b/src/packages/database/validation/interfaces.js index 2f1d6b9f..539f0920 100644 --- a/src/packages/database/validation/interfaces.js +++ b/src/packages/database/validation/interfaces.js @@ -1,7 +1,7 @@ /* @flow */ export type Validation$opts = { - key: string; - value: T; - validator: (value?: T) => boolean; -}; + key: string, + value: T, + validator: (value?: T) => boolean, +} diff --git a/src/packages/freezeable/__tests__/freezeable.test.js b/src/packages/freezeable/__tests__/freezeable.test.js index 131b7a13..c4df1682 100644 --- a/src/packages/freezeable/__tests__/freezeable.test.js +++ b/src/packages/freezeable/__tests__/freezeable.test.js @@ -8,11 +8,7 @@ describe('module "freezeable"', () => { let subject beforeAll(() => { - subject = new FreezeableMap([ - ['a', 1], - ['b', 2], - ['c', 3] - ]) + subject = new FreezeableMap([['a', 1], ['b', 2], ['c', 3]]) }) test('returns a mutable `Map` interface', () => { @@ -39,15 +35,10 @@ describe('module "freezeable"', () => { const d = { a: 1, b: 2, - c: 3 + c: 3, } - subject = new FreezeableMap([ - ['a', 1], - ['b', 2], - ['c', 3], - ['d', d] - ]) + subject = new FreezeableMap([['a', 1], ['b', 2], ['c', 3], ['d', d]]) }) test('returns `this`', () => { @@ -110,7 +101,7 @@ describe('module "freezeable"', () => { const obj = { a: 1, b: 2, - c: 3 + c: 3, } beforeEach(() => { diff --git a/src/packages/freezeable/index.js b/src/packages/freezeable/index.js index 9bdeb6e4..62692373 100644 --- a/src/packages/freezeable/index.js +++ b/src/packages/freezeable/index.js @@ -6,5 +6,5 @@ export { freezeArray, freezeValue, freezeProps, - deepFreezeProps + deepFreezeProps, } from './utils/freeze' diff --git a/src/packages/freezeable/utils/freeze.js b/src/packages/freezeable/utils/freeze.js index bbb4d01c..3c417b83 100644 --- a/src/packages/freezeable/utils/freeze.js +++ b/src/packages/freezeable/utils/freeze.js @@ -1,8 +1,8 @@ /* @flow */ import { FREEZER } from '../constants' -import insert from '../../../utils/insert' -import isObject from '../../../utils/is-object' +import insert from '@lux/utils/insert' +import { isObject } from '@lux/utils/is-type' /** * @private @@ -42,15 +42,21 @@ export function freezeProps( makePublic: boolean, ...props: Array ): T { - Object.defineProperties(target, props.reduce((obj, key) => ({ - ...obj, - [key]: { - value: Reflect.get(target, key), - writable: false, - enumerable: makePublic, - configurable: false, - } - }), {})) + Object.defineProperties( + target, + props.reduce( + (obj, key) => ({ + ...obj, + [key]: { + value: Reflect.get(target, key), + writable: false, + enumerable: makePublic, + configurable: false, + }, + }), + {}, + ), + ) return target } @@ -63,25 +69,28 @@ export function deepFreezeProps( makePublic: boolean, ...props: Array ): T { - Object.defineProperties(target, props.reduce((obj, key) => { - let value = Reflect.get(target, key) + Object.defineProperties( + target, + props.reduce((obj, key) => { + let value = Reflect.get(target, key) - if (Array.isArray(value)) { - value = freezeArray(value) - } else { - value = freezeValue(value) - } + if (Array.isArray(value)) { + value = freezeArray(value) + } else { + value = freezeValue(value) + } - return { - ...obj, - [key]: { - value, - writable: false, - enumerable: makePublic, - configurable: false, + return { + ...obj, + [key]: { + value, + writable: false, + enumerable: makePublic, + configurable: false, + }, } - } - }, {})) + }, {}), + ) return target } diff --git a/src/packages/fs/__tests__/__mocks__/fs.js b/src/packages/fs/__tests__/__mocks__/fs.js deleted file mode 100644 index 055a44fb..00000000 --- a/src/packages/fs/__tests__/__mocks__/fs.js +++ /dev/null @@ -1,170 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -let ROOT - -const flatten = parts => ( - parts - .reduce((arr, part) => arr.concat(part.split(path.sep)), []) - .filter(Boolean) -) - -const walk = (dir, ...parts) => { - if (dir instanceof Map) { - const keys = flatten(parts) - - if (keys.length === 1) { - return dir.get(keys[0]) - } - - return walk(dir.get(keys[0]), ...keys.slice(1)) - } - - return dir -} - -export const __reset__ = () => { - ROOT = new Map([ - ['tmp', new Map([ - ['fs-test', Buffer.from('test')], - ['rmrf-test', new Map([ - ['data.txt', Buffer.from('test')], - ])], - ['readdir-rec-test', new Map([ - ['directory', new Map([ - ['x.txt', Buffer.from('x')], - ['y.txt', Buffer.from('y')], - ['z.txt', Buffer.from('z')], - ])], - ])], - ])], - ]) -} - -export const mkdir = ( - jest.fn().mockImplementation((...args) => { - const [key, , cb] = args - - if (key.endsWith('throw')) { - cb(new Error()) - return - } - - const dir = walk(ROOT, path.dirname(key)) - - if (dir instanceof Map) { - const name = path.basename(key) - - if (dir.has(name)) { - // $FlowIgnore - const err = Object.assign(new Error(), { - code: 'EEXIST', - }) - - cb(err) - return - } - - dir.set(name, new Map()) - } - - cb(null, undefined) - }) -) - -export const rmdir = ( - jest.fn().mockImplementation((...args) => { - const [key, cb] = args - const dir = walk(ROOT, path.dirname(key)) - - if (dir instanceof Map) { - dir.delete(path.basename(key)) - } - - cb(null, undefined) - }) -) - -export const readdir = ( - jest.fn().mockImplementation((...args) => { - const [dirPath, cb] = args - const result = walk(ROOT, dirPath) - - if (result instanceof Map) { - cb(null, [...result.keys()]) - return - } - - cb(null, []) - }) -) - -export const readFile = ( - jest.fn().mockImplementation((...args) => { - const [, options, cb] = args - - cb(null, options.encoding ? '' : new Buffer('')) - }) -) - -export const writeFile = ( - jest.fn().mockImplementation((...args) => { - const [, , , cb] = args - - cb(null, undefined) - }) -) - -export const appendFile = ( - jest.fn().mockImplementation((...args) => { - const [, , , cb] = args - - cb(null, undefined) - }) -) - -export const stat = ( - jest.fn().mockImplementation((...args) => { - const [key, cb] = args - const result = walk(ROOT, key) - - if (result) { - const isDirectory = () => result instanceof Map - const isFile = () => !isDirectory() - - cb(null, { isFile, isDirectory }) - return - } - - // $FlowIgnore - const err = Object.assign(new Error(), { - code: 'ENOENT', - }) - - cb(err) - }) -) - -export const unlink = ( - jest.fn().mockImplementation((...args) => { - const [key, cb] = args - const dir = walk(ROOT, path.dirname(key)) - - if (dir instanceof Map) { - dir.delete(path.basename(key)) - } - - cb(null, undefined) - }) -) - -export const watch = ( - jest.fn().mockImplementation((...args) => { - const [, , cb] = args - - return () => cb('update', 'index.js') - }) -) - -__reset__() diff --git a/src/packages/fs/__tests__/__mocks__/os.js b/src/packages/fs/__tests__/__mocks__/os.js deleted file mode 100644 index e73d04aa..00000000 --- a/src/packages/fs/__tests__/__mocks__/os.js +++ /dev/null @@ -1,9 +0,0 @@ -/* @flow */ - -let PLATFORM = 'linux' - -export const __setPlatform__ = (value: string) => { - PLATFORM = value -} - -export const platform = () => PLATFORM diff --git a/src/packages/fs/__tests__/__snapshots__/fs.test.js.snap b/src/packages/fs/__tests__/__snapshots__/fs.test.js.snap deleted file mode 100644 index 4b10e2c9..00000000 --- a/src/packages/fs/__tests__/__snapshots__/fs.test.js.snap +++ /dev/null @@ -1,10 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`module "fs" #readdirRec() recursively reads a directory 1`] = ` -Array [ - "directory", - "directory/x.txt", - "directory/y.txt", - "directory/z.txt", -] -`; diff --git a/src/packages/fs/__tests__/create-path-remover.test.js b/src/packages/fs/__tests__/create-path-remover.test.js deleted file mode 100644 index 2a5e9065..00000000 --- a/src/packages/fs/__tests__/create-path-remover.test.js +++ /dev/null @@ -1,45 +0,0 @@ -/* @flow */ - -import * as os from 'os' -import * as path from 'path' - -jest.mock('os') - -describe('module "fs/utils/create-path-remover"', () => { - let createPathRemover - - describe('#default()', () => { - ['win32', 'linux', 'darwin'].forEach(platform => { - describe(`- platform ${platform}`, () => { - const file = 'index.js' - let subject - let basePath - - beforeAll(() => { - // $FlowIgnore - os.__setPlatform__(platform) - - if (platform === 'win32') { - basePath = path.win32.join(path.win32.sep, 'tmp', 'test') - subject = path.win32.join(basePath, file) - } else { - basePath = path.posix.join(path.posix.sep, 'tmp', 'test') - subject = path.posix.join(basePath, file) - } - - createPathRemover = require('../utils/create-path-remover').default - }) - - afterAll(() => { - jest.resetModules() - }) - - test('creates a path remover function', () => { - const removePath = createPathRemover(basePath) - - expect(removePath(subject)).toEqual(file) - }) - }) - }) - }) -}) diff --git a/src/packages/fs/__tests__/fs.test.js b/src/packages/fs/__tests__/fs.test.js deleted file mode 100644 index cabf4472..00000000 --- a/src/packages/fs/__tests__/fs.test.js +++ /dev/null @@ -1,138 +0,0 @@ -/* @flow */ - -import * as path from 'path' -// $FlowIgnore -import { __reset__ } from 'fs' - -import * as fs from '../index' - -jest.mock('fs') - -describe('module "fs"', () => { - afterAll(() => { - jest.unmock('fs') - }) - - afterEach(__reset__) - - describe('#exists()', () => { - const tmp = path.join(path.sep, 'tmp', 'fs-test') - - test('is true if "PATH" exists', async () => { - expect(await fs.exists(tmp)).toBe(true) - }) - - test('is false if "PATH" does not exist', async () => { - expect(await fs.exists('does-not-exist.tmp')).toBe(false) - }) - - test('is true if regexp "PATH" exists within "DIR"', async () => { - const result = await fs.exists( - new RegExp(path.basename(tmp)), - path.dirname(tmp) - ) - - expect(result).toBe(true) - }) - - test('is false if regexp "PATH" does not exist within "DIR"', async () => { - const result = await fs.exists( - new RegExp('does-not-exist.tmp'), - path.dirname(tmp) - ) - - expect(result).toBe(false) - }) - }) - - describe('#rmrf()', () => { - const tmp = path.join(path.sep, 'tmp', 'rmrf-test', 'data.txt') - - test('removes a file', async () => { - await fs.rmrf(tmp) - expect(await fs.exists(tmp)).toBe(false) - }) - - test('removes a directory and its contents', async () => { - const target = path.dirname(tmp) - - await fs.rmrf(target) - expect(await fs.exists(target)).toBe(false) - }) - }) - - describe('#parsePath()', () => { - const parts = [ - path.sep, - 'test', - 'index.js', - ] - - test('correctly parses a file path', () => { - expect(fs.parsePath(...parts)).toEqual( - expect.objectContaining({ - absolute: path.join(...parts), - relative: path.join(...parts.slice(1)), - }) - ) - }) - - test('can be called with no arguments', () => { - expect(fs.parsePath()).toEqual( - expect.objectContaining({ - absolute: process.cwd(), - relative: process.cwd(), - }) - ) - }) - }) - - describe('#isJSFile()', () => { - const [a, b, c] = [ - 'author.js', - 'author.rb', - '.gitkeep' - ] - - test('is true if a file has a `.js` extension', () => { - expect(fs.isJSFile(a)).toBe(true) - }) - - test('is false if a file does not have a `.js` extension', () => { - expect(fs.isJSFile(b)).toBe(false) - }) - - test('is false if the file is prefixed with `.`', () => { - expect(fs.isJSFile(c)).toBe(false) - }) - }) - - describe('#mkdirRec()', () => { - const tmp = path.join(path.sep, 'tmp', 'mkdir-rec-test', 'directory') - - test('creates a directory recursively', async () => { - await fs.mkdirRec(tmp) - expect(await fs.exists(tmp)).toBe(true) - }) - - test('does not throw when the directory already exists', async () => { - await fs.mkdirRec(tmp) - await fs.mkdirRec(tmp) - expect(await fs.exists(tmp)).toBe(true) - }) - - test('properly rejects when a valid error occurs', async () => { - await fs.mkdirRec(path.join(path.sep, 'tmp', 'throw')).catch(err => { - expect(err).toBeInstanceOf(Error) - }) - }) - }) - - describe('#readdirRec()', () => { - const tmp = path.join(path.sep, 'tmp', 'readdir-rec-test') - - test('recursively reads a directory', async () => { - expect(await fs.readdirRec(tmp)).toMatchSnapshot() - }) - }) -}) diff --git a/src/packages/fs/__tests__/watcher.test.js b/src/packages/fs/__tests__/watcher.test.js deleted file mode 100644 index 5fd645e5..00000000 --- a/src/packages/fs/__tests__/watcher.test.js +++ /dev/null @@ -1,73 +0,0 @@ -/* @flow */ - -import { tmpdir } from 'os' -import { join as joinPath } from 'path' - -import { APPVEYOR } from '../../../constants' -import Watcher from '../watcher' -import { rmrf, mkdirRec, writeFile } from '../index' - -describe('module "fs"', () => { - const tmpDirPath = joinPath(tmpdir(), `lux-${Date.now()}`) - const tmpAppPath = joinPath(tmpDirPath, 'app') - - beforeAll(async () => { - await mkdirRec(tmpAppPath) - }) - - afterAll(async () => { - await rmrf(tmpDirPath) - }) - - describe('class Watcher', () => { - if (!APPVEYOR) { - describe('- client Watchman', () => { - let subject - - beforeAll(async () => { - subject = await new Watcher(tmpDirPath) - }) - - describe('event "change"', () => { - test('is called when a file is modified', async () => { - subject.once('change', files => { - expect(files).toEqual(expect.any(Array)) - }) - - await writeFile(joinPath(tmpAppPath, 'index.js'), Buffer.from('')) - }) - }) - - describe('#destroy()', () => { - test('does not throw an error', () => { - expect(() => subject.destroy()).not.toThrow() - }) - }) - }) - } - - describe('- client FSWatcher', () => { - let subject - - beforeAll(async () => { - subject = await new Watcher(tmpDirPath, false) - }) - - describe('event "change"', () => { - test('is called when a file is modified', async () => { - subject.once('change', files => { - expect(files).toEqual(expect.any(Array)) - }) - - await writeFile(joinPath(tmpAppPath, 'index.js'), Buffer.from('')) - }) - }) - - describe('#destroy()', () => { - test('does not throw an error', () => { - expect(() => subject.destroy()).not.toThrow() - }) - }) - }) - }) -}) diff --git a/src/packages/fs/index.js b/src/packages/fs/index.js deleted file mode 100644 index 0ca03d87..00000000 --- a/src/packages/fs/index.js +++ /dev/null @@ -1,127 +0,0 @@ -/* @flow */ - -import * as fs from 'fs' -import * as path from 'path' -// eslint-disable-next-line -import type { Stats } from 'fs'; - -import promisify from '../../utils/promisify' - -import Watcher from './watcher' -import createPathRemover from './utils/create-path-remover' - -export { default as rmrf } from './utils/rmrf' -export { default as exists } from './utils/exists' -export { default as isJSFile } from './utils/is-js-file' -export { default as parsePath } from './utils/parse-path' - -/** - * @private - */ -export const stat: (path: string) => Promise = ( - promisify(fs.stat) -) - -/** - * @private - */ -export const mkdir: (path: string, mode?: number) => Promise = ( - promisify(fs.mkdir) -) - -/** - * @private - */ -export const rmdir: (path: string) => Promise = ( - promisify(fs.rmdir) -) - -/** - * @private - */ -export const unlink: (path: string) => Promise = ( - promisify(fs.unlink) -) - -/** - * @private - */ -export const readdir: (path: string) => Promise> = ( - promisify(fs.readdir) -) - -/** - * @private - */ -export const readFile: (path: string) => Promise = ( - promisify(fs.readFile) -) - -/** - * @private - */ -export const writeFile: (path: string, data: Buffer) => Promise = ( - promisify(fs.writeFile) -) - -/** - * @private - */ -export const appendFile: (path: string, data: Buffer) => Promise = ( - promisify(fs.appendFile) -) - -/** - * @private - */ -export function watch(watchPath: string): Promise { - return new Watcher(watchPath) -} - -/** - * @private - */ -export function mkdirRec(dirPath: string, mode: number = 511): Promise { - const parent = path.resolve(dirPath, '..') - - return stat(parent) - .catch(() => mkdirRec(parent, mode)) - .then(() => mkdir(dirPath, mode)) - .catch(err => { - if (err.code !== 'EEXIST') { - return Promise.reject(err) - } - return Promise.resolve() - }) -} - -/** - * @private - */ -export function readdirRec(dirPath: string): Promise> { - const stripPath = createPathRemover(dirPath) - - return readdir(dirPath) - .then(files => Promise.all( - files.map(file => { - const filePath = path.join(dirPath, file) - - return Promise.all([filePath, stat(filePath)]) - }) - )) - .then(files => Promise.all( - files.map(([file, stats]) => Promise.all([ - file, - stats.isDirectory() ? readdirRec(file) : [] - ])) - )) - .then(files => files.reduce((arr, [file, children]) => { - const basename = stripPath(file) - - return [ - ...arr, - basename, - ...children.map(child => path.join(basename, stripPath(child))) - ] - }, [])) -} diff --git a/src/packages/fs/utils/create-path-remover.js b/src/packages/fs/utils/create-path-remover.js deleted file mode 100644 index 31a13d36..00000000 --- a/src/packages/fs/utils/create-path-remover.js +++ /dev/null @@ -1,20 +0,0 @@ -/* @flow */ - -import { PLATFORM } from '../../../constants' - -/** - * @private - */ -function createPathRemover(path: string): (src: string) => string { - let pattern = new RegExp(`${path}(/)?(.+)`) - - if (PLATFORM.startsWith('win')) { - const sep = '\\\\' - - pattern = new RegExp(`${path.replace(/\\/g, sep)}(${sep})?(.+)`) - } - - return source => source.replace(pattern, '$2') -} - -export default createPathRemover diff --git a/src/packages/fs/utils/exists.js b/src/packages/fs/utils/exists.js deleted file mode 100644 index d1a1f301..00000000 --- a/src/packages/fs/utils/exists.js +++ /dev/null @@ -1,26 +0,0 @@ -/* @flow */ - -import { stat, readdir } from '../index' - -/** - * @private - */ -async function exists(path: string | RegExp, dir?: string): Promise { - if (path instanceof RegExp) { - const pattern = path - let files = [] - - if (dir) { - files = await readdir(dir) - } - - return files.some(file => pattern.test(file)) - } - - return stat(path).then( - () => true, - () => false - ) -} - -export default exists diff --git a/src/packages/fs/utils/is-js-file.js b/src/packages/fs/utils/is-js-file.js deleted file mode 100644 index b657e7d7..00000000 --- a/src/packages/fs/utils/is-js-file.js +++ /dev/null @@ -1,10 +0,0 @@ -/* @flow */ - -import { extname } from 'path' - -/** - * @private - */ -export default function isJSFile(target: string): boolean { - return extname(target) === '.js' -} diff --git a/src/packages/fs/utils/parse-path.js b/src/packages/fs/utils/parse-path.js deleted file mode 100644 index 2113fd36..00000000 --- a/src/packages/fs/utils/parse-path.js +++ /dev/null @@ -1,35 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -import { CWD } from '../../../constants' - -type ParsedPath = { - absolute: string; - ext: string; - dir: string; - base: string; - name: string; - relative: string; - root: string; -} - -/** - * @private - */ -export default function parsePath( - cwd?: string = CWD, - dir?: string = '', - name?: string = '' -): ParsedPath { - const parsed = path.parse(path.join(cwd, dir, ...name.split(path.sep))) - - return { - ...parsed, - absolute: path.join(parsed.dir, parsed.base), - relative: path.join( - parsed.dir.substr(parsed.dir.indexOf(dir)), - parsed.base - ), - } -} diff --git a/src/packages/fs/utils/rmrf.js b/src/packages/fs/utils/rmrf.js deleted file mode 100644 index 7ff6f449..00000000 --- a/src/packages/fs/utils/rmrf.js +++ /dev/null @@ -1,31 +0,0 @@ -/* @flow */ - -import * as path from 'path' - -import noop from '../../../utils/noop' -import { stat, rmdir, readdir, unlink } from '../index' - -/** - * @private - */ -async function rmrf(target: string): Promise { - const stats = await stat(target).catch(noop) - - if (stats) { - if (stats.isDirectory()) { - const files = await readdir(target) - - await Promise.all( - files.map(file => rmrf(path.join(target, file))) - ) - - await rmdir(target).catch(noop) - } else { - await unlink(target) - } - } - - return true -} - -export default rmrf diff --git a/src/packages/fs/watcher/initialize.js b/src/packages/fs/watcher/initialize.js deleted file mode 100644 index 9a7c7ec9..00000000 --- a/src/packages/fs/watcher/initialize.js +++ /dev/null @@ -1,132 +0,0 @@ -/* @flow */ - -import { join as joinPath } from 'path' -import { watch as nativeWatch } from 'fs' -import type { FSWatcher } from 'fs' // eslint-disable-line no-duplicate-imports - -import { Client as Watchman } from 'fb-watchman' - -import exec from '../../../utils/exec' -import tryCatch from '../../../utils/try-catch' -import isJSFile from '../utils/is-js-file' -import { freezeProps } from '../../freezeable' - -// eslint-disable-next-line no-unused-vars -import type Watcher, { Client } from './index' - -const SUBSCRIPTION_NAME = 'lux-watcher' - -/** - * @private - */ -function fallback(instance: Watcher, path: string): FSWatcher { - return nativeWatch(path, { - recursive: true - }, (type, name) => { - if (isJSFile(name)) { - instance.emit('change', [{ name, type }]) - } - }) -} - -/** - * @private - */ -function setupWatchmen(instance: Watcher, path: string): Promise { - return new Promise((resolve, reject) => { - const client = new Watchman() - - client.capabilityCheck({}, (capabilityErr) => { - if (capabilityErr) { - reject(capabilityErr) - return - } - - client.command(['watch-project', path], (watchErr, { - watch, - relative_path: relativePath - } = {}) => { - if (watchErr) { - reject(watchErr) - return - } - - client.command(['clock', watch], (clockErr, { clock: since }) => { - if (clockErr) { - reject(clockErr) - return - } - - client.command(['subscribe', watch, SUBSCRIPTION_NAME, { - since, - relative_root: relativePath, // eslint-disable-line camelcase - - fields: [ - 'name', - 'size', - 'exists', - 'type' - ], - - expression: [ - 'allof', [ - 'match', - '*.js' - ] - ] - }], (subscribeErr) => { - if (subscribeErr) { - reject(subscribeErr) - return - } - - client.on('subscription', ({ - files, - subscription - }: { - files: Array, - subscription: string - }): void => { - if (subscription === SUBSCRIPTION_NAME) { - instance.emit('change', files) - } - }) - - resolve(client) - }) - }) - }) - }) - }) -} - -/** - * @private - */ -export default async function initialize( - instance: T, - path: string, - useWatchman: boolean -): Promise { - const appPath = joinPath(path, 'app') - let client - - if (useWatchman) { - await tryCatch(async () => { - await exec('which watchman') - client = await setupWatchmen(instance, appPath) - }) - } - - Object.assign(instance, { - path: appPath, - client: client || fallback(instance, appPath) - }) - - freezeProps(instance, true, - 'path', - 'client' - ) - - return instance -} diff --git a/src/packages/inflector/casing.js b/src/packages/inflector/casing.js new file mode 100644 index 00000000..073a8882 --- /dev/null +++ b/src/packages/inflector/casing.js @@ -0,0 +1,26 @@ +/* @flow */ + +import { tokenize } from './utils' + +export const capitalize = (value: string): string => { + // $FlowFixMe + const [first, ...chars] = value + + return first.toUpperCase() + chars.join('') +} + +export const classify = (value: string): string => + tokenize(value).map(capitalize).join('') + +export const camelize = (value: string): string => + tokenize(value).reduce( + (result, token, index) => result + (index > 0 ? capitalize(token) : token), + '', + ) + +export const dasherize = (value: string): string => tokenize(value).join('-') + +export const titleize = (value: string) => + tokenize(value).map(capitalize).join(' ') + +export const underscore = (value: string): string => tokenize(value).join('_') diff --git a/src/packages/inflector/index.js b/src/packages/inflector/index.js new file mode 100644 index 00000000..c1614fa4 --- /dev/null +++ b/src/packages/inflector/index.js @@ -0,0 +1,3 @@ +/* @flow */ + +export * from './casing' diff --git a/src/packages/inflector/utils.js b/src/packages/inflector/utils.js new file mode 100644 index 00000000..543ac1a1 --- /dev/null +++ b/src/packages/inflector/utils.js @@ -0,0 +1,22 @@ +/* @flow */ + +const DELIMITER = '__INFLECTOR__' +const PATTERN = /(?:[_-\s]|(?:[a-z][A-Z]))+/g + +const replacer = token => { + switch (token.charAt(0)) { + case '-': + case '_': + case ' ': + return DELIMITER + + default: + return token.split('').join(DELIMITER) + } +} + +export const tokenize = (value: string): Array => + value + .replace(PATTERN, replacer) + .split(DELIMITER) + .map(token => token.toLowerCase()) diff --git a/src/packages/jsonapi/errors/index.js b/src/packages/jsonapi/errors/index.js index 03c23673..b5531247 100644 --- a/src/packages/jsonapi/errors/index.js +++ b/src/packages/jsonapi/errors/index.js @@ -1,13 +1,11 @@ /* @flow */ -export { - default as NotAcceptableError -} from './not-acceptable-error' +export { default as NotAcceptableError } from './not-acceptable-error' export { - default as UnsupportedMediaTypeError + default as UnsupportedMediaTypeError, } from './unsupported-media-type-error' export { - default as InvalidContentTypeError + default as InvalidContentTypeError, } from './invalid-content-type-error' diff --git a/src/packages/jsonapi/errors/invalid-content-type-error.js b/src/packages/jsonapi/errors/invalid-content-type-error.js index 59e97fd8..7af796f5 100644 --- a/src/packages/jsonapi/errors/invalid-content-type-error.js +++ b/src/packages/jsonapi/errors/invalid-content-type-error.js @@ -1,7 +1,7 @@ /* @flow */ import { MIME_TYPE } from '../constants' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' import createServerError from '../../../errors/utils/create-server-error' /** diff --git a/src/packages/jsonapi/errors/not-acceptable-error.js b/src/packages/jsonapi/errors/not-acceptable-error.js index 055cad3a..84035946 100644 --- a/src/packages/jsonapi/errors/not-acceptable-error.js +++ b/src/packages/jsonapi/errors/not-acceptable-error.js @@ -1,7 +1,7 @@ /* @flow */ import { MIME_TYPE } from '../constants' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' import createServerError from '../../../errors/utils/create-server-error' /** diff --git a/src/packages/jsonapi/errors/unsupported-media-type-error.js b/src/packages/jsonapi/errors/unsupported-media-type-error.js index cfbcdeea..b3e3a050 100644 --- a/src/packages/jsonapi/errors/unsupported-media-type-error.js +++ b/src/packages/jsonapi/errors/unsupported-media-type-error.js @@ -1,7 +1,7 @@ /* @flow */ import { MIME_TYPE } from '../constants' -import { line } from '../../logger' +import { line } from '@lux/packages/logger' import createServerError from '../../../errors/utils/create-server-error' /** diff --git a/src/packages/jsonapi/index.js b/src/packages/jsonapi/index.js index 4a3e1b63..b2f0a06e 100644 --- a/src/packages/jsonapi/index.js +++ b/src/packages/jsonapi/index.js @@ -4,82 +4,76 @@ import type { ObjectMap } from '../../interfaces' /* eslint-disable no-use-before-define */ -type Value = - | string - | number - | boolean - | BaseObject - | Array +type Value = string | number | boolean | BaseObject | Array type BaseObject = ObjectMap & { - meta?: BaseObject; + meta?: BaseObject, } /* eslint-enable no-use-before-define */ export type Link = { - href: string; - meta?: BaseObject; + href: string, + meta?: BaseObject, } export type Links = { - self?: ?(string | Link); - related?: ?(string | Link); + self?: ?(string | Link), + related?: ?(string | Link), } -export type Version = - | '1.0' +export type Version = '1.0' export type Identifier = { - id: string; - type: string; - meta?: BaseObject; + id: string, + type: string, + meta?: BaseObject, } export type Relationship = { - data: Identifier; - meta?: BaseObject; - links?: Links; + data: Identifier, + meta?: BaseObject, + links?: Links, } export type Resource = { - id: string; - type: string; - links?: Links; - attributes?: BaseObject; - relationships?: ObjectMap; + id: string, + type: string, + links?: Links, + attributes?: BaseObject, + relationships?: ObjectMap, } export type ErrorData = { - id?: string; - code?: string; - meta?: BaseObject; - title?: string; - status?: string; - detail?: string; + id?: string, + code?: string, + meta?: BaseObject, + title?: string, + status?: string, + detail?: string, links?: { - about: Link; - }; + about: Link, + }, source?: { - pointer?: string; - parameter?: string; - }; + pointer?: string, + parameter?: string, + }, } export type Document = { - data?: Resource | Array; + data?: Resource | Array, links?: Links & { - first?: ?(string | Link); - last?: ?(string | Link); - prev?: ?(string | Link); - next?: ?(string | Link); - }; - errors?: Array; - included?: Array; + first?: ?(string | Link), + last?: ?(string | Link), + prev?: ?(string | Link), + next?: ?(string | Link), + }, + errors?: Array, + included?: Array, jsonapi?: { - version: Version; - meta?: BaseObject; - }; + version: Version, + meta?: BaseObject, + }, } export * from './constants' diff --git a/src/packages/loader/__tests__/loader.test.js b/src/packages/loader/__tests__/loader.test.js index aad5877e..31f3aa3b 100644 --- a/src/packages/loader/__tests__/loader.test.js +++ b/src/packages/loader/__tests__/loader.test.js @@ -2,7 +2,7 @@ import * as path from 'path' -import { FreezeableMap } from '../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import { createLoader } from '../index' const APP_PATH = path.join( @@ -42,9 +42,9 @@ describe('module "loader"', () => { expect(result instanceof FreezeableMap).toBe(true) result.forEach(value => { - expect( - Reflect.getPrototypeOf(value).name.endsWith('Controller') - ).toBe(true) + expect(Reflect.getPrototypeOf(value).name.endsWith('Controller')).toBe( + true, + ) }) }) @@ -82,9 +82,9 @@ describe('module "loader"', () => { expect(result instanceof FreezeableMap).toBe(true) result.forEach(value => { - expect( - Reflect.getPrototypeOf(value).name.endsWith('Serializer') - ).toBe(true) + expect(Reflect.getPrototypeOf(value).name.endsWith('Serializer')).toBe( + true, + ) }) }) }) diff --git a/src/packages/loader/builder/__tests__/create-parent-builder.test.js b/src/packages/loader/builder/__tests__/create-parent-builder.test.js index 5e3ad794..65151724 100644 --- a/src/packages/loader/builder/__tests__/create-parent-builder.test.js +++ b/src/packages/loader/builder/__tests__/create-parent-builder.test.js @@ -2,10 +2,10 @@ import { posix } from 'path' -import { Model } from '../../../database' -import Controller from '../../../controller' -import Serializer from '../../../serializer' -import { FreezeableMap } from '../../../freezeable' +import { Model } from '@lux/packages/database' +import Controller from '@lux/packages/controller' +import Serializer from '@lux/packages/serializer' +import { FreezeableMap } from '@lux/packages/freezeable' import createParentBuilder from '../utils/create-parent-builder' describe('module "loader/builder"', () => { @@ -25,27 +25,31 @@ describe('module "loader/builder"', () => { parent: null, }) - return Reflect.construct(target, [{ - parent, - namespace, - serializer, - model: Model, - }]) + return Reflect.construct(target, [ + { + parent, + namespace, + serializer, + model: Model, + }, + ]) }) }) test('correctly builds parent objects', () => { - subject(new FreezeableMap([ - ['root', new FreezeableMap([ - ['application', ApplicationController] - ])], - ['api', new FreezeableMap([ - ['application', ApiApplicationController] - ])], - ['api/v1', new FreezeableMap([ - ['application', ApiV1ApplicationController] - ])] - ])).forEach(({ key, parent }) => { + subject( + new FreezeableMap([ + ['root', new FreezeableMap([['application', ApplicationController]])], + [ + 'api', + new FreezeableMap([['application', ApiApplicationController]]), + ], + [ + 'api/v1', + new FreezeableMap([['application', ApiV1ApplicationController]]), + ], + ]), + ).forEach(({ key, parent }) => { switch (key) { case 'root': expect(parent).toBeInstanceOf(ApplicationController) diff --git a/src/packages/loader/builder/__tests__/sort-by-namespace.test.js b/src/packages/loader/builder/__tests__/sort-by-namespace.test.js index 7fbcd84f..01b9a825 100644 --- a/src/packages/loader/builder/__tests__/sort-by-namespace.test.js +++ b/src/packages/loader/builder/__tests__/sort-by-namespace.test.js @@ -1,6 +1,6 @@ /* @flow */ -import { FreezeableMap } from '../../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import sortByNamespace from '../utils/sort-by-namespace' describe('module "loader/builder"', () => { @@ -8,7 +8,7 @@ describe('module "loader/builder"', () => { test('returns -1 if "root" is the first argument', () => { const result = sortByNamespace( ['root', new FreezeableMap()], - ['api', new FreezeableMap()] + ['api', new FreezeableMap()], ) expect(result).toBe(-1) @@ -17,7 +17,7 @@ describe('module "loader/builder"', () => { test('returns 1 if "root" is the second argument', () => { const result = sortByNamespace( ['api', new FreezeableMap()], - ['root', new FreezeableMap()] + ['root', new FreezeableMap()], ) expect(result).toBe(1) @@ -26,7 +26,7 @@ describe('module "loader/builder"', () => { test('returns -1 if the first argument is shorter than the second', () => { const result = sortByNamespace( ['api', new FreezeableMap()], - ['admin', new FreezeableMap()] + ['admin', new FreezeableMap()], ) expect(result).toBe(-1) @@ -35,7 +35,7 @@ describe('module "loader/builder"', () => { test('returns 1 if the first argument is longer than the second', () => { const result = sortByNamespace( ['admin', new FreezeableMap()], - ['api', new FreezeableMap()] + ['api', new FreezeableMap()], ) expect(result).toBe(1) diff --git a/src/packages/loader/builder/index.js b/src/packages/loader/builder/index.js index fd81fa51..1553b8c3 100644 --- a/src/packages/loader/builder/index.js +++ b/src/packages/loader/builder/index.js @@ -1,8 +1,8 @@ /* @flow */ -import { FreezeableMap } from '../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import { resolve } from '../resolver' -import chain from '../../../utils/chain' +import chain from '@lux/utils/chain' import type { Bundle$Namespace, Bundle$NamespaceGroup } from '../index' // eslint-disable-line max-len, no-unused-vars import createParentBuilder from './utils/create-parent-builder' @@ -14,7 +14,7 @@ import type { Builder$Construct } from './interfaces' */ export function build( group: Bundle$Namespace>, - construct: Builder$Construct + construct: Builder$Construct, ): Bundle$Namespace { return chain(group) .pipe(resolve) diff --git a/src/packages/loader/builder/interfaces.js b/src/packages/loader/builder/interfaces.js index e9c292cf..c24d2bf6 100644 --- a/src/packages/loader/builder/interfaces.js +++ b/src/packages/loader/builder/interfaces.js @@ -1,23 +1,23 @@ /* @flow */ -import type { Bundle$Namespace, Bundle$NamespaceGroup } from '../index'; +import type { Bundle$Namespace, Bundle$NamespaceGroup } from '../index' export type Builder$NamespaceMeta = { - key: string; - value: Bundle$Namespace>; - parent: ?T; -}; + key: string, + value: Bundle$Namespace>, + parent: ?T, +} export type Builder$ParentBuilder = ( - target: Bundle$NamespaceGroup> -) => Array>; + target: Bundle$NamespaceGroup>, +) => Array> export type Builder$ChildrenBuilder = ( - target: Array> -) => Array>; + target: Array>, +) => Array> export type Builder$Construct = ( key: string, value: Class, - parent: ?T -) => T; + parent: ?T, +) => T diff --git a/src/packages/loader/builder/utils/create-children-builder.js b/src/packages/loader/builder/utils/create-children-builder.js index 781a1d77..e0a333b2 100644 --- a/src/packages/loader/builder/utils/create-children-builder.js +++ b/src/packages/loader/builder/utils/create-children-builder.js @@ -3,25 +3,18 @@ import type { Builder$Construct, Builder$ChildrenBuilder } from '../interfaces' export default function createChildrenBuilder( - construct: Builder$Construct + construct: Builder$Construct, ): Builder$ChildrenBuilder { - return target => target.map(({ - key, - value, - parent - }) => [...value].map(([name, constructor]) => { - const normalized = key === 'root' ? name : `${key}/${name}` + return target => + target.map(({ key, value, parent }) => + [...value].map(([name, constructor]) => { + const normalized = key === 'root' ? name : `${key}/${name}` - if (parent && normalized.endsWith('application')) { - return [ - normalized, - parent - ] - } + if (parent && normalized.endsWith('application')) { + return [normalized, parent] + } - return [ - normalized, - construct(normalized, constructor, parent) - ] - })) + return [normalized, construct(normalized, constructor, parent)] + }), + ) } diff --git a/src/packages/loader/builder/utils/create-parent-builder.js b/src/packages/loader/builder/utils/create-parent-builder.js index 082649f2..52dc1b60 100644 --- a/src/packages/loader/builder/utils/create-parent-builder.js +++ b/src/packages/loader/builder/utils/create-parent-builder.js @@ -7,12 +7,10 @@ import type { Builder$Construct, Builder$ParentBuilder } from '../interfaces' import sortByNamespace from './sort-by-namespace' export default function createParentBuilder( - construct: Builder$Construct + construct: Builder$Construct, ): Builder$ParentBuilder { - return target => Array - .from(target) - .sort(sortByNamespace) - .reduce((result, [key, value]) => { + return target => + Array.from(target).sort(sortByNamespace).reduce((result, [key, value]) => { let parent = value.get('application') || null if (parent) { @@ -37,10 +35,13 @@ export default function createParentBuilder( parent = construct(`${key}/application`, parent, grandparent) } - return [...result, { - key, - value, - parent - }] + return [ + ...result, + { + key, + value, + parent, + }, + ] }, []) } diff --git a/src/packages/loader/builder/utils/sort-by-namespace.js b/src/packages/loader/builder/utils/sort-by-namespace.js index d45ea965..cb342b2f 100644 --- a/src/packages/loader/builder/utils/sort-by-namespace.js +++ b/src/packages/loader/builder/utils/sort-by-namespace.js @@ -7,7 +7,7 @@ import type { Bundle$Namespace } from '../../index' */ export default function sortByNamespace( [a]: [string, Bundle$Namespace], - [b]: [string, Bundle$Namespace] + [b]: [string, Bundle$Namespace], ): number { if (a === 'root') { return -1 diff --git a/src/packages/loader/index.js b/src/packages/loader/index.js index 3ea07309..b110494f 100644 --- a/src/packages/loader/index.js +++ b/src/packages/loader/index.js @@ -24,5 +24,5 @@ export { closestAncestor, closestChild } from './resolver' export type { Loader, Bundle$Namespace, - Bundle$NamespaceGroup + Bundle$NamespaceGroup, } from './interfaces' diff --git a/src/packages/loader/interfaces.js b/src/packages/loader/interfaces.js index 2bad9f89..53204da8 100644 --- a/src/packages/loader/interfaces.js +++ b/src/packages/loader/interfaces.js @@ -1,13 +1,10 @@ /* @flow */ -import type Controller from '../controller'; -import type Serializer from '../serializer'; -import type { Model } from '../database'; -import type { FreezeableMap } from '../freezeable'; +import type { FreezeableMap } from '@lux/packages/freezeable' -export type Loader = (type: string) => any; -export type Bundle$Namespace = FreezeableMap; +export type Loader = (type: string) => any +export type Bundle$Namespace = FreezeableMap export type Bundle$NamespaceGroup = FreezeableMap< string, - Bundle$Namespace ->; + Bundle$Namespace, +> diff --git a/src/packages/loader/resolver/index.js b/src/packages/loader/resolver/index.js index ff80e146..88019189 100644 --- a/src/packages/loader/resolver/index.js +++ b/src/packages/loader/resolver/index.js @@ -1,16 +1,15 @@ /* @flow */ -import { FreezeableMap } from '../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import type { Bundle$Namespace, Bundle$NamespaceGroup } from '../index' /** * @private */ export function resolve( - group: Bundle$Namespace + group: Bundle$Namespace, ): Bundle$NamespaceGroup { - return Array - .from(group) + return Array.from(group) .map(([key, value]) => { let namespace = key.split('/') @@ -19,18 +18,10 @@ export function resolve( .join('/') if (namespace) { - return [ - key.substr(namespace.length + 1), - value, - namespace - ] + return [key.substr(namespace.length + 1), value, namespace] } - return [ - key, - value, - 'root' - ] + return [key, value, 'root'] }) .reduce((map, [key, value, namespace]) => { let nsValue = map.get(namespace) diff --git a/src/packages/loader/resolver/utils/closest-ancestor.js b/src/packages/loader/resolver/utils/closest-ancestor.js index c06f41d4..bb232084 100644 --- a/src/packages/loader/resolver/utils/closest-ancestor.js +++ b/src/packages/loader/resolver/utils/closest-ancestor.js @@ -6,7 +6,7 @@ import type { Bundle$Namespace } from '../../index' export default function closestAncestor( source: Bundle$Namespace, - key: string + key: string, ): void | T { const name = posix.basename(key) let namespace = posix.dirname(key) @@ -23,8 +23,5 @@ export default function closestAncestor( return ancestor } - return closestAncestor( - source, - posix.join(posix.dirname(namespace), name) - ) + return closestAncestor(source, posix.join(posix.dirname(namespace), name)) } diff --git a/src/packages/loader/resolver/utils/closest-child.js b/src/packages/loader/resolver/utils/closest-child.js index 70a2d464..08a7ba31 100644 --- a/src/packages/loader/resolver/utils/closest-child.js +++ b/src/packages/loader/resolver/utils/closest-child.js @@ -6,10 +6,9 @@ import type { Bundle$Namespace } from '../../index' export default function closestChild( source: Bundle$Namespace, - key: string + key: string, ): void | T { - const [[, result] = []] = Array - .from(source) + const [[, result] = []] = Array.from(source) .map(([path, value]) => [posix.basename(path), value]) .filter(([resource]) => key === resource) diff --git a/src/packages/loader/utils/bundle-for.js b/src/packages/loader/utils/bundle-for.js index 58b914c4..63656f3b 100644 --- a/src/packages/loader/utils/bundle-for.js +++ b/src/packages/loader/utils/bundle-for.js @@ -2,12 +2,12 @@ import { join as joinPath } from 'path' -import { Migration } from '../../database' -import { FreezeableMap } from '../../freezeable' -import { createDefaultConfig } from '../../config' -import merge from '../../../utils/merge' -import chain from '../../../utils/chain' -import entries from '../../../utils/entries' +import { Migration } from '@lux/packages/database' +import { FreezeableMap } from '@lux/packages/freezeable' +import { createDefaultConfig } from '@lux/packages/config' +import merge from '@lux/utils/merge' +import chain from '@lux/utils/chain' +import { isObject } from '@lux/utils/is-type' import formatKey from './format-key' @@ -17,69 +17,76 @@ const SUFFIX_PATTERN = /^.+(Controller|Down|Serializer|Up)/ * @private */ function normalize(manifest: Object) { - return entries(manifest).reduce((obj, [key, value]) => { - if (SUFFIX_PATTERN.test(key)) { - const suffix = key.replace(SUFFIX_PATTERN, '$1') - const stripSuffix = source => source.replace(suffix, '') - - switch (suffix) { - case 'Controller': - obj.controllers.set(formatKey(key, stripSuffix), value) - break - - case 'Serializer': - obj.serializers.set(formatKey(key, stripSuffix), value) - break - - case 'Up': - case 'Down': - obj.migrations.set( - formatKey(key), - Reflect.construct(Migration, [value]) - ) - break - - default: - break - } - } else { - switch (key) { - case 'Application': - case 'routes': - case 'seed': - Reflect.set(obj, formatKey(key), value) - break - - case 'config': - Reflect.set(obj, 'config', { - ...merge(createDefaultConfig(), { + return Object.entries(manifest).reduce( + (obj, [key, value]) => { + if (SUFFIX_PATTERN.test(key)) { + const suffix = key.replace(SUFFIX_PATTERN, '$1') + const stripSuffix = source => source.replace(suffix, '') + + switch (suffix) { + case 'Controller': + obj.controllers.set(formatKey(key, stripSuffix), value) + break + + case 'Serializer': + obj.serializers.set(formatKey(key, stripSuffix), value) + break + + case 'Up': + case 'Down': + obj.migrations.set( + formatKey(key), + Reflect.construct(Migration, [value]), + ) + break + + default: + break + } + } else { + switch (key) { + case 'Application': + case 'routes': + case 'seed': + Reflect.set(obj, formatKey(key), value) + break + + case 'config': { + if (isObject(value)) { + Reflect.set(obj, 'config', { + ...merge(createDefaultConfig(), { + ...obj.config, + ...value, + }), + }) + } + + break + } + + case 'database': + Reflect.set(obj, 'config', { ...obj.config, - ...value + database: value, }) - }) - break - - case 'database': - Reflect.set(obj, 'config', { - ...obj.config, - database: value - }) - break - - default: - obj.models.set(formatKey(key), value) - break + break + + default: + obj.models.set(formatKey(key), value) + break + } } - } - - return obj - }, { - config: {}, - controllers: new FreezeableMap(), - migrations: new FreezeableMap(), - models: new FreezeableMap(), - serializers: new FreezeableMap() - }) + + return obj + }, + { + config: {}, + controllers: new FreezeableMap(), + migrations: new FreezeableMap(), + models: new FreezeableMap(), + serializers: new FreezeableMap(), + }, + ) } /** @@ -87,12 +94,12 @@ function normalize(manifest: Object) { */ export default function bundleFor(path: string): FreezeableMap { const manifest: Object = Reflect.apply(require, null, [ - joinPath(path, 'dist', 'bundle') + joinPath(path, 'dist', 'bundle'), ]) return chain(manifest) .pipe(normalize) - .pipe(entries) + .pipe(Object.entries) .construct(FreezeableMap) .value() .freeze() diff --git a/src/packages/loader/utils/format-key.js b/src/packages/loader/utils/format-key.js index faea69ad..79e3154c 100644 --- a/src/packages/loader/utils/format-key.js +++ b/src/packages/loader/utils/format-key.js @@ -2,8 +2,8 @@ import { dasherize } from 'inflection' -import chain from '../../../utils/chain' -import underscore from '../../../utils/underscore' +import chain from '@lux/utils/chain' +import underscore from '@lux/utils/underscore' const NAMESPACE_DELIMITER = /\$-/g @@ -12,7 +12,7 @@ const NAMESPACE_DELIMITER = /\$-/g */ export default function formatKey( key: string, - formatter?: (source: string) => string + formatter?: (source: string) => string, ) { return chain(key) .pipe(str => { diff --git a/src/packages/logger/__tests__/filter-params.test.js b/src/packages/logger/__tests__/filter-params.test.js index 1845e12c..4d676556 100644 --- a/src/packages/logger/__tests__/filter-params.test.js +++ b/src/packages/logger/__tests__/filter-params.test.js @@ -7,13 +7,10 @@ describe('module "logger"', () => { const params = { id: 1, username: 'test', - password: 'test' + password: 'test', } - const filter = [ - 'username', - 'password' - ] + const filter = ['username', 'password'] test('replaces the value of filtered params', () => { expect(filterParams(params, ...filter)).toMatchSnapshot() diff --git a/src/packages/logger/__tests__/logger.test.js b/src/packages/logger/__tests__/logger.test.js index 8b4ae167..1dc7ec21 100644 --- a/src/packages/logger/__tests__/logger.test.js +++ b/src/packages/logger/__tests__/logger.test.js @@ -8,11 +8,7 @@ function isLoggerData(ln: string) { try { const data = JSON.parse(ln) - return ( - data.timestamp - && data.message - && data.level - ) + return data.timestamp && data.message && data.level } catch (ex) { return false } @@ -26,15 +22,18 @@ function hookWrite(cb) { if (isLoggerData(...args)) { Reflect.apply(cb, null, args) } - }; + } - // Class methods are read-only in flow, cast to Object to intercept - (process.stdout: Object).write = cbWrapper; - (process.stderr: Object).write = cbWrapper + // $FlowFixMe + process.stdout.write = cbWrapper + // $FlowFixMe + process.stderr.write = cbWrapper return function reset() { - (process.stdout: Object).write = oldStdoutWrite; - (process.stderr: Object).write = oldStderrorWrite + // $FlowFixMe + process.stdout.write = oldStdoutWrite + // $FlowFixMe + process.stderr.write = oldStderrorWrite } } @@ -49,7 +48,7 @@ describe('module "logger"', () => { level: 'INFO', format: 'json', enabled: true, - filter: { params: [] } + filter: { params: [] }, } jsonLogger = new Logger(baseConfig) const disabledConfig = Object.assign({}, baseConfig, { enabled: false }) @@ -63,7 +62,7 @@ describe('module "logger"', () => { } }) - test('writes to stdout at the logger level', (done) => { + test('writes to stdout at the logger level', done => { unhookWrite = hookWrite(ln => { const { message, level } = JSON.parse(ln) expect(message).toBe(TEST_MESSAGE) @@ -73,7 +72,7 @@ describe('module "logger"', () => { jsonLogger.info(TEST_MESSAGE) }) - test('does write messages above the logger level', (done) => { + test('does write messages above the logger level', done => { unhookWrite = hookWrite(ln => { const { message, level } = JSON.parse(ln) expect(message).toBe(TEST_MESSAGE) @@ -83,7 +82,7 @@ describe('module "logger"', () => { jsonLogger.warn(TEST_MESSAGE) }) - test('does not write messages below the logger level', (done) => { + test('does not write messages below the logger level', done => { unhookWrite = hookWrite(() => { done(new Error('Should not log message of lower level.')) }) @@ -91,7 +90,7 @@ describe('module "logger"', () => { setTimeout(() => done(), 50) }) - test('writes with a recent timestamp', (done) => { + test('writes with a recent timestamp', done => { const oldTimestamp = Date.now() unhookWrite = hookWrite(ln => { const { timestamp } = JSON.parse(ln) @@ -101,7 +100,7 @@ describe('module "logger"', () => { jsonLogger.info(TEST_MESSAGE) }) - test('writes json', (done) => { + test('writes json', done => { unhookWrite = hookWrite(ln => { const trimmed = ln.trim() @@ -111,7 +110,7 @@ describe('module "logger"', () => { jsonLogger.info(TEST_MESSAGE) }) - test('does not write when disabled', (done) => { + test('does not write when disabled', done => { unhookWrite = hookWrite(() => { done(new Error('Logger should not write when disabled')) }) @@ -122,12 +121,14 @@ describe('module "logger"', () => { describe('#line()', () => { test('returns a single line string from a multi-line string', () => { - expect(line` + expect( + line` this is a test - `).toBe('this is a test') + `, + ).toBe('this is a test') }) }) }) diff --git a/src/packages/logger/__tests__/request-logger.test.js b/src/packages/logger/__tests__/request-logger.test.js index 47b3e4c9..77337f08 100644 --- a/src/packages/logger/__tests__/request-logger.test.js +++ b/src/packages/logger/__tests__/request-logger.test.js @@ -4,14 +4,7 @@ import { FORMATS } from '../constants' import { createRequestLogger } from '../request-logger' import Logger from '../index' -const { - stdout: { - write: writeOut, - }, - stderr: { - write: writeErr, - }, -} = process +const { stdout: { write: writeOut }, stderr: { write: writeErr } } = process describe('module "logger/request-logger"', () => { describe('#createRequestLogger()', () => { @@ -35,8 +28,8 @@ describe('module "logger/request-logger"', () => { level: 'INFO', enabled: true, filter: { - params: [] - } + params: [], + }, }) subject = createRequestLogger(logger) @@ -52,7 +45,7 @@ describe('module "logger/request-logger"', () => { expect(() => { // subject(req, res, { // startTime: Date.now() - // }); + // }) }).not.toThrow() }) }) diff --git a/src/packages/logger/__tests__/writer.test.js b/src/packages/logger/__tests__/writer.test.js index 66c7da65..788f63e2 100644 --- a/src/packages/logger/__tests__/writer.test.js +++ b/src/packages/logger/__tests__/writer.test.js @@ -1,16 +1,9 @@ /* @flow */ import { WARN, ERROR, LEVELS, FORMATS } from '../constants' -import { createWriter } from '../writer' +import * as writer from '../writer' -const { - stdout: { - write: writeOut, - }, - stderr: { - write: writeErr, - }, -} = process +const { stdout: { write: writeOut }, stderr: { write: writeErr } } = process describe('module "logger/writer"', () => { describe('#createWriter()', () => { @@ -29,7 +22,7 @@ describe('module "logger/writer"', () => { let subject beforeAll(() => { - subject = createWriter(format) + subject = writer.create(format) }) LEVELS.forEach((num, level) => { diff --git a/src/packages/logger/constants.js b/src/packages/logger/constants.js index e0fe02fc..898da815 100644 --- a/src/packages/logger/constants.js +++ b/src/packages/logger/constants.js @@ -1,6 +1,6 @@ /* @flow */ -import { FreezeableMap, FreezeableSet } from '../freezeable' +import { FreezeableMap, FreezeableSet } from '@lux/packages/freezeable' import type { Level, Format } from './index' @@ -9,19 +9,18 @@ export const INFO = 'INFO' export const WARN = 'WARN' export const ERROR = 'ERROR' -export const FORMATS: FreezeableSet = ( - new FreezeableSet(['text', 'json']) -) +export const FORMATS: FreezeableSet = new FreezeableSet([ + 'text', + 'json', +]) FORMATS.freeze() -export const LEVELS: FreezeableMap = ( - new FreezeableMap([ - [DEBUG, 0], - [INFO, 1], - [WARN, 2], - [ERROR, 3], - ]) -) +export const LEVELS: FreezeableMap = new FreezeableMap([ + [DEBUG, 0], + [INFO, 1], + [WARN, 2], + [ERROR, 3], +]) LEVELS.freeze() diff --git a/src/packages/logger/index.js b/src/packages/logger/index.js index d8bb0a8b..f4cbe34f 100644 --- a/src/packages/logger/index.js +++ b/src/packages/logger/index.js @@ -1,31 +1,27 @@ /* @flow */ -import { LUX_CONSOLE } from '../../constants' -import K from '../../utils/k' +import { LUX_CONSOLE } from '@lux/constants' +import K from '@lux/utils/k' import { LEVELS } from './constants' -import { createWriter } from './writer' +import * as writer from './writer' import { createRequestLogger } from './request-logger' import type { RequestLogger } from './request-logger' export type Format = 'text' | 'json' export type LogFunction = (data: string | Object) => void -export type Level = - | 'DEBUG' - | 'INFO' - | 'WARN' - | 'ERROR' +export type Level = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' export type Filter = { - params: Array; + params: Array, } export type Config = { - level: Level; - format: Format; - filter: Filter; - enabled: boolean; + level: Level, + format: Format, + filter: Filter, + enabled: boolean, } /** @@ -40,7 +36,7 @@ class Logger { * @type {String} * @public */ - level: Level; + level: Level /** * The output format of log data (text or json). @@ -49,7 +45,7 @@ class Logger { * @type {String} * @public */ - format: Format; + format: Format /** * Hackers love logs. It's easy to get sensitive user information from log @@ -68,7 +64,7 @@ class Logger { * params: ['password'] * } * } - * }; + * } * ``` * * Now that we've added password to the array of parameters we want to filter @@ -120,7 +116,7 @@ class Logger { * @type {Object} * @public */ - filter: Filter; + filter: Filter /** * A boolean flag that determines whether or not the logger is enabled. @@ -129,13 +125,13 @@ class Logger { * @type {Boolean} * @public */ - enabled: boolean; + enabled: boolean /** * Log a message at the DEBUG level. * * ```javascript - * logger.debug('Hello World!'); + * logger.debug('Hello World!') * // => [6/4/16 5:46:53 PM] Hello World! * ``` * @@ -144,13 +140,13 @@ class Logger { * @return {void} * @public */ - debug: LogFunction; + debug: LogFunction /** * Log a message at the INFO level. * * ```javascript - * logger.info('Hello World!'); + * logger.info('Hello World!') * // => [6/4/16 5:46:53 PM] Hello World! * ``` * @@ -159,13 +155,13 @@ class Logger { * @return {void} * @public */ - info: LogFunction; + info: LogFunction /** * Log a message at the WARN level. * * ```javascript - * logger.warn('Good Bye World!'); + * logger.warn('Good Bye World!') * // => [6/4/16 5:46:53 PM] Good Bye World! * ``` * @@ -174,13 +170,13 @@ class Logger { * @return {void} * @public */ - warn: LogFunction; + warn: LogFunction /** * Log a message at the ERROR level. * * ```javascript - * logger.warn('HELP!'); + * logger.warn('HELP!') * // => [6/4/16 5:46:53 PM] HELP! * ``` * @@ -189,7 +185,7 @@ class Logger { * @return {void} * @public */ - error: LogFunction; + error: LogFunction /** * Internal method used for logging requests. @@ -203,14 +199,15 @@ class Logger { * @return {void} * @private */ - request: RequestLogger; + request: RequestLogger constructor({ level, format, filter, enabled }: Config) { - let write = K + const mockWrite = writer.mock() + let write = mockWrite let request = K if (!LUX_CONSOLE && enabled) { - write = createWriter(format) + write = writer.create(format) request = createRequestLogger(this) } @@ -219,60 +216,53 @@ class Logger { value: level, writable: false, enumerable: true, - configurable: false + configurable: false, }, format: { value: format, writable: false, enumerable: true, - configurable: false + configurable: false, }, filter: { value: filter, writable: false, enumerable: true, - configurable: false + configurable: false, }, enabled: { value: Boolean(enabled), writable: false, enumerable: true, - configurable: false + configurable: false, }, request: { value: request, writable: false, enumerable: false, - configurable: false - } + configurable: false, + }, }) const levelNum = LEVELS.get(level) || 0 LEVELS.forEach((val, key) => { Object.defineProperty(this, key.toLowerCase(), { - value: val >= levelNum ? (message: void | ?mixed) => { - write({ - message, - level: key, - timestamp: this.getTimestamp() - }) - } : K, + value: val >= levelNum + ? (message: void | ?mixed) => { + write({ + message, + level: key, + timestamp: new Date().toISOString(), + }) + } + : mockWrite, writable: false, enumerable: false, configurable: false, }) }) } - - /** - * @method getTimestamp - * @return {String} The current time as an ISO8601 string. - * @private - */ - getTimestamp() { - return new Date().toISOString() - } } export default Logger diff --git a/src/packages/logger/request-logger/index.js b/src/packages/logger/request-logger/index.js index 427e377e..fb10130c 100644 --- a/src/packages/logger/request-logger/index.js +++ b/src/packages/logger/request-logger/index.js @@ -1,7 +1,7 @@ /* @flow */ -import type Request from '../../request' -import type Response from '../../response' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import type Logger from '../index' import logText from './utils/log-text' @@ -11,8 +11,8 @@ export type RequestLogger = ( req: Request, res: Response, options: { - startTime: number; - } + startTime: number, + }, ) => void /** @@ -24,13 +24,13 @@ export function createRequestLogger(logger: Logger): RequestLogger { logJSON(logger, { startTime, request: req, - response: res + response: res, }) } else { logText(logger, { startTime, request: req, - response: res + response: res, }) } } diff --git a/src/packages/logger/request-logger/interfaces.js b/src/packages/logger/request-logger/interfaces.js index f3654379..f3cb7371 100644 --- a/src/packages/logger/request-logger/interfaces.js +++ b/src/packages/logger/request-logger/interfaces.js @@ -1,16 +1,14 @@ /* @flow */ -import type { Route } from '../../router'; - export type RequestLogger$templateData = { - path: string; - stats: Array; - method: string; - params: any; - startTime: number; - endTime: number; - statusCode: string; - statusMessage: string; - remoteAddress: string; - colorStr(source: string): string; -}; + path: string, + stats: Array, + method: string, + params: any, + startTime: number, + endTime: number, + statusCode: string, + statusMessage: string, + remoteAddress: string, + colorStr(source: string): string, +} diff --git a/src/packages/logger/request-logger/templates.js b/src/packages/logger/request-logger/templates.js index 8f8bac1a..b4a0ab5f 100644 --- a/src/packages/logger/request-logger/templates.js +++ b/src/packages/logger/request-logger/templates.js @@ -36,16 +36,14 @@ export const debugTemplate = ({ endTime, statusCode, statusMessage, - remoteAddress + remoteAddress, }: any) => `\ ${line` Processed ${cyan(`${method}`)} "${path}" from ${remoteAddress} with ${Reflect.apply(colorStr, null, [`${statusCode}`])} - ${Reflect.apply(colorStr, null, [`${statusMessage}`])} by ${ - route - ? `${yellow(route.controller.constructor.name)}#${blue(route.action)}` - : null - } + ${Reflect.apply(colorStr, null, [`${statusMessage}`])} by ${route + ? `${yellow(route.controller.constructor.name)}#${blue(route.action)}` + : null} `} ${magenta('Params')} @@ -54,23 +52,27 @@ ${JSON.stringify(params, null, 2)} ${magenta('Stats')} -${stats.map(stat => { - const { type, duration, controller } = stat - let { name } = stat +${stats + .map(stat => { + const { type, duration, controller } = stat + let { name } = stat - name = blue(name) + name = blue(name) - if (type === 'action') { - name = `${yellow(controller)}#${name}` - } + if (type === 'action') { + name = `${yellow(controller)}#${name}` + } - return `${pad(startTime, endTime, duration)} ms ${name}` -}).join('\n')} -${pad(startTime, - endTime, - stats.reduce((total, { duration }) => total + duration, 0))} ms Total + return `${pad(startTime, endTime, duration)} ms ${name}` + }) + .join('\n')} +${pad( + startTime, + endTime, + stats.reduce((total, { duration }) => total + duration, 0), +)} ms Total ${(endTime - startTime).toString()} ms Actual\ -` + ` /** * @private @@ -84,13 +86,12 @@ export const infoTemplate = ({ endTime, statusCode, statusMessage, - remoteAddress + remoteAddress, }: any) => line` -Processed ${cyan(`${method}`)} "${path}" ${magenta('Params')} ${ - JSON.stringify(params)} from ${remoteAddress -} in ${(endTime - startTime).toString()} ms with ${ - Reflect.apply(colorStr, null, [`${statusCode}`]) -} ${ - Reflect.apply(colorStr, null, [`${statusMessage}`]) -} -` +Processed ${cyan(`${method}`)} "${path}" ${magenta('Params')} ${JSON.stringify( + params, +)} from ${remoteAddress} in ${(endTime - + startTime).toString()} ms with ${Reflect.apply(colorStr, null, [ + `${statusCode}`, +])} ${Reflect.apply(colorStr, null, [`${statusMessage}`])} + ` diff --git a/src/packages/logger/request-logger/utils/filter-params.js b/src/packages/logger/request-logger/utils/filter-params.js index 33780eb4..14b78d69 100644 --- a/src/packages/logger/request-logger/utils/filter-params.js +++ b/src/packages/logger/request-logger/utils/filter-params.js @@ -1,7 +1,5 @@ /* @flow */ -import entries from '../../../../utils/entries' - /** * @private */ @@ -9,15 +7,18 @@ export default function filterParams( params: Object, ...filtered: Array ): Object { - return entries(params) + return Object.entries(params) .map(([key, value]) => [ key, - filtered.indexOf(key) >= 0 ? '[FILTERED]' : value + filtered.indexOf(key) >= 0 ? '[FILTERED]' : value, ]) - .reduce((result, [key, value]) => ({ - ...result, - [key]: value && typeof value === 'object' && !Array.isArray(value) - ? filterParams(value, ...filtered) - : value - }), {}) + .reduce( + (result, [key, value]) => ({ + ...result, + [key]: value && typeof value === 'object' && !Array.isArray(value) + ? filterParams(value, ...filtered) + : value, + }), + {}, + ) } diff --git a/src/packages/logger/request-logger/utils/log-json.js b/src/packages/logger/request-logger/utils/log-json.js index 58d6b4f7..0d8e9b75 100644 --- a/src/packages/logger/request-logger/utils/log-json.js +++ b/src/packages/logger/request-logger/utils/log-json.js @@ -1,16 +1,16 @@ /* @flow */ import type Logger from '../../index' -import type Request from '../../../request' -import type Response from '../../../response' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import filterParams from './filter-params' const MESSAGE = 'Processed Request' type Options = { - request: Request; - response: Response; + request: Request, + response: Response, } /** @@ -35,6 +35,6 @@ export default function logJSON(logger: Logger, options: Options): void { status, protocol, userAgent, - remoteAddress: '::1' + remoteAddress: '::1', }) } diff --git a/src/packages/logger/request-logger/utils/log-text.js b/src/packages/logger/request-logger/utils/log-text.js index 93464222..6b27f932 100644 --- a/src/packages/logger/request-logger/utils/log-text.js +++ b/src/packages/logger/request-logger/utils/log-text.js @@ -5,15 +5,15 @@ import chalk from 'chalk' import { DEBUG } from '../../constants' import { infoTemplate, debugTemplate } from '../templates' import type Logger from '../../index' -import type Request from '../../../request' -import type Response from '../../../response' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import filterParams from './filter-params' type Options = { - request: Request; - response: Response; - startTime: number; + request: Request, + response: Response, + startTime: number, } /** @@ -54,7 +54,7 @@ export default function logText(logger: Logger, options: Options): void { endTime, statusCode, statusMessage, - remoteAddress: '::1' + remoteAddress: '::1', } if (logger.level === DEBUG) { diff --git a/src/packages/logger/utils/line.js b/src/packages/logger/utils/line.js index e277e1cb..13ca81e2 100644 --- a/src/packages/logger/utils/line.js +++ b/src/packages/logger/utils/line.js @@ -1,6 +1,6 @@ /* @flow */ -import { insertValues } from '../../template' +import { insertValues } from '@lux/packages/template' /** * @private diff --git a/src/packages/logger/utils/sql.js b/src/packages/logger/utils/sql.js index 410a990e..e275d146 100644 --- a/src/packages/logger/utils/sql.js +++ b/src/packages/logger/utils/sql.js @@ -1,6 +1,6 @@ /* @flow */ -import { insertValues } from '../../template' +import { insertValues } from '@lux/packages/template' const PATTERN = /(?:,?`|'|").+(?:`|'|"),?/ diff --git a/src/packages/logger/writer/index.js b/src/packages/logger/writer/index.js index 1d948ee8..a9f4b6dd 100644 --- a/src/packages/logger/writer/index.js +++ b/src/packages/logger/writer/index.js @@ -5,71 +5,70 @@ import { WriteStream } from 'tty' import { dim, red, yellow } from 'chalk' import { WARN, ERROR } from '../constants' -import omit from '../../../utils/omit' +import omit from '@lux/utils/omit' import type { Format } from '../index' import { STDOUT, STDERR } from './constants' import formatMessage from './utils/format-message' -/** - * @private - */ -export function createWriter(format: Format): (data: any) => void { - return function write(data) { - const { level, ...etc } = data - let { message, timestamp } = etc - let output - - if (format === 'json') { - output = {} - - if (message && typeof message === 'object' && message.message) { - output = { - timestamp, - level, - message: message.message, - ...omit(message, 'message') - } - } else { - output = { - timestamp, - level, - message, - ...etc - } - } +export type Writer = (data: any) => void - output = formatMessage(output, 'json') - } else { - let columns = 0 +export const mock = (): Writer => () => undefined + +export const create = (format: Format): Writer => data => { + const { level, ...etc } = data + let { message, timestamp } = etc + let output + + if (format === 'json') { + output = {} - if (process.stdout instanceof WriteStream) { - columns = process.stdout.columns + if (message && typeof message === 'object' && message.message) { + output = { + timestamp, + level, + message: message.message, + ...omit(message, 'message'), } + } else { + output = { + timestamp, + level, + message, + ...etc, + } + } - message = formatMessage(message, 'text') + output = formatMessage(output, 'json') + } else { + let columns = 0 - switch (level) { - case WARN: - timestamp = yellow(`[${timestamp}]`) - break + if (process.stdout instanceof WriteStream) { + columns = process.stdout.columns + } - case ERROR: - timestamp = red(`[${timestamp}]`) - break + message = formatMessage(message, 'text') - default: - timestamp = dim(`[${timestamp}]`) - break - } + switch (level) { + case WARN: + timestamp = yellow(`[${timestamp}]`) + break - output = `${timestamp} ${message}\n\n${dim('-').repeat(columns)}\n` - } + case ERROR: + timestamp = red(`[${timestamp}]`) + break - if (STDOUT.test(level)) { - process.stdout.write(`${output}\n`) - } else if (STDERR.test(level)) { - process.stderr.write(`${output}\n`) + default: + timestamp = dim(`[${timestamp}]`) + break } + + output = `${timestamp} ${message}\n\n${dim('-').repeat(columns)}\n` + } + + if (STDOUT.test(level)) { + process.stdout.write(`${output}\n`) + } else if (STDERR.test(level)) { + process.stderr.write(`${output}\n`) } } diff --git a/src/packages/logger/writer/utils/format-message.js b/src/packages/logger/writer/utils/format-message.js index 704fd736..b77eb002 100644 --- a/src/packages/logger/writer/utils/format-message.js +++ b/src/packages/logger/writer/utils/format-message.js @@ -1,7 +1,7 @@ /* @flow */ import { ANSI } from '../constants' -import stringify from '../../../../utils/stringify' +import stringify from '@lux/utils/stringify' import type { Format } from '../../index' export default function formatMessage(data?: ?mixed, format: Format): string { diff --git a/src/packages/luxify/__tests__/luxify.test.js b/src/packages/luxify/__tests__/luxify.test.js index 3e4c5511..a77415c0 100644 --- a/src/packages/luxify/__tests__/luxify.test.js +++ b/src/packages/luxify/__tests__/luxify.test.js @@ -1,19 +1,18 @@ /* @flow */ import luxify from '../index' -import K from '../../../utils/k' -import setType from '../../../utils/set-type' +import noop from '@lux/utils/noop' describe('module "luxify"', () => { describe('#luxify()', () => { - const [request, response] = setType(() => [ + const [request, response]: any = [ {}, { - getHeader: K, - setHeader: K, - removeHeader: K - } - ]) + getHeader: noop, + setHeader: noop, + removeHeader: noop, + }, + ] test('promisifies a callback based middleware function', () => { const subject = luxify((req, res, next) => { @@ -45,14 +44,16 @@ describe('module "luxify"', () => { test('resolves when Response#json is called', () => { const subject = luxify((req, res) => { - Reflect.apply(Reflect.get(res, 'json'), res, [{ - data: 'Hello world!' - }]) + Reflect.apply(Reflect.get(res, 'json'), res, [ + { + data: 'Hello world!', + }, + ]) }) return subject(request, response).then(data => { expect(data).toEqual({ - data: 'Hello world!' + data: 'Hello world!', }) }) }) diff --git a/src/packages/luxify/index.js b/src/packages/luxify/index.js index 4da8381e..b6f34115 100644 --- a/src/packages/luxify/index.js +++ b/src/packages/luxify/index.js @@ -1,8 +1,8 @@ /* @flow */ -import type { Action } from '../router' -import type Request from '../request' -import type Response from '../response' +import type { Action } from '@lux/packages/router' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import createResponseProxy from './utils/create-response-proxy' @@ -18,28 +18,25 @@ export default function luxify( middleware: ( req: Request, res: Response, - next: (err?: Error) => void - ) => void + next: (err?: Error) => void, + ) => void, ): Action { - const result = function (req, res) { // eslint-disable-line func-names - return new Promise((resolve, reject) => { - Reflect.apply(middleware, null, [ + const result = (req, res) => + new Promise((resolve, reject) => { + middleware.apply(null, [ req, createResponseProxy(res, resolve), - (err) => { + err => { if (err && err instanceof Error) { reject(err) } else { resolve() } - } + }, ]) }) - } - Reflect.defineProperty(result, 'name', { - value: middleware.name + return Object.defineProperty(result, 'name', { + value: middleware.name, }) - - return result } diff --git a/src/packages/luxify/utils/create-response-proxy.js b/src/packages/luxify/utils/create-response-proxy.js index 2c032145..875171e8 100644 --- a/src/packages/luxify/utils/create-response-proxy.js +++ b/src/packages/luxify/utils/create-response-proxy.js @@ -1,6 +1,6 @@ /* @flow */ -import type Response from '../../response' +import type Response from '@lux/packages/response' /** * Create a Proxy that will trap typical node middleware callback invocations @@ -10,7 +10,7 @@ import type Response from '../../response' */ export default function createResponseProxy( res: Response, - resolve: (result: mixed) => void + resolve: (result: mixed) => void, ): Response { return new Proxy(res, { get(target, key) { @@ -23,6 +23,6 @@ export default function createResponseProxy( default: return Reflect.get(target, key) } - } + }, }) } diff --git a/src/packages/pm/cluster/index.js b/src/packages/pm/cluster/index.js index d67f3b42..a7553ffc 100644 --- a/src/packages/pm/cluster/index.js +++ b/src/packages/pm/cluster/index.js @@ -7,43 +7,42 @@ import EventEmitter from 'events' import { red, green } from 'chalk' -import { NODE_ENV } from '../../../constants' -import { line } from '../../logger' -import omit from '../../../utils/omit' -import range from '../../../utils/range' -import { composeAsync } from '../../../utils/compose' -// eslint-disable-next-line no-duplicate-imports -import type Logger from '../../logger' +import { NODE_ENV } from '@lux/constants' +import { line } from '@lux/packages/logger' +import omit from '@lux/utils/omit' +import range from '@lux/utils/range' +import { composeAsync } from '@lux/utils/compose' +import type Logger from '@lux/packages/logger' export type Worker = EventEmitter & { - id: string; - process: Process; - suicide: boolean; - kill(signal?: string): void; - send(message: any): void; - disconnect(): void; + id: string, + process: Process, + suicide: boolean, + kill(signal?: string): void, + send(message: any): void, + disconnect(): void, } export type Options = { - path: string; - port: number; - logger: Logger; - maxWorkers?: number; + path: string, + port: number, + logger: Logger, + maxWorkers?: number, } /** * @private */ class Cluster extends EventEmitter { - path: string; + path: string - port: number; + port: number - logger: Logger; + logger: Logger - workers: Set; + workers: Set - maxWorkers: number; + maxWorkers: number constructor(options: Options) { super() @@ -53,39 +52,39 @@ class Cluster extends EventEmitter { value: options.path, writable: false, enumerable: true, - configurable: false + configurable: false, }, port: { value: options.port, writable: false, enumerable: true, - configurable: false + configurable: false, }, logger: { value: options.logger, writable: false, enumerable: true, - configurable: false + configurable: false, }, workers: { value: new Set(), writable: false, enumerable: true, - configurable: false + configurable: false, }, maxWorkers: { value: options.maxWorkers || os.cpus().length, writable: false, enumerable: true, - configurable: false - } + configurable: false, + }, }) cluster.setupMaster({ exec: path.join(options.path, 'dist', 'boot.js'), }) - process.on('update', (changed) => { + process.on('update', changed => { changed.forEach(({ name: filename }) => { options.logger.info(`${green('update')} ${filename}`) }) @@ -99,10 +98,10 @@ class Cluster extends EventEmitter { fork(retry: boolean = true) { return new Promise(resolve => { if (this.workers.size < this.maxWorkers) { - // $FlowIgnore + // $FlowFixMe const worker: Worker = cluster.fork({ NODE_ENV, - PORT: this.port + PORT: this.port, }) const timeout = setTimeout(() => { @@ -220,22 +219,20 @@ class Cluster extends EventEmitter { reload() { if (this.workers.size) { - const groups = Array - .from(this.workers) - .reduce((arr, item, idx, src) => { - if ((idx + 1) % 2) { - const group = src.slice(idx, idx + 2) - - return [ - ...arr, - () => Promise.all(group.map(worker => this.shutdown(worker))) - ] - } + const groups = Array.from(this.workers).reduce((arr, item, idx, src) => { + if ((idx + 1) % 2) { + const group = src.slice(idx, idx + 2) + + return [ + ...arr, + () => Promise.all(group.map(worker => this.shutdown(worker))), + ] + } - return arr - }, []) + return arr + }, []) - // $FlowIgnore + // $FlowFixMe return composeAsync(...groups)() } diff --git a/src/packages/pm/index.js b/src/packages/pm/index.js index 1a348ae7..e66b83a0 100644 --- a/src/packages/pm/index.js +++ b/src/packages/pm/index.js @@ -1,7 +1,6 @@ /* @flow */ import Cluster from './cluster' -// eslint-disable-next-line no-duplicate-imports import type { Options } from './cluster' /** diff --git a/src/packages/request/constants.js b/src/packages/request/constants.js index 8ef8bc3b..b7322e20 100644 --- a/src/packages/request/constants.js +++ b/src/packages/request/constants.js @@ -3,13 +3,11 @@ import type { Method } from './index' export const HAS_BODY: RegExp = /^(?:POST|PATCH)$/i -export const METHODS: Set = ( - new Set([ - 'GET', - 'HEAD', - 'POST', - 'PATCH', - 'DELETE', - 'OPTIONS', - ]) -) +export const METHODS: Set = new Set([ + 'GET', + 'HEAD', + 'POST', + 'PATCH', + 'DELETE', + 'OPTIONS', +]) diff --git a/src/packages/request/index.js b/src/packages/request/index.js index 884a24e6..d7997e5b 100644 --- a/src/packages/request/index.js +++ b/src/packages/request/index.js @@ -1,42 +1,36 @@ /* @flow */ -import type Logger from '../logger' +import type Logger from '@lux/packages/logger' import type { ObjectMap } from '../../interfaces' export type URL = { - protocol?: string; - slashes?: boolean; - auth?: string; - host?: string; - port?: string; - hostname?: string; - hash?: string; - search?: string; - query?: any; - pathname?: string; - path?: string; - href: string; - params: Array; + protocol?: string, + slashes?: boolean, + auth?: string, + host?: string, + port?: string, + hostname?: string, + hash?: string, + search?: string, + query?: any, + pathname?: string, + path?: string, + href: string, + params: Array, } export type Params = ObjectMap -export type Method = - | 'GET' - | 'HEAD' - | 'POST' - | 'PATCH' - | 'DELETE' - | 'OPTIONS' +export type Method = 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'DELETE' | 'OPTIONS' export type Options = { - url: URL; - params: ObjectMap; - logger: Logger; - method: Method; - headers: Map; - encrypted: boolean; - defaultParams: ObjectMap; + url: URL, + params: ObjectMap, + logger: Logger, + method: Method, + headers: Map, + encrypted: boolean, + defaultParams: ObjectMap, } /** @@ -44,13 +38,13 @@ export type Options = { * @public */ class Request { - url: URL; - params: ObjectMap; - logger: Logger; - method: Method; - headers: Map; - encrypted: boolean; - defaultParams: ObjectMap; + url: URL + params: ObjectMap + logger: Logger + method: Method + headers: Map + encrypted: boolean + defaultParams: ObjectMap constructor(options: Options) { Object.assign(this, options) @@ -58,4 +52,4 @@ class Request { } export default Request -export * from './constants' +export * from '@lux/constants' diff --git a/src/packages/responder/__tests__/responder.test.js b/src/packages/responder/__tests__/responder.test.js index ac77346e..31df0934 100644 --- a/src/packages/responder/__tests__/responder.test.js +++ b/src/packages/responder/__tests__/responder.test.js @@ -1,8 +1,8 @@ /* @flow */ -import Logger from '../../logger' +import Logger from '@lux/packages/logger' import { request, response } from '../../adapter/mock' -import noop from '../../../utils/noop' +import noop from '@lux/utils/noop' import setEnv from '../../../../test/utils/set-env' import * as responder from '../index' @@ -35,7 +35,7 @@ describe('module "responder"', () => { response.create({ logger, resolve, - }) + }), ) }) @@ -118,7 +118,7 @@ describe('module "responder"', () => { test('works with errors containing a `statusCode` property', () => { class ForbiddenError extends Error { - statusCode = 403; + statusCode = 403 constructor() { super('Forbidden') diff --git a/src/packages/responder/index.js b/src/packages/responder/index.js index f380aaa8..b99c70dd 100644 --- a/src/packages/responder/index.js +++ b/src/packages/responder/index.js @@ -1,7 +1,7 @@ /* @flow */ -import type Request from '../request' -import type Response from '../response' +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' import normalize from './utils/normalize' diff --git a/src/packages/responder/utils/data-for.js b/src/packages/responder/utils/data-for.js index d5fa89d0..86c75b35 100644 --- a/src/packages/responder/utils/data-for.js +++ b/src/packages/responder/utils/data-for.js @@ -1,10 +1,9 @@ /* @flow */ -import { VERSION } from '../../jsonapi' -import { STATUS_CODES } from '../../../constants' -import * as env from '../../../utils/env' -// eslint-disable-next-line no-duplicate-imports -import type { Document, ErrorData } from '../../jsonapi' +import { VERSION } from '@lux/packages/jsonapi' +import { STATUS_CODES } from '@lux/constants' +import * as env from '@lux/utils/env' +import type { Document, ErrorData } from '@lux/packages/jsonapi' /** * @private @@ -16,7 +15,7 @@ function dataFor(status: number, err?: Error): string | Document { const title = STATUS_CODES.get(status) const errData: ErrorData = { - status: String(status) + status: String(status), } if (title) { @@ -28,9 +27,7 @@ function dataFor(status: number, err?: Error): string | Document { } return { - errors: [ - errData, - ], + errors: [errData], jsonapi: { version: VERSION, }, diff --git a/src/packages/responder/utils/normalize.js b/src/packages/responder/utils/normalize.js index fa017e17..ad720f15 100644 --- a/src/packages/responder/utils/normalize.js +++ b/src/packages/responder/utils/normalize.js @@ -1,15 +1,15 @@ /* @flow */ -import { MIME_TYPE } from '../../jsonapi' -import { STATUS_CODES } from '../../response' -import stringify from '../../../utils/stringify' +import { MIME_TYPE } from '@lux/packages/jsonapi' +import { STATUS_CODES } from '@lux/packages/response' +import stringify from '@lux/utils/stringify' import dataFor from './data-for' type ResponseData = { - data: string; - mimeType: string; - statusCode: number; + data: string, + mimeType: string, + statusCode: number, } /** diff --git a/src/packages/response/constants.js b/src/packages/response/constants.js index 7b68f7b3..f2d52a55 100644 --- a/src/packages/response/constants.js +++ b/src/packages/response/constants.js @@ -1,68 +1,66 @@ /* @flow */ -export const STATUS_CODES: Map = ( - new Map([ - [100, 'Continue'], - [101, 'Switching Protocols'], - [102, 'Processing'], - [200, 'OK'], - [201, 'Created'], - [202, 'Accepted'], - [203, 'Non-Authoritative Information'], - [204, 'No Content'], - [205, 'Reset Content'], - [206, 'Partial Content'], - [207, 'Multi-Status'], - [208, 'Already Reported'], - [226, 'IM Used'], - [300, 'Multiple Choices'], - [301, 'Moved Permanently'], - [302, 'Found'], - [303, 'See Other'], - [304, 'Not Modified'], - [305, 'Use Proxy'], - [307, 'Temporary Redirect'], - [308, 'Permanent Redirect'], - [400, 'Bad Request'], - [401, 'Unauthorized'], - [402, 'Payment Required'], - [403, 'Forbidden'], - [404, 'Not Found'], - [405, 'Method Not Allowed'], - [406, 'Not Acceptable'], - [407, 'Proxy Authentication Required'], - [408, 'Request Timeout'], - [409, 'Conflict'], - [410, 'Gone'], - [411, 'Length Required'], - [412, 'Precondition Failed'], - [413, 'Payload Too Large'], - [414, 'URI Too Long'], - [415, 'Unsupported Media Type'], - [416, 'Range Not Satisfiable'], - [417, 'Expectation Failed'], - [418, 'I\'m a teapot'], - [421, 'Misdirected Request'], - [422, 'Unprocessable Entity'], - [423, 'Locked'], - [424, 'Failed Dependency'], - [425, 'Unordered Collection'], - [426, 'Upgrade Required'], - [428, 'Precondition Required'], - [429, 'Too Many Requests'], - [431, 'Request Header Fields Too Large'], - [451, 'Unavailable For Legal Reasons'], - [500, 'Internal Server Error'], - [501, 'Not Implemented'], - [502, 'Bad Gateway'], - [503, 'Service Unavailable'], - [504, 'Gateway Timeout'], - [505, 'HTTP Version Not Supported'], - [506, 'Variant Also Negotiates'], - [507, 'Insufficient Storage'], - [508, 'Loop Detected'], - [509, 'Bandwidth Limit Exceeded'], - [510, 'Not Extended'], - [511, 'Network Authentication Required'], - ]) -) +export const STATUS_CODES: Map = new Map([ + [100, 'Continue'], + [101, 'Switching Protocols'], + [102, 'Processing'], + [200, 'OK'], + [201, 'Created'], + [202, 'Accepted'], + [203, 'Non-Authoritative Information'], + [204, 'No Content'], + [205, 'Reset Content'], + [206, 'Partial Content'], + [207, 'Multi-Status'], + [208, 'Already Reported'], + [226, 'IM Used'], + [300, 'Multiple Choices'], + [301, 'Moved Permanently'], + [302, 'Found'], + [303, 'See Other'], + [304, 'Not Modified'], + [305, 'Use Proxy'], + [307, 'Temporary Redirect'], + [308, 'Permanent Redirect'], + [400, 'Bad Request'], + [401, 'Unauthorized'], + [402, 'Payment Required'], + [403, 'Forbidden'], + [404, 'Not Found'], + [405, 'Method Not Allowed'], + [406, 'Not Acceptable'], + [407, 'Proxy Authentication Required'], + [408, 'Request Timeout'], + [409, 'Conflict'], + [410, 'Gone'], + [411, 'Length Required'], + [412, 'Precondition Failed'], + [413, 'Payload Too Large'], + [414, 'URI Too Long'], + [415, 'Unsupported Media Type'], + [416, 'Range Not Satisfiable'], + [417, 'Expectation Failed'], + [418, "I'm a teapot"], + [421, 'Misdirected Request'], + [422, 'Unprocessable Entity'], + [423, 'Locked'], + [424, 'Failed Dependency'], + [425, 'Unordered Collection'], + [426, 'Upgrade Required'], + [428, 'Precondition Required'], + [429, 'Too Many Requests'], + [431, 'Request Header Fields Too Large'], + [451, 'Unavailable For Legal Reasons'], + [500, 'Internal Server Error'], + [501, 'Not Implemented'], + [502, 'Bad Gateway'], + [503, 'Service Unavailable'], + [504, 'Gateway Timeout'], + [505, 'HTTP Version Not Supported'], + [506, 'Variant Also Negotiates'], + [507, 'Insufficient Storage'], + [508, 'Loop Detected'], + [509, 'Bandwidth Limit Exceeded'], + [510, 'Not Extended'], + [511, 'Network Authentication Required'], +]) diff --git a/src/packages/response/index.js b/src/packages/response/index.js index 2ae88a31..0d119168 100644 --- a/src/packages/response/index.js +++ b/src/packages/response/index.js @@ -1,21 +1,21 @@ /* @flow */ -import type Logger from '../logger' +import type Logger from '@lux/packages/logger' /* eslint-disable no-use-before-define */ export type Options = { - stats: Array; - logger: Logger; - headers: Map; - statusCode: number; - statusMessage: string; - end(data: string): void; - send(data: string): void; - status(code: number): Response; - getHeader(key: string): void | string; - setHeader(key: string, value: string): void; - removeHeader(key: string): void; + stats: Array, + logger: Logger, + headers: Map, + statusCode: number, + statusMessage: string, + end(data: string): void, + send(data: string): void, + status(code: number): Response, + getHeader(key: string): void | string, + setHeader(key: string, value: string): void, + removeHeader(key: string): void, } /* eslint-enable no-use-before-define */ @@ -25,17 +25,17 @@ export type Options = { * @public */ class Response { - stats: Array; - logger: Logger; - headers: Map; - statusCode: number; - statusMessage: string; - end: (data: string) => void; - send: (data: string) => void; - status: (code: number) => Response; - getHeader: (key: string) => void | string; - setHeader: (key: string, value: string) => void; - removeHeader: (key: string) => void; + stats: Array + logger: Logger + headers: Map + statusCode: number + statusMessage: string + end: (data: string) => void + send: (data: string) => void + status: (code: number) => Response + getHeader: (key: string) => void | string + setHeader: (key: string, value: string) => void + removeHeader: (key: string) => void constructor(options: Options) { Object.assign(this, options) diff --git a/src/packages/router/__tests__/create-replacer.test.js b/src/packages/router/__tests__/create-replacer.test.js index a8c03a56..4147bdd8 100644 --- a/src/packages/router/__tests__/create-replacer.test.js +++ b/src/packages/router/__tests__/create-replacer.test.js @@ -1,6 +1,6 @@ /* @flow */ -import Controller from '../../controller' +import Controller from '@lux/packages/controller' import createReplacer from '../utils/create-replacer' describe('module "router"', () => { @@ -13,16 +13,24 @@ describe('module "router"', () => { class AdminPostsController extends PostsController {} class AdminHealthController extends HealthController {} - subject = createReplacer(new Map([ - ['posts', new PostsController()], - ['health', new HealthController()], - ['admin/posts', new AdminPostsController({ - namespace: 'admin', - })], - ['admin/health', new AdminHealthController({ - namespace: 'admin', - })] - ])) + subject = createReplacer( + new Map([ + ['posts', new PostsController()], + ['health', new HealthController()], + [ + 'admin/posts', + new AdminPostsController({ + namespace: 'admin', + }), + ], + [ + 'admin/health', + new AdminHealthController({ + namespace: 'admin', + }), + ], + ]), + ) }) test('returns an instance of RegExp', () => { @@ -30,13 +38,9 @@ describe('module "router"', () => { }) test('correctly replaces dynamic parts', () => { - expect( - 'posts/1'.replace(subject, '$1/:dynamic') - ).toBe('posts/:dynamic') + expect('posts/1'.replace(subject, '$1/:dynamic')).toBe('posts/:dynamic') - expect( - 'health/1'.replace(subject, '$1/:dynamic') - ).toBe('health/:dynamic') + expect('health/1'.replace(subject, '$1/:dynamic')).toBe('health/:dynamic') }) }) }) diff --git a/src/packages/router/__tests__/namespace.test.js b/src/packages/router/__tests__/namespace.test.js index a27508a2..105fe8eb 100644 --- a/src/packages/router/__tests__/namespace.test.js +++ b/src/packages/router/__tests__/namespace.test.js @@ -1,9 +1,8 @@ /* @flow */ import Namespace from '../namespace' -import setType from '../../../utils/set-type' import { getTestApp } from '../../../../test/utils/test-app' -import type Controller from '../../controller' +import type Controller from '@lux/packages/controller' describe('module "router/namespace"', () => { describe('class Namespace', () => { @@ -23,16 +22,18 @@ describe('module "router/namespace"', () => { } beforeAll(async () => { - app = await getTestApp(); - ({ controllers } = app) - // $FlowIgnore + app = await getTestApp() + ;({ controllers } = app) + // $FlowFixMe controller = controllers.get('admin/application') - createRootNamespace = (): Namespace => new Namespace({ - controllers, - path: '/', - name: 'root', - controller: setType(() => app.controllers.get('application')), - }) + createRootNamespace = (): Namespace => + new Namespace({ + controllers, + path: '/', + name: 'root', + // $FlowFixMe + controller: app.controllers.get('application'), + }) }) afterAll(async () => { diff --git a/src/packages/router/__tests__/router.test.js b/src/packages/router/__tests__/router.test.js index d5dd1d5c..e93e69da 100644 --- a/src/packages/router/__tests__/router.test.js +++ b/src/packages/router/__tests__/router.test.js @@ -1,12 +1,12 @@ /* @flow */ -import Logger from '../../logger' +import Logger from '@lux/packages/logger' import Route from '../route' import Router from '../index' -import Controller from '../../controller' -import Serializer from '../../serializer' -import { Model } from '../../database' -import { FreezeableMap } from '../../freezeable' +import Controller from '@lux/packages/controller' +import Serializer from '@lux/packages/serializer' +import { Model } from '@lux/packages/database' +import { FreezeableMap } from '@lux/packages/freezeable' import { request } from '../../adapter/mock' describe('module "router"', () => { @@ -20,13 +20,13 @@ describe('module "router"', () => { }) class Post extends Model { - static resourceName = 'posts'; - static columnFor = columnFor; + static resourceName = 'posts' + static columnFor = columnFor } class User extends Model { - static resourceName = 'users'; - static columnFor = columnFor; + static resourceName = 'users' + static columnFor = columnFor } const appController = new Controller() @@ -37,22 +37,31 @@ describe('module "router"', () => { controller = appController controllers = new FreezeableMap([ ['application', controller], - ['posts', new Controller({ - model: Post, - parent: controller, - serializer: new Serializer(), - })], - ['users', new Controller({ - model: User, - parent: controller, - serializer: new Serializer(), - })], + [ + 'posts', + new Controller({ + model: Post, + parent: controller, + serializer: new Serializer(), + }), + ], + [ + 'users', + new Controller({ + model: User, + parent: controller, + serializer: new Serializer(), + }), + ], ['admin/application', adminController], - ['admin/posts', new Controller({ - model: Post, - parent: adminController, - serializer: new Serializer(), - })] + [ + 'admin/posts', + new Controller({ + model: Post, + parent: adminController, + serializer: new Serializer(), + }), + ], ]) }) @@ -64,9 +73,9 @@ describe('module "router"', () => { routes() { this.resource('users', { - only: ['index'] + only: ['index'], }) - } + }, }) expect(subject.has('GET:/users')).toBe(true) @@ -81,7 +90,7 @@ describe('module "router"', () => { routes() { this.resource('posts') - } + }, }) expect(subject.has('GET:/posts')).toBe(true) @@ -96,15 +105,16 @@ describe('module "router"', () => { }) test('throws an error when a controller is missing', () => { - expect(() => ( - new Router({ - controller, - controllers, - routes() { - this.resource('articles') - }, - }) - )).toThrow() + expect( + () => + new Router({ + controller, + controllers, + routes() { + this.resource('articles') + }, + }), + ).toThrow() }) }) @@ -132,17 +142,18 @@ describe('module "router"', () => { }) test('throws an error when a controller is missing', () => { - expect(() => ( - new Router({ - controller, - controllers, - routes() { - this.namespace('v1', function v1() { - this.resource('posts') - }) - } - }) - )).toThrow() + expect( + () => + new Router({ + controller, + controllers, + routes() { + this.namespace('v1', function v1() { + this.resource('posts') + }) + }, + }), + ).toThrow() }) }) @@ -182,8 +193,8 @@ describe('module "router"', () => { headers: new Map(), encrypted: false, defaultParams: {}, - }) - ) + }), + ), ).toBeInstanceOf(Route) }) @@ -198,8 +209,8 @@ describe('module "router"', () => { headers: new Map(), encrypted: false, defaultParams: {}, - }) - ) + }), + ), ).toBeInstanceOf(Route) }) }) diff --git a/src/packages/router/definitions/__tests__/normalize-resource-args.test.js b/src/packages/router/definitions/__tests__/normalize-resource-args.test.js index 6bcf7308..43475858 100644 --- a/src/packages/router/definitions/__tests__/normalize-resource-args.test.js +++ b/src/packages/router/definitions/__tests__/normalize-resource-args.test.js @@ -1,6 +1,6 @@ /* @flow */ -import { BUILT_IN_ACTIONS } from '../../../controller' +import { BUILT_IN_ACTIONS } from '@lux/packages/controller' import normalizeResourceArgs from '../context/utils/normalize-resource-args' describe('module "router/definitions/context"', () => { @@ -16,37 +16,37 @@ describe('module "router/definitions/context"', () => { only: BUILT_IN_ACTIONS, }, expect.any(Function), - ]) + ]), ) }) test('normalizes arguments with a name and options', () => { - const result = normalizeResourceArgs(['posts', { - only: [ - 'show', - 'index' - ] - }]) + const result = normalizeResourceArgs([ + 'posts', + { + only: ['show', 'index'], + }, + ]) expect(result).toEqual( expect.arrayContaining([ { name: 'posts', path: '/posts', - only: [ - 'show', - 'index', - ], + only: ['show', 'index'], }, expect.any(Function), - ]) + ]), ) }) test('normalizes arguments with a name and builder', () => { - const result = normalizeResourceArgs(['posts', function build() { - return undefined - }]) + const result = normalizeResourceArgs([ + 'posts', + function build() { + return undefined + }, + ]) expect(result).toEqual( expect.arrayContaining([ @@ -56,32 +56,30 @@ describe('module "router/definitions/context"', () => { only: BUILT_IN_ACTIONS, }, expect.any(Function), - ]) + ]), ) }) test('normalizes arguments with a name, options, and builder', () => { - const result = normalizeResourceArgs(['posts', { - only: [ - 'show', - 'index' - ] - }, function build() { - return undefined - }]) + const result = normalizeResourceArgs([ + 'posts', + { + only: ['show', 'index'], + }, + function build() { + return undefined + }, + ]) expect(result).toEqual( expect.arrayContaining([ { name: 'posts', path: '/posts', - only: [ - 'show', - 'index', - ], + only: ['show', 'index'], }, expect.any(Function), - ]) + ]), ) }) }) diff --git a/src/packages/router/definitions/context/index.js b/src/packages/router/definitions/context/index.js index 45ec0ad0..215fc6b4 100644 --- a/src/packages/router/definitions/context/index.js +++ b/src/packages/router/definitions/context/index.js @@ -2,11 +2,10 @@ import Resource from '../../resource' import Namespace from '../../namespace' -import K from '../../../../utils/k' -import type { Router$Namespace } from '../../index' // eslint-disable-line max-len, no-unused-vars +import K from '@lux/utils/k' +import ControllerMissingError from '@lux/errors/controller-missing-error' +import type { Router$Namespace } from '../../index' import type { Router$DefinitionBuilder } from '../interfaces' -import ControllerMissingError - from '../../../../errors/controller-missing-error' import createDefinitionGroup from './utils/create-definition-group' import normalizeResourceArgs from './utils/normalize-resource-args' @@ -22,7 +21,7 @@ export function contextFor(build: Router$DefinitionBuilder<*>) { resource: K, namespace: K, collection: K, - ...createDefinitionGroup('custom', namespace) + ...createDefinitionGroup('custom', namespace), } if (namespace instanceof Resource) { @@ -39,7 +38,7 @@ export function contextFor(build: Router$DefinitionBuilder<*>) { const childCtx = createDefinitionGroup('collection', namespace) Reflect.apply(builder, childCtx, []) - } + }, } } else { context = { @@ -63,7 +62,7 @@ export function contextFor(build: Router$DefinitionBuilder<*>) { path, namespace, controller, - controllers + controllers, }) build(builder, child) @@ -84,10 +83,13 @@ export function contextFor(build: Router$DefinitionBuilder<*>) { const controllerKey = path .split('/') .filter(Boolean) - .reduce((arr, str, index, parts) => [ - ...arr, - index === parts.length - 1 ? opts.name : str - ], []) + .reduce( + (arr, str, index, parts) => [ + ...arr, + index === parts.length - 1 ? opts.name : str, + ], + [], + ) .join('/') const controller = controllers.get(controllerKey) @@ -101,16 +103,16 @@ export function contextFor(build: Router$DefinitionBuilder<*>) { path, namespace, controller, - controllers + controllers, }) build(builder, child) namespace.add(child) - } + }, } } return context - } + }, } } diff --git a/src/packages/router/definitions/context/utils/create-definition-group.js b/src/packages/router/definitions/context/utils/create-definition-group.js index 107eb93c..9ed9486a 100644 --- a/src/packages/router/definitions/context/utils/create-definition-group.js +++ b/src/packages/router/definitions/context/utils/create-definition-group.js @@ -1,8 +1,7 @@ /* @flow */ -import { METHODS } from '../../../../request' -import type { Method } from '../../../../request' -// eslint-disable-next-line no-unused-vars +import { METHODS } from '@lux/packages/request' +import type { Method } from '@lux/packages/request' import type { Route$type, Router$Namespace } from '../../../index' import createDefinition from './create-definition' @@ -11,7 +10,7 @@ import createDefinition from './create-definition' * @private */ type DefinitionGroup = { - [key: Method]: (name: string, action?: string) => void; + [key: Method]: (name: string, action?: string) => void, } /** @@ -19,20 +18,19 @@ type DefinitionGroup = { */ function createDefinitionGroup( type: Route$type, - namespace: T + namespace: T, ): DefinitionGroup { - return Array - .from(METHODS) - .reduce((methods, method) => ({ + return Array.from(METHODS).reduce( + (methods, method) => ({ ...methods, - [method.toLowerCase()]: ( - createDefinition({ - type, - method, - namespace, - }) - ), - }), {}) + [method.toLowerCase()]: createDefinition({ + type, + method, + namespace, + }), + }), + {}, + ) } export default createDefinitionGroup diff --git a/src/packages/router/definitions/context/utils/create-definition.js b/src/packages/router/definitions/context/utils/create-definition.js index 1d6e61df..0b9d4670 100644 --- a/src/packages/router/definitions/context/utils/create-definition.js +++ b/src/packages/router/definitions/context/utils/create-definition.js @@ -2,51 +2,59 @@ import { Route } from '../../../index' import { normalizeName, normalizePath } from '../../../namespace' -import type { Method } from '../../../../request' +import type { Method } from '@lux/packages/request' import type { Router$Namespace, Route$type } from '../../../index' // eslint-disable-line max-len, no-duplicate-imports -/** - * @private - */ -export default function createDefinition({ type, method, namespace }: { - type: Route$type; - method: Method; - namespace: Router$Namespace; -}) { - return function define(name: string, action?: string = normalizeName(name)) { - const normalized = normalizeName(name) - const { controller } = namespace - let { path } = namespace - - if (type === 'member') { - path += `/:id/${normalized}` - } else { - path += `/${normalized}` - } - - path = normalizePath(path) - - const opts = { - type, - path, - action, - method, - controller - } - - namespace - .add(new Route(opts)) - .add(new Route({ +type Define = (name: string, action?: string) => void + +type Options = { + type: Route$type, + method: Method, + namespace: Router$Namespace, +} + +const createDefinition = ({ type, method, namespace }: Options): Define => ( + name, + action = normalizeName(name), +) => { + const normalized = normalizeName(name) + const { controller } = namespace + let { path } = namespace + + if (type === 'member') { + path += `/:id/${normalized}` + } else { + path += `/${normalized}` + } + + path = normalizePath(path) + + const opts = { + type, + path, + action, + method, + controller, + } + + namespace + .add(new Route(opts)) + .add( + new Route({ ...opts, type: 'custom', method: 'HEAD', - action: 'preflight' - })) - .add(new Route({ + action: 'preflight', + }), + ) + .add( + new Route({ ...opts, type: 'custom', method: 'OPTIONS', - action: 'preflight' - })) - } + action: 'preflight', + }), + ) } + +export default createDefinition diff --git a/src/packages/router/definitions/context/utils/normalize-resource-args.js b/src/packages/router/definitions/context/utils/normalize-resource-args.js index 3233fc15..5f5e137c 100644 --- a/src/packages/router/definitions/context/utils/normalize-resource-args.js +++ b/src/packages/router/definitions/context/utils/normalize-resource-args.js @@ -1,24 +1,28 @@ /* @flow */ -import { BUILT_IN_ACTIONS } from '../../../../controller' -// eslint-disable-next-line no-duplicate-imports -import type { BuiltInAction } from '../../../../controller' +import { BUILT_IN_ACTIONS } from '@lux/packages/controller' +import type { BuiltInAction } from '@lux/packages/controller' /** * @private */ -export default function normalizeResourceArgs(args: Array): [{ - name: string, - path: string, - only: Array -}, Function] { +export default function normalizeResourceArgs( + args: Array, +): [ + { + name: string, + path: string, + only: Array, + }, + Function, +] { const [name] = args let [, opts, builder] = args if (!opts) { opts = { path: '', - only: undefined + only: undefined, } } @@ -26,7 +30,7 @@ export default function normalizeResourceArgs(args: Array): [{ builder = opts opts = { path: '', - only: undefined + only: undefined, } } @@ -36,20 +40,20 @@ export default function normalizeResourceArgs(args: Array): [{ opts = { ...opts, - name + name, } if (!opts.path) { opts = { ...opts, - path: `/${name}` + path: `/${name}`, } } if (!opts.only) { opts = { ...opts, - only: [...BUILT_IN_ACTIONS] + only: [...BUILT_IN_ACTIONS], } } diff --git a/src/packages/router/definitions/interfaces.js b/src/packages/router/definitions/interfaces.js index 2122954c..4005355f 100644 --- a/src/packages/router/definitions/interfaces.js +++ b/src/packages/router/definitions/interfaces.js @@ -1,10 +1,10 @@ /* @flow */ -import type { Router$Namespace, Resource$opts } from '../index'; +import type { Router$Namespace, Resource$opts } from '../index' export type Router$DefinitionBuilder = ( builder?: () => void, - namespace: T -) => T; + namespace: T, +) => T -export type Router$resourceArgs = [string, ?Resource$opts, ?() => void]; +export type Router$resourceArgs = [string, ?Resource$opts, ?() => void] diff --git a/src/packages/router/index.js b/src/packages/router/index.js index f65ece8a..671377f5 100644 --- a/src/packages/router/index.js +++ b/src/packages/router/index.js @@ -1,7 +1,7 @@ /* @flow */ -import { FreezeableMap } from '../freezeable' -import type Request from '../request' +import { FreezeableMap } from '@lux/packages/freezeable' +import type Request from '@lux/packages/request' import Namespace from './namespace' import { build, define } from './definitions' @@ -13,15 +13,18 @@ import type Route from './route' * @private */ class Router extends FreezeableMap { - replacer: RegExp; + replacer: RegExp constructor({ routes, controller, controllers }: Router$opts) { - const definitions = build(routes, new Namespace({ - controller, - controllers, - path: '/', - name: 'root' - })) + const definitions = build( + routes, + new Namespace({ + controller, + controllers, + path: '/', + name: 'root', + }), + ) super() define(this, definitions) @@ -30,13 +33,15 @@ class Router extends FreezeableMap { value: createReplacer(controllers), writable: false, enumerable: false, - configurable: false + configurable: false, }) this.freeze() } - match({ method, url }: Request): void | Route { + match(request: Request): void | Route { + const { method, url } = request + if (url.pathname) { const params = [] const staticPath = url.pathname.replace(this.replacer, (str, g1, g2) => { @@ -44,7 +49,6 @@ class Router extends FreezeableMap { return `${g1}/:dynamic` }) - // eslint-disable-next-line no-param-reassign url.params = params return this.get(`${method}:${staticPath}`) } diff --git a/src/packages/router/interfaces.js b/src/packages/router/interfaces.js index 1fd42f3f..2e12e649 100644 --- a/src/packages/router/interfaces.js +++ b/src/packages/router/interfaces.js @@ -1,25 +1,22 @@ /* @flow */ -import type Route from './route'; -import type Controller from '../controller'; -import type { FreezeableSet } from '../freezeable'; - -export type Router$opts = { - controller: Controller; - controllers: Map; - - routes(): void; -}; - -type Router$NS$content = - | Route - | Router$Namespace; +import type Route from './route' +import type Controller from '@lux/packages/controller' +import type { FreezeableSet } from '@lux/packages/freezeable' export interface Router$Namespace extends FreezeableSet { - name: string; - path: string; - isRoot: boolean; - namespace: Router$Namespace; - controller: Controller; - controllers: Map; + name: string, + path: string, + isRoot: boolean, + namespace: Router$Namespace, + controller: Controller, + controllers: Map, } + +export type Router$opts = { + controller: Controller, + controllers: Map, + routes(): void, +} + +type Router$NS$content = Route | Router$Namespace diff --git a/src/packages/router/namespace/index.js b/src/packages/router/namespace/index.js index 33cd0655..21ed2745 100644 --- a/src/packages/router/namespace/index.js +++ b/src/packages/router/namespace/index.js @@ -1,7 +1,7 @@ /* @flow */ -import { FreezeableSet, freezeProps } from '../../freezeable' -import type Controller from '../../controller' +import { FreezeableSet, freezeProps } from '@lux/packages/freezeable' +import type Controller from '@lux/packages/controller' import type { Route, Router$Namespace } from '../index' import normalizeName from './utils/normalize-name' @@ -12,24 +12,24 @@ import type { Namespace$opts } from './interfaces' * @private */ class Namespace extends FreezeableSet { - name: string; + name: string - path: string; + path: string - isRoot: boolean; + isRoot: boolean - namespace: Router$Namespace; + namespace: Router$Namespace - controller: Controller; + controller: Controller - controllers: Map; + controllers: Map constructor({ name, path, namespace, controller, - controllers + controllers, }: Namespace$opts) { super() @@ -39,20 +39,12 @@ class Namespace extends FreezeableSet { name: normalizeName(name), path: normalizePath(path), isRoot: path === '/', - namespace: namespace || this + namespace: namespace || this, }) - freezeProps(this, true, - 'name', - 'path', - 'controller', - 'namespace' - ) + freezeProps(this, true, 'name', 'path', 'controller', 'namespace') - freezeProps(this, false, - 'isRoot', - 'controllers' - ) + freezeProps(this, false, 'isRoot', 'controllers') } } diff --git a/src/packages/router/namespace/interfaces.js b/src/packages/router/namespace/interfaces.js index 6c7e86eb..6f97d5ea 100644 --- a/src/packages/router/namespace/interfaces.js +++ b/src/packages/router/namespace/interfaces.js @@ -1,12 +1,12 @@ /* @flow */ -import type Controller from '../../controller'; -import type { Router$Namespace } from '../index'; +import type Controller from '@lux/packages/controller' +import type { Router$Namespace } from '../index' export type Namespace$opts = { - name: string; - path: string; - namespace?: Router$Namespace; - controller: Controller; - controllers: Map; -}; + name: string, + path: string, + namespace?: Router$Namespace, + controller: Controller, + controllers: Map, +} diff --git a/src/packages/router/resource/index.js b/src/packages/router/resource/index.js index b948fd30..0bc60f8a 100644 --- a/src/packages/router/resource/index.js +++ b/src/packages/router/resource/index.js @@ -1,8 +1,8 @@ /* @flow */ import Namespace from '../namespace' -import { FreezeableSet } from '../../freezeable' -import type { BuiltInAction } from '../../controller' +import { FreezeableSet } from '@lux/packages/freezeable' +import type { BuiltInAction } from '@lux/packages/controller' import normalizeOnly from './utils/normalize-only' import type { Resource$opts } from './interfaces' @@ -11,7 +11,7 @@ import type { Resource$opts } from './interfaces' * @private */ class Resource extends Namespace { - only: FreezeableSet; + only: FreezeableSet constructor({ only, ...opts }: Resource$opts) { super(opts) @@ -20,7 +20,7 @@ class Resource extends Namespace { value: new FreezeableSet(normalizeOnly(only)), writable: false, enumerable: false, - configurable: false + configurable: false, }) this.only.freeze() diff --git a/src/packages/router/resource/interfaces.js b/src/packages/router/resource/interfaces.js index 23a4c3ce..e640103b 100644 --- a/src/packages/router/resource/interfaces.js +++ b/src/packages/router/resource/interfaces.js @@ -1,8 +1,8 @@ /* @flow */ -import type Controller, { BuiltInAction } from '../../controller'; -import type { Namespace$opts } from '../namespace'; +import type { BuiltInAction } from '@lux/packages/controller' +import type { Namespace$opts } from '../namespace' export type Resource$opts = Namespace$opts & { - only: Array; -}; + only: Array, +} diff --git a/src/packages/router/resource/utils/normalize-only.js b/src/packages/router/resource/utils/normalize-only.js index b63ee302..ed04e584 100644 --- a/src/packages/router/resource/utils/normalize-only.js +++ b/src/packages/router/resource/utils/normalize-only.js @@ -1,8 +1,7 @@ /* @flow */ -import { BUILT_IN_ACTIONS } from '../../../controller' -// eslint-disable-next-line no-duplicate-imports -import type { BuiltInAction } from '../../../controller' +import { BUILT_IN_ACTIONS } from '@lux/packages/controller' +import type { BuiltInAction } from '@lux/packages/controller' /** * @private diff --git a/src/packages/router/route/__tests__/route.test.js b/src/packages/router/route/__tests__/route.test.js index 21f8b9c5..91a3e896 100644 --- a/src/packages/router/route/__tests__/route.test.js +++ b/src/packages/router/route/__tests__/route.test.js @@ -1,8 +1,8 @@ /* @flow */ -import Controller from '../../../controller' -import * as Adapters from '../../../adapter' -import K from '../../../../utils/k' +import Controller from '@lux/packages/controller' +import * as Adapters from '@lux/packages/adapter' +import K from '@lux/utils/k' import { getTestApp } from '../../../../../test/utils/test-app' import Route from '../index' @@ -24,7 +24,7 @@ describe('module "router/route"', () => { let controller: Controller beforeAll(() => { - // $FlowIgnore + // $FlowFixMe controller = app.controllers.get('posts') }) @@ -34,46 +34,49 @@ describe('module "router/route"', () => { type: 'collection', path: 'posts', action: 'index', - method: 'GET' + method: 'GET', }) expect(result).toBeInstanceOf(Route) }) test('throws when a handler is not found', () => { - expect(() => ( - new Route({ - controller, - type: 'collection', - path: 'posts', - action: 'invalidHandler', - method: 'GET' - }) - )).toThrow() + expect( + () => + new Route({ + controller, + type: 'collection', + path: 'posts', + action: 'invalidHandler', + method: 'GET', + }), + ).toThrow() }) test('throws when an an action is not provided', () => { - expect(() => ( - // $FlowIgnore - new Route({ - controller, - type: 'collection', - path: 'posts', - method: 'GET' - }) - )).toThrow() + expect( + () => + // $FlowFixMe + new Route({ + controller, + type: 'collection', + path: 'posts', + method: 'GET', + }), + ).toThrow() }) test('throws when an an controller is not provided', () => { - expect(() => ( - // $FlowIgnore - new Route({ - type: 'collection', - path: 'posts', - action: 'index', - method: 'GET' - }) - )).toThrow() + expect( + () => + // $FlowFixMe + new Route({ + type: 'collection', + path: 'posts', + action: 'index', + method: 'GET', + }), + ).toThrow() }) }) @@ -82,7 +85,7 @@ describe('module "router/route"', () => { let dynamicRoute: Route beforeAll(() => { - // $FlowIgnore + // $FlowFixMe const controller: Controller = app.controllers.get('posts') staticRoute = new Route({ @@ -117,24 +120,23 @@ describe('module "router/route"', () => { describe('#execHandlers()', () => { let subject: Route - const mockArgs = () => ( + const mockArgs = () => adapter({ url: '/tests', method: 'GET', headers: {}, resolve: K, }) - ) describe('- with action only', () => { beforeAll(async () => { class TestController extends Controller { - // $FlowIgnore + // $FlowFixMe index = async () => ({ meta: { - success: true - } - }); + success: true, + }, + }) } subject = new Route({ @@ -143,8 +145,8 @@ describe('module "router/route"', () => { action: 'index', method: 'GET', controller: new TestController({ - namespace: '' - }) + namespace: '', + }), }) }) @@ -162,17 +164,17 @@ describe('module "router/route"', () => { beforeAction = [ async () => ({ meta: { - beforeSuccess: true - } - }) - ]; + beforeSuccess: true, + }, + }), + ] - // $FlowIgnore + // $FlowFixMe index = async () => ({ meta: { - success: true - } - }); + success: true, + }, + }) } subject = new Route({ @@ -181,8 +183,8 @@ describe('module "router/route"', () => { action: 'index', method: 'GET', controller: new TestController({ - namespace: '' - }) + namespace: '', + }), }) }) @@ -197,13 +199,13 @@ describe('module "router/route"', () => { describe('- with `afterAction`', () => { beforeAll(async () => { class TestController extends Controller { - // $FlowIgnore + // $FlowFixMe index = async () => ({ meta: { success: true, - afterSuccess: true - } - }); + afterSuccess: true, + }, + }) } subject = new Route({ @@ -212,8 +214,8 @@ describe('module "router/route"', () => { action: 'index', method: 'GET', controller: new TestController({ - namespace: '' - }) + namespace: '', + }), }) }) @@ -232,23 +234,23 @@ describe('module "router/route"', () => { beforeAction = jest.fn() class TestController extends Controller { - beforeAction = [beforeAction]; + beforeAction = [beforeAction] afterAction = [ async (req, res, { meta }) => ({ meta: { ...meta, - afterSuccess: true - } - }) - ]; + afterSuccess: true, + }, + }), + ] - // $FlowIgnore + // $FlowFixMe index = async () => ({ meta: { - success: true - } - }); + success: true, + }, + }) } subject = new Route({ @@ -257,8 +259,8 @@ describe('module "router/route"', () => { action: 'index', method: 'GET', controller: new TestController({ - namespace: '' - }) + namespace: '', + }), }) }) @@ -280,11 +282,10 @@ describe('module "router/route"', () => { let controller: Controller beforeAll(() => { - // $FlowIgnore + // $FlowFixMe controller = app.controllers.get('posts') - }); - - ['GET', 'OPTIONS'].forEach(method => { + }) + ;['GET', 'OPTIONS'].forEach(method => { describe(`- method "${method}"`, () => { let subject @@ -307,7 +308,7 @@ describe('module "router/route"', () => { controller, type: 'collection', path: 'posts', - action: 'preflight' + action: 'preflight', }) }) diff --git a/src/packages/router/route/action/__tests__/action.test.js b/src/packages/router/route/action/__tests__/action.test.js index 14b316b6..4e067f64 100644 --- a/src/packages/router/route/action/__tests__/action.test.js +++ b/src/packages/router/route/action/__tests__/action.test.js @@ -1,11 +1,11 @@ /* @flow */ -import noop from '../../../../../utils/noop' -import Logger from '../../../../logger' +import noop from '@lux/utils/noop' +import Logger from '@lux/packages/logger' import { request, response } from '../../../../adapter/mock' import { createAction, createPageLinks } from '../index' import { getTestApp } from '../../../../../../test/utils/test-app' -import type Controller from '../../../../controller' +import type Controller from '@lux/packages/controller' import type { Action } from '../index' const DOMAIN = 'http://localhost:4000' @@ -28,7 +28,7 @@ describe('module "router/route/action"', () => { beforeAll(async () => { app = await getTestApp() - // $FlowIgnore + // $FlowFixMe const controller: Controller = app.controllers.get('health') const action: Action = controller.index @@ -59,7 +59,7 @@ describe('module "router/route/action"', () => { response.create({ logger, resolve: noop, - }) + }), ) expect(data).toBe(204) @@ -67,30 +67,31 @@ describe('module "router/route/action"', () => { }) describe('#createPageLinks()', () => { - const getOptions = ({ - total = 100, - params = {} - }: { - total?: number; - params?: Object; - } = {}) => ({ + const getOptions = ( + { + total = 100, + params = {}, + }: { + total?: number, + params?: Object, + } = {}, + ) => ({ total, params, domain: DOMAIN, pathname: `/${RESOURCE}`, - defaultPerPage: 25 + defaultPerPage: 25, }) test('works with vanilla params', () => { - const base = `${DOMAIN}/${RESOURCE}`; - - [1, 2, 3, 4].forEach(number => { + const base = `${DOMAIN}/${RESOURCE}` + ;[1, 2, 3, 4].forEach(number => { const opts = getOptions({ params: { page: { - number - } - } + number, + }, + }, }) let target = { @@ -98,7 +99,7 @@ describe('module "router/route/action"', () => { first: base, last: `${base}?page%5Bnumber%5D=4`, prev: `${base}?page%5Bnumber%5D=${number - 1}`, - next: `${base}?page%5Bnumber%5D=${number + 1}` + next: `${base}?page%5Bnumber%5D=${number + 1}`, } // eslint-disable-next-line default-case @@ -107,21 +108,21 @@ describe('module "router/route/action"', () => { target = { ...target, self: target.first, - prev: null + prev: null, } break case 2: target = { ...target, - prev: target.first + prev: target.first, } break case 4: target = { ...target, - next: null + next: null, } break } @@ -132,16 +133,15 @@ describe('module "router/route/action"', () => { test('works with a custom size', () => { const size = 10 - const base = `${DOMAIN}/${RESOURCE}?page%5Bsize%5D=${size}`; - - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].forEach(number => { + const base = `${DOMAIN}/${RESOURCE}?page%5Bsize%5D=${size}` + ;[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].forEach(number => { const opts = getOptions({ params: { page: { size, - number - } - } + number, + }, + }, }) let target = { @@ -149,7 +149,7 @@ describe('module "router/route/action"', () => { first: base, last: `${base}&page%5Bnumber%5D=10`, prev: `${base}&page%5Bnumber%5D=${number - 1}`, - next: `${base}&page%5Bnumber%5D=${number + 1}` + next: `${base}&page%5Bnumber%5D=${number + 1}`, } // eslint-disable-next-line default-case @@ -158,21 +158,21 @@ describe('module "router/route/action"', () => { target = { ...target, self: target.first, - prev: null + prev: null, } break case 2: target = { ...target, - prev: target.first + prev: target.first, } break case 10: target = { ...target, - next: null + next: null, } break } @@ -182,29 +182,23 @@ describe('module "router/route/action"', () => { }) test('works with complex parameter sets', () => { + const iters = [1, 2, 3, 4] const base = - `${DOMAIN}/${RESOURCE}?sort=-created-at&include=user&fields%5Bposts%5D=` - + 'title&fields%5Busers%5D=name'; - - [1, 2, 3, 4].forEach(number => { + `${DOMAIN}/${RESOURCE}?sort=-created-at&include=user` + + '&fields%5Bposts%5D=title&fields%5Busers%5D=name' + iters.forEach(number => { const opts = getOptions({ params: { sort: '-created-at', - include: [ - 'user' - ], + include: ['user'], fields: { - posts: [ - 'title' - ], - users: [ - 'name' - ] + posts: ['title'], + users: ['name'], }, page: { - number - } - } + number, + }, + }, }) let target = { @@ -212,7 +206,7 @@ describe('module "router/route/action"', () => { first: base, last: `${base}&page%5Bnumber%5D=4`, prev: `${base}&page%5Bnumber%5D=${number - 1}`, - next: `${base}&page%5Bnumber%5D=${number + 1}` + next: `${base}&page%5Bnumber%5D=${number + 1}`, } // eslint-disable-next-line default-case @@ -221,21 +215,21 @@ describe('module "router/route/action"', () => { target = { ...target, self: target.first, - prev: null + prev: null, } break case 2: target = { ...target, - prev: target.first + prev: target.first, } break case 4: target = { ...target, - next: null + next: null, } break } diff --git a/src/packages/router/route/action/__tests__/resource.test.js b/src/packages/router/route/action/__tests__/resource.test.js index d4fd84be..968d71d7 100644 --- a/src/packages/router/route/action/__tests__/resource.test.js +++ b/src/packages/router/route/action/__tests__/resource.test.js @@ -1,35 +1,20 @@ /* @flow */ -import { VERSION } from '../../../../jsonapi' -import Logger from '../../../../logger' +import { VERSION } from '@lux/packages/jsonapi' +import Logger from '@lux/packages/logger' import { request, response } from '../../../../adapter/mock' -import noop from '../../../../../utils/noop' +import noop from '@lux/utils/noop' import { getTestApp } from '../../../../../../test/utils/test-app' import resource from '../enhancers/resource' const DOMAIN = 'localhost:4000' const DEFAULT_FIELDS = { - posts: [ - 'body', - 'title', - 'createdAt', - 'updatedAt', - ], - users: [ - 'id', - ], - images: [ - 'id', - ], - comments: [ - 'id', - ], - reactions: [ - 'id', - ], - tags: [ - 'id', - ], + posts: ['body', 'title', 'createdAt', 'updatedAt'], + users: ['id'], + images: ['id'], + comments: ['id'], + reactions: ['id'], + tags: ['id'], } const logger = new Logger({ @@ -89,7 +74,7 @@ describe('module "router/route/action"', () => { beforeAll(() => { const controller = app.controllers.get('posts') - // $FlowIgnore + // $FlowFixMe subject = resource(controller.index.bind(controller), controller) }) @@ -103,16 +88,14 @@ describe('module "router/route/action"', () => { expect(await subject(req, res)).toEqual( expect.objectContaining({ - data: expect.arrayContaining([ - expect.anything(), - ]), + data: expect.arrayContaining([expect.anything()]), links: expect.objectContaining({ self: expect.any(String), }), jsonapi: { version: VERSION, }, - }) + }), ) }) }) @@ -149,7 +132,7 @@ describe('module "router/route/action"', () => { return [req, res] } - const getExpectedResult = () => ( + const getExpectedResult = () => expect.objectContaining({ data: expect.objectContaining({ id: '1', @@ -164,7 +147,6 @@ describe('module "router/route/action"', () => { version: VERSION, }, }) - ) describe('- with "root" namespace', () => { let subject @@ -172,7 +154,7 @@ describe('module "router/route/action"', () => { beforeAll(() => { const controller = app.controllers.get('posts') - // $FlowIgnore + // $FlowFixMe subject = resource(controller.show.bind(controller), controller) }) @@ -194,7 +176,7 @@ describe('module "router/route/action"', () => { beforeAll(async () => { const controller = app.controllers.get('admin/posts') - // $FlowIgnore + // $FlowFixMe subject = resource(controller.show.bind(controller), controller) }) @@ -216,7 +198,7 @@ describe('module "router/route/action"', () => { beforeAll(() => { const controller = app.controllers.get('posts') - // $FlowIgnore + // $FlowFixMe subject = resource(() => Promise.resolve(null), controller) }) @@ -241,7 +223,7 @@ describe('module "router/route/action"', () => { response.create({ logger, resolve: noop, - }) + }), ) expect(result).toBeNull() diff --git a/src/packages/router/route/action/enhancers/resource.js b/src/packages/router/route/action/enhancers/resource.js index c255ebe7..8fc95181 100644 --- a/src/packages/router/route/action/enhancers/resource.js +++ b/src/packages/router/route/action/enhancers/resource.js @@ -1,10 +1,10 @@ /* @flow */ -import { Query } from '../../../../database' -import getDomain from '../../../../../utils/get-domain' +import { Query } from '@lux/packages/database' +import getDomain from '@lux/utils/get-domain' import createPageLinks from '../utils/create-page-links' -import type Controller from '../../../../controller' -import type { Document } from '../../../../jsonapi' +import type Controller from '@lux/packages/controller' +import type { Document } from '@lux/packages/jsonapi' import type { Action } from '../interfaces' /** @@ -12,10 +12,9 @@ import type { Action } from '../interfaces' */ export default function resource( action: Action, - controller: Controller + controller: Controller, ): Action { - // eslint-disable-next-line func-names - const resourceAction = async function (req, res) { + const resourceAction = async (req, res) => { const { name: actionName } = action const result = action(req, res) let links: $PropertyType = {} @@ -23,10 +22,7 @@ export default function resource( let total if (actionName === 'index' && result instanceof Query) { - [data, total] = await Promise.all([ - result, - Query.from(result).count() - ]) + [data, total] = await Promise.all([result, Query.from(result).count()]) } else { data = await result } @@ -55,7 +51,7 @@ export default function resource( links = { self } } else if (actionName !== 'index' && !namespace) { links = { - self: domain + (path || '') + self: domain + (path || ''), } } @@ -63,7 +59,7 @@ export default function resource( data, links, domain, - include + include, }) } @@ -76,9 +72,6 @@ export default function resource( }, isFinal: { value: action.isFinal, - writable: false, - enumerable: false, - configurable: false, }, }) diff --git a/src/packages/router/route/action/index.js b/src/packages/router/route/action/index.js index e9594e5b..2394192d 100644 --- a/src/packages/router/route/action/index.js +++ b/src/packages/router/route/action/index.js @@ -1,6 +1,6 @@ /* @flow */ -import type Controller from '../../../controller' +import type Controller from '@lux/packages/controller' import resource from './enhancers/resource' import type { Action } from './interfaces' @@ -11,7 +11,7 @@ import type { Action } from './interfaces' export function createAction( type: string, action: Action, - controller: Controller + controller: Controller, ): Array> { let fn = action.bind(controller) @@ -26,11 +26,7 @@ export function createAction( fn = resource(fn, controller) } - return [ - ...controller.beforeAction, - fn, - ...controller.afterAction, - ] + return [...controller.beforeAction, fn, ...controller.afterAction] } export { FINAL_HANDLER } from './constants' diff --git a/src/packages/router/route/action/interfaces.js b/src/packages/router/route/action/interfaces.js index 60e0ef99..8590ed95 100644 --- a/src/packages/router/route/action/interfaces.js +++ b/src/packages/router/route/action/interfaces.js @@ -1,6 +1,10 @@ /* @flow */ -import type Request from '../../../request'; -import type Response from '../../../response'; +import type Request from '@lux/packages/request' +import type Response from '@lux/packages/response' -export type Action = (request: Request, response: Response) => Promise; +export type Action = ( + request: Request, + response: Response, + data?: T, +) => Promise diff --git a/src/packages/router/route/action/utils/create-page-links.js b/src/packages/router/route/action/utils/create-page-links.js index 91cffff1..14d835db 100644 --- a/src/packages/router/route/action/utils/create-page-links.js +++ b/src/packages/router/route/action/utils/create-page-links.js @@ -1,18 +1,18 @@ /* @flow */ -import omit from '../../../../../utils/omit' -import merge from '../../../../../utils/merge' -import createQueryString from '../../../../../utils/create-query-string' -import type { Params } from '../../../../request' -import type { Document } from '../../../../jsonapi' +import omit from '@lux/utils/omit' +import merge from '@lux/utils/merge' +import createQueryString from '@lux/utils/create-query-string' +import type { Params } from '@lux/packages/request' +import type { Document } from '@lux/packages/jsonapi' type Links = $PropertyType type Options = { - total: number; - params: Params; - domain: string; - pathname: void | string; - defaultPerPage: number; + total: number, + params: Params, + domain: string, + pathname: void | string, + defaultPerPage: number, } function createLinkTemplate(options: Options) { @@ -51,8 +51,8 @@ function createLinkTemplate(options: Options) { } else if (normalized > 1) { const paramsForPage = merge(baseParams, { page: { - number: normalized - } + number: normalized, + }, }) return queryURL + createQueryString(paramsForPage) @@ -62,7 +62,7 @@ function createLinkTemplate(options: Options) { } } - return () => null + return (..._) => null } /** diff --git a/src/packages/router/route/index.js b/src/packages/router/route/index.js index eddcd097..3b138285 100644 --- a/src/packages/router/route/index.js +++ b/src/packages/router/route/index.js @@ -1,61 +1,54 @@ /* @flow */ -import { FreezeableSet, freezeProps, deepFreezeProps } from '../../freezeable' -import type Controller from '../../controller' -import type Request, { Method } from '../../request' -import type Response from '../../response' +import { + FreezeableSet, + freezeProps, + deepFreezeProps, +} from '@lux/packages/freezeable' +import type Controller from '@lux/packages/controller' +import type Request, { Method } from '@lux/packages/request' +import type Response from '@lux/packages/response' import { createAction } from './action' import { paramsFor, defaultParamsFor, validateResourceId } from './params' import getStaticPath from './utils/get-static-path' import getDynamicSegments from './utils/get-dynamic-segments' -// eslint-disable-next-line no-duplicate-imports import type { Action } from './action' -// eslint-disable-next-line no-duplicate-imports import type { ParameterGroup } from './params' -export type Type = - | 'custom' - | 'member' - | 'collection' +export type Type = 'custom' | 'member' | 'collection' export type Options = { - type: Type; - path: string; - action: string; - method: Method; - controller: Controller; + type: Type, + path: string, + action: string, + method: Method, + controller: Controller, } /** * @private */ class Route extends FreezeableSet> { - type: string; + type: string - path: string; + path: string - action: string; + action: string - params: ParameterGroup; + params: ParameterGroup - method: Method; + method: Method - controller: Controller; + controller: Controller - staticPath: string; + staticPath: string - defaultParams: Object; + defaultParams: Object - dynamicSegments: Array; + dynamicSegments: Array - constructor({ - type, - path, - action, - method, - controller - }: Options) { + constructor({ type, path, action, method, controller }: Options) { const dynamicSegments = getDynamicSegments(path) if (action && controller) { @@ -66,14 +59,14 @@ class Route extends FreezeableSet> { type, method, controller, - dynamicSegments + dynamicSegments, }) const staticPath = getStaticPath(path, dynamicSegments) const defaultParams = defaultParamsFor({ type, - controller + controller, }) super(createAction(type, handler, controller)) @@ -87,40 +80,32 @@ class Route extends FreezeableSet> { controller, staticPath, defaultParams, - dynamicSegments + dynamicSegments, }) - freezeProps(this, true, - 'type', - 'path' - ) + freezeProps(this, true, 'type', 'path') - freezeProps(this, false, + freezeProps( + this, + false, 'action', 'params', 'method', 'controller', - 'staticPath' + 'staticPath', ) - deepFreezeProps(this, false, - 'defaultParams', - 'dynamicSegments' - ) + deepFreezeProps(this, false, 'defaultParams', 'dynamicSegments') } else { - const { - constructor: { - name: controllerName - } - } = controller + const { constructor: { name: controllerName } } = controller throw new TypeError( - `Handler for ${controllerName}#${action} is not a function.` + `Handler for ${controllerName}#${action} is not a function.`, ) } } else { throw new TypeError( - 'Arguments `controller` and `action` must not be undefined' + 'Arguments `controller` and `action` must not be undefined', ) } @@ -134,7 +119,7 @@ class Route extends FreezeableSet> { if (key) { return { ...result, - [key]: Number.parseInt(value, 10) + [key]: Number.parseInt(value, 10), } } @@ -146,6 +131,7 @@ class Route extends FreezeableSet> { let calledFinal = false let data + // eslint-disable-next-line no-restricted-syntax for (const handler of this) { // eslint-disable-next-line no-await-in-loop data = await handler(req, res, data) @@ -166,7 +152,7 @@ class Route extends FreezeableSet> { const { defaultParams } = this let params = { ...request.params, - ...this.parseParams(request.url.params) + ...this.parseParams(request.url.params), } if (request.method !== 'OPTIONS') { diff --git a/src/packages/router/route/interfaces.js b/src/packages/router/route/interfaces.js index 83978349..642d885f 100644 --- a/src/packages/router/route/interfaces.js +++ b/src/packages/router/route/interfaces.js @@ -1,17 +1,14 @@ /* @flow */ -import type Controller from '../../controller'; -import type { Method } from '../../request'; +import type Controller from '@lux/packages/controller' +import type { Method } from '@lux/packages/request' -export type Route$type = - | 'custom' - | 'member' - | 'collection'; +export type Route$type = 'custom' | 'member' | 'collection' export type Route$opts = { - type: Route$type; - path: string; - action: string; - method: Method; - controller: Controller; -}; + type: Route$type, + path: string, + action: string, + method: Method, + controller: Controller, +} diff --git a/src/packages/router/route/params/__tests__/parameter-group.test.js b/src/packages/router/route/params/__tests__/parameter-group.test.js index b803f94b..8419f264 100644 --- a/src/packages/router/route/params/__tests__/parameter-group.test.js +++ b/src/packages/router/route/params/__tests__/parameter-group.test.js @@ -8,42 +8,54 @@ describe('module "router/route/params"', () => { let subject: ParameterGroup beforeAll(() => { - subject = new ParameterGroup([ - ['id', new Parameter({ - type: 'number', - path: 'id', - required: true - })], - ['meta', new ParameterGroup([ - ['date', new Parameter({ - type: 'string', - path: 'meta.date', - required: true - })], - ['vowel', new Parameter({ - type: 'string', - path: 'meta.vowel', - values: [ - 'a', - 'e', - 'i', - 'o', - 'u' - ] - })], - ], { - path: 'meta', - sanitize: true - })] - ], { - path: '', - required: true - }) + subject = new ParameterGroup( + [ + [ + 'id', + new Parameter({ + type: 'number', + path: 'id', + required: true, + }), + ], + [ + 'meta', + new ParameterGroup( + [ + [ + 'date', + new Parameter({ + type: 'string', + path: 'meta.date', + required: true, + }), + ], + [ + 'vowel', + new Parameter({ + type: 'string', + path: 'meta.vowel', + values: ['a', 'e', 'i', 'o', 'u'], + }), + ], + ], + { + path: 'meta', + sanitize: true, + }, + ), + ], + ], + { + path: '', + required: true, + }, + ) }) describe('#validate()', () => { test('returns null when then value is null', () => { - // $FlowIgnore + // $FlowFixMe expect(subject.validate(null)).toBeNull() }) @@ -58,8 +70,8 @@ describe('module "router/route/params"', () => { subject.validate({ id: '1', meta: { - date: Date.now() - } + date: Date.now(), + }, }) }).toThrow() }) @@ -70,8 +82,8 @@ describe('module "router/route/params"', () => { id: 1, meta: { date: new Date().toISOString(), - vowel: 'p' - } + vowel: 'p', + }, }) }).toThrow() }) @@ -81,8 +93,8 @@ describe('module "router/route/params"', () => { id: 1, meta: { date: Date(), - vowel: 'a' - } + vowel: 'a', + }, } expect(subject.validate(params)).toEqual(params) @@ -98,14 +110,14 @@ describe('module "router/route/params"', () => { meta: { date: Date(), colors: ['red', 'green', 'blue'], - } + }, } expect(subject.validate(params)).toEqual({ id: 1, meta: { - date: params.meta.date - } + date: params.meta.date, + }, }) }) }) diff --git a/src/packages/router/route/params/__tests__/parameter.test.js b/src/packages/router/route/params/__tests__/parameter.test.js index 0ebba48f..affb0999 100644 --- a/src/packages/router/route/params/__tests__/parameter.test.js +++ b/src/packages/router/route/params/__tests__/parameter.test.js @@ -11,31 +11,31 @@ describe('module "router/route/params"', () => { type: 'boolean', valid: true, falsy: false, - invalid: 'true' + invalid: 'true', }, { type: 'string', valid: 'test', falsy: '', - invalid: 1 + invalid: 1, }, { type: 'number', valid: 1, falsy: 0, - invalid: '1' - } + invalid: '1', + }, ] describe('- type "array"', () => { - [true, false].forEach(required => { + ;[true, false].forEach(required => { describe(`- ${required ? 'required' : 'optional'}`, () => { beforeEach(() => { subject = new Parameter({ required, type: 'array', path: 'meta.test', - values: [1, 'test', false] + values: [1, 'test', false], }) }) @@ -58,17 +58,14 @@ describe('module "router/route/params"', () => { }) test('returns the value when the type and value match', () => { - expect(subject.validate(['test', false])).toEqual([ - 'test', - false - ]) + expect(subject.validate(['test', false])).toEqual(['test', false]) }) }) }) }) describe('- type "buffer"', () => { - [true, false].forEach(required => { + ;[true, false].forEach(required => { describe(`- ${required ? 'required' : 'optional'}`, () => { let value @@ -77,7 +74,7 @@ describe('module "router/route/params"', () => { subject = new Parameter({ required, type: 'buffer', - path: 'meta.test' + path: 'meta.test', }) }) @@ -103,7 +100,7 @@ describe('module "router/route/params"', () => { }) describe('- type "object"', () => { - [true, false].forEach(required => { + ;[true, false].forEach(required => { describe(`- ${required ? 'required' : 'optional'}`, () => { let value @@ -112,7 +109,7 @@ describe('module "router/route/params"', () => { subject = new Parameter({ required, type: 'object', - path: 'meta.test' + path: 'meta.test', }) }) @@ -138,7 +135,7 @@ describe('module "router/route/params"', () => { }) describe('- type "date"', () => { - [true, false].forEach(required => { + ;[true, false].forEach(required => { describe(`- ${required ? 'required' : 'optional'}`, () => { let value @@ -147,7 +144,7 @@ describe('module "router/route/params"', () => { subject = new Parameter({ required, type: 'date', - path: 'meta.test' + path: 'meta.test', }) }) @@ -174,13 +171,13 @@ describe('module "router/route/params"', () => { primitives.forEach(({ type, valid, falsy, invalid }) => { describe(`- type "${type}"`, () => { - [true, false].forEach(required => { + ;[true, false].forEach(required => { describe(`- ${required ? 'required' : 'optional'}`, () => { beforeEach(() => { subject = new Parameter({ type, required, - path: 'meta.test' + path: 'meta.test', }) }) diff --git a/src/packages/router/route/params/__tests__/params.test.js b/src/packages/router/route/params/__tests__/params.test.js index 4ad07f1b..1998e271 100644 --- a/src/packages/router/route/params/__tests__/params.test.js +++ b/src/packages/router/route/params/__tests__/params.test.js @@ -2,7 +2,7 @@ import { paramsFor, defaultParamsFor } from '../index' import { getTestApp } from '../../../../../../test/utils/test-app' -import type Controller from '../../../../controller' +import type Controller from '@lux/packages/controller' describe('module "router/route/params"', () => { let app @@ -19,7 +19,7 @@ describe('module "router/route/params"', () => { let getController beforeAll(() => { - // $FlowIgnore + // $FlowFixMe getController = (name: string): Controller => app.controllers.get(name) }) @@ -31,7 +31,7 @@ describe('module "router/route/params"', () => { type: 'custom', method: 'GET', controller: getController('custom'), - dynamicSegments: [] + dynamicSegments: [], }) }) @@ -45,7 +45,7 @@ describe('module "router/route/params"', () => { let getController beforeAll(() => { - // $FlowIgnore + // $FlowFixMe getController = (name: string): Controller => app.controllers.get(name) }) @@ -57,7 +57,7 @@ describe('module "router/route/params"', () => { controller = getController('posts') params = defaultParamsFor({ controller, - type: 'collection' + type: 'collection', }) }) @@ -65,7 +65,7 @@ describe('module "router/route/params"', () => { expect(params).toEqual( expect.objectContaining({ sort: expect.anything(), - }) + }), ) }) @@ -76,7 +76,7 @@ describe('module "router/route/params"', () => { size: expect.anything(), number: expect.anything(), }, - }) + }), ) }) @@ -88,7 +88,7 @@ describe('module "router/route/params"', () => { fields: expect.objectContaining({ [model.resourceName]: attributes, }), - }) + }), ) }) }) @@ -101,7 +101,7 @@ describe('module "router/route/params"', () => { controller = getController('posts') params = defaultParamsFor({ controller, - type: 'member' + type: 'member', }) }) @@ -113,7 +113,7 @@ describe('module "router/route/params"', () => { fields: expect.objectContaining({ [model.resourceName]: attributes, }), - }) + }), ) }) }) @@ -124,7 +124,7 @@ describe('module "router/route/params"', () => { beforeAll(() => { params = defaultParamsFor({ type: 'custom', - controller: getController('posts') + controller: getController('posts'), }) }) @@ -139,7 +139,7 @@ describe('module "router/route/params"', () => { beforeAll(() => { params = defaultParamsFor({ type: 'custom', - controller: getController('health') + controller: getController('health'), }) }) diff --git a/src/packages/router/route/params/errors/parameter-type-error.js b/src/packages/router/route/params/errors/parameter-type-error.js index 5058511c..24fae68c 100644 --- a/src/packages/router/route/params/errors/parameter-type-error.js +++ b/src/packages/router/route/params/errors/parameter-type-error.js @@ -1,6 +1,6 @@ /* @flow */ -import { line } from '../../../../logger' +import { line } from '@lux/packages/logger' import createServerError from '../../../../../errors/utils/create-server-error' import type { ParameterLike } from '../index' diff --git a/src/packages/router/route/params/errors/parameter-value-error.js b/src/packages/router/route/params/errors/parameter-value-error.js index bdbfdec9..ad5ffc2c 100644 --- a/src/packages/router/route/params/errors/parameter-value-error.js +++ b/src/packages/router/route/params/errors/parameter-value-error.js @@ -1,6 +1,6 @@ /* @flow */ -import { line } from '../../../../logger' +import { line } from '@lux/packages/logger' import createServerError from '../../../../../errors/utils/create-server-error' import type { ParameterLike } from '../index' diff --git a/src/packages/router/route/params/errors/resource-mismatch-error.js b/src/packages/router/route/params/errors/resource-mismatch-error.js index 3ceb32e5..40814186 100644 --- a/src/packages/router/route/params/errors/resource-mismatch-error.js +++ b/src/packages/router/route/params/errors/resource-mismatch-error.js @@ -1,7 +1,7 @@ /* @flow */ import createServerError from '../../../../../errors/utils/create-server-error' -import { line } from '../../../../logger' +import { line } from '@lux/packages/logger' /** * @private diff --git a/src/packages/router/route/params/index.js b/src/packages/router/route/params/index.js index 2d6877bd..5b9a41c1 100644 --- a/src/packages/router/route/params/index.js +++ b/src/packages/router/route/params/index.js @@ -1,6 +1,6 @@ /* @flow */ -import type Controller from '../../../controller' +import type Controller from '@lux/packages/controller' import ParameterGroup from './parameter-group' import getURLParams from './utils/get-url-params' @@ -11,7 +11,7 @@ import type { Params$opts } from './interfaces' import { getMemberQueryParams, getCollectionQueryParams, - getCustomParams + getCustomParams, } from './utils/get-query-params' /** @@ -21,44 +21,29 @@ export function paramsFor({ type, method, controller, - dynamicSegments + dynamicSegments, }: Params$opts) { let params = getURLParams(dynamicSegments) if (type === 'member') { - params = [ - ...params, - ...getMemberQueryParams(controller) - ] + params = [...params, ...getMemberQueryParams(controller)] if (method === 'POST' || method === 'PATCH') { - params = [ - ...params, - getDataParams(controller, true) - ] + params = [...params, getDataParams(controller, true)] } } else if (type === 'collection') { - params = [ - ...params, - ...getCollectionQueryParams(controller) - ] + params = [...params, ...getCollectionQueryParams(controller)] if (method === 'POST' || method === 'PATCH') { - params = [ - ...params, - getDataParams(controller, false) - ] + params = [...params, getDataParams(controller, false)] } } else if (type === 'custom') { - params = [ - ...params, - ...getCustomParams(controller) - ] + params = [...params, ...getCustomParams(controller)] } return new ParameterGroup(params, { path: '', - required: true + required: true, }) } @@ -67,10 +52,10 @@ export function paramsFor({ */ export function defaultParamsFor({ type, - controller + controller, }: { - type: string; - controller: Controller + type: string, + controller: Controller, }): Object { const { hasModel } = controller diff --git a/src/packages/router/route/params/interfaces.js b/src/packages/router/route/params/interfaces.js index f2a004ab..d72f2cf2 100644 --- a/src/packages/router/route/params/interfaces.js +++ b/src/packages/router/route/params/interfaces.js @@ -1,30 +1,30 @@ /* @flow */ -import type Controller from '../../../controller'; -import type { Route$type } from '../index'; -import type { Method } from '../../../request'; -import type { Lux$Collection } from '../../../../interfaces'; +import type Controller from '@lux/packages/controller' +import type { Route$type } from '../index' +import type { Method } from '@lux/packages/request' +import type { Lux$Collection } from '../../../../interfaces' export type Params$opts = { - type: Route$type; - method: Method; - controller: Controller; - dynamicSegments: Array; -}; + type: Route$type, + method: Method, + controller: Controller, + dynamicSegments: Array, +} export type ParameterLike$opts = { - path: string; - type?: string; - values?: Array; - required?: boolean; - sanitize?: boolean; -}; + path: string, + type?: string, + values?: Array, + required?: boolean, + sanitize?: boolean, +} export interface ParameterLike extends Lux$Collection { - path: string; - type: string; - required: boolean; - sanitize: boolean; + path: string, + type: string, + required: boolean, + sanitize: boolean, - validate(value: V): V; + validate(value: V): V, } diff --git a/src/packages/router/route/params/parameter-group/index.js b/src/packages/router/route/params/parameter-group/index.js index 104cfa99..122dcb37 100644 --- a/src/packages/router/route/params/parameter-group/index.js +++ b/src/packages/router/route/params/parameter-group/index.js @@ -1,9 +1,8 @@ /* @flow */ -import { FreezeableMap } from '../../../../freezeable' +import { FreezeableMap } from '@lux/packages/freezeable' import { InvalidParameterError } from '../errors' -import isNull from '../../../../../utils/is-null' -import entries from '../../../../../utils/entries' +import { isNull } from '@lux/utils/is-type' import validateType from '../utils/validate-type' import type { ParameterLike, ParameterLike$opts } from '../index' @@ -13,26 +12,25 @@ import hasRequiredParams from './utils/has-required-params' * @private */ class ParameterGroup extends FreezeableMap { - type: string; + type: string - path: string; + path: string - required: boolean; + required: boolean - sanitize: boolean; + sanitize: boolean - constructor(contents: Array, { - path, - required, - sanitize - }: ParameterLike$opts) { + constructor( + contents: Array, + { path, required, sanitize }: ParameterLike$opts, + ) { super(contents) Object.assign(this, { path, type: 'object', required: Boolean(required), - sanitize: Boolean(sanitize) + sanitize: Boolean(sanitize), }) this.freeze() @@ -53,7 +51,7 @@ class ParameterGroup extends FreezeableMap { path = `${path}.` } - for (const [key, value] of entries(params)) { + Object.entries(params).forEach(([key, value]) => { const match = this.get(key) if (match) { @@ -61,10 +59,10 @@ class ParameterGroup extends FreezeableMap { } else if (!match && !sanitize) { throw new InvalidParameterError(`${path}${key}`) } - } + }) } - // $FlowIgnore + // $FlowFixMe return validated } } diff --git a/src/packages/router/route/params/parameter-group/utils/has-required-params.js b/src/packages/router/route/params/parameter-group/utils/has-required-params.js index e1af7379..5b378c7b 100644 --- a/src/packages/router/route/params/parameter-group/utils/has-required-params.js +++ b/src/packages/router/route/params/parameter-group/utils/has-required-params.js @@ -1,20 +1,20 @@ /* @flow */ import { ParameterRequiredError } from '../../errors' +import hasOwnProperty from '@lux/utils/has-own-property' import type ParameterGroup from '../index' -/** - * @private - */ -export default function hasRequiredParams( +const hasRequiredParams = ( group: ParameterGroup, - params: Object -): boolean { - for (const [key, { path, required }] of group) { - if (required && !Reflect.has(params, key)) { + params: T, +): boolean => { + group.forEach(({ path, required }, key) => { + if (required && !hasOwnProperty(params, key)) { throw new ParameterRequiredError(path) } - } + }) return true } + +export default hasRequiredParams diff --git a/src/packages/router/route/params/parameter/index.js b/src/packages/router/route/params/parameter/index.js index 8bb62327..a700b8a3 100644 --- a/src/packages/router/route/params/parameter/index.js +++ b/src/packages/router/route/params/parameter/index.js @@ -1,6 +1,6 @@ /* @flow */ -import { FreezeableSet } from '../../../../freezeable' +import { FreezeableSet } from '@lux/packages/freezeable' import validateType from '../utils/validate-type' import validateValue from './utils/validate-value' @@ -10,28 +10,22 @@ import type { Parameter$opts } from './interfaces' * @private */ class Parameter extends FreezeableSet { - path: string; + path: string - type: string; + type: string - required: boolean; + required: boolean - sanitize: boolean; + sanitize: boolean - constructor({ - path, - type, - values, - required, - sanitize - }: Parameter$opts) { + constructor({ path, type, values, required, sanitize }: Parameter$opts) { super(values) Object.assign(this, { path, type, required: Boolean(required), - sanitize: Boolean(sanitize) + sanitize: Boolean(sanitize), }) this.freeze() diff --git a/src/packages/router/route/params/parameter/interfaces.js b/src/packages/router/route/params/parameter/interfaces.js index b52ab6e9..929e0310 100644 --- a/src/packages/router/route/params/parameter/interfaces.js +++ b/src/packages/router/route/params/parameter/interfaces.js @@ -1,7 +1,7 @@ /* @flow */ -import type { ParameterLike$opts } from '../index'; +import type { ParameterLike$opts } from '../index' export type Parameter$opts = ParameterLike$opts & { - values?: Array; -}; + values?: Array, +} diff --git a/src/packages/router/route/params/parameter/utils/validate-value.js b/src/packages/router/route/params/parameter/utils/validate-value.js index 90628737..bf5da359 100644 --- a/src/packages/router/route/params/parameter/utils/validate-value.js +++ b/src/packages/router/route/params/parameter/utils/validate-value.js @@ -1,6 +1,6 @@ /* @flow */ -import isNull from '../../../../../../utils/is-null' +import { isNull } from '@lux/utils/is-type' import { ParameterValueError, ResourceMismatchError } from '../../errors' import type Parameter from '../index' @@ -17,7 +17,7 @@ function validateOne(param: Parameter, value: V): V { switch (param.path) { case 'data.type': - [expected] = [...param.values()] + ;[expected] = [...param.values()] throw new ResourceMismatchError(param.path, expected, value) default: @@ -37,9 +37,7 @@ export default function validateValue(param: Parameter, value: V): V { return value.filter(item => param.has(item)) } - for (const item of value) { - validateOne(param, item) - } + value.forEach(item => validateOne(param, item)) } else { validateOne(param, value) } diff --git a/src/packages/router/route/params/utils/get-data-params.js b/src/packages/router/route/params/utils/get-data-params.js index 57198336..e6ed4114 100644 --- a/src/packages/router/route/params/utils/get-data-params.js +++ b/src/packages/router/route/params/utils/get-data-params.js @@ -2,9 +2,9 @@ import Parameter from '../parameter' import ParameterGroup from '../parameter-group' -import isNull from '../../../../../utils/is-null' -import { typeForColumn } from '../../../../database' -import type Controller from '../../../../controller' +import { isNull } from '@lux/utils/is-type' +import { typeForColumn } from '@lux/packages/database' +import type Controller from '@lux/packages/controller' import type { ParameterLike } from '../interfaces' /** @@ -18,25 +18,29 @@ function getIDParam({ model }: Controller): [string, ParameterLike] { primaryKeyType = typeForColumn(primaryKeyColumn) } - return ['id', new Parameter({ - type: primaryKeyType, - path: 'data.id', - required: true - })] + return [ + 'id', + new Parameter({ + type: primaryKeyType, + path: 'data.id', + required: true, + }), + ] } /** * @private */ -function getTypeParam({ - model -}: Controller): [string, ParameterLike] { - return ['type', new Parameter({ - type: 'string', - path: 'data.type', - values: [model.resourceName], - required: true - })] +function getTypeParam({ model }: Controller): [string, ParameterLike] { + return [ + 'type', + new Parameter({ + type: 'string', + path: 'data.type', + values: [model.resourceName], + required: true, + }), + ] } /** @@ -44,27 +48,30 @@ function getTypeParam({ */ function getAttributesParam({ model, - params + params, }: Controller): [string, ParameterLike] { - return ['attributes', new ParameterGroup(params.reduce((group, param) => { - const col = model.columnFor(param) - - if (col) { - const type = typeForColumn(col) - const path = `data.attributes.${param}` - const required = !col.nullable && isNull(col.defaultValue) - - return [ - ...group, - [param, new Parameter({ type, path, required })] - ] - } - - return group - }, []), { - path: 'data.attributes', - sanitize: true - })] + return [ + 'attributes', + new ParameterGroup( + params.reduce((group, param) => { + const col = model.columnFor(param) + + if (col) { + const type = typeForColumn(col) + const path = `data.attributes.${param}` + const required = !col.nullable && isNull(col.defaultValue) + + return [...group, [param, new Parameter({ type, path, required })]] + } + + return group + }, []), + { + path: 'data.attributes', + sanitize: true, + }, + ), + ] } /** @@ -72,68 +79,101 @@ function getAttributesParam({ */ function getRelationshipsParam({ model, - params + params, }: Controller): [string, ParameterLike] { - return ['relationships', new ParameterGroup(params.reduce((group, param) => { - const path = `data.relationships.${param}` - const opts = model.relationshipFor(param) - - if (!opts) { - return group - } - - if (opts.type === 'hasMany') { - return [ - ...group, - - [param, new ParameterGroup([ - ['data', new Parameter({ - type: 'array', - path: `${path}.data`, - required: true - })] - ], { - path - })] - ] - } - - const primaryKeyColumn = opts.model.columnFor(opts.model.primaryKey) - let primaryKeyType = 'number' - - if (primaryKeyColumn) { - primaryKeyType = typeForColumn(primaryKeyColumn) - } - - return [ - ...group, - - [param, new ParameterGroup([ - ['data', new ParameterGroup([ - ['id', new Parameter({ - type: primaryKeyType, - path: `${path}.data.id`, - required: true - })], - - ['type', new Parameter({ - type: 'string', - path: `${path}.data.type`, - values: [opts.model.resourceName], - required: true - })] - ], { - type: 'array', - path: `${path}.data`, - required: true - })] - ], { - path - })] - ] - }, []), { - path: 'data.relationships' - })] + return [ + 'relationships', + new ParameterGroup( + params.reduce((group, param) => { + const path = `data.relationships.${param}` + const opts = model.relationshipFor(param) + + if (!opts) { + return group + } + + if (opts.type === 'hasMany') { + return [ + ...group, + + [ + param, + new ParameterGroup( + [ + [ + 'data', + new Parameter({ + type: 'array', + path: `${path}.data`, + required: true, + }), + ], + ], + { + path, + }, + ), + ], + ] + } + + const primaryKeyColumn = opts.model.columnFor(opts.model.primaryKey) + let primaryKeyType = 'number' + + if (primaryKeyColumn) { + primaryKeyType = typeForColumn(primaryKeyColumn) + } + + return [ + ...group, + + [ + param, + new ParameterGroup( + [ + [ + 'data', + new ParameterGroup( + [ + [ + 'id', + new Parameter({ + type: primaryKeyType, + path: `${path}.data.id`, + required: true, + }), + ], + + [ + 'type', + new Parameter({ + type: 'string', + path: `${path}.data.type`, + values: [opts.model.resourceName], + required: true, + }), + ], + ], + { + type: 'array', + path: `${path}.data`, + required: true, + }, + ), + ], + ], + { + path, + }, + ), + ], + ] + }, []), + { + path: 'data.relationships', + }, + ), + ] } /** @@ -141,7 +181,7 @@ function getRelationshipsParam({ */ export default function getDataParams( controller: Controller, - includeID: boolean + includeID: boolean, ): [string, ParameterLike] { let params = [getTypeParam(controller)] @@ -149,19 +189,19 @@ export default function getDataParams( params = [ getAttributesParam(controller), getRelationshipsParam(controller), - ...params + ...params, ] if (includeID) { - params = [ - getIDParam(controller), - ...params - ] + params = [getIDParam(controller), ...params] } } - return ['data', new ParameterGroup(params, { - path: 'data', - required: true - })] + return [ + 'data', + new ParameterGroup(params, { + path: 'data', + required: true, + }), + ] } diff --git a/src/packages/router/route/params/utils/get-default-collection-params.js b/src/packages/router/route/params/utils/get-default-collection-params.js index 63615431..f85c6f1d 100644 --- a/src/packages/router/route/params/utils/get-default-collection-params.js +++ b/src/packages/router/route/params/utils/get-default-collection-params.js @@ -1,6 +1,6 @@ /* @flow */ -import type Controller from '../../../../controller' +import type Controller from '@lux/packages/controller' import getDefaultMemberParams from './get-default-member-params' @@ -14,8 +14,8 @@ function getDefaultCollectionParams(controller: Controller): Object { sort: 'createdAt', page: { size: controller.defaultPerPage, - number: 1 - } + number: 1, + }, } } diff --git a/src/packages/router/route/params/utils/get-default-member-params.js b/src/packages/router/route/params/utils/get-default-member-params.js index a9158d85..53b608ee 100644 --- a/src/packages/router/route/params/utils/get-default-member-params.js +++ b/src/packages/router/route/params/utils/get-default-member-params.js @@ -1,17 +1,13 @@ /* @flow */ -import type Controller from '../../../../controller' +import type Controller from '@lux/packages/controller' /** * @private */ export default function getDefaultMemberParams({ model, - serializer: { - hasOne, - hasMany, - attributes - } + serializer: { hasOne, hasMany, attributes }, }: Controller): Object { return { fields: { @@ -25,9 +21,9 @@ export default function getDefaultMemberParams({ return { ...include, - [opts.model.resourceName]: [opts.model.primaryKey] + [opts.model.resourceName]: [opts.model.primaryKey], } - }, {}) - } + }, {}), + }, } } diff --git a/src/packages/router/route/params/utils/get-query-params.js b/src/packages/router/route/params/utils/get-query-params.js index ddc3bc68..1cdffc50 100644 --- a/src/packages/router/route/params/utils/get-query-params.js +++ b/src/packages/router/route/params/utils/get-query-params.js @@ -2,52 +2,60 @@ import Parameter from '../parameter' import ParameterGroup from '../parameter-group' -import type Controller from '../../../../controller' +import type Controller from '@lux/packages/controller' import type { ParameterLike } from '../interfaces' /** * @private */ function getPageParam(): [string, ParameterLike] { - return ['page', new ParameterGroup([ - ['size', new Parameter({ path: 'page.size', type: 'number' })], - ['number', new Parameter({ path: 'page.number', type: 'number' })] - ], { - path: 'page' - })] + return [ + 'page', + new ParameterGroup( + [ + ['size', new Parameter({ path: 'page.size', type: 'number' })], + ['number', new Parameter({ path: 'page.number', type: 'number' })], + ], + { + path: 'page', + }, + ), + ] } /** * @private */ -function getSortParam({ - sort -}: Controller): [string, ParameterLike] { - return ['sort', new Parameter({ - path: 'sort', - type: 'string', +function getSortParam({ sort }: Controller): [string, ParameterLike] { + return [ + 'sort', + new Parameter({ + path: 'sort', + type: 'string', - values: [ - ...sort, - ...sort.map(value => `-${value}`) - ] - })] + values: [...sort, ...sort.map(value => `-${value}`)], + }), + ] } /** * @private */ -function getFilterParam({ - filter -}: Controller): [string, ParameterLike] { - return ['filter', new ParameterGroup(filter.map(param => [ - param, - new Parameter({ - path: `filter.${param}` - }) - ]), { - path: 'filter' - })] +function getFilterParam({ filter }: Controller): [string, ParameterLike] { + return [ + 'filter', + new ParameterGroup( + filter.map(param => [ + param, + new Parameter({ + path: `filter.${param}`, + }), + ]), + { + path: 'filter', + }, + ), + ] } /** @@ -55,89 +63,100 @@ function getFilterParam({ */ function getFieldsParam({ model, - serializer: { - hasOne, - hasMany, - attributes - } + serializer: { hasOne, hasMany, attributes }, }: Controller): [string, ParameterLike] { const relationships = [...hasOne, ...hasMany] - return ['fields', new ParameterGroup([ - [model.resourceName, new Parameter({ - path: `fields.${model.resourceName}`, - type: 'array', - values: attributes, - sanitize: true - })], - ...relationships.reduce((result, relationship) => { - const opts = model.relationshipFor(relationship) - - if (opts) { - return [ - ...result, - - [opts.model.resourceName, new Parameter({ - path: `fields.${opts.model.resourceName}`, + return [ + 'fields', + new ParameterGroup( + [ + [ + model.resourceName, + new Parameter({ + path: `fields.${model.resourceName}`, type: 'array', + values: attributes, sanitize: true, - - values: [ - opts.model.primaryKey, - ...opts.model.serializer.attributes + }), + ], + ...relationships.reduce((result, relationship) => { + const opts = model.relationshipFor(relationship) + + if (opts) { + return [ + ...result, + + [ + opts.model.resourceName, + new Parameter({ + path: `fields.${opts.model.resourceName}`, + type: 'array', + sanitize: true, + + values: [ + opts.model.primaryKey, + ...opts.model.serializer.attributes, + ], + }), + ], ] - })] - ] - } - - return result - }, []) - ], { - path: 'fields', - sanitize: true - })] + } + + return result + }, []), + ], + { + path: 'fields', + sanitize: true, + }, + ), + ] } /** * @private */ function getIncludeParam({ - serializer: { - hasOne, - hasMany - } + serializer: { hasOne, hasMany }, }: Controller): [string, ParameterLike] { const relationships = [...hasOne, ...hasMany] - return ['include', new Parameter({ - path: 'include', - type: 'array', - values: relationships - })] + return [ + 'include', + new Parameter({ + path: 'include', + type: 'array', + values: relationships, + }), + ] } /** * @private */ export function getCustomParams({ - query + query, }: Controller): Array<[string, ParameterLike]> { - return query.map(param => [param, new Parameter({ - path: param - })]) + return query.map(param => [ + param, + new Parameter({ + path: param, + }), + ]) } /** * @private */ export function getMemberQueryParams( - controller: Controller + controller: Controller, ): Array<[string, ParameterLike]> { if (controller.hasModel) { return [ getFieldsParam(controller), getIncludeParam(controller), - ...getCustomParams(controller) + ...getCustomParams(controller), ] } @@ -148,7 +167,7 @@ export function getMemberQueryParams( * @private */ export function getCollectionQueryParams( - controller: Controller + controller: Controller, ): Array<[string, ParameterLike]> { if (controller.hasModel) { return [ @@ -157,7 +176,7 @@ export function getCollectionQueryParams( getFilterParam(controller), getFieldsParam(controller), getIncludeParam(controller), - ...getCustomParams(controller) + ...getCustomParams(controller), ] } diff --git a/src/packages/router/route/params/utils/get-url-params.js b/src/packages/router/route/params/utils/get-url-params.js index 9c266c1b..1458276e 100644 --- a/src/packages/router/route/params/utils/get-url-params.js +++ b/src/packages/router/route/params/utils/get-url-params.js @@ -7,10 +7,13 @@ import type { ParameterLike } from '../interfaces' * @private */ export default function getURLParams( - dynamicSegments: Array + dynamicSegments: Array, ): Array<[string, ParameterLike]> { - return dynamicSegments.map(param => [param, new Parameter({ - path: param, - required: true - })]) + return dynamicSegments.map(param => [ + param, + new Parameter({ + path: param, + required: true, + }), + ]) } diff --git a/src/packages/router/route/params/utils/validate-resource-id.js b/src/packages/router/route/params/utils/validate-resource-id.js index 5a3817e4..f362c2f2 100644 --- a/src/packages/router/route/params/utils/validate-resource-id.js +++ b/src/packages/router/route/params/utils/validate-resource-id.js @@ -1,18 +1,13 @@ /* @flow */ import { ResourceMismatchError } from '../errors' -import type Request from '../../../../request' +import type Request from '@lux/packages/request' /** * @private */ export default function validateResourceId({ - params: { - id, - data: { - id: resourceId - } - } + params: { id, data: { id: resourceId } }, }: Request): true { if (id !== resourceId) { throw new ResourceMismatchError('data.id', String(id), String(resourceId)) diff --git a/src/packages/router/route/params/utils/validate-type.js b/src/packages/router/route/params/utils/validate-type.js index fe315d4f..061b02bd 100644 --- a/src/packages/router/route/params/utils/validate-type.js +++ b/src/packages/router/route/params/utils/validate-type.js @@ -2,9 +2,7 @@ import ParameterTypeError from '../errors/parameter-type-error' import ParameterNotNullableError from '../errors/parameter-not-nullable-error' -import isNull from '../../../../../utils/is-null' -import isObject from '../../../../../utils/is-object' -import isBuffer from '../../../../../utils/is-buffer' +import { isNull, isObject } from '@lux/utils/is-type' import type { Parameter, ParameterGroup } from '../index' /** @@ -12,7 +10,7 @@ import type { Parameter, ParameterGroup } from '../index' */ export default function validateType( param: Parameter | ParameterGroup, - value: mixed + value: mixed, ): true { const { type, required } = param const valueIsNull = isNull(value) @@ -32,7 +30,7 @@ export default function validateType( break case 'buffer': - isValid = isBuffer(value) + isValid = Buffer.isBuffer(value) break case 'object': diff --git a/src/packages/router/route/utils/get-dynamic-segments.js b/src/packages/router/route/utils/get-dynamic-segments.js index ff362d4e..c0736499 100644 --- a/src/packages/router/route/utils/get-dynamic-segments.js +++ b/src/packages/router/route/utils/get-dynamic-segments.js @@ -1,7 +1,7 @@ /* @flow */ import { DYNAMIC_PATTERN } from '../constants' -import insert from '../../../../utils/insert' +import insert from '@lux/utils/insert' /** * @private diff --git a/src/packages/router/route/utils/get-static-path.js b/src/packages/router/route/utils/get-static-path.js index 1329c1d5..9d93a175 100644 --- a/src/packages/router/route/utils/get-static-path.js +++ b/src/packages/router/route/utils/get-static-path.js @@ -5,7 +5,7 @@ */ export default function getStaticPath( path: string, - dynamicSegments: Array + dynamicSegments: Array, ) { let staticPath = path diff --git a/src/packages/router/utils/create-replacer.js b/src/packages/router/utils/create-replacer.js index 27aad2ac..4b49fba0 100644 --- a/src/packages/router/utils/create-replacer.js +++ b/src/packages/router/utils/create-replacer.js @@ -1,15 +1,14 @@ /* @flow */ -import type Controller from '../../controller' +import type Controller from '@lux/packages/controller' /** * @private */ export default function createReplacer( - controllers: Map + controllers: Map, ): RegExp { - const names = Array - .from(controllers) + const names = Array.from(controllers) .map(([, controller]) => { const { model, namespace } = controller @@ -19,15 +18,11 @@ export default function createReplacer( let { constructor: { name } } = controller - name = name - .replace(/controller/ig, '') - .toLowerCase() + name = name.replace(/controller/gi, '').toLowerCase() return namespace .split('/') - .reduce((str, part) => ( - str.replace(new RegExp(part, 'ig'), '') - ), name) + .reduce((str, part) => str.replace(new RegExp(part, 'ig'), ''), name) }) .filter((str, idx, arr) => idx === arr.lastIndexOf(str)) .join('|') diff --git a/src/packages/serializer/__tests__/serializer.test.js b/src/packages/serializer/__tests__/serializer.test.js index 630ffe83..78c45e8d 100644 --- a/src/packages/serializer/__tests__/serializer.test.js +++ b/src/packages/serializer/__tests__/serializer.test.js @@ -6,9 +6,8 @@ import { getTestApp } from '../../../../test/utils/test-app' const DOMAIN = 'http://localhost:4000' -const linkFor = (type, id) => ( +const linkFor = (type, id) => id ? `${DOMAIN}/${type}/${id}` : `${DOMAIN}/${type}` -) const createSorter = field => { const extractValue = (src: ObjectMap) => { @@ -23,19 +22,20 @@ const createSorter = field => { return 0 } - return (direction = 'asc', tiebreaker = () => 0) => ( - (a: ObjectMap, b: ObjectMap) => { - let result = 0 + return (direction = 'asc', tiebreaker = (..._) => 0) => ( + a: ObjectMap, + b: ObjectMap, + ) => { + let result = 0 - if (direction === 'asc') { - result = extractValue(a) - extractValue(b) - } else { - result = extractValue(b) - extractValue(a) - } - - return result || tiebreaker(a, b) + if (direction === 'asc') { + result = extractValue(a) - extractValue(b) + } else { + result = extractValue(b) - extractValue(a) } - ) + + return result || tiebreaker(a, b) + } } describe('module "serializer"', () => { @@ -57,34 +57,22 @@ describe('module "serializer"', () => { beforeAll(() => { const { store, serializers } = app - const hasOne = [ - 'user', - 'image', - ] + const hasOne = ['user', 'image'] - const hasMany = [ - 'tags', - 'comments', - 'reactions', - ] + const hasMany = ['tags', 'comments', 'reactions'] - const attributes = [ - 'body', - 'title', - 'createdAt', - 'updatedAt', - ] + const attributes = ['body', 'title', 'createdAt', 'updatedAt'] class TestSerializer extends Serializer { - hasOne = hasOne; - hasMany = hasMany; - attributes = attributes; + hasOne = hasOne + hasMany = hasMany + attributes = attributes } class AdminTestSerializer extends Serializer { - hasOne = hasOne; - hasMany = hasMany; - attributes = attributes; + hasOne = hasOne + hasMany = hasMany + attributes = attributes } Post = store.modelFor('post') @@ -165,8 +153,8 @@ describe('module "serializer"', () => { domain: DOMAIN, include: [], links: { - self: linkFor('posts') - } + self: linkFor('posts'), + }, }) result.data.forEach(sortRelationships) @@ -178,10 +166,7 @@ describe('module "serializer"', () => { const result = await adminSubject.format({ data: posts, domain: DOMAIN, - include: [ - 'user', - 'comments', - ], + include: ['user', 'comments'], links: { self: linkFor('admin/posts'), }, @@ -198,9 +183,7 @@ describe('module "serializer"', () => { const result = await subject.format({ data: post, domain: DOMAIN, - include: [ - 'image', - ], + include: ['image'], links: { self: linkFor('posts', id), }, @@ -217,9 +200,7 @@ describe('module "serializer"', () => { const result = await subject.format({ data: post, domain: DOMAIN, - include: [ - 'user', - ], + include: ['user'], links: { self: linkFor('posts', id), }, @@ -236,9 +217,7 @@ describe('module "serializer"', () => { const result = await subject.format({ data: post, domain: DOMAIN, - include: [ - 'comments', - ], + include: ['comments'], links: { self: linkFor('posts', id), }, @@ -255,9 +234,7 @@ describe('module "serializer"', () => { const result = await subject.format({ data: post, domain: DOMAIN, - include: [ - 'tags', - ], + include: ['tags'], links: { self: linkFor('posts', id), }, diff --git a/src/packages/serializer/index.js b/src/packages/serializer/index.js index b529df3d..4d7aa202 100644 --- a/src/packages/serializer/index.js +++ b/src/packages/serializer/index.js @@ -2,16 +2,14 @@ import { dasherize } from 'inflection' -import { VERSION } from '../jsonapi' -import { freezeProps } from '../freezeable' -import uniq from '../../utils/uniq' -import underscore from '../../utils/underscore' -import promiseHash from '../../utils/promise-hash' -import { dasherizeKeys } from '../../utils/transform-keys' -// eslint-disable-next-line no-unused-vars -import type { Model } from '../database' -// eslint-disable-next-line no-duplicate-imports -import type { Document, Resource, Relationship } from '../jsonapi' +import { VERSION } from '@lux/packages/jsonapi' +import { freezeProps } from '@lux/packages/freezeable' +import uniq from '@lux/utils/uniq' +import underscore from '@lux/utils/underscore' +import promiseHash from '@lux/utils/promise-hash' +import { dasherizeKeys } from '@lux/utils/transform-keys' +import type { Model } from '@lux/packages/database' +import type { Document, Resource, Relationship } from '@lux/packages/jsonapi' import type { ObjectMap } from '../../interfaces' type Options = { @@ -43,7 +41,7 @@ type Options = { * 'username', * 'createdAt', * 'updatedAt' - * ]; + * ] * } * ``` * @@ -52,17 +50,17 @@ type Options = { * what the Serializer needs to build the response. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class PostsSerializer extends Serializer { * attributes = [ * 'body', * 'title', * 'createdAt' - * ]; + * ] * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * The Serializer above would result in resources returned from the `/posts` @@ -71,7 +69,7 @@ type Options = { * to add `'isPublic'` to the `attributes` property. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class PostsSerializer extends Serializer { * attributes = [ @@ -79,10 +77,10 @@ type Options = { * 'title', * 'isPublic', * 'createdAt' - * ]; + * ] * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * #### Associations @@ -95,14 +93,14 @@ type Options = { * `hasOne` array property. * * ```javascript - * import { Model } from 'lux-framework'; + * import { Model } from 'lux-framework' * * class Post extends Model { * static hasOne = { * image: { * inverse: 'post' * } - * }; + * } * * static hasMany = { * tags: { @@ -113,16 +111,16 @@ type Options = { * comments: { * inverse: 'post' * } - * }; + * } * * static belongsTo = { * user: { * inverse: 'posts' * } - * }; + * } * } * - * export default Post; + * export default Post * ``` * * To include the `user` and `image` associations in the response returned from @@ -130,37 +128,37 @@ type Options = { * property array of the Serializer. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class PostsSerializer extends Serializer { * hasOne = [ * 'user', * 'image' - * ]; + * ] * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * If we wanted to also include the `tags` and `comments` in the response, we * have to add a `hasMany` array property containing `'tags'` and `'comments'`. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class PostsSerializer extends Serializer { * hasOne = [ * 'user', * 'image' - * ]; + * ] * * hasMany = [ * 'tags', * 'comments' - * ]; + * ] * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * You no longer need to specify that `tags` is a many to many relationship @@ -198,27 +196,27 @@ type Options = { * `app/serializers/posts.js`, you are not required to extend `PostsSerializer`. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class PostsSerializer extends Serializer { * attributes = [ * 'body', * 'title', * 'createdAt' - * ]; + * ] * * hasOne = [ * 'user', * 'image' - * ]; + * ] * * hasMany = [ * 'tags', * 'comments' - * ]; + * ] * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * To add the `isPublic` attribute to the response payload of requests to a @@ -226,7 +224,7 @@ type Options = { * * ```javascript * // app/serializers/admin/posts.js - * import PostsSerializer from 'app/serializers/posts'; + * import PostsSerializer from 'app/serializers/posts' * * class AdminPostsSerializer extends PostsSerializer { * attributes = [ @@ -234,17 +232,17 @@ type Options = { * 'title', * 'isPublic', * 'createdAt' - * ]; + * ] * } * - * export default AdminPostsSerializer; + * export default AdminPostsSerializer * ``` * * OR * * ```javascript * // app/serializers/admin/posts.js - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * class AdminPostsSerializer extends Serializer { * attributes = [ @@ -252,87 +250,87 @@ type Options = { * 'title', * 'isPublic', * 'createdAt' - * ]; + * ] * * hasOne = [ * 'user', * 'image' - * ]; + * ] * * hasMany = [ * 'tags', * 'comments' - * ]; + * ] * } * - * export default AdminPostsSerializer; + * export default AdminPostsSerializer * ``` * * Even with inheritance, the examples above are a tad repetitive. We can * improve this code by exporting constants from `app/serializers/posts.js`. * * ```javascript - * import { Serializer } from 'lux-framework'; + * import { Serializer } from 'lux-framework' * * export const HAS_ONE = [ * 'user', * 'image' - * ]; + * ] * * export const HAS_MANY = [ * 'tags', * 'comments' - * ]; + * ] * * export const ATTRIBUTES = [ * 'body', * 'title', * 'createdAt' - * ]; + * ] * * class PostsSerializer extends Serializer { - * hasOne = HAS_ONE; - * hasMany = HAS_MANY; - * attributes = ATTRIBUTES; + * hasOne = HAS_ONE + * hasMany = HAS_MANY + * attributes = ATTRIBUTES * } * - * export default PostsSerializer; + * export default PostsSerializer * ``` * * If we choose to use inheritance, our code can look like this: * * ```javascript * // app/serializers/admin/posts.js - * import PostsSerializer, { ATTRIBUTES } from 'app/serializers/posts'; + * import PostsSerializer, { ATTRIBUTES } from 'app/serializers/posts' * * class AdminPostsSerializer extends PostsSerializer { * attributes = [ * ...ATTRIBUTES, * 'isPublic' - * ]; + * ] * } * - * export default AdminPostsSerializer; + * export default AdminPostsSerializer * ``` * * If we choose not use inheritance, our code can look like this: * * ```javascript * // app/serializers/admin/posts.js - * import { Serializer } from 'lux-framework'; - * import { HAS_ONE, HAS_MANY, ATTRIBUTES } from 'app/serializers/posts'; + * import { Serializer } from 'lux-framework' + * import { HAS_ONE, HAS_MANY, ATTRIBUTES } from 'app/serializers/posts' * * class AdminPostsSerializer extends PostsSerializer { - * hasOne = HAS_ONE; - * hasMany = HAS_MANY; + * hasOne = HAS_ONE + * hasMany = HAS_MANY * * attributes = [ * ...ATTRIBUTES, * 'isPublic' - * ]; + * ] * } * - * export default AdminPostsSerializer; + * export default AdminPostsSerializer * ``` * * @class Serializer @@ -348,7 +346,7 @@ class Serializer { * class PostsSerializer extends Serializer { * hasOne = [ * 'user' - * ]; + * ] * } * ``` * @@ -357,7 +355,7 @@ class Serializer { * @default [] * @public */ - hasOne: Array = []; + hasOne: Array = [] /** * An Array of the `hasMany` relationships on a Serializer instance's Model to @@ -367,7 +365,7 @@ class Serializer { * class PostsSerializer extends Serializer { * hasMany = [ * 'comments' - * ]; + * ] * } * ``` * @@ -376,7 +374,7 @@ class Serializer { * @default [] * @public */ - hasMany: Array = []; + hasMany: Array = [] /** * An array of the `attributes` on a Serializer instance's Model to include in @@ -387,7 +385,7 @@ class Serializer { * attributes = [ * 'body', * 'title' - * ]; + * ] * } * ``` * @@ -396,7 +394,7 @@ class Serializer { * @default [] * @public */ - attributes: Array = []; + attributes: Array = [] /** * The resolved Model that a Serializer instance represents. @@ -405,7 +403,7 @@ class Serializer { * @type {Model} * @private */ - model: Class; + model: Class /** * A reference to the root Serializer for the namespace that a Serializer @@ -415,7 +413,7 @@ class Serializer { * @type {?Serializer} * @private */ - parent: ?Serializer<*>; + parent: ?Serializer<*> /** * The namespace that a Serializer instance is a member of. @@ -424,7 +422,7 @@ class Serializer { * @type {String} * @private */ - namespace: string; + namespace: string constructor(options: Options = {}) { const { model, parent } = options @@ -440,11 +438,7 @@ class Serializer { namespace, }) - freezeProps(this, true, - 'model', - 'parent', - 'namespace' - ) + freezeProps(this, true, 'model', 'parent', 'namespace') } /** @@ -481,12 +475,12 @@ class Serializer { data, links, domain, - include + include, }: { - data: T | Array; - links: $PropertyType; - domain: string; - include: Array; + data: T | Array, + links: $PropertyType, + domain: string, + include: Array, }): Promise { let serialized = {} const included: Array = [] @@ -494,13 +488,15 @@ class Serializer { if (Array.isArray(data)) { serialized = { data: await Promise.all( - data.map(item => this.formatOne({ - item, - domain, - include, - included - })) - ) + data.map(item => + this.formatOne({ + item, + domain, + include, + included, + }), + ), + ), } } else { serialized = { @@ -509,15 +505,15 @@ class Serializer { include, included, item: data, - links: false - }) + links: false, + }), } } if (included.length) { serialized = { ...serialized, - included: uniq(included, 'id', 'type') + included: uniq(included, 'id', 'type'), } } @@ -526,8 +522,8 @@ class Serializer { links, jsonapi: { - version: VERSION - } + version: VERSION, + }, } } @@ -574,14 +570,14 @@ class Serializer { domain, include, included, - formatRelationships = true + formatRelationships = true, }: { - item: T; - links?: boolean; - domain: string; - include: Array; - included: Array; - formatRelationships?: boolean + item: T, + links?: boolean, + domain: string, + include: Array, + included: Array, + formatRelationships?: boolean, }): Promise { const { resourceName: type } = item const id = String(item.getPrimaryKey()) @@ -589,10 +585,10 @@ class Serializer { const attributes = dasherizeKeys( item.getAttributes( - ...Object - .keys(item.rawColumnData) - .filter(key => this.attributes.includes(key)) - ) + ...Object.keys(item.rawColumnData).filter(key => + this.attributes.includes(key), + ), + ), ) const serialized: Resource = { @@ -603,43 +599,46 @@ class Serializer { if (formatRelationships) { relationships = await promiseHash( - [...this.hasOne, ...this.hasMany].reduce((hash, name) => ({ - ...hash, - - [dasherize(underscore(name))]: (async () => { - const related = await Reflect.get(item, name) + [...this.hasOne, ...this.hasMany].reduce( + (hash, name) => ({ + ...hash, + + [dasherize(underscore(name))]: (async () => { + const related = await Reflect.get(item, name) + + if (Array.isArray(related)) { + return { + data: await Promise.all( + related.map(async relatedItem => { + const { + data: relatedData, + } = await this.formatRelationship({ + domain, + included, + item: relatedItem, + include: include.includes(name), + }) + + return relatedData + }), + ), + } + } else if (related && related.id) { + return this.formatRelationship({ + domain, + included, + item: related, + include: include.includes(name), + }) + } - if (Array.isArray(related)) { return { - data: await Promise.all( - related.map(async (relatedItem) => { - const { - data: relatedData - } = await this.formatRelationship({ - domain, - included, - item: relatedItem, - include: include.includes(name) - }) - - return relatedData - }) - ) + data: null, } - } else if (related && related.id) { - return this.formatRelationship({ - domain, - included, - item: related, - include: include.includes(name) - }) - } - - return { - data: null - } - })() - }), {}) + })(), + }), + {}, + ), ) } @@ -652,11 +651,11 @@ class Serializer { if (namespace) { serialized.links = { - self: `${domain}/${namespace}/${type}/${id}` + self: `${domain}/${namespace}/${type}/${id}`, } } else { serialized.links = { - self: `${domain}/${type}/${id}` + self: `${domain}/${type}/${id}`, } } } @@ -696,12 +695,12 @@ class Serializer { item, domain, include, - included + included, }: { - item: Model; - domain: string; - include: boolean; - included: Array; + item: Model, + domain: string, + include: boolean, + included: Array, }): Promise { const { namespace } = this const { resourceName: type, constructor: { serializer } } = item @@ -710,11 +709,11 @@ class Serializer { if (namespace) { links = { - self: `${domain}/${namespace}/${type}/${id}` + self: `${domain}/${namespace}/${type}/${id}`, } } else { links = { - self: `${domain}/${type}/${id}` + self: `${domain}/${type}/${id}`, } } @@ -725,17 +724,17 @@ class Serializer { domain, include: [], included: [], - formatRelationships: false - }) + formatRelationships: false, + }), ) } return { data: { id, - type + type, }, - links + links, } } } diff --git a/src/packages/serializer/interfaces.js b/src/packages/serializer/interfaces.js index ca10e43a..41431c77 100644 --- a/src/packages/serializer/interfaces.js +++ b/src/packages/serializer/interfaces.js @@ -1,10 +1,10 @@ /* @flow */ -import type Serializer from './index'; -import type { Model } from '../database'; +import type Serializer from './index' +import type { Model } from '@lux/packages/database' export type Serializer$opts = { - model: Class; - parent: ?Serializer<*>; - namespace: string; -}; + model: Class, + parent: ?Serializer<*>, + namespace: string, +} diff --git a/src/packages/template/index.js b/src/packages/template/index.js index 2c140d93..95e33a8e 100644 --- a/src/packages/template/index.js +++ b/src/packages/template/index.js @@ -21,7 +21,8 @@ export default function template( indentLevel = /^\s{0,2}(.+)$/g } - return body.split('\n') + return body + .split('\n') .slice(1) .map(line => { let str = line.replace(indentLevel, '$1') diff --git a/src/packages/testing/fetch.js b/src/packages/testing/fetch.js index 78e0259f..0d5b6c9f 100644 --- a/src/packages/testing/fetch.js +++ b/src/packages/testing/fetch.js @@ -1,15 +1,15 @@ /* @flow */ -import { MIME_TYPE } from '../jsonapi' -import type Application from '../application' -import type { Method } from '../request' +import { MIME_TYPE } from '@lux/packages/jsonapi' +import type Application from '@lux/packages/application' +import type { Method } from '@lux/packages/request' type Options = { - body?: Object; - mode?: string; - cache?: string; - method?: Method; - headers?: Object; + body?: Object, + mode?: string, + cache?: string, + method?: Method, + headers?: Object, } export type Fetch = (url: string, options: Options) => Promise @@ -20,7 +20,7 @@ const getDefaultHeaders = () => ({ }) export function mockFetch({ exec }: Application): Fetch { - return (url, { method = 'GET', headers = {} }) => ( + return (url, { method = 'GET', headers = {} }) => new Promise(resolve => { exec({ url, @@ -29,5 +29,4 @@ export function mockFetch({ exec }: Application): Fetch { headers: Object.assign(getDefaultHeaders(), headers), }) }) - ) } diff --git a/src/types.js b/src/types.js new file mode 100644 index 00000000..f71ae355 --- /dev/null +++ b/src/types.js @@ -0,0 +1,7 @@ +/* @flow */ + +export type Environment = 'development' | 'production' | 'test' + +export type ObjectMap = { + [key: string]: T, +} diff --git a/src/utils/__mocks__/fs.js b/src/utils/__mocks__/fs.js new file mode 100644 index 00000000..d5944ba4 --- /dev/null +++ b/src/utils/__mocks__/fs.js @@ -0,0 +1,45 @@ +/* @flow */ + +import MemoryFileSystem from 'memory-fs' + +const fs = new MemoryFileSystem() + +export const reset = () => { + fs.data = {} +} + +export const stat = jest.fn().mockImplementation((...args) => { + fs.stat(...args) +}) + +export const readdir = jest.fn().mockImplementation((...args) => { + fs.readdir(...args) +}) + +export const rmdir = jest.fn().mockImplementation((...args) => { + fs.rmdir(...args) +}) + +export const unlink = jest.fn().mockImplementation((...args) => { + fs.unlink(...args) +}) + +export const readlink = jest.fn().mockImplementation((...args) => { + fs.readlink(...args) +}) + +export const mkdir = jest.fn().mockImplementation((...args) => { + fs.mkdir(...args) +}) + +export const readFile = jest.fn().mockImplementation((...args) => { + fs.readFile(...args) +}) + +export const exists = jest.fn().mockImplementation((...args) => { + fs.exists(...args) +}) + +export const writeFile = jest.fn().mockImplementation((...args) => { + fs.writeFile(...args) +}) diff --git a/src/utils/__tests__/__snapshots__/compact.test.js.snap b/src/utils/__tests__/__snapshots__/compact.test.js.snap new file mode 100644 index 00000000..93ea027c --- /dev/null +++ b/src/utils/__tests__/__snapshots__/compact.test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`compact() 1`] = ` +Array [ + 0, + "a", + 1, + Object {}, + false, +] +`; diff --git a/src/utils/__tests__/__snapshots__/entries.test.js.snap b/src/utils/__tests__/__snapshots__/entries.test.js.snap deleted file mode 100644 index 9ef31401..00000000 --- a/src/utils/__tests__/__snapshots__/entries.test.js.snap +++ /dev/null @@ -1,35 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`util entries() - with Object.entries() creates an \`Array\` of key-value pairs from an object 1`] = ` -Array [ - Array [ - "a", - 1, - ], - Array [ - "b", - 2, - ], - Array [ - "c", - 3, - ], -] -`; - -exports[`util entries() - without Object.entries() creates an \`Array\` of key-value pairs from an object 1`] = ` -Array [ - Array [ - "a", - 1, - ], - Array [ - "b", - 2, - ], - Array [ - "c", - 3, - ], -] -`; diff --git a/src/utils/__tests__/__snapshots__/flatten.test.js.snap b/src/utils/__tests__/__snapshots__/flatten.test.js.snap new file mode 100644 index 00000000..68ad8d21 --- /dev/null +++ b/src/utils/__tests__/__snapshots__/flatten.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`#deep() 1`] = ` +Array [ + 1, + 2, + 3, +] +`; + +exports[`#shallow() 1`] = ` +Array [ + 1, + 2, + Array [ + 3, + ], +] +`; diff --git a/src/utils/__tests__/__snapshots__/fs-extras.test.js.snap b/src/utils/__tests__/__snapshots__/fs-extras.test.js.snap new file mode 100644 index 00000000..520e74db --- /dev/null +++ b/src/utils/__tests__/__snapshots__/fs-extras.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`readdirRec() 1`] = ` +Array [ + "y/z/z.txt", + "y/y.txt", + "x.txt", +] +`; diff --git a/src/utils/__tests__/compact.test.js b/src/utils/__tests__/compact.test.js index 990adca1..62089d87 100644 --- a/src/utils/__tests__/compact.test.js +++ b/src/utils/__tests__/compact.test.js @@ -2,30 +2,6 @@ import compact from '../compact' -describe('util compact()', () => { - test('removes null and undefined values from an `Array`', () => { - const result = compact([0, 'a', 1, null, {}, undefined, false]) - - expect(result).toHaveLength(5) - expect(result).not.toContain(null) - expect(result).not.toContain(undefined) - }) - - test('removes null and undefined values from an `Object`', () => { - const values = { - a: 0, - b: 'a', - c: 1, - d: {}, - e: false - } - - const result = compact({ - ...values, - f: null, - g: undefined - }) - - expect(result).toEqual(values) - }) +test('compact()', () => { + expect(compact([0, 'a', 1, null, {}, undefined, false])).toMatchSnapshot() }) diff --git a/src/utils/__tests__/compose.test.js b/src/utils/__tests__/compose.test.js index 1aacc794..469a190a 100644 --- a/src/utils/__tests__/compose.test.js +++ b/src/utils/__tests__/compose.test.js @@ -8,12 +8,12 @@ const log = console.log describe('util compose', () => { describe('.tap()', () => { beforeEach(() => { - // $FlowIgnore + // $FlowFixMe console.log = jest.fn() }) afterEach(() => { - // $FlowIgnore + // $FlowFixMe console.log = log jest.resetAllMocks() }) @@ -28,10 +28,7 @@ describe('util compose', () => { describe('.compose()', () => { test('returns a composed function', () => { - const shout = compose( - str => `${str}!`, - str => str.toUpperCase() - ) + const shout = compose(str => `${str}!`, str => str.toUpperCase()) expect(shout).toHaveLength(1) expect(typeof shout).toBe('function') @@ -43,7 +40,7 @@ describe('util compose', () => { test('returns a composed asyncfunction', () => { const shout = composeAsync( str => Promise.resolve(`${str}!`), - str => Promise.resolve(str.toUpperCase()) + str => Promise.resolve(str.toUpperCase()), ) expect(shout).toEqual(expect.any(Function)) diff --git a/src/utils/__tests__/diff.test.js b/src/utils/__tests__/diff.test.js index e1aca9da..0c9e914c 100644 --- a/src/utils/__tests__/diff.test.js +++ b/src/utils/__tests__/diff.test.js @@ -6,19 +6,12 @@ describe('util diff', () => { describe('.map()', () => { test('returns a map containing the difference between two maps', () => { const result = diff.map( - new Map([ - ['x', 1] - ]), - new Map([ - ['x', 1], - ['y', 2] - ]) + new Map([['x', 1]]), + new Map([['x', 1], ['y', 2]]), ) expect(result instanceof Map).toBe(true) - expect([...result]).toEqual([ - ['y', 2] - ]) + expect([...result]).toEqual([['y', 2]]) }) }) }) diff --git a/src/utils/__tests__/entries.test.js b/src/utils/__tests__/entries.test.js deleted file mode 100644 index 96143a65..00000000 --- a/src/utils/__tests__/entries.test.js +++ /dev/null @@ -1,31 +0,0 @@ -/* @flow */ - -describe('util entries()', () => { - let entries - - describe('- with Object.entries()', () => { - beforeAll(() => { - global.Object.entries = require('object.entries'); - ({ default: entries } = require('../entries')) - }) - - afterAll(() => { - delete global.Object.entries - jest.resetModules() - }) - - test('creates an `Array` of key-value pairs from an object', () => { - expect(entries({ a: 1, b: 2, c: 3 })).toMatchSnapshot() - }) - }) - - describe('- without Object.entries()', () => { - beforeAll(() => { - ({ default: entries } = require('../entries')) - }) - - test('creates an `Array` of key-value pairs from an object', () => { - expect(entries({ a: 1, b: 2, c: 3 })).toMatchSnapshot() - }) - }) -}) diff --git a/src/utils/__tests__/env.test.js b/src/utils/__tests__/env.test.js index e88b0038..353b76b8 100644 --- a/src/utils/__tests__/env.test.js +++ b/src/utils/__tests__/env.test.js @@ -20,3 +20,10 @@ test('isProduction()', () => { test('isTest()', () => { expect(env.isTest()).toBe(true) }) + +test('name()', () => { + ;['development', 'production', 'test'].forEach(name => { + setEnv(name) + expect(env.name()).toBe(name) + }) +}) diff --git a/src/utils/__tests__/flatten.test.js b/src/utils/__tests__/flatten.test.js new file mode 100644 index 00000000..654c3278 --- /dev/null +++ b/src/utils/__tests__/flatten.test.js @@ -0,0 +1,11 @@ +/* @flow */ + +import * as flatten from '@lux/utils/flatten' + +test('#deep()', () => { + expect(flatten.deep([1, [2], [[3]]])).toMatchSnapshot() +}) + +test('#shallow()', () => { + expect(flatten.shallow([1, [2], [[3]]])).toMatchSnapshot() +}) diff --git a/src/utils/__tests__/fs-extras.test.js b/src/utils/__tests__/fs-extras.test.js new file mode 100644 index 00000000..4009c015 --- /dev/null +++ b/src/utils/__tests__/fs-extras.test.js @@ -0,0 +1,93 @@ +/* @flow */ + +import * as mockFs from 'fs' +import * as path from 'path' + +import * as fs from 'mz/fs' + +import * as fse from '@lux/utils/fs-extras' + +jest.mock('fs') + +// $FlowFixMe +afterEach(mockFs.reset) + +describe('rmrf()', () => { + const root = path.join(path.sep, 'x', 'y', 'z') + const file = path.join(root, 'test.json') + + beforeEach(async () => { + await fse.mkdirRec(root) + await fs.writeFile(file, '{}') + }) + + afterEach(async () => { + await fse.rmrf(root) + }) + + test('it can remove a file', async () => { + expect(await fse.rmrf(file)).toBe(true) + expect(await fs.exists(file)).toBe(false) + }) + + test('it can remove a directory and its contents', async () => { + expect(await fse.rmrf(root)).toBe(true) + expect(await fs.exists(root)).toBe(false) + }) + + test('it does not fail if the target does not exist', async () => { + const target = path.join(root, 'not-a-file') + + expect(await fse.rmrf(target)).toBe(true) + }) + + test('valid errors bubble up', async () => { + await fse.rmrf('test').catch(err => { + expect(err).toEqual(expect.any(Error)) + }) + }) +}) + +test('existsInDir()', async () => { + const root = path.join(path.sep, 'test') + + await fs.mkdir(root) + await fs.writeFile(path.join(root, 'package.json'), '{}') + + expect(await fse.existsInDir(root, /\.json$/)).toBe(true) +}) + +test('readdirRec()', async () => { + await fse.mkdirRec(path.join(path.sep, 'x', 'y', 'z')) + await Promise.all([ + fs.writeFile(path.join(path.sep, 'x', 'x.txt'), 'test x'), + fs.writeFile(path.join(path.sep, 'x', 'y', 'y.txt'), 'test y'), + fs.writeFile(path.join(path.sep, 'x', 'y', 'z', 'z.txt'), 'test z'), + ]) + + expect(await fse.readdirRec(path.join(path.sep, 'x'))).toMatchSnapshot() +}) + +describe('mkdirRec()', () => { + test('it can recursively create a directory', async () => { + const target = path.join(path.sep, 'x', 'y', 'z') + + expect(await fs.exists(target)).toBe(false) + + await fse.mkdirRec(target) + expect(await fs.exists(target)).toBe(true) + }) + + test('valid errors still bubble up', async () => { + await fse.mkdirRec('test').catch(err => { + expect(err).toEqual(expect.any(Error)) + }) + }) +}) + +test('isExt()', () => { + const isJSFile = fse.isExt('.js') + + expect(isJSFile('test.js')).toBe(true) + expect(isJSFile('test.json')).toBe(false) +}) diff --git a/src/utils/__tests__/github.test.js b/src/utils/__tests__/github.test.js index f63e0163..25df1a7b 100644 --- a/src/utils/__tests__/github.test.js +++ b/src/utils/__tests__/github.test.js @@ -17,7 +17,7 @@ describe('util github', () => { describe('- with `branch` option', () => { test('builds the correct url', () => { const result = github.fileLink('src/index.js', { - branch: 'branch-name' + branch: 'branch-name', }) expect(result).toBe(`${baseURL}/branch-name/src/index.js`) @@ -27,7 +27,7 @@ describe('util github', () => { describe('- with `line` option', () => { test('builds the correct url', () => { const result = github.fileLink('src/index.js', { - line: 2 + line: 2, }) expect(result).toBe(`${baseURL}/master/src/index.js#2`) @@ -35,7 +35,7 @@ describe('util github', () => { test('ignores line if it is > 0', () => { const result = github.fileLink('src/index.js', { - line: -10 + line: -10, }) expect(result).toBe(`${baseURL}/master/src/index.js`) diff --git a/src/utils/__tests__/has-own-property.test.js b/src/utils/__tests__/has-own-property.test.js index c618530e..31fbf7fd 100644 --- a/src/utils/__tests__/has-own-property.test.js +++ b/src/utils/__tests__/has-own-property.test.js @@ -6,11 +6,14 @@ describe('util hasOwnProperty()', () => { let subject beforeEach(() => { - subject = Object.create({ y: 'y' }, { - x: { - value: 'x' - } - }) + subject = Object.create( + { y: 'y' }, + { + x: { + value: 'x', + }, + }, + ) }) test('returns true when an object has a property', () => { @@ -19,7 +22,7 @@ describe('util hasOwnProperty()', () => { expect(result).toBe(true) }) - test('returns false when an object\'s prototype has a property', () => { + test("returns false when an object's prototype has a property", () => { const result = hasOwnProperty(subject, 'y') expect(result).toBe(false) diff --git a/src/utils/__tests__/is-buffer.test.js b/src/utils/__tests__/is-buffer.test.js deleted file mode 100644 index 0180df0f..00000000 --- a/src/utils/__tests__/is-buffer.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* @flow */ - -import isBuffer from '../is-buffer.js' - -describe('util isBuffer()', () => { - test('returns true when a `Buffer` is passed in as an argument', () => { - expect(isBuffer(new Buffer('', 'utf8'))).toBe(true) - }) -}) diff --git a/src/utils/__tests__/is-null.test.js b/src/utils/__tests__/is-null.test.js deleted file mode 100644 index 1ef146bd..00000000 --- a/src/utils/__tests__/is-null.test.js +++ /dev/null @@ -1,20 +0,0 @@ -/* @flow */ - -import isNull from '../is-null' - -describe('util isNull()', () => { - test('returns false when an `Object` is passed in as an argument', () => { - expect(isNull({})).toBe(false) - }) - - test('returns false when falsy values are passed in as an argument', () => { - expect(isNull(0)).toBe(false) - expect(isNull('')).toBe(false) - expect(isNull(NaN)).toBe(false) - expect(isNull(undefined)).toBe(false) - }) - - test('returns true when `null` is passed in as an argument', () => { - expect(isNull(null)).toBe(true) - }) -}) diff --git a/src/utils/__tests__/is-object.test.js b/src/utils/__tests__/is-object.test.js deleted file mode 100644 index 231ebabe..00000000 --- a/src/utils/__tests__/is-object.test.js +++ /dev/null @@ -1,21 +0,0 @@ -/* @flow */ - -import isObject from '../is-object' - -describe('util isObject()', () => { - test('returns false when an `null` is passed in as an argument', () => { - expect(isObject(null)).toBe(false) - }) - - test('returns false when an `Array` is passed in as an argument', () => { - expect(isObject([])).toBe(false) - }) - - test('returns true when an `Object` is passed in as an argument', () => { - class SomeObject {} - - expect(isObject({})).toBe(true) - expect(isObject(new SomeObject())).toBe(true) - expect(isObject(Object.create(null))).toBe(true) - }) -}) diff --git a/src/utils/__tests__/is-type.js b/src/utils/__tests__/is-type.js new file mode 100644 index 00000000..4b35a39e --- /dev/null +++ b/src/utils/__tests__/is-type.js @@ -0,0 +1,55 @@ +/* @flow */ + +import { + isNil, + isNull, + isObject, + isString, + isUndefined, +} from '@lux/utils/is-type' + +test('isNil()', () => { + expect(isNil(0)).toBe(false) + expect(isNil('')).toBe(false) + expect(isNil(NaN)).toBe(false) + + expect(isNil(null)).toBe(true) + expect(isNil(undefined)).toBe(true) +}) + +test('isNull()', () => { + expect(isNull({})).toBe(false) + expect(isNull(0)).toBe(false) + expect(isNull('')).toBe(false) + expect(isNull(NaN)).toBe(false) + expect(isNull(undefined)).toBe(false) + + expect(isNull(null)).toBe(true) +}) + +test('isObject()', () => { + class SomeObject {} + + expect(isObject(null)).toBe(false) + expect(isObject([])).toBe(false) + + expect(isObject({})).toBe(true) + expect(isObject(new SomeObject())).toBe(true) + expect(isObject(Object.create(null))).toBe(true) +}) + +test('isString()', () => { + expect(isString([])).toBe(false) + + expect(isString('')).toBe(true) +}) + +test('isUndefined()', () => { + expect(isUndefined(0)).toBe(false) + expect(isUndefined('')).toBe(false) + expect(isUndefined(NaN)).toBe(false) + expect(isUndefined(null)).toBe(false) + + expect(isUndefined()).toBe(true) + expect(isUndefined(undefined)).toBe(true) +}) diff --git a/src/utils/__tests__/is-undefined.test.js b/src/utils/__tests__/is-undefined.test.js deleted file mode 100644 index a2a6302f..00000000 --- a/src/utils/__tests__/is-undefined.test.js +++ /dev/null @@ -1,17 +0,0 @@ -/* @flow */ - -import isUndefined from '../is-undefined' - -describe('util isUndefined()', () => { - test('returns false when falsy values are passed in as an argument', () => { - expect(isUndefined(0)).toBe(false) - expect(isUndefined('')).toBe(false) - expect(isUndefined(NaN)).toBe(false) - expect(isUndefined(null)).toBe(false) - }) - - test('returns true when `undefined` is passed in as an argument', () => { - expect(isUndefined()).toBe(true) - expect(isUndefined(undefined)).toBe(true) - }) -}) diff --git a/src/utils/__tests__/map-to-object.test.js b/src/utils/__tests__/map-to-object.test.js index 26e7216d..02862913 100644 --- a/src/utils/__tests__/map-to-object.test.js +++ b/src/utils/__tests__/map-to-object.test.js @@ -4,16 +4,10 @@ import mapToObject from '../map-to-object' describe('util mapToObject()', () => { test('returns an object containing key, value pairs from a map', () => { - expect(mapToObject( - new Map([ - ['x', 1], - ['y', 2], - ['z', 3] - ]) - )).toEqual({ + expect(mapToObject(new Map([['x', 1], ['y', 2], ['z', 3]]))).toEqual({ x: 1, y: 2, - z: 3 + z: 3, }) }) }) diff --git a/src/utils/__tests__/merge.test.js b/src/utils/__tests__/merge.test.js index 92acb600..5c7e802a 100644 --- a/src/utils/__tests__/merge.test.js +++ b/src/utils/__tests__/merge.test.js @@ -11,8 +11,8 @@ describe('util merge()', () => { i: 'a', ii: 'b', iii: 'c', - iv: [1, 2, 3] - } + iv: [1, 2, 3], + }, } const y = { @@ -21,8 +21,8 @@ describe('util merge()', () => { c: { i: 1, ii: 'b', - iii: 3 - } + iii: 3, + }, } expect(merge(x, y)).toEqual({ @@ -32,8 +32,8 @@ describe('util merge()', () => { i: 1, ii: 'b', iii: 3, - iv: [1, 2, 3] - } + iv: [1, 2, 3], + }, }) }) @@ -45,8 +45,8 @@ describe('util merge()', () => { i: 'a', ii: 'b', iii: 'c', - iv: [1, 2, 3] - } + iv: [1, 2, 3], + }, } const y = { @@ -55,8 +55,8 @@ describe('util merge()', () => { c: { i: 1, ii: 'b', - iii: 3 - } + iii: 3, + }, } merge(x, y) @@ -68,8 +68,8 @@ describe('util merge()', () => { i: 'a', ii: 'b', iii: 'c', - iv: [1, 2, 3] - } + iv: [1, 2, 3], + }, }) expect(y).toEqual({ @@ -78,8 +78,8 @@ describe('util merge()', () => { c: { i: 1, ii: 'b', - iii: 3 - } + iii: 3, + }, }) }) }) diff --git a/src/utils/__tests__/promise-hash.test.js b/src/utils/__tests__/promise-hash.test.js index 72abab03..2adf465e 100644 --- a/src/utils/__tests__/promise-hash.test.js +++ b/src/utils/__tests__/promise-hash.test.js @@ -7,7 +7,7 @@ describe('util promiseHash()', () => { const subject = { a: 1, b: Promise.resolve(2), - c: Promise.all([Promise.resolve(3), Promise.resolve(4)]) + c: Promise.all([Promise.resolve(3), Promise.resolve(4)]), } return promiseHash(subject).then(({ a, b, c }) => { @@ -21,7 +21,7 @@ describe('util promiseHash()', () => { const subject = { a: 1, b: Promise.reject(new Error('Test')), - c: Promise.all([Promise.resolve(3), Promise.resolve(4)]) + c: Promise.all([Promise.resolve(3), Promise.resolve(4)]), } return promiseHash(subject).catch(err => { diff --git a/src/utils/__tests__/proxy.test.js b/src/utils/__tests__/proxy.test.js index f7de4e32..b5d0fb91 100644 --- a/src/utils/__tests__/proxy.test.js +++ b/src/utils/__tests__/proxy.test.js @@ -8,7 +8,7 @@ describe('util proxy', () => { let proxied class Circle { - radius: number; + radius: number constructor(radius) { this.radius = radius @@ -19,7 +19,7 @@ describe('util proxy', () => { } area() { - return Math.PI * (this.radius ** 2) + return Math.PI * this.radius ** 2 } } @@ -29,18 +29,18 @@ describe('util proxy', () => { shortArea(target) { return Math.round(target.area() * 100) / 100 - } + }, } base = new Circle(10) proxied = new Proxy(base, { - get: proxy.trapGet(traps) + get: proxy.trapGet(traps), }) }) describe('- properties', () => { test('captures and returns values defined in as traps', () => { - // $FlowIgnore + // $FlowFixMe expect(proxied.isProxied).toBe(true) }) @@ -51,7 +51,7 @@ describe('util proxy', () => { describe('- methods', () => { test('captures and returns values defined in as traps', () => { - // $FlowIgnore + // $FlowFixMe expect(proxied.shortArea()).toBe(314.16) }) @@ -62,7 +62,7 @@ describe('util proxy', () => { describe('#unwrap', () => { test('returns the proxy target', () => { - // $FlowIgnore + // $FlowFixMe expect(proxied.unwrap()).toBe(base) }) }) diff --git a/src/utils/__tests__/range.test.js b/src/utils/__tests__/range.test.js index 1785414e..f3eb9291 100644 --- a/src/utils/__tests__/range.test.js +++ b/src/utils/__tests__/range.test.js @@ -8,22 +8,22 @@ describe('util range()', () => { expect(subject.next()).toEqual({ done: false, - value: 1 + value: 1, }) expect(subject.next()).toEqual({ done: false, - value: 2 + value: 2, }) expect(subject.next()).toEqual({ done: false, - value: 3 + value: 3, }) expect(subject.next()).toEqual({ done: true, - value: undefined + value: undefined, }) }) }) diff --git a/src/utils/__tests__/set-type.test.js b/src/utils/__tests__/set-type.test.js deleted file mode 100644 index 34f5ee32..00000000 --- a/src/utils/__tests__/set-type.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* @flow */ - -import setType from '../set-type' - -describe('util setType()', () => { - test('returns the function call of the first and only argument', () => { - expect(setType(() => 'Test')).toBe('Test') - }) -}) diff --git a/src/utils/__tests__/stringify.test.js b/src/utils/__tests__/stringify.test.js index 4c822ae7..94568e4d 100644 --- a/src/utils/__tests__/stringify.test.js +++ b/src/utils/__tests__/stringify.test.js @@ -6,7 +6,7 @@ const DEFAULT = 'default' const CIRCULAR = 'circular' describe('util fn()', () => { - [DEFAULT, CIRCULAR].forEach(method => { + ;[DEFAULT, CIRCULAR].forEach(method => { describe(`- ${method}`, () => { const fn = stringify[method] diff --git a/src/utils/__tests__/transform-keys.test.js b/src/utils/__tests__/transform-keys.test.js index 2b08150d..17408292 100644 --- a/src/utils/__tests__/transform-keys.test.js +++ b/src/utils/__tests__/transform-keys.test.js @@ -4,7 +4,7 @@ import { transformKeys, camelizeKeys, dasherizeKeys, - underscoreKeys + underscoreKeys, } from '../transform-keys' describe('util camelizeKeys()', () => { @@ -122,15 +122,4 @@ describe('util transformKeys()', () => { test('does not mutate the source object', () => { expect(subject).toMatchSnapshot() }) - - test('throws when something other than an object is passed in', () => { - // $FlowIgnore - expect(() => transformKeys('', key => key, true)).toThrow() - }) - - test('does not fail when an array is used as a source object', () => { - const source = [1, 2, 3] - - expect(transformKeys(source, key => key, true)).toEqual(source) - }) }) diff --git a/src/utils/__tests__/try-catch.test.js b/src/utils/__tests__/try-catch.test.js index b8ae9b81..88f73755 100644 --- a/src/utils/__tests__/try-catch.test.js +++ b/src/utils/__tests__/try-catch.test.js @@ -8,9 +8,12 @@ describe('util tryCatch()', () => { expect(value).toBe(false) - await tryCatch(() => Promise.reject(new Error('Test')), () => { - value = true - }) + await tryCatch( + () => Promise.reject(new Error('Test')), + () => { + value = true + }, + ) expect(value).toBe(true) }) @@ -22,11 +25,14 @@ describe('util tryCatchSync()', () => { expect(value).toBe(false) - tryCatchSync(() => { - throw new Error('Test') - }, () => { - value = true - }) + tryCatchSync( + () => { + throw new Error('Test') + }, + () => { + value = true + }, + ) expect(value).toBe(true) }) diff --git a/src/utils/__tests__/uniq.test.js b/src/utils/__tests__/uniq.test.js index cea8c7c1..787df1f2 100644 --- a/src/utils/__tests__/uniq.test.js +++ b/src/utils/__tests__/uniq.test.js @@ -11,27 +11,27 @@ describe('util uniq()', () => { const subject = [ { id: 1, - name: 'Test 1' + name: 'Test 1', }, { id: 1, - name: 'Test One' + name: 'Test One', }, { id: 2, - name: 'Test 2' - } + name: 'Test 2', + }, ] expect(uniq(subject, 'id')).toEqual([ { id: 1, - name: 'Test 1' + name: 'Test 1', }, { id: 2, - name: 'Test 2' - } + name: 'Test 2', + }, ]) }) diff --git a/src/utils/chain.js b/src/utils/chain.js index d13d02d3..f58e0a69 100644 --- a/src/utils/chain.js +++ b/src/utils/chain.js @@ -17,6 +17,6 @@ export default function chain(source: T): Chain { construct>(constructor: V): Chain { return chain(Reflect.construct(constructor, [source])) - } + }, } } diff --git a/src/utils/compact.js b/src/utils/compact.js index 0bc41b15..f9dd5974 100644 --- a/src/utils/compact.js +++ b/src/utils/compact.js @@ -1,24 +1,8 @@ /* @flow */ -import isNull from './is-null' -import entries from './entries' -import setType from './set-type' -import isUndefined from './is-undefined' +import { isNil } from '@lux/utils/is-type' -/** - * @private - */ -export default function compact>(source: T): T { - return setType(() => { - if (Array.isArray(source)) { - return source.filter(value => !isNull(value) && !isUndefined(value)) - } +const compact = (source: Array): Array => + source.filter(value => !isNil(value)) - return entries(source) - .filter(([, value]) => !isNull(value) && !isUndefined(value)) - .reduce((result, [key, value]) => ({ - ...result, - [key]: value - }), {}) - }) -} +export default compact diff --git a/src/utils/compose.js b/src/utils/compose.js index aa9fe553..7d9a7a96 100644 --- a/src/utils/compose.js +++ b/src/utils/compose.js @@ -15,10 +15,7 @@ export function compose( main: (input: any) => U, ...etc: Array ): (input: T) => U { - return input => main(etc.reduceRight( - (value, fn) => fn(value), - input - )) + return input => main(etc.reduceRight((value, fn) => fn(value), input)) } /** @@ -28,8 +25,11 @@ export function composeAsync( main: (input: any) => Promise, ...etc: Array ): (input: T | Promise) => Promise { - return input => etc.reduceRight( - (value, fn) => Promise.resolve(value).then(fn), - Promise.resolve(input) - ).then(main) + return input => + etc + .reduceRight( + (value, fn) => Promise.resolve(value).then(fn), + Promise.resolve(input), + ) + .then(main) } diff --git a/src/utils/create-query-string.js b/src/utils/create-query-string.js index 2a982a79..ad79585f 100644 --- a/src/utils/create-query-string.js +++ b/src/utils/create-query-string.js @@ -1,14 +1,12 @@ /* @flow */ -import entries from './entries' - /** * A replacement for querystring.stringify that supports nested objects. * * @private */ export default function createQueryString(src: Object, prop?: string): string { - return entries(src).reduce((str, [key, value], index) => { + return Object.entries(src).reduce((str, [key, value], index) => { let result = str if (index > 0) { @@ -16,13 +14,10 @@ export default function createQueryString(src: Object, prop?: string): string { } if (prop) { - result += ( - `${prop - + encodeURIComponent('[') - + key - + encodeURIComponent(']') - }=` - ) + result += `${prop + + encodeURIComponent('[') + + key + + encodeURIComponent(']')}=` } else { result += `${key}=` } @@ -31,15 +26,14 @@ export default function createQueryString(src: Object, prop?: string): string { if (Array.isArray(value)) { result += value.map(encodeURIComponent).join() } else { - result = ( - result.substr(0, result.length - (key.length + 1)) - + createQueryString(value, key) - ) + result = + result.substr(0, result.length - (key.length + 1)) + + createQueryString(value, key) } } else if (!value && typeof value !== 'number') { result += 'null' } else { - result += encodeURIComponent(value) + result += encodeURIComponent(String(value)) } return result diff --git a/src/utils/diff.js b/src/utils/diff.js index e9bf311d..417f9e7d 100644 --- a/src/utils/diff.js +++ b/src/utils/diff.js @@ -4,7 +4,9 @@ * @private */ export function map(a: Map, b: Map): Map { - return [...b].reduce((result, [key, value]) => ( - a.get(key) !== value ? result.set(key, value) : result - ), new Map()) + return [...b].reduce( + (result, [key, value]) => + a.get(key) !== value ? result.set(key, value) : result, + new Map(), + ) } diff --git a/src/utils/entries.js b/src/utils/entries.js deleted file mode 100644 index 45616b36..00000000 --- a/src/utils/entries.js +++ /dev/null @@ -1,28 +0,0 @@ -/* @flow */ - -const METHOD_MISSING = typeof Object.entries !== 'function' - -/** - * @private - */ -export default function entries(source: Object): Array<[string, any]> { - if (METHOD_MISSING) { - const keys = Object.keys(source) - const result = new Array(keys.length) - - return keys.reduce((prev, key, idx) => { - const next = prev - const entry = new Array(2) - - entry[0] = key - entry[1] = source[key] - - // $FlowIgnore - next[idx] = entry - - return next - }, result) - } - - return Object.entries(source) -} diff --git a/src/utils/env.js b/src/utils/env.js index 49ee7fdb..6aa3137e 100644 --- a/src/utils/env.js +++ b/src/utils/env.js @@ -1,7 +1,20 @@ /* @flow */ -const isEnv = value => () => process.env.NODE_ENV === value +import type { Environment } from '@lux/types' -export const isDevelopment: () => boolean = isEnv('development') -export const isProduction: () => boolean = isEnv('production') -export const isTest: () => boolean = isEnv('test') +export const name = (): Environment => { + const { env: { NODE_ENV } } = process + + switch (NODE_ENV) { + case 'production': + case 'test': + return NODE_ENV + + default: + return 'development' + } +} + +export const isDevelopment = (): boolean => name() === 'development' +export const isProduction = (): boolean => name() === 'production' +export const isTest = (): boolean => name() === 'test' diff --git a/src/utils/exec.js b/src/utils/exec.js index fdaa26b1..c73c0267 100644 --- a/src/utils/exec.js +++ b/src/utils/exec.js @@ -5,22 +5,22 @@ import * as cp from 'child_process' import promisify from './promisify' type Options = { - cwd?: string; - env?: Object; - uid?: number; - gid?: number; - shell?: string; - timeout?: number; - encoding?: string; - maxBuffer?: number; - killSignal?: string; + cwd?: string, + env?: Object, + uid?: number, + gid?: number, + shell?: string, + timeout?: number, + encoding?: string, + maxBuffer?: number, + killSignal?: string, } /** * @private */ -const exec: (command: string, options?: Options) => Promise = ( - promisify(cp.exec) +const exec: (command: string, options?: Options) => Promise = promisify( + cp.exec, ) export default exec diff --git a/src/utils/flatten.js b/src/utils/flatten.js new file mode 100644 index 00000000..d6096743 --- /dev/null +++ b/src/utils/flatten.js @@ -0,0 +1,18 @@ +/* @flow */ + +type TwoDimArray = Array> +type MultiDimArray = Array<$Supertype>> + +export const shallow = (source: TwoDimArray): Array => + Array.prototype.concat.apply([], source) + +export const deep = (source: MultiDimArray): Array => + source.reduce((dest, node) => { + let flatNode = node + + if (Array.isArray(flatNode)) { + flatNode = deep(flatNode) + } + + return dest.concat(flatNode) + }, []) diff --git a/src/utils/fs-extras.js b/src/utils/fs-extras.js new file mode 100644 index 00000000..a2169cc9 --- /dev/null +++ b/src/utils/fs-extras.js @@ -0,0 +1,91 @@ +/* @flow */ + +import * as path from 'path' + +import * as fs from 'mz/fs' + +import * as flatten from '@lux/utils/flatten' + +/** + * Recursively remove files and directories if they exist. YOLO. + */ +const rmrf = (target: string): Promise => + fs + .stat(target) + .then( + stats => + stats.isDirectory() + ? fs + .readdir(target) + .then(files => files.map(file => path.join(target, file))) + .then(files => files.map(rmrf)) + .then(promises => Promise.all(promises)) + .then(() => fs.rmdir(target)) + : fs.unlink(target), + ) + .then(() => true) + .catch(err => { + if (err.code === 'ENOENT') { + return true + } + return err + }) + +/** + * Determine if a file in a directory matches a pattern. + */ +const existsInDir = (dir: string, pattern: RegExp): Promise => + fs.readdir(dir).then(files => files.some(file => pattern.test(file))) + +/** + * Recursively read a directory. + */ +const readdirRec = ( + target: string, + stripPath?: boolean = true, +): Promise> => + fs + .readdir(target) + .then(files => + files + .map(file => path.join(target, file)) + .map(file => fs.stat(file).then(stats => [file, stats])), + ) + .then(promises => Promise.all(promises)) + .then(files => + files.map(([file, stats]) => { + if (stats.isDirectory()) { + return readdirRec(file, false) + } + return file + }), + ) + .then(promises => Promise.all(promises)) + .then(flatten.shallow) + .then( + files => + stripPath ? files.map(file => path.relative(target, file)) : files, + ) + +/** + * Recursively create a directory path. + */ +const mkdirRec = (target: string): Promise => + fs + .mkdir(path.dirname(target)) + .catch(err => { + if (err.code === 'ENOENT') { + return mkdirRec(path.dirname(target)) + } + return err + }) + .then(() => fs.mkdir(target)) + +/** + * Higher order function that returns a function that determins if a + * file has a matching extension. + */ +const isExt = (ext: string): ((file: string) => boolean) => file => + path.extname(file) === ext + +export { existsInDir, isExt, mkdirRec, readdirRec, rmrf } diff --git a/src/utils/github.js b/src/utils/github.js index 9596e8ca..a9799662 100644 --- a/src/utils/github.js +++ b/src/utils/github.js @@ -3,8 +3,8 @@ const GITHUB_URL = 'https://github.com/postlight/lux' type Options = { - line?: number; - branch?: string; + line?: number, + branch?: string, } /** diff --git a/src/utils/has-own-property.js b/src/utils/has-own-property.js index aa6d32f0..867eb6bf 100644 --- a/src/utils/has-own-property.js +++ b/src/utils/has-own-property.js @@ -1,9 +1,5 @@ /* @flow */ export default function hasOwnProperty(target: Object, key: string): boolean { - return Reflect.apply( - Object.prototype.hasOwnProperty, - target, - [key] - ) + return Reflect.apply(Object.prototype.hasOwnProperty, target, [key]) } diff --git a/src/utils/is-buffer.js b/src/utils/is-buffer.js deleted file mode 100644 index 2c1f76a7..00000000 --- a/src/utils/is-buffer.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ - -/** - * @private - */ -export default function isBuffer(value: mixed): boolean { - return value instanceof Buffer -} diff --git a/src/utils/is-null.js b/src/utils/is-null.js deleted file mode 100644 index 8a26965b..00000000 --- a/src/utils/is-null.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ - -/** - * @private - */ -export default function isNull(value: ?mixed): boolean { - return value === null -} diff --git a/src/utils/is-object.js b/src/utils/is-object.js deleted file mode 100644 index 30be0644..00000000 --- a/src/utils/is-object.js +++ /dev/null @@ -1,21 +0,0 @@ -/* @flow */ - -/** - * Determine wether or not a value is an Object. - * - * @example - * const a = null; - * const b = []; - * const c = {}; - * - * console.log(typeof a, typeof b, typeof c); - * // => 'object', 'object', 'object' 👎 - * - * console.log(isObject(a), isObject(b), isObject(c)); - * // => false, false, true 👍 - * - * @private - */ -export default function isObject(value: mixed): boolean { - return Boolean(value) && typeof value === 'object' && !Array.isArray(value) -} diff --git a/src/utils/is-type.js b/src/utils/is-type.js new file mode 100644 index 00000000..dd348d2b --- /dev/null +++ b/src/utils/is-type.js @@ -0,0 +1,21 @@ +/* @flow */ + +export const isInstance = (lhs: mixed, rhs: Class): boolean %checks => + lhs instanceof rhs + +export const isFunction = (value: mixed): boolean %checks => + typeof value === 'function' + +export const isNil = (value: mixed): boolean %checks => + isUndefined(value) || isNull(value) + +export const isNull = (value: mixed): boolean %checks => value === null + +export const isObject = (value: mixed): boolean %checks => + !isNull(value) && typeof value === 'object' && !Array.isArray(value) + +export const isString = (value: mixed): boolean %checks => + typeof value === 'string' + +export const isUndefined = (value: mixed): boolean %checks => + value === undefined diff --git a/src/utils/is-undefined.js b/src/utils/is-undefined.js deleted file mode 100644 index 7f3c70f0..00000000 --- a/src/utils/is-undefined.js +++ /dev/null @@ -1,8 +0,0 @@ -/* @flow */ - -/** - * @private - */ -export default function isUndefined(value: mixed): boolean { - return typeof value === 'undefined' -} diff --git a/src/utils/k.js b/src/utils/k.js index 38296cb5..ebab6344 100644 --- a/src/utils/k.js +++ b/src/utils/k.js @@ -9,6 +9,6 @@ * * @private */ -export default function K(): any { +export default function K(..._: Array<*>): any { return this } diff --git a/src/utils/map-to-object.js b/src/utils/map-to-object.js index c117acaf..7c50852f 100644 --- a/src/utils/map-to-object.js +++ b/src/utils/map-to-object.js @@ -1,12 +1,13 @@ /* @flow */ export default function mapToObject( - source: Map + source: Map, ): { [key: string]: T } { - return Array - .from(source) - .reduce((obj, [key, value]) => ({ + return Array.from(source).reduce( + (obj, [key, value]) => ({ ...obj, - [String(key)]: value - }), {}) + [String(key)]: value, + }), + {}, + ) } diff --git a/src/utils/merge.js b/src/utils/merge.js index 08de2f1c..f8df39d6 100644 --- a/src/utils/merge.js +++ b/src/utils/merge.js @@ -1,34 +1,22 @@ /* @flow */ -import entries from './entries' -import setType from './set-type' -import isObject from './is-object' +import { isObject } from '@lux/utils/is-type' -function hasOwnProperty(target: Object, key: string): boolean { - return Reflect.apply(Object.prototype.hasOwnProperty, target, [key]) -} +// $FlowFixMe +const merge = (dest: T, source: U): { ...T, ...U } => + Object.entries(dest) + .concat(Object.entries(source)) + .reduce((prev, [key, value]) => { + const currentValue = prev[key] + const next = prev -/** - * @private - */ -export default function merge(dest: T, source: U): T & U { - return setType(() => entries(source).reduce((result, [key, value]) => { - if (hasOwnProperty(result, key) && isObject(value)) { - const currentValue = Reflect.get(result, key) - - if (isObject(currentValue)) { - return { - ...result, - [key]: merge(currentValue, value) - } + if (isObject(currentValue) && isObject(value)) { + next[key] = merge(currentValue, value) + } else { + next[key] = value } - } - return { - ...result, - [key]: value - } - }, { - ...dest - })) -} + return next + }, {}) + +export default merge diff --git a/src/utils/noop.js b/src/utils/noop.js index 0aa223ed..6f564484 100644 --- a/src/utils/noop.js +++ b/src/utils/noop.js @@ -1,5 +1,6 @@ /* @flow */ -export default function noop(): void { - return undefined -} +type Noop = (...arguments: Array<*>) => void + +const noop: Noop = () => undefined +export default noop diff --git a/src/utils/omit.js b/src/utils/omit.js index f3b79001..bd89594d 100644 --- a/src/utils/omit.js +++ b/src/utils/omit.js @@ -1,16 +1,12 @@ /* @flow */ -import entries from './entries' -import setType from './set-type' - -/** - * @private - */ -export default function omit(src: T, ...omitted: Array): T { - return setType(() => entries(src) - .filter(([key]) => omitted.indexOf(key) < 0) - .reduce((result, [key, value]: [string, mixed]) => ({ +const omit = (src: T, ...omitted: Array): Object => + Object.entries(src).filter(([key]) => omitted.indexOf(key) < 0).reduce( + (result, [key, value]) => ({ ...result, - [key]: value - }), {})) -} + [key]: value, + }), + {}, + ) + +export default omit diff --git a/src/utils/pick.js b/src/utils/pick.js index 3b2e8290..213d4acf 100644 --- a/src/utils/pick.js +++ b/src/utils/pick.js @@ -1,16 +1,18 @@ /* @flow */ -import setType from './set-type' +const pick = (source: T, ...keys: Array): T => { + // $FlowFixMe + const dest: T = {} -/** - * @private - */ -export default function pick(src: T, ...keys: Array): T { - return setType(() => keys - .map((key): [string, mixed] => [key, Reflect.get(src, key)]) - .filter(([, value]) => typeof value !== 'undefined') - .reduce((result, [key, value]) => ({ - ...result, - [key]: value - }), {})) + return keys + .map(key => [key, source[key]]) + .filter(([, value]) => value !== undefined) + .reduce((prev, [key, value]) => { + const next = prev + + next[key] = value + return next + }, dest) } + +export default pick diff --git a/src/utils/present.js b/src/utils/present.js index 2cf57bbb..b99f8f96 100644 --- a/src/utils/present.js +++ b/src/utils/present.js @@ -1,11 +1,10 @@ /* @flow */ -import isNull from './is-null' -import isUndefined from './is-undefined' +import { isNil } from '@lux/utils/is-type' /** * @private */ export default function present(...values: Array): boolean { - return values.every(value => !isNull(value) && !isUndefined(value)) + return values.every(value => !isNil(value)) } diff --git a/src/utils/promise-hash.js b/src/utils/promise-hash.js index a0963edc..7ed9ab90 100644 --- a/src/utils/promise-hash.js +++ b/src/utils/promise-hash.js @@ -1,29 +1,30 @@ /* @flow */ -import entries from './entries' - /** * @private */ export default function promiseHash(promises: Object): Promise { if (Object.keys(promises).length) { return Promise.all( - entries(promises) - .map(([key, promise]: [string, Promise]) => ( + Object.entries(promises).map( + ([key, promise]) => new Promise((resolve, reject) => { if (promise && typeof promise.then === 'function') { - promise - .then((value) => resolve({ [key]: value })) - .catch(reject) + promise.then(value => resolve({ [key]: value })).catch(reject) } else { resolve({ [key]: promise }) } - }) - )) - ).then((objects) => objects.reduce((hash, object) => ({ - ...hash, - ...object - }), {})) + }), + ), + ).then(objects => + objects.reduce( + (hash, object) => ({ + ...hash, + ...object, + }), + {}, + ), + ) } return Promise.resolve({}) diff --git a/src/utils/promisify.js b/src/utils/promisify.js index 1a126703..fe87aef6 100644 --- a/src/utils/promisify.js +++ b/src/utils/promisify.js @@ -7,17 +7,19 @@ type Target = (...args: Array) => Promise * that implements a Promise based interface. */ function promisify(source: Function, context?: ?Object): Target { - return (...args: Array) => ( + return (...args: Array) => new Promise((resolve, reject) => { - source.apply(context, [...args, (err, ...result) => { - if (err) { - reject(err) - return - } - resolve(result.length > 1 ? result : result[0]) - }]) + source.apply(context, [ + ...args, + (err, ...result) => { + if (err) { + reject(err) + return + } + resolve(result.length > 1 ? result : result[0]) + }, + ]) }) - ) } export default promisify diff --git a/src/utils/range.js b/src/utils/range.js index b055d113..9d08cfd9 100644 --- a/src/utils/range.js +++ b/src/utils/range.js @@ -5,7 +5,7 @@ */ export default function* range( start: number, - end: number + end: number, ): Generator { for (let i = start; i <= end; i += 1) { yield i diff --git a/src/utils/set-type.js b/src/utils/set-type.js deleted file mode 100644 index b170d5ef..00000000 --- a/src/utils/set-type.js +++ /dev/null @@ -1,23 +0,0 @@ -/* @flow */ - -/** - * Use this util as a brute force way of tricking flow into understanding intent - * to extend or combine a type in a polymorphic function. - * - * In essence, this function allows you to declare your types for a high order - * function that wraps the inner logic of this function without flow throwing - * any type errors. This allows you to properly set the return value of the - * high order function to whatever you like so consumers of the high order - * function can still benifit from type inference and safety as long as the - * return value type declaration is 100% accurate. - * - * WARNING: - * This function should rarely be used as it requires a good understanding of - * the flow type system to ensure that the function this util wraps is still - * type safe. - * - * @private - */ -export default function setType(fn: () => any): any { - return fn() -} diff --git a/src/utils/stringify.js b/src/utils/stringify.js index 4a76ada4..4860af16 100644 --- a/src/utils/stringify.js +++ b/src/utils/stringify.js @@ -1,6 +1,6 @@ /* @flow */ -import isObject from './is-object' +import { isObject } from '@lux/utils/is-type' /** * @private @@ -38,14 +38,18 @@ export function circular(value?: ?mixed, spaces?: number): string { return 'undefined' default: - return JSON.stringify(value, (key, val) => { - if (isObject(val)) { - if (cache.has(val)) { - return undefined + return JSON.stringify( + value, + (key, val) => { + if (isObject(val)) { + if (cache.has(val)) { + return undefined + } + cache.add(val) } - cache.add(val) - } - return val - }, spaces) + return val + }, + spaces, + ) } } diff --git a/src/utils/transform-keys.js b/src/utils/transform-keys.js index 8043b444..65f611bf 100644 --- a/src/utils/transform-keys.js +++ b/src/utils/transform-keys.js @@ -1,71 +1,37 @@ /* @flow */ -import { camelize, dasherize } from 'inflection' - -import entries from './entries' -import underscore from './underscore' - -/** - * @private - */ -export function transformKeys>( - source: T, - transformer: (key: string) => string, - deep: boolean = false -): T { - const sourceType = typeof source - - if (Array.isArray(source)) { - return source.slice(0) - } else if (source && sourceType === 'object') { - // $FlowIgnore - return entries(source).reduce((result, [key, value]) => { - const recurse = ( - deep - && value - && typeof value === 'object' - && !Array.isArray(value) - && !(value instanceof Date) - ) - - // eslint-disable-next-line no-param-reassign - result[transformer(key)] = ( - recurse ? transformKeys(value, transformer, true) : value - ) - - return result - }, {}) - } - - throw new TypeError(`Expected array or object. Received ${sourceType}.`) +import { camelize, dasherize, underscore } from '@lux/packages/inflector' +import { isInstance, isObject } from '@lux/utils/is-type' + +type Transform = (key: string) => string + +export const transformKeys = ( + src: T, + fn: Transform, + deep?: boolean, +): T => { + // $FlowFixMe + const dest: T = {} + + return Object.entries(src).reduce((prev, entry) => { + const next = prev + const [key] = entry + let [, value] = entry + + if (deep && isObject(value) && !isInstance(value, Date)) { + value = transformKeys(value, fn, true) + } + + next[fn(key)] = value + return next + }, dest) } -/** - * @private - */ -export function camelizeKeys>( - source: T, - deep?: boolean -): T { - return transformKeys(source, key => camelize(underscore(key), true), deep) -} +export const camelizeKeys = (source: T, deep?: boolean) => + transformKeys(source, camelize, deep) -/** - * @private - */ -export function dasherizeKeys>( - source: T, - deep?: boolean -): T { - return transformKeys(source, key => dasherize(underscore(key), true), deep) -} +export const dasherizeKeys = (source: T, deep?: boolean) => + transformKeys(source, dasherize, deep) -/** - * @private - */ -export function underscoreKeys>( - source: T, - deep?: boolean -): T { - return transformKeys(source, key => underscore(key), deep) -} +export const underscoreKeys = (source: T, deep?: boolean) => + transformKeys(source, underscore, deep) diff --git a/src/utils/try-catch.js b/src/utils/try-catch.js index 69d96557..90d03cf3 100644 --- a/src/utils/try-catch.js +++ b/src/utils/try-catch.js @@ -18,24 +18,24 @@ import K from './k' * * @example * tryCatch(() => { - * const n = Math.floor(Math.random() * 6); + * const n = Math.floor(Math.random() * 6) * * if (n >= 4) { - * throw new Error('You lose!'); + * throw new Error('You lose!') * } else { - * return Promise.resolve(n); + * return Promise.resolve(n) * } * }, err => { - * console.error(err); + * console.error(err) * }).then(luckyNumber => { - * console.log(`Your lucky number is ${luckyNumber}.`); - * }); + * console.log(`Your lucky number is ${luckyNumber}.`) + * }) * * @private */ -export default async function tryCatch Promise>( +export default (async function tryCatch Promise>( fn: F, - rescue: Function = K + rescue: Function = K, ): Promise { let result @@ -46,33 +46,32 @@ export default async function tryCatch Promise>( } return result -} - +}) /** * A syncronous implementation of the `tryCatch` utility. * * @example * const luckyNumber = tryCatchSync(() => { - * const n = Math.floor(Math.random() * 6); + * const n = Math.floor(Math.random() * 6) * * if (n >= 4) { - * throw new Error('You lose!'); + * throw new Error('You lose!') * } else { - * return n; + * return n * } * }, err => { - * console.error(err); - * }); + * console.error(err) + * }) * * if (luckyNumber) { - * console.log(`Your lucky number is ${luckyNumber}.`); + * console.log(`Your lucky number is ${luckyNumber}.`) * } * * @private */ -export function tryCatchSync T>( +export function tryCatchSync T>( fn: F, - rescue: Function = K + rescue: Function = K, ): void | T { let result diff --git a/src/utils/underscore.js b/src/utils/underscore.js index 1c30be91..8887ef8e 100644 --- a/src/utils/underscore.js +++ b/src/utils/underscore.js @@ -7,7 +7,7 @@ import { underscore as _ } from 'inflection' */ export default function underscore( source: string = '', - upper: boolean = false + upper: boolean = false, ): string { return _(source, upper).replace(/-/g, '_') } diff --git a/src/utils/uniq.js b/src/utils/uniq.js index 276679fe..dc7ac616 100644 --- a/src/utils/uniq.js +++ b/src/utils/uniq.js @@ -13,9 +13,9 @@ export default function uniq>( let lastIdx if (hasKeys) { - lastIdx = arr.findIndex((y, yIdx) => ( - yIdx > xIdx || keys.every(key => x[key] === y[key]) - )) + lastIdx = arr.findIndex( + (y, yIdx) => yIdx > xIdx || keys.every(key => x[key] === y[key]), + ) } else { lastIdx = src.lastIndexOf(x) } diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 00000000..4619f0f1 --- /dev/null +++ b/test/setup.js @@ -0,0 +1,12 @@ +/* @flow */ + +import entries from 'object.entries' +import values from 'object.values' + +if (Object.entries === undefined) { + entries.shim() +} + +if (Object.values === undefined) { + values.shim() +} diff --git a/test/test-app/.eslintrc.json b/test/test-app/.eslintrc.json index 430efe0c..4254cf13 100644 --- a/test/test-app/.eslintrc.json +++ b/test/test-app/.eslintrc.json @@ -1,56 +1,54 @@ { "parser": "babel-eslint", - "plugins": ["flowtype"], - "extends": "eslint:recommended", + "plugins": [ + "jest", + "flowtype" + ], + "extends": [ + "airbnb-base", + "plugin:flowtype/recommended", + "prettier" + ], "env": { + "jest/globals": true, "node": true }, - "globals": { - "T": true, - "Map": true, - "Set": true, - "Proxy": true, - "Promise": true, - "Reflect": true, - "WeakMap": true, - "WeakSet": true, - "Iterable": true - }, "settings": { "flowtype": { "onlyFilesWithFlowAnnotation": true } }, "rules": { - "semi": ["error", "never"], - "strict": 0, - "max-len": ["error", 80], - "arrow-parens": 0, - "comma-dangle": [2, "only-multiline"], - "global-require": 0, - "no-underscore-dangle": 0, - "class-methods-use-this": 0, - "no-irregular-whitespace": 0, - "no-restricted-syntax": [ + "import/first": "off", + "arrow-parens": "off", + "comma-dangle": [ + "error", + { + "arrays": "always-multiline", + "exports": "always-multiline", + "functions": "always-multiline", + "imports": "always-multiline", + "objects": "always-multiline" + } + ], + "max-len": [ + "error", + 80 + ], + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "_", + "varsIgnorePattern": "_" + } + ], + "semi": [ "error", - "ForInStatement", - "LabeledStatement", - "WithStatement" + "never" ], - "import/order": ["warn", { - "groups": [ - "builtin", - "external", - "internal", - "parent", - "sibling", - "index" - ], - "newlines-between": "always" - }], - "import/extensions": 0, - "import/no-named-default": 0, - "import/no-dynamic-require": 0, - "import/prefer-default-export": 0 + "import/extensions": "off", + "import/no-extraneous-dependencies": "off", + "import/no-unresolved": "off", + "import/prefer-default-export": "off" } } diff --git a/test/test-app/app/controllers/actions.js b/test/test-app/app/controllers/actions.js index 3bb695b2..620b145a 100644 --- a/test/test-app/app/controllers/actions.js +++ b/test/test-app/app/controllers/actions.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class ActionsController extends Controller { diff --git a/test/test-app/app/controllers/application.js b/test/test-app/app/controllers/application.js index cfd2eda6..2cec9321 100644 --- a/test/test-app/app/controllers/application.js +++ b/test/test-app/app/controllers/application.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class ApplicationController extends Controller { diff --git a/test/test-app/app/controllers/categorizations.js b/test/test-app/app/controllers/categorizations.js index 313f31d1..f80a3aa2 100644 --- a/test/test-app/app/controllers/categorizations.js +++ b/test/test-app/app/controllers/categorizations.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class CategorizationsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/comments.js b/test/test-app/app/controllers/comments.js index c19320ca..492f54cb 100644 --- a/test/test-app/app/controllers/comments.js +++ b/test/test-app/app/controllers/comments.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class CommentsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/custom.js b/test/test-app/app/controllers/custom.js index 675d8867..08cb95be 100644 --- a/test/test-app/app/controllers/custom.js +++ b/test/test-app/app/controllers/custom.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class CustomController extends Controller { query = [ diff --git a/test/test-app/app/controllers/friendships.js b/test/test-app/app/controllers/friendships.js index 288aaf3f..303611f0 100644 --- a/test/test-app/app/controllers/friendships.js +++ b/test/test-app/app/controllers/friendships.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class FriendshipsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/health.js b/test/test-app/app/controllers/health.js index 77eba323..6f969148 100644 --- a/test/test-app/app/controllers/health.js +++ b/test/test-app/app/controllers/health.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class HealthController extends Controller { index = () => 204; diff --git a/test/test-app/app/controllers/images.js b/test/test-app/app/controllers/images.js index eb0df04b..27c9c2e6 100644 --- a/test/test-app/app/controllers/images.js +++ b/test/test-app/app/controllers/images.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class ImagesController extends Controller { params = [ diff --git a/test/test-app/app/controllers/notifications.js b/test/test-app/app/controllers/notifications.js index 7fe9441f..548e7bea 100644 --- a/test/test-app/app/controllers/notifications.js +++ b/test/test-app/app/controllers/notifications.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class NotificationsController extends Controller { diff --git a/test/test-app/app/controllers/posts.js b/test/test-app/app/controllers/posts.js index c859d22a..f1b503cc 100644 --- a/test/test-app/app/controllers/posts.js +++ b/test/test-app/app/controllers/posts.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class PostsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/reactions.js b/test/test-app/app/controllers/reactions.js index 0f0a1589..583c6b75 100644 --- a/test/test-app/app/controllers/reactions.js +++ b/test/test-app/app/controllers/reactions.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class ReactionsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/tags.js b/test/test-app/app/controllers/tags.js index e441c869..1c22c05d 100644 --- a/test/test-app/app/controllers/tags.js +++ b/test/test-app/app/controllers/tags.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' class TagsController extends Controller { params = [ diff --git a/test/test-app/app/controllers/users.js b/test/test-app/app/controllers/users.js index d8ecedf8..ebd1c2d6 100644 --- a/test/test-app/app/controllers/users.js +++ b/test/test-app/app/controllers/users.js @@ -1,4 +1,4 @@ -import { Controller } from 'LUX_LOCAL' +import { Controller } from 'lux-framework' import User from '../models/user' diff --git a/test/test-app/app/index.js b/test/test-app/app/index.js index 6b29d2d2..062f1a16 100644 --- a/test/test-app/app/index.js +++ b/test/test-app/app/index.js @@ -1,4 +1,4 @@ -import { Application } from 'LUX_LOCAL' +import { Application } from 'lux-framework' class TestApp extends Application { diff --git a/test/test-app/app/models/action.js b/test/test-app/app/models/action.js index 683c78ae..5b4cc225 100644 --- a/test/test-app/app/models/action.js +++ b/test/test-app/app/models/action.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' import Comment from './comment' import Notification from './notification' diff --git a/test/test-app/app/models/categorization.js b/test/test-app/app/models/categorization.js index 409b3786..d8c49b87 100644 --- a/test/test-app/app/models/categorization.js +++ b/test/test-app/app/models/categorization.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Categorization extends Model { static belongsTo = { diff --git a/test/test-app/app/models/comment.js b/test/test-app/app/models/comment.js index de2ea120..eecd726b 100644 --- a/test/test-app/app/models/comment.js +++ b/test/test-app/app/models/comment.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' import track from '../utils/track' diff --git a/test/test-app/app/models/friendship.js b/test/test-app/app/models/friendship.js index 8c63ec81..03867432 100644 --- a/test/test-app/app/models/friendship.js +++ b/test/test-app/app/models/friendship.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Friendship extends Model { static belongsTo = { diff --git a/test/test-app/app/models/image.js b/test/test-app/app/models/image.js index 21213387..0899d2f0 100644 --- a/test/test-app/app/models/image.js +++ b/test/test-app/app/models/image.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Image extends Model { static belongsTo = { diff --git a/test/test-app/app/models/notification.js b/test/test-app/app/models/notification.js index fb15e51b..a0792adf 100644 --- a/test/test-app/app/models/notification.js +++ b/test/test-app/app/models/notification.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Notification extends Model { static belongsTo = { diff --git a/test/test-app/app/models/post.js b/test/test-app/app/models/post.js index ad29d09b..684728e4 100644 --- a/test/test-app/app/models/post.js +++ b/test/test-app/app/models/post.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' import track from '../utils/track' diff --git a/test/test-app/app/models/reaction.js b/test/test-app/app/models/reaction.js index e82bbb7f..9573ce3a 100644 --- a/test/test-app/app/models/reaction.js +++ b/test/test-app/app/models/reaction.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' import track from '../utils/track' diff --git a/test/test-app/app/models/tag.js b/test/test-app/app/models/tag.js index 79e1425b..0c4eefee 100644 --- a/test/test-app/app/models/tag.js +++ b/test/test-app/app/models/tag.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Tag extends Model { static hasMany = { diff --git a/test/test-app/app/models/test.js b/test/test-app/app/models/test.js index e805e3c0..dec303c3 100644 --- a/test/test-app/app/models/test.js +++ b/test/test-app/app/models/test.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' class Test extends Model { diff --git a/test/test-app/app/models/user.js b/test/test-app/app/models/user.js index d9789627..ab9aa97d 100644 --- a/test/test-app/app/models/user.js +++ b/test/test-app/app/models/user.js @@ -1,4 +1,4 @@ -import { Model } from 'LUX_LOCAL' +import { Model } from 'lux-framework' import { hashPassword, comparePassword } from '../utils/password' diff --git a/test/test-app/app/serializers/actions.js b/test/test-app/app/serializers/actions.js index 245b157e..cd0286b9 100644 --- a/test/test-app/app/serializers/actions.js +++ b/test/test-app/app/serializers/actions.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class ActionsSerializer extends Serializer { diff --git a/test/test-app/app/serializers/application.js b/test/test-app/app/serializers/application.js index afed268b..6333baec 100644 --- a/test/test-app/app/serializers/application.js +++ b/test/test-app/app/serializers/application.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class ApplicationSerializer extends Serializer { diff --git a/test/test-app/app/serializers/categorizations.js b/test/test-app/app/serializers/categorizations.js index 5bbe1bbe..f4b55ef9 100644 --- a/test/test-app/app/serializers/categorizations.js +++ b/test/test-app/app/serializers/categorizations.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class CategorizationsSerializer extends Serializer { hasOne = [ diff --git a/test/test-app/app/serializers/comments.js b/test/test-app/app/serializers/comments.js index fb471922..3100dd60 100644 --- a/test/test-app/app/serializers/comments.js +++ b/test/test-app/app/serializers/comments.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class CommentsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/friendships.js b/test/test-app/app/serializers/friendships.js index e8a96c4e..d6b41301 100644 --- a/test/test-app/app/serializers/friendships.js +++ b/test/test-app/app/serializers/friendships.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class FriendshipsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/images.js b/test/test-app/app/serializers/images.js index 48acfdf3..49fc6b5a 100644 --- a/test/test-app/app/serializers/images.js +++ b/test/test-app/app/serializers/images.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class ImagesSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/notifications.js b/test/test-app/app/serializers/notifications.js index 572e613c..917a2852 100644 --- a/test/test-app/app/serializers/notifications.js +++ b/test/test-app/app/serializers/notifications.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class NotificationsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/posts.js b/test/test-app/app/serializers/posts.js index 2b52bda0..dfdb7963 100644 --- a/test/test-app/app/serializers/posts.js +++ b/test/test-app/app/serializers/posts.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class PostsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/reactions.js b/test/test-app/app/serializers/reactions.js index 31f5217e..9b9352c5 100644 --- a/test/test-app/app/serializers/reactions.js +++ b/test/test-app/app/serializers/reactions.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class ReactionsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/tags.js b/test/test-app/app/serializers/tags.js index f5fd843c..90e495fa 100644 --- a/test/test-app/app/serializers/tags.js +++ b/test/test-app/app/serializers/tags.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class TagsSerializer extends Serializer { attributes = [ diff --git a/test/test-app/app/serializers/users.js b/test/test-app/app/serializers/users.js index 478c3b07..5e99bae3 100644 --- a/test/test-app/app/serializers/users.js +++ b/test/test-app/app/serializers/users.js @@ -1,4 +1,4 @@ -import { Serializer } from 'LUX_LOCAL' +import { Serializer } from 'lux-framework' class UsersSerializer extends Serializer { attributes = [ diff --git a/test/test-app/package.json b/test/test-app/package.json index dec00db8..66c95f5c 100644 --- a/test/test-app/package.json +++ b/test/test-app/package.json @@ -10,14 +10,15 @@ "author": "", "license": "MIT", "dependencies": { - "babel-core": "6.24.1", + "babel-core": "6.25.0", "babel-preset-lux": "2.0.2", "bcryptjs": "2.4.3", "faker": "4.1.0", "knex": "0.13.0", + "lux-framework": "file:../../", "mssql": "4.0.4", - "mysql2": "1.2.0", - "pg": "6.2.2", + "mysql2": "1.3.6", + "pg": "6.4.1", "source-map-support": "0.4.15", "sqlite3": "3.1.8" } diff --git a/test/test-app/yarn.lock b/test/test-app/yarn.lock index 791a1c13..9304f61b 100644 --- a/test/test-app/yarn.lock +++ b/test/test-app/yarn.lock @@ -6,13 +6,56 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" -ajv@^4.9.1: +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" + +acorn@4.x: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.0.1: + version "5.0.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0, ajv@^4.9.1: version "4.11.5" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + json-schema-traverse "^0.3.0" + json-stable-stringify "^1.0.1" + +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" + +ansi-regex@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -21,10 +64,20 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" + dependencies: + color-convert "^1.0.0" + ansicolors@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + ap@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" @@ -40,6 +93,12 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.0 || ^1.1.13" +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -50,10 +109,24 @@ arr-flatten@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -86,7 +159,7 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6.24.1, babel-core@^6.24.1: +babel-core@6, babel-core@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" dependencies: @@ -110,6 +183,39 @@ babel-core@6.24.1, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" +babel-core@6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" + dependencies: + babel-code-frame "^6.22.0" + babel-generator "^6.25.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.25.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" + convert-source-map "^1.1.0" + debug "^2.1.1" + json5 "^0.5.0" + lodash "^4.2.0" + minimatch "^3.0.2" + path-is-absolute "^1.0.0" + private "^0.1.6" + slash "^1.0.0" + source-map "^0.5.0" + +babel-eslint@7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" + dependencies: + babel-code-frame "^6.22.0" + babel-traverse "^6.23.1" + babel-types "^6.23.0" + babylon "^6.17.0" + babel-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497" @@ -123,6 +229,19 @@ babel-generator@^6.24.1: source-map "^0.5.0" trim-right "^1.0.1" +babel-generator@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.25.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" @@ -131,6 +250,15 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" +babel-helper-define-map@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + lodash "^4.2.0" + babel-helper-explode-assignable-expression@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" @@ -149,6 +277,16 @@ babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: babel-traverse "^6.23.0" babel-types "^6.23.0" +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helper-get-function-arity@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" @@ -156,6 +294,20 @@ babel-helper-get-function-arity@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + babel-helper-remap-async-to-generator@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383" @@ -166,6 +318,17 @@ babel-helper-remap-async-to-generator@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" @@ -222,6 +385,20 @@ babel-plugin-transform-class-properties@^6.19.0: babel-runtime "^6.22.0" babel-template "^6.23.0" +babel-plugin-transform-es2015-classes@^6.9.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-plugin-transform-exponentiation-operator@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" @@ -284,7 +461,17 @@ babel-template@^6.22.0, babel-template@^6.23.0, babel-template@^6.24.1: babylon "^6.11.0" lodash "^4.2.0" -babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.24.1: +babel-template@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" + lodash "^4.2.0" + +babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695" dependencies: @@ -298,6 +485,20 @@ babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.24.1: invariant "^2.2.0" lodash "^4.2.0" +babel-traverse@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" + dependencies: + babel-code-frame "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.25.0" + babylon "^6.17.2" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + babel-types@^6.22.0, babel-types@^6.23.0, babel-types@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975" @@ -307,14 +508,31 @@ babel-types@^6.22.0, babel-types@^6.23.0, babel-types@^6.24.1: lodash "^4.2.0" to-fast-properties "^1.0.1" +babel-types@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" + dependencies: + babel-runtime "^6.22.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + babylon@^6.11.0, babylon@^6.15.0: version "6.16.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" +babylon@^6.17.0, babylon@^6.17.2: + version "6.17.3" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.3.tgz#1327d709950b558f204e5352587fd0290f8d8e48" + balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" @@ -358,6 +576,13 @@ brace-expansion@^1.0.0: balanced-match "^0.4.1" concat-map "0.0.1" +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" @@ -366,7 +591,19 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -buffer-shims@^1.0.0, buffer-shims@~1.0.0: +browser-resolve@^1.11.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + dependencies: + resolve "1.1.7" + +bser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" + dependencies: + node-int64 "^0.4.0" + +buffer-shims@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" @@ -374,6 +611,20 @@ buffer-writer@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" +builtin-modules@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + cardinal@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-1.0.0.tgz#50e21c1b0aa37729f9377def196b5a9cec932ee9" @@ -385,7 +636,15 @@ caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -chalk@^1.0.0, chalk@^1.1.0: +chalk@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -395,6 +654,24 @@ chalk@^1.0.0, chalk@^1.1.0: strip-ansi "^3.0.0" supports-color "^2.0.0" +circular-json@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -403,12 +680,26 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +color-convert@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: delayed-stream "~1.0.0" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + commander@^2.2.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -419,6 +710,14 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -453,10 +752,39 @@ debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3: dependencies: ms "0.7.2" +debug@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + deep-extend@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -481,20 +809,133 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" dependencies: jsbn "~0.1.0" -escape-string-regexp@^1.0.2: +eol@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/eol/-/eol-0.5.1.tgz#a2f15f9be38ac160f27c4e394fde02a9731a410c" + +es-abstract@^1.6.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.0" + is-callable "^1.1.3" + is-regex "^1.0.3" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@4.2.0, eslint@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.2.0.tgz#a2b3184111b198e02e9c7f3cca625a5e01c56b3d" + dependencies: + ajv "^5.2.0" + babel-code-frame "^6.22.0" + chalk "^1.1.3" + concat-stream "^1.6.0" + debug "^2.6.8" + doctrine "^2.0.0" + eslint-scope "^3.7.1" + espree "^3.4.3" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.8.4" + json-stable-stringify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" + dependencies: + acorn "^5.0.1" + acorn-jsx "^3.0.0" + +esprima@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + esprima@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + dependencies: + estraverse "~4.1.0" + object-assign "^4.0.1" + +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estraverse@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" + +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + +estree-walker@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -521,6 +962,14 @@ extend@^3.0.0, extend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" + dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" + tmp "^0.0.31" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -535,6 +984,33 @@ faker@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f" +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fb-watchman@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" + dependencies: + bser "^2.0.0" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + filename-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" @@ -562,6 +1038,15 @@ flagged-respawn@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5" +flat-cache@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -572,6 +1057,10 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -609,6 +1098,10 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" +function-bind@^1.0.2, function-bind@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + gauge@~2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.3.tgz#1c23855f962f17b3ad3d0dc7443f304542edfe09" @@ -653,7 +1146,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.5: +glob@^7.0.3, glob@^7.0.5: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -664,6 +1157,17 @@ glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-modules@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" @@ -680,10 +1184,21 @@ global-prefix@^0.1.4: is-windows "^0.2.0" which "^1.2.12" -globals@^9.0.0: +globals@^9.0.0, globals@^9.17.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -709,10 +1224,20 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -747,10 +1272,26 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@^0.4.11, iconv-lite@^0.4.13: +iconv-lite@^0.4.11: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" +iconv-lite@^0.4.17, iconv-lite@^0.4.18: + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" + +ignore@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflection@1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -758,7 +1299,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@~2.0.0, inherits@~2.0.1: +inherits@2, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -766,6 +1307,25 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" +inquirer@^3.0.6: + version "3.1.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.1.tgz#87621c4fba4072f48a8dd71c9f9df6f100b2d534" + dependencies: + ansi-escapes "^2.0.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + interpret@^0.6.5: version "0.6.6" resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" @@ -780,6 +1340,14 @@ is-buffer@^1.0.2: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + is-dotfile@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" @@ -810,18 +1378,42 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" dependencies: is-extglob "^1.0.0" +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + is-number@^2.0.2, is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" dependencies: kind-of "^3.0.2" +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -830,6 +1422,26 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-regex@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -842,7 +1454,7 @@ isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -870,14 +1482,29 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" +js-yaml@^3.8.4: + version "3.8.4" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" + dependencies: + argparse "^1.0.7" + esprima "^3.1.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -938,6 +1565,13 @@ knex@0.13.0: uuid "^3.0.0" v8flags "^2.0.2" +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + liftoff@~2.2.0: version "2.2.5" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.2.5.tgz#998c2876cff484b103e4423b93d356da44734c91" @@ -948,10 +1582,16 @@ liftoff@~2.2.0: rechoir "^0.6.2" resolve "^1.1.7" -lodash@^4.2.0, lodash@^4.6.0: +lodash@^4.0.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + long@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" @@ -966,14 +1606,53 @@ lru-cache@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.5.0.tgz#d82388ae9c960becbea0c73bb9eb79b6c6ce9aeb" -lru-cache@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" +lru-cache@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" dependencies: - pseudomap "^1.0.1" - yallist "^2.0.0" + pseudomap "^1.0.2" + yallist "^2.1.2" -micromatch@^2.3.7: +"lux-framework@file:../../": + version "1.2.0" + dependencies: + ansi-regex "3.0.0" + babel-eslint "7.2.3" + chalk "2.0.1" + commander "2.11.0" + eslint "4.2.0" + fb-watchman "2.0.0" + inflection "1.12.0" + knex "0.13.0" + mz "2.6.0" + object.entries "1.0.4" + object.values "1.0.4" + ora "1.3.0" + qs "6.5.0" + rollup "0.45.2" + rollup-plugin-alias zacharygolba/rollup-plugin-alias#resolve-index-prebuilt + rollup-plugin-babel "2.7.1" + rollup-plugin-cleanup "1.0.1" + rollup-plugin-eslint "4.0.0" + rollup-plugin-json "2.3.0" + rollup-plugin-lux "3.0.0" + rollup-plugin-node-resolve "3.0.0" + slash "1.0.0" + source-map-support "0.4.15" + +magic-string@*: + version "0.21.3" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.21.3.tgz#87e201009ebfde6f46dc5757305a70af71e31624" + dependencies: + vlq "^0.2.1" + +magic-string@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.19.0.tgz#198948217254e3e0b93080e01146b7c73b2a06b2" + dependencies: + vlq "^0.2.1" + +micromatch@^2.3.11, micromatch@^2.3.7: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" dependencies: @@ -1001,12 +1680,22 @@ mime-types@^2.1.12, mime-types@~2.1.7: dependencies: mime-db "~1.27.0" +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + minimatch@^3.0.0, minimatch@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: brace-expansion "^1.0.0" +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -1029,6 +1718,10 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + mssql@4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/mssql/-/mssql-4.0.4.tgz#416d67df7653536cb6384951891fa1a47572a49b" @@ -1037,23 +1730,35 @@ mssql@4.0.4: generic-pool "^3.1.7" tedious "^2.0.0" -mysql2@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-1.2.0.tgz#3ac6a419a783a66aac8fd7eab8a71089a2612b79" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +mysql2@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-1.3.6.tgz#d5c14917de0b15801a6c1883599bcf6fb27c1a1e" dependencies: cardinal "1.0.0" denque "^1.1.1" generate-function "^2.0.0" - iconv-lite "^0.4.13" + iconv-lite "^0.4.18" long "^3.2.0" - lru-cache "^4.0.1" + lru-cache "^4.1.1" named-placeholders "1.1.1" object-assign "^4.1.1" - readable-stream "2.2.2" + readable-stream "2.3.2" safe-buffer "^5.0.1" seq-queue "0.0.5" sqlstring "^2.2.0" +mz@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.6.0.tgz#c8b8521d958df0a4f2768025db69c719ee4ef1ce" + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + named-placeholders@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.1.tgz#3b7a0d26203dd74b3a9df4c9cfb827b2fb907e64" @@ -1064,6 +1769,14 @@ nan@~2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + node-pre-gyp@~0.6.31: version "0.6.34" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" @@ -1110,10 +1823,23 @@ object-assign@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +object.entries@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1121,17 +1847,52 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.values@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + once@^1.3.0, once@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +ora@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a" + dependencies: + chalk "^1.1.1" + cli-cursor "^2.1.0" + cli-spinners "^1.0.0" + log-symbols "^1.0.2" + os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -1163,6 +1924,10 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -1192,24 +1957,42 @@ pg-types@1.*: postgres-date "~1.0.0" postgres-interval "~1.0.0" -pg@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/pg/-/pg-6.2.2.tgz#f778c129e16c6f88da564f76faf854f832c724c0" +pg@6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" dependencies: buffer-writer "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" pg-pool "1.*" pg-types "1.*" - pgpass "1.x" + pgpass "1.*" semver "4.3.2" -pgpass@1.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.1.tgz#0de8b5bef993295d90a7e17d976f568dcd25d49f" +pgpass@1.*: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" dependencies: split "^1.0.0" +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" + postgres-array@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" @@ -1228,6 +2011,10 @@ postgres-interval@~1.0.0: dependencies: xtend "^4.0.0" +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -1240,7 +2027,11 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -pseudomap@^1.0.1: +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + +pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -1248,6 +2039,10 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +qs@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -1268,16 +2063,16 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -readable-stream@2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" +readable-stream@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.2.tgz#5a04df05e4f57fe3f0dc68fdd11dc5c97c7e6f4d" dependencies: - buffer-shims "^1.0.0" core-util-is "~1.0.0" - inherits "~2.0.1" + inherits "~2.0.3" isarray "~1.0.0" process-nextick-args "~1.0.6" - string_decoder "~0.10.x" + safe-buffer "~5.1.0" + string_decoder "~1.0.0" util-deprecate "~1.0.1" readable-stream@^1.1.12: @@ -1289,7 +2084,7 @@ readable-stream@^1.1.12: isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.2.6: +"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6: version "2.2.9" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" dependencies: @@ -1365,6 +2160,13 @@ request@^2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + resolve-dir@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" @@ -1372,22 +2174,130 @@ resolve-dir@^0.1.0: expand-tilde "^1.2.2" global-modules "^0.2.3" +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + resolve@^1.1.6, resolve@^1.1.7: version "1.3.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" dependencies: path-parse "^1.0.5" -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: glob "^7.0.5" +rollup-plugin-alias@zacharygolba/rollup-plugin-alias#resolve-index-prebuilt: + version "1.3.1" + resolved "https://codeload.github.com/zacharygolba/rollup-plugin-alias/tar.gz/3624fc5695fba5e98678f6d4311228f32da7213b" + dependencies: + slash "^1.0.0" + +rollup-plugin-babel@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-2.7.1.tgz#16528197b0f938a1536f44683c7a93d573182f57" + dependencies: + babel-core "6" + babel-plugin-transform-es2015-classes "^6.9.0" + object-assign "^4.1.0" + rollup-pluginutils "^1.5.0" + +rollup-plugin-cleanup@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-cleanup/-/rollup-plugin-cleanup-1.0.1.tgz#ca056c74fe6ea21783f99851963b173cbe8e9359" + dependencies: + acorn "4.x" + magic-string "*" + rollup-pluginutils "*" + +rollup-plugin-eslint@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-eslint/-/rollup-plugin-eslint-4.0.0.tgz#9fb97c0ef5bc0d7a54eef1f28170f1974dc938ec" + dependencies: + eslint "^4.1.1" + rollup-pluginutils "^2.0.1" + +rollup-plugin-json@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-2.3.0.tgz#3c07a452c1b5391be28006fbfff3644056ce0add" + dependencies: + rollup-pluginutils "^2.0.1" + +rollup-plugin-lux@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-lux/-/rollup-plugin-lux-3.0.0.tgz#680d3d2d0b58ad3c4d72f41d3e4fc47f559bdec1" + dependencies: + acorn "4.0.4" + eol "0.5.1" + magic-string "0.19.0" + +rollup-plugin-node-resolve@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz#8b897c4c3030d5001277b0514b25d2ca09683ee0" + dependencies: + browser-resolve "^1.11.0" + builtin-modules "^1.1.0" + is-module "^1.0.0" + resolve "^1.1.6" + +rollup-pluginutils@*, rollup-pluginutils@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup-pluginutils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" + dependencies: + estree-walker "^0.3.0" + micromatch "^2.3.11" + +rollup@0.45.2: + version "0.45.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.45.2.tgz#63a284c2b31234656f24e9e9717fabb6a7f0fa43" + dependencies: + source-map-support "^0.4.0" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + safe-buffer@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" +safe-buffer@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" @@ -1404,21 +2314,25 @@ set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -slash@^1.0.0: +slash@1.0.0, slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" dependencies: hoek "2.x.x" -source-map-support@0.4.15, source-map-support@^0.4.2: +source-map-support@0.4.15, source-map-support@^0.4.0, source-map-support@^0.4.2: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" dependencies: @@ -1434,6 +2348,10 @@ split@^1.0.0: dependencies: through "2" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + sprintf@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/sprintf/-/sprintf-0.1.5.tgz#8f83e39a9317c1a502cb7db8050e51c679f6edcf" @@ -1472,6 +2390,13 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -1500,6 +2425,23 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" +supports-color@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.0.tgz#ad986dc7eb2315d009b4d77c8169c2231a684037" + dependencies: + has-flag "^2.0.0" + +table@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + tar-pack@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" @@ -1532,7 +2474,23 @@ tedious@^2.0.0: readable-stream "^2.2.6" sprintf "0.1.5" -through@2: +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + dependencies: + any-promise "^1.0.0" + +through@2, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1542,6 +2500,12 @@ tildify@~1.0.0: dependencies: user-home "^1.0.0" +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" @@ -1556,6 +2520,10 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -1566,6 +2534,16 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -1594,6 +2572,10 @@ verror@1.3.6: dependencies: extsprintf "1.0.2" +vlq@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1" + which@^1.2.12: version "1.2.14" resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" @@ -1606,14 +2588,24 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.1" +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" -yallist@^2.0.0: +yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" diff --git a/test/utils/debugger/rollup.config.js b/test/utils/debugger/rollup.config.js index 676d1076..e6a13a53 100644 --- a/test/utils/debugger/rollup.config.js +++ b/test/utils/debugger/rollup.config.js @@ -8,11 +8,10 @@ export default { dest: './test/utils/debugger/dist/debug.js', entry: './test/utils/debugger/src/debug.js', format: 'cjs', - banner: ( - 'require(\'source-map-support\').install({\n' - + ' environment: \'node\'\n' - + '});\n' - ), + banner: + "require('source-map-support').install({\n" + + " environment: 'node'\n" + + '});\n', onwarn: ({ code, message }) => { if (code === 'UNUSED_EXTERNAL_IMPORT') { return @@ -20,19 +19,16 @@ export default { // eslint-disable-next-line no-console console.warn(message) }, - plugins: [ - json(), - babel(), - resolve() - ], - external: id => !( - id.startsWith('.') - || id.startsWith('/') // Absolute path on Unix - || /^[A-Z]:[\\/]/.test(id) // Absolute path on Windows - || id.startsWith('src') - || id.startsWith(path.join(__dirname, 'src')) - || id === 'babelHelpers' - || id === '\u0000babelHelpers' - ), - sourceMap: true + plugins: [json(), babel(), resolve()], + external: id => + !( + id.startsWith('.') || + id.startsWith('/') || // Absolute path on Unix + /^[A-Z]:[\\/]/.test(id) || // Absolute path on Windows + id.startsWith('src') || + id.startsWith(path.join(__dirname, 'src')) || + id === 'babelHelpers' || + id === '\u0000babelHelpers' + ), + sourceMap: true, } diff --git a/test/utils/debugger/src/debug.js b/test/utils/debugger/src/debug.js index 5331c6a3..a09b97db 100644 --- a/test/utils/debugger/src/debug.js +++ b/test/utils/debugger/src/debug.js @@ -11,7 +11,7 @@ const repoDir = process.cwd() // Shortcut for console.log // eslint-disable-next-line no-console -function log(...msg) { console.log(...msg) } +const log = (...msg) => console.log(...msg) // @async runCommand // Run a terminal command @@ -37,8 +37,8 @@ async function runCommand(command, args = [], messages = []) { run.once('exit', () => resolve(successMsg)) }) - .then(log) - .catch(err => log(err.toString())) + .then(log) + .catch(err => log(err.toString())) } // @async runInspector @@ -58,7 +58,7 @@ function runInspector() { runCommand( 'osascript', ['-e', `tell application "Google Chrome" to open location "${target}"`], - ['Opening in Google Chrome (OSX Users only)'] + ['Opening in Google Chrome (OSX Users only)'], ) } @@ -68,7 +68,7 @@ function runInspector() { return `chrome-devtools${parts[1]}`.replace(/\s+/g, '') } - run.stderr.on('data', (buff) => { + run.stderr.on('data', buff => { if (url) { return } @@ -81,10 +81,10 @@ function runInspector() { }) run.stdout.on('data', data => log(data.toString())) - run.on('exit', (code) => log(`Child exited with code ${code}`)) + run.on('exit', code => log(`Child exited with code ${code}`)) }) - .then(msg => log(msg)) - .catch(err => log(err.toString)) + .then(msg => log(msg)) + .catch(err => log(err.toString)) } // @listener @@ -92,12 +92,11 @@ function runInspector() { process.on('exit', () => { process.chdir(repoDir) -}); +}) // @async // Run commands - -(async function main() { +;(async function main() { const cleanArgs = [ 'rm', '-rf', @@ -108,22 +107,21 @@ process.on('exit', () => { 'test-results.xml', ] - await runCommand('shx', cleanArgs, [ - 'Cleaning Lux repo...', - 'Repo cleaned.', - ]) + await runCommand('shx', cleanArgs, ['Cleaning Lux repo...', 'Repo cleaned.']) - await runCommand('rollup', ['-c'], [ - 'Building Lux source...', - 'Lux source built.', - ]) + await runCommand( + 'rollup', + ['-c'], + ['Building Lux source...', 'Lux source built.'], + ) process.chdir('./test/test-app') - await runCommand('lux', ['build'], [ - 'Building Lux test-app...', - 'Lux test-app built.', - ]) + await runCommand( + 'lux', + ['build'], + ['Building Lux test-app...', 'Lux test-app built.'], + ) await runInspector() -}()) +})() diff --git a/test/utils/set-env.js b/test/utils/set-env.js index 0fab5dd0..10db245e 100644 --- a/test/utils/set-env.js +++ b/test/utils/set-env.js @@ -1,8 +1,6 @@ /* @flow */ -type Environment = 'development' - | 'production' - | 'test' +type Environment = 'development' | 'production' | 'test' export default function setEnv(value: Environment): void { global.process.env.NODE_ENV = value diff --git a/test/utils/test-app.js b/test/utils/test-app.js index 8595a865..6a2df94e 100644 --- a/test/utils/test-app.js +++ b/test/utils/test-app.js @@ -7,20 +7,20 @@ import type Application from '../../src/packages/application' export function getTestApp(): Promise { const path = joinPath(__dirname, '..', 'test-app') - /* eslint-disable import/no-unresolved */ + /* eslint-disable global-require, import/no-unresolved */ const { config, database, - Application: TestApp - }: { - config: Object; - database: Object; - Application: Class; - // $FlowIgnore + Application: TestApp, + }: { + config: Object, + database: Object, + Application: Class, + // $FlowFixMe } = require('../test-app/dist/bundle') - /* eslint-enable import/no-unresolved */ + /* eslint-enable global-require, import/no-unresolved */ return new TestApp({ ...config, diff --git a/yarn.lock b/yarn.lock index 858b7206..76879d45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,7 +22,7 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn@4.0.4, acorn@^4.0.4: +acorn@4.0.4, acorn@4.x, acorn@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" @@ -45,6 +45,15 @@ ajv@^4.7.0, ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + json-schema-traverse "^0.3.0" + json-stable-stringify "^1.0.1" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -57,11 +66,19 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" -ansi-regex@2.1.1, ansi-regex@^2.0.0, ansi-regex@^2.1.1: +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" + +ansi-regex@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -75,6 +92,16 @@ ansi-styles@^3.0.0: dependencies: color-convert "^1.0.0" +ansi-styles@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" + dependencies: + color-convert "^1.0.0" + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + anymatch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" @@ -82,6 +109,10 @@ anymatch@^1.3.0: arrify "^1.0.0" micromatch "^2.1.5" +app-root-path@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46" + append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" @@ -185,7 +216,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: +babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -193,20 +224,20 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6, babel-core@6.24.1, babel-core@^6.0.0, babel-core@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" +babel-core@6, babel-core@6.25.0, babel-core@^6.0.0, babel-core@^6.24.1: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.24.1" + babel-generator "^6.25.0" babel-helpers "^6.24.1" babel-messages "^6.23.0" babel-register "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babylon "^6.11.0" + babel-template "^6.25.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" convert-source-map "^1.1.0" debug "^2.1.1" json5 "^0.5.0" @@ -226,13 +257,13 @@ babel-eslint@7.2.3: babel-types "^6.23.0" babylon "^6.17.0" -babel-generator@^6.18.0, babel-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497" +babel-generator@^6.18.0, babel-generator@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" dependencies: babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.24.1" + babel-types "^6.25.0" detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.2.0" @@ -481,17 +512,31 @@ babel-runtime@^6.11.6, babel-runtime@^6.22.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-template@^6.16.0, babel-template@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333" +babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" dependencies: babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babylon "^6.11.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" + lodash "^4.2.0" + +babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" + dependencies: + babel-code-frame "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.25.0" + babylon "^6.17.2" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" lodash "^4.2.0" -babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1: +babel-traverse@^6.23.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695" dependencies: @@ -505,7 +550,16 @@ babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1: invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.18.0, babel-types@^6.23.0, babel-types@^6.24.1: +babel-types@^6.18.0, babel-types@^6.24.1, babel-types@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" + dependencies: + babel-runtime "^6.22.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babel-types@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975" dependencies: @@ -514,7 +568,11 @@ babel-types@^6.18.0, babel-types@^6.23.0, babel-types@^6.24.1: lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0, babylon@^6.17.0: +babylon@^6.13.0, babylon@^6.15.0, babylon@^6.17.2: + version "6.17.3" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.3.tgz#1327d709950b558f204e5352587fd0290f8d8e48" + +babylon@^6.17.0: version "6.17.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f" @@ -651,7 +709,15 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -704,7 +770,7 @@ circular-json@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" -cli-cursor@^1.0.1: +cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: @@ -716,10 +782,21 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + cli-spinners@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a" +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" @@ -784,9 +861,13 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.9.0, commander@^2.2.0, commander@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + +commander@^2.2.0, commander@^2.9.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.10.0.tgz#e1f5d3245de246d1a5ca04702fa1ad1bd7e405fe" dependencies: graceful-readlink ">= 1.0.0" @@ -794,7 +875,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.5.1, concat-stream@^1.5.2: +concat-stream@^1.5.1, concat-stream@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -826,6 +907,27 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +cosmiconfig@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-1.1.0.tgz#0dea0f9804efdfb929fbb1b188e25553ea053d37" + dependencies: + graceful-fs "^4.1.2" + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.0.1" + os-homedir "^1.0.1" + parse-json "^2.2.0" + pinkie-promise "^2.0.0" + require-from-string "^1.1.0" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -846,29 +948,21 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" +date-fns@^1.27.2: + version "1.28.5" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf" -debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3: - version "2.6.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" +debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: - ms "0.7.3" + ms "2.0.0" decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" @@ -951,11 +1045,15 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + eol@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/eol/-/eol-0.5.1.tgz#a2f15f9be38ac160f27c4e394fde02a9731a410c" -"errno@>=0.1.1 <0.2.0-0": +"errno@>=0.1.1 <0.2.0-0", errno@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" dependencies: @@ -984,62 +1082,10 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.18" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.18.tgz#dc239d3dce4c22b9c939aa180878837a3c0b5c92" - dependencies: - es6-iterator "2" - es6-symbol "~3.1" - -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - es6-object-assign@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1055,100 +1101,108 @@ escodegen@^1.6.1: optionalDependencies: source-map "~0.2.0" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-config-airbnb-base@11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz#19a9dc4481a26f70904545ec040116876018f853" -eslint-import-resolver-node@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" +eslint-config-prettier@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.3.0.tgz#b75b1eabea0c8b97b34403647ee25db349b9d8a0" dependencies: - debug "^2.2.0" - object-assign "^4.0.1" - resolve "^1.1.6" + get-stdin "^5.0.1" -eslint-module-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce" +eslint-import-resolver-node@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" dependencies: - debug "2.2.0" + debug "^2.6.8" + resolve "^1.2.0" + +eslint-module-utils@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" pkg-dir "^1.0.0" -eslint-plugin-flowtype@2.33.0: - version "2.33.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.33.0.tgz#b2783814ed2ddcf729953b8f65ff73c90cabee4b" +eslint-plugin-flowtype@2.35.0: + version "2.35.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.35.0.tgz#d17494f0ae8b727c632d8b9d4b4a848e7e0c04af" dependencies: lodash "^4.15.0" -eslint-plugin-import@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" +eslint-plugin-import@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" - debug "^2.2.0" + debug "^2.6.8" doctrine "1.5.0" - eslint-import-resolver-node "^0.2.0" - eslint-module-utils "^2.0.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" has "^1.0.1" lodash.cond "^4.3.0" minimatch "^3.0.3" - pkg-up "^1.0.0" + read-pkg-up "^2.0.0" eslint-plugin-jest@20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-20.0.3.tgz#ec15eba6ac0ab44a67ebf6e02672ca9d7e7cba29" -eslint@3.19.0, eslint@^3.4.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" +eslint-plugin-prettier@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.1.2.tgz#4b90f4ee7f92bfbe2e926017e1ca40eb628965ea" + dependencies: + fast-diff "^1.1.1" + jest-docblock "^20.0.1" + +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@4.2.0, eslint@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.2.0.tgz#a2b3184111b198e02e9c7f3cca625a5e01c56b3d" dependencies: - babel-code-frame "^6.16.0" + ajv "^5.2.0" + babel-code-frame "^6.22.0" chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" + concat-stream "^1.6.0" + debug "^2.6.8" doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" + eslint-scope "^3.7.1" + espree "^3.4.3" esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" + inquirer "^3.0.6" is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" + js-yaml "^3.8.4" + json-stable-stringify "^1.0.1" levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" strip-json-comments "~2.0.1" - table "^3.7.8" + table "^4.0.1" text-table "~0.2.0" - user-home "^2.0.0" -espree@^3.4.0: +espree@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" dependencies: @@ -1192,23 +1246,32 @@ estree-walker@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" +estree-walker@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - exec-sh@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.0.tgz#14f75de3f20d286ef933099b2ce50a90359cef10" dependencies: merge "^1.1.3" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -1235,6 +1298,14 @@ extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" + dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" + tmp "^0.0.31" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -1249,6 +1320,14 @@ faker@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f" +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-diff@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.1.tgz#0aea0e4e605b6a2189f0e936d4b7fbaf1b7cfd9b" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -1271,13 +1350,19 @@ fb-watchman@^1.8.0: dependencies: bser "1.0.2" -figures@^1.3.5: +figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: escape-string-regexp "^1.0.5" object-assign "^4.1.0" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" @@ -1313,7 +1398,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.1.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: @@ -1341,9 +1426,9 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flow-bin@0.46.0: - version "0.46.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.46.0.tgz#06ad7fe19dddb1042264438064a2a32fee12b872" +flow-bin@0.50.0: + version "0.50.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.50.0.tgz#d4cdb2430dee1a3599f0eb6fe551146e3027256a" flow-typed@2.1.2: version "2.1.2" @@ -1482,6 +1567,14 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1507,14 +1600,14 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" @@ -1534,7 +1627,7 @@ global-prefix@^0.1.4: is-windows "^0.2.0" which "^1.2.12" -globals@^9.0.0, globals@^9.14.0: +globals@^9.0.0, globals@^9.17.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" @@ -1607,6 +1700,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -1661,18 +1758,40 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +husky@0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" + dependencies: + is-ci "^1.0.10" + normalize-path "^1.0.0" + strip-indent "^2.0.0" + iconv-lite@0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" -ignore@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.0.tgz#3812d22cbe9125f2c2b4915755a1b8abd745a001" +iconv-lite@^0.4.17: + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" + +ignore@^3.2.0, ignore@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indent-string@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.1.0.tgz#08ff4334603388399b329e6b9538dc7a3cf5de7d" + inflection@1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" @@ -1692,21 +1811,22 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" +inquirer@^3.0.6: + version "3.1.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.1.tgz#87621c4fba4072f48a8dd71c9f9df6f100b2d534" dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" + ansi-escapes "^2.0.0" chalk "^1.0.0" - cli-cursor "^1.0.1" + cli-cursor "^2.1.0" cli-width "^2.0.0" - figures "^1.3.5" + external-editor "^2.0.4" + figures "^2.0.0" lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.0.0" strip-ansi "^3.0.0" through "^2.3.6" @@ -1841,7 +1961,7 @@ is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" -is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: +is-my-json-valid@^2.12.4: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" dependencies: @@ -1888,6 +2008,10 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" @@ -1904,6 +2028,10 @@ is-resolvable@^1.0.0: dependencies: tryit "^1.0.1" +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" @@ -2017,9 +2145,9 @@ jest-changed-files@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" -jest-cli@20.0.3, jest-cli@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.3.tgz#fe88ddbb7a9f3a16d0ed55339a0a2424f7f0d361" +jest-cli@20.0.4, jest-cli@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93" dependencies: ansi-escapes "^1.4.0" callsites "^2.0.0" @@ -2031,15 +2159,15 @@ jest-cli@20.0.3, jest-cli@^20.0.3: istanbul-lib-instrument "^1.4.2" istanbul-lib-source-maps "^1.1.0" jest-changed-files "^20.0.3" - jest-config "^20.0.3" + jest-config "^20.0.4" jest-docblock "^20.0.3" jest-environment-jsdom "^20.0.3" - jest-haste-map "^20.0.3" - jest-jasmine2 "^20.0.3" + jest-haste-map "^20.0.4" + jest-jasmine2 "^20.0.4" jest-message-util "^20.0.3" jest-regex-util "^20.0.3" jest-resolve-dependencies "^20.0.3" - jest-runtime "^20.0.3" + jest-runtime "^20.0.4" jest-snapshot "^20.0.3" jest-util "^20.0.3" micromatch "^2.3.11" @@ -2052,18 +2180,18 @@ jest-cli@20.0.3, jest-cli@^20.0.3: worker-farm "^1.3.1" yargs "^7.0.2" -jest-config@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.3.tgz#a934f27eea764915801cdda26f6f8eec2ac79266" +jest-config@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea" dependencies: chalk "^1.1.3" glob "^7.1.1" jest-environment-jsdom "^20.0.3" jest-environment-node "^20.0.3" - jest-jasmine2 "^20.0.3" + jest-jasmine2 "^20.0.4" jest-matcher-utils "^20.0.3" jest-regex-util "^20.0.3" - jest-resolve "^20.0.3" + jest-resolve "^20.0.4" jest-validate "^20.0.3" pretty-format "^20.0.3" @@ -2076,7 +2204,7 @@ jest-diff@^20.0.3: jest-matcher-utils "^20.0.3" pretty-format "^20.0.3" -jest-docblock@^20.0.3: +jest-docblock@^20.0.1, jest-docblock@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" @@ -2095,9 +2223,9 @@ jest-environment-node@^20.0.3: jest-mock "^20.0.3" jest-util "^20.0.3" -jest-haste-map@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.3.tgz#6377d537eaf34eb5f75121a691cae3fde82ba971" +jest-haste-map@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.4.tgz#653eb55c889ce3c021f7b94693f20a4159badf03" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" @@ -2106,9 +2234,9 @@ jest-haste-map@^20.0.3: sane "~1.6.0" worker-farm "^1.3.1" -jest-jasmine2@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.3.tgz#18c4e9d029da7ed1ae727c55300064d1a0542974" +jest-jasmine2@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1" dependencies: chalk "^1.1.3" graceful-fs "^4.1.11" @@ -2158,17 +2286,17 @@ jest-resolve-dependencies@^20.0.3: dependencies: jest-regex-util "^20.0.3" -jest-resolve@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.3.tgz#375307aa40f78532d40ff8b17d5300b1519f8dd4" +jest-resolve@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5" dependencies: browser-resolve "^1.11.2" is-builtin-module "^1.0.0" resolve "^1.3.2" -jest-runtime@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.3.tgz#dddd22bbc429e26e6a96d1acd46ca55714b09252" +jest-runtime@^20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8" dependencies: babel-core "^6.0.0" babel-jest "^20.0.3" @@ -2176,10 +2304,10 @@ jest-runtime@^20.0.3: chalk "^1.1.3" convert-source-map "^1.4.0" graceful-fs "^4.1.11" - jest-config "^20.0.3" - jest-haste-map "^20.0.3" + jest-config "^20.0.4" + jest-haste-map "^20.0.4" jest-regex-util "^20.0.3" - jest-resolve "^20.0.3" + jest-resolve "^20.0.4" jest-util "^20.0.3" json-stable-stringify "^1.0.1" micromatch "^2.3.11" @@ -2218,11 +2346,11 @@ jest-validate@^20.0.3: leven "^2.1.0" pretty-format "^20.0.3" -jest@20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.3.tgz#e4fd054c4f1170a116a00761da4cfdb73f1cdc33" +jest@20.0.4: + version "20.0.4" + resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" dependencies: - jest-cli "^20.0.3" + jest-cli "^20.0.4" jodid25519@^1.0.0: version "1.0.2" @@ -2234,7 +2362,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.5.1, js-yaml@^3.6.1, js-yaml@^3.7.0: +js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.8.4: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -2245,6 +2373,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a" + jsdom@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" @@ -2273,11 +2405,15 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: +json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: @@ -2374,6 +2510,67 @@ liftoff@~2.2.0: rechoir "^0.6.2" resolve "^1.1.7" +lint-staged@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-4.0.1.tgz#05365469898439dbade8a455893cf11e24d12b0f" + dependencies: + app-root-path "^2.0.0" + cosmiconfig "^1.1.0" + execa "^0.7.0" + listr "^0.12.0" + lodash.chunk "^4.2.0" + minimatch "^3.0.0" + npm-which "^3.0.1" + p-map "^1.1.1" + staged-git-files "0.0.4" + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.0.tgz#44dc01bb0c34a03c572154d4d08cde9b1dc5620f" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.2.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^5.0.0-beta.11" + stream-to-observable "^0.1.0" + strip-ansi "^3.0.1" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -2384,6 +2581,15 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + load-plugin@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/load-plugin/-/load-plugin-2.1.0.tgz#5c688c560261997b47dfd0a7361faeb152acf7f5" @@ -2402,11 +2608,15 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" +lodash.chunk@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" + lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.0: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2416,6 +2626,13 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + longest-streak@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.1.tgz#42d291b5411e40365c00e63193497e2247316e35" @@ -2430,7 +2647,14 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0" -magic-string@0.19.0: +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +magic-string@*, magic-string@0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.19.0.tgz#198948217254e3e0b93080e01146b7c73b2a06b2" dependencies: @@ -2488,6 +2712,13 @@ mdast-util-to-string@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.2.tgz#dc996a24d2b521178d3fac3993680c03a683e1dd" +memory-fs@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + merge@^1.1.3: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" @@ -2528,7 +2759,7 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -2552,17 +2783,21 @@ mkdirp@0.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" +mz@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.6.0.tgz#c8b8521d958df0a4f2768025db69c719ee4ef1ce" + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" nan@^2.3.0: version "2.6.2" @@ -2619,12 +2854,22 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" +npm-path@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.3.tgz#15cff4e1c89a38da77f56f6055b24f975dfb2bbe" + dependencies: + which "^1.2.10" + npm-prefix@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/npm-prefix/-/npm-prefix-1.2.0.tgz#e619455f7074ba54cc66d6d0d37dd9f1be6bcbc0" @@ -2633,6 +2878,20 @@ npm-prefix@^1.2.0: shellsubstitute "^1.1.0" untildify "^2.1.0" +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npm-which@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" + dependencies: + commander "^2.9.0" + npm-path "^2.0.2" + which "^1.2.10" + npmlog@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5" @@ -2678,6 +2937,15 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.values@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + once@^1.3.0, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2712,15 +2980,24 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -ora@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-1.2.0.tgz#32fb3183500efe83f5ea89101785f0ee6060fec9" +ora@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a" dependencies: chalk "^1.1.1" cli-cursor "^2.1.0" cli-spinners "^1.0.0" log-symbols "^1.0.2" +ora@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -2731,7 +3008,7 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -2746,6 +3023,10 @@ osenv@^0.1.4: version "0.0.5" resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + p-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" @@ -2809,10 +3090,14 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -2825,6 +3110,12 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" @@ -2853,21 +3144,15 @@ pkg-dir@^1.0.0: dependencies: find-up "^1.0.0" -pkg-up@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" - dependencies: - find-up "^1.0.0" - plur@^2.0.0, plur@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" dependencies: irregular-plurals "^1.0.0" -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" prelude-ls@~1.1.2: version "1.1.2" @@ -2877,6 +3162,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.5.3.tgz#59dadc683345ec6b88f88b94ed4ae7e1da394bfe" + pretty-format@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14" @@ -2892,14 +3181,18 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + "pullstream@>= 0.4.1 < 1": version "0.4.1" resolved "https://registry.yarnpkg.com/pullstream/-/pullstream-0.4.1.tgz#d6fb3bf5aed697e831150eb1002c25a3f8ae1314" @@ -2913,14 +3206,18 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -qs@6.4.0, qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + randomatic@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" @@ -2944,6 +3241,13 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -2952,6 +3256,14 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + readable-stream@^1.1.12: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -2961,7 +3273,7 @@ readable-stream@^1.1.12: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: version "2.2.9" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" dependencies: @@ -2991,14 +3303,6 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -3321,11 +3625,15 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-uncached@^1.0.2: +require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: @@ -3351,7 +3659,7 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: @@ -3383,9 +3691,9 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1: dependencies: glob "^7.0.5" -rollup-plugin-alias@1.3.1: +rollup-plugin-alias@zacharygolba/rollup-plugin-alias#resolve-index-prebuilt: version "1.3.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-alias/-/rollup-plugin-alias-1.3.1.tgz#a9152fec4b6a6510dae93989517ca7853c32a6fa" + resolved "https://codeload.github.com/zacharygolba/rollup-plugin-alias/tar.gz/3624fc5695fba5e98678f6d4311228f32da7213b" dependencies: slash "^1.0.0" @@ -3398,18 +3706,26 @@ rollup-plugin-babel@2.7.1: object-assign "^4.1.0" rollup-pluginutils "^1.5.0" -rollup-plugin-eslint@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-eslint/-/rollup-plugin-eslint-3.0.0.tgz#4354c4e585e0d2bd925814e3dfc864cb792ec9a4" +rollup-plugin-cleanup@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-cleanup/-/rollup-plugin-cleanup-1.0.1.tgz#ca056c74fe6ea21783f99851963b173cbe8e9359" dependencies: - eslint "^3.4.0" - rollup-pluginutils "^1.3.1" + acorn "4.x" + magic-string "*" + rollup-pluginutils "*" -rollup-plugin-json@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-2.1.1.tgz#933390dff3c9e3e654157d61304c5e167fc58623" +rollup-plugin-eslint@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-eslint/-/rollup-plugin-eslint-4.0.0.tgz#9fb97c0ef5bc0d7a54eef1f28170f1974dc938ec" + dependencies: + eslint "^4.1.1" + rollup-pluginutils "^2.0.1" + +rollup-plugin-json@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-2.3.0.tgz#3c07a452c1b5391be28006fbfff3644056ce0add" dependencies: - rollup-pluginutils "^1.5.2" + rollup-pluginutils "^2.0.1" rollup-plugin-lux@3.0.0: version "3.0.0" @@ -3428,28 +3744,47 @@ rollup-plugin-node-resolve@3.0.0: is-module "^1.0.0" resolve "^1.1.6" -rollup-pluginutils@^1.3.1, rollup-pluginutils@^1.5.0, rollup-pluginutils@^1.5.2: +rollup-pluginutils@*, rollup-pluginutils@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" dependencies: estree-walker "^0.2.1" minimatch "^3.0.2" -rollup@0.41.6: - version "0.41.6" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.6.tgz#e0d05497877a398c104d816d2733a718a7a94e2a" +rollup-pluginutils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" + dependencies: + estree-walker "^0.3.0" + micromatch "^2.3.11" + +rollup@0.45.2: + version "0.45.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.45.2.tgz#63a284c2b31234656f24e9e9717fabb6a7f0fa43" dependencies: source-map-support "^0.4.0" -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" dependencies: - once "^1.3.0" + is-promise "^2.1.0" -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +rxjs@^5.0.0-beta.11: + version "5.4.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.1.tgz#b62f757f279445d265a18a58fb0a70dc90e91626" + dependencies: + symbol-observable "^1.0.1" safe-buffer@^5.0.1: version "5.0.1" @@ -3487,7 +3822,17 @@ set-immediate-shim@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" -shelljs@^0.7.3, shelljs@^0.7.5: +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shelljs@^0.7.3: version "0.7.7" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" dependencies: @@ -3515,7 +3860,7 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -slash@^1.0.0: +slash@1.0.0, slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -3594,10 +3939,18 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +staged-git-files@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35" + state-toggle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" +stream-to-observable@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" + string-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" @@ -3659,6 +4012,14 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -3673,6 +4034,16 @@ supports-color@^3.1.2: dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.0.tgz#ad986dc7eb2315d009b4d77c8169c2231a684037" + dependencies: + has-flag "^2.0.0" + +symbol-observable@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" + symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -3688,6 +4059,17 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" +table@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + tar-pack@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" @@ -3723,6 +4105,18 @@ text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + dependencies: + any-promise "^1.0.0" + throat@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.0.0.tgz#e7c64c867cbb3845f10877642f7b60055b8ec0d6" @@ -3737,6 +4131,12 @@ tildify@~1.0.0: dependencies: user-home "^1.0.0" +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -3945,12 +4345,6 @@ user-home@^1.0.0, user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - dependencies: - os-homedir "^1.0.0" - util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -4048,7 +4442,7 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -which@^1.2.11, which@^1.2.12: +which@^1.2.10, which@^1.2.11, which@^1.2.12, which@^1.2.9: version "1.2.14" resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" dependencies: @@ -4127,6 +4521,10 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4"