Compare commits
2 Commits
smart-sele
...
redis-json
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
941d17d669 | ||
|
|
fd2b93d38b |
@@ -1,3 +0,0 @@
|
||||
module.exports = require('../../@xen-orchestra/babel-config')(
|
||||
require('./package.json')
|
||||
)
|
||||
@@ -1,24 +0,0 @@
|
||||
/benchmark/
|
||||
/benchmarks/
|
||||
*.bench.js
|
||||
*.bench.js.map
|
||||
|
||||
/examples/
|
||||
example.js
|
||||
example.js.map
|
||||
*.example.js
|
||||
*.example.js.map
|
||||
|
||||
/fixture/
|
||||
/fixtures/
|
||||
*.fixture.js
|
||||
*.fixture.js.map
|
||||
*.fixtures.js
|
||||
*.fixtures.js.map
|
||||
|
||||
/test/
|
||||
/tests/
|
||||
*.spec.js
|
||||
*.spec.js.map
|
||||
|
||||
__snapshots__/
|
||||
@@ -1,76 +0,0 @@
|
||||
# ${pkg.name} [](https://travis-ci.org/${pkg.shortGitHubPath})
|
||||
|
||||
> ${pkg.description}
|
||||
|
||||
Differences with [reselect](https://github.com/reactjs/reselect):
|
||||
|
||||
- simpler: no custom memoization
|
||||
- inputs (and their selectors): are stored in objects, not arrays
|
||||
- lazy:
|
||||
- inputs are not computed before accessed
|
||||
- unused inputs do not trigger a call to the transform function
|
||||
|
||||
## Install
|
||||
|
||||
Installation of the [npm package](https://npmjs.org/package/${pkg.name}):
|
||||
|
||||
```
|
||||
> npm install --save ${pkg.name}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import createSelector from 'smart-selector'
|
||||
|
||||
const getVisibleTodos = createSelector(
|
||||
{
|
||||
filter: state => state.filter,
|
||||
todos: state => state.todos,
|
||||
},
|
||||
inputs => {
|
||||
switch (inputs.filter) {
|
||||
case 'ALL':
|
||||
return inputs.todos
|
||||
case 'COMPLETED':
|
||||
return inputs.todos.filter(todo => todo.completed)
|
||||
case 'ACTIVE':
|
||||
return inputs.todos.filter(todo => !todo.completed)
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```
|
||||
# Install dependencies
|
||||
> yarn
|
||||
|
||||
# Run the tests
|
||||
> yarn test
|
||||
|
||||
# Continuously compile
|
||||
> yarn dev
|
||||
|
||||
# Continuously run the tests
|
||||
> yarn dev-test
|
||||
|
||||
# Build for production (automatically called by npm install)
|
||||
> yarn build
|
||||
```
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are *very* welcomed, either on the documentation or on
|
||||
the code.
|
||||
|
||||
You may:
|
||||
|
||||
- report any [issue](https://github.com/vatesfr/xo-web/issues)
|
||||
you've encountered;
|
||||
- fork and create a pull request.
|
||||
|
||||
## License
|
||||
|
||||
ISC © [Vates SAS](https://vates.fr)
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "smart-selector",
|
||||
"version": "0.0.0",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/smart-selector",
|
||||
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Julien Fontanet",
|
||||
"email": "julien.fontanet@isonoe.net"
|
||||
},
|
||||
"preferGlobal": false,
|
||||
"main": "dist/",
|
||||
"bin": {},
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.1.5",
|
||||
"@babel/core": "7.1.5",
|
||||
"@babel/preset-env": "7.1.5",
|
||||
"babel-plugin-lodash": "^3.3.2",
|
||||
"cross-env": "^5.1.1",
|
||||
"rimraf": "^2.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||
"clean": "rimraf dist/",
|
||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||
"prebuild": "yarn run clean",
|
||||
"predev": "yarn run clean",
|
||||
"prepublishOnly": "yarn run build"
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
const { create, keys } = Object
|
||||
|
||||
const createSelector = (inputSelectors, transform) => {
|
||||
const previousArgs = [{}] // initialize with non-repeatable args
|
||||
let cache, previousResult, previousThisArg
|
||||
let previousInputs = {}
|
||||
|
||||
const spyDescriptors = {}
|
||||
const inputs = keys(inputSelectors)
|
||||
for (let i = 0, n = inputs.length; i < n; ++i) {
|
||||
const input = inputs[i]
|
||||
spyDescriptors[input] = {
|
||||
enumerable: true,
|
||||
get: () =>
|
||||
input in previousInputs
|
||||
? previousInputs[input]
|
||||
: (previousInputs[input] =
|
||||
input in cache
|
||||
? cache[input]
|
||||
: inputSelectors[input].apply(previousThisArg, previousArgs)),
|
||||
}
|
||||
}
|
||||
const spy = create(null, spyDescriptors)
|
||||
|
||||
function selector () {
|
||||
// handle arguments
|
||||
{
|
||||
const { length } = arguments
|
||||
let i = 0
|
||||
if (this === previousThisArg && length === previousArgs.length) {
|
||||
while (i < length && arguments[i] === previousArgs[i]) {
|
||||
++i
|
||||
}
|
||||
if (i === length) {
|
||||
return previousResult
|
||||
}
|
||||
} else {
|
||||
previousArgs.length = length
|
||||
previousThisArg = this
|
||||
}
|
||||
while (i < length) {
|
||||
previousArgs[i] = arguments[i]
|
||||
++i
|
||||
}
|
||||
}
|
||||
|
||||
// handle inputs
|
||||
cache = previousInputs
|
||||
previousInputs = {}
|
||||
{
|
||||
const inputs = keys(cache)
|
||||
const { length } = inputs
|
||||
if (length !== 0) {
|
||||
let i = 0
|
||||
while (true) {
|
||||
if (i === length) {
|
||||
// inputs are unchanged
|
||||
return previousResult
|
||||
}
|
||||
|
||||
const input = inputs[i++]
|
||||
const value = inputSelectors[input].apply(this, arguments)
|
||||
if (value !== cache[input]) {
|
||||
// update the value
|
||||
cache[input] = value
|
||||
|
||||
// remove non-computed values
|
||||
while (i < length) {
|
||||
delete cache[inputs[i++]]
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (previousResult = transform(spy))
|
||||
}
|
||||
return selector
|
||||
}
|
||||
export { createSelector as default }
|
||||
@@ -1,99 +0,0 @@
|
||||
/* eslint-env jest */
|
||||
|
||||
import createSelector from './'
|
||||
|
||||
const noop = () => {}
|
||||
|
||||
describe('createSelector', () => {
|
||||
it('calls input selectors with this and arguments', () => {
|
||||
const thisArg = {}
|
||||
const args = ['arg1', 'arg2']
|
||||
const foo = jest.fn()
|
||||
|
||||
createSelector({ foo }, ({ foo }) => {}).apply(thisArg, args)
|
||||
|
||||
expect(foo.mock.instances).toEqual([thisArg])
|
||||
expect(foo.mock.calls).toEqual([args])
|
||||
})
|
||||
|
||||
it('calls input selectors only when accessed', () => {
|
||||
const foo = jest.fn()
|
||||
createSelector({ foo }, inputs => {
|
||||
expect(foo.mock.calls.length).toBe(0)
|
||||
noop(inputs.foo)
|
||||
expect(foo.mock.calls.length).toBe(1)
|
||||
})()
|
||||
})
|
||||
|
||||
it('does not call the input selectors if this arguments did not change', () => {
|
||||
const foo = jest.fn()
|
||||
const selector = createSelector({ foo }, ({ foo }) => {})
|
||||
|
||||
selector('arg1')
|
||||
expect(foo.mock.calls.length).toBe(1)
|
||||
|
||||
selector('arg1')
|
||||
expect(foo.mock.calls.length).toBe(1)
|
||||
|
||||
selector('arg1', 'arg2')
|
||||
expect(foo.mock.calls.length).toBe(2)
|
||||
|
||||
selector.call({}, 'arg1', 'arg2')
|
||||
expect(foo.mock.calls.length).toBe(3)
|
||||
})
|
||||
|
||||
it('does not call the transform if inputs did not change', () => {
|
||||
const transform = jest.fn(({ foo }) => {})
|
||||
const selector = createSelector(
|
||||
{
|
||||
foo: () => 'foo',
|
||||
},
|
||||
transform
|
||||
)
|
||||
|
||||
selector({})
|
||||
expect(transform.mock.calls.length).toBe(1)
|
||||
|
||||
selector({})
|
||||
expect(transform.mock.calls.length).toBe(1)
|
||||
})
|
||||
|
||||
it('computes only the necessary inputs to determine if transform should be called', () => {
|
||||
let foo = 'foo 1'
|
||||
const bar = 'bar 1'
|
||||
const inputs = {
|
||||
foo: jest.fn(() => foo),
|
||||
bar: jest.fn(() => bar),
|
||||
}
|
||||
const transform = jest.fn(inputs => {
|
||||
if (inputs.foo !== 'foo 1') {
|
||||
return inputs.bar
|
||||
}
|
||||
})
|
||||
const selector = createSelector(inputs, transform)
|
||||
|
||||
selector({})
|
||||
expect(inputs.foo.mock.calls.length).toBe(1)
|
||||
expect(inputs.bar.mock.calls.length).toBe(0)
|
||||
|
||||
selector({})
|
||||
expect(inputs.foo.mock.calls.length).toBe(2)
|
||||
expect(inputs.bar.mock.calls.length).toBe(0)
|
||||
|
||||
foo = 'foo 2'
|
||||
|
||||
selector({})
|
||||
expect(inputs.foo.mock.calls.length).toBe(3)
|
||||
expect(inputs.bar.mock.calls.length).toBe(1)
|
||||
|
||||
foo = 'foo 1'
|
||||
|
||||
selector({})
|
||||
expect(inputs.foo.mock.calls.length).toBe(4)
|
||||
expect(inputs.bar.mock.calls.length).toBe(1)
|
||||
|
||||
selector({})
|
||||
expect(inputs.foo.mock.calls.length).toBe(5)
|
||||
expect(inputs.bar.mock.calls.length).toBe(1)
|
||||
})
|
||||
})
|
||||
@@ -34,6 +34,16 @@ import Collection, { ModelAlreadyExists } from '../collection'
|
||||
|
||||
const VERSION = '20170905'
|
||||
|
||||
const serialize = JSON.stringify
|
||||
const unserialize = JSON.parse
|
||||
const tryUnserialize = value => {
|
||||
try {
|
||||
return unserialize(value)
|
||||
} catch (_) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
export default class Redis extends Collection {
|
||||
constructor({ connection, indexes = [], prefix, uri }) {
|
||||
super()
|
||||
@@ -108,6 +118,10 @@ export default class Redis extends Collection {
|
||||
return
|
||||
}
|
||||
|
||||
Object.keys(model).forEach(key => {
|
||||
model[key] = tryUnserialize(model[key])
|
||||
})
|
||||
|
||||
// Mix the identifier in.
|
||||
model.id = id
|
||||
|
||||
@@ -161,7 +175,7 @@ export default class Redis extends Collection {
|
||||
}
|
||||
|
||||
if (value !== undefined) {
|
||||
params.push(name, value)
|
||||
params.push(name, serialize(value))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export class Groups extends Collection {
|
||||
async save(group) {
|
||||
// Serializes.
|
||||
let tmp
|
||||
group.users = isEmpty((tmp = group.users)) ? undefined : JSON.stringify(tmp)
|
||||
group.users = isEmpty((tmp = group.users)) ? undefined : tmp
|
||||
|
||||
return /* await */ this.update(group)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import Collection from '../collection/redis'
|
||||
import createLogger from '@xen-orchestra/log'
|
||||
import Model from '../model'
|
||||
import { forEach } from '../utils'
|
||||
|
||||
const log = createLogger('xo:plugin-metadata')
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@@ -16,14 +12,6 @@ export class PluginsMetadata extends Collection {
|
||||
return PluginMetadata
|
||||
}
|
||||
|
||||
async save({ id, autoload, configuration }) {
|
||||
return /* await */ this.update({
|
||||
id,
|
||||
autoload: autoload ? 'true' : 'false',
|
||||
configuration: configuration && JSON.stringify(configuration),
|
||||
})
|
||||
}
|
||||
|
||||
async merge(id, data) {
|
||||
const pluginMetadata = await this.first(id)
|
||||
if (pluginMetadata === undefined) {
|
||||
@@ -35,23 +23,4 @@ export class PluginsMetadata extends Collection {
|
||||
...data,
|
||||
})
|
||||
}
|
||||
|
||||
async get(properties) {
|
||||
const pluginsMetadata = await super.get(properties)
|
||||
|
||||
// Deserializes.
|
||||
forEach(pluginsMetadata, pluginMetadata => {
|
||||
const { autoload, configuration } = pluginMetadata
|
||||
pluginMetadata.autoload = autoload === 'true'
|
||||
try {
|
||||
pluginMetadata.configuration =
|
||||
configuration && JSON.parse(configuration)
|
||||
} catch (error) {
|
||||
log.warn(`cannot parse pluginMetadata.configuration: ${configuration}`)
|
||||
pluginMetadata.configuration = []
|
||||
}
|
||||
})
|
||||
|
||||
return pluginsMetadata
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Collection from '../collection/redis'
|
||||
import Model from '../model'
|
||||
import { forEach } from '../utils'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@@ -10,16 +9,4 @@ export class Remotes extends Collection {
|
||||
get Model() {
|
||||
return Remote
|
||||
}
|
||||
|
||||
async get(properties) {
|
||||
const remotes = await super.get(properties)
|
||||
forEach(remotes, remote => {
|
||||
remote.benchmarks =
|
||||
remote.benchmarks !== undefined
|
||||
? JSON.parse(remote.benchmarks)
|
||||
: undefined
|
||||
remote.enabled = remote.enabled === 'true'
|
||||
})
|
||||
return remotes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,49 +71,7 @@ export type Executor = ({|
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const normalize = job => {
|
||||
Object.keys(job).forEach(key => {
|
||||
try {
|
||||
const value = (job[key] = JSON.parse(job[key]))
|
||||
|
||||
// userId are always strings, even if the value is numeric, which might to
|
||||
// them being parsed as numbers.
|
||||
//
|
||||
// The issue has been introduced by
|
||||
// 48b2297bc151df582160be7c1bf1e8ee160320b8.
|
||||
if (key === 'userId' && typeof value === 'number') {
|
||||
job[key] = String(value)
|
||||
}
|
||||
} catch (_) {}
|
||||
})
|
||||
return job
|
||||
}
|
||||
|
||||
const serialize = (job: {| [string]: any |}) => {
|
||||
Object.keys(job).forEach(key => {
|
||||
const value = job[key]
|
||||
if (typeof value !== 'string') {
|
||||
job[key] = JSON.stringify(job[key])
|
||||
}
|
||||
})
|
||||
return job
|
||||
}
|
||||
|
||||
class JobsDb extends Collection {
|
||||
async create(job): Promise<Job> {
|
||||
return normalize((await this.add(serialize((job: any)))).properties)
|
||||
}
|
||||
|
||||
async save(job): Promise<void> {
|
||||
await this.update(serialize((job: any)))
|
||||
}
|
||||
|
||||
async get(properties): Promise<Array<Job>> {
|
||||
const jobs = await super.get(properties)
|
||||
jobs.forEach(normalize)
|
||||
return jobs
|
||||
}
|
||||
}
|
||||
class JobsDb extends Collection {}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -150,7 +108,7 @@ export default class Jobs {
|
||||
xo.addConfigManager(
|
||||
'jobs',
|
||||
() => jobsDb.get(),
|
||||
jobs => Promise.all(mapToArray(jobs, job => jobsDb.save(job))),
|
||||
jobs => Promise.all(mapToArray(jobs, job => jobsDb.update(job))),
|
||||
['users']
|
||||
)
|
||||
})
|
||||
@@ -211,8 +169,8 @@ export default class Jobs {
|
||||
return job
|
||||
}
|
||||
|
||||
createJob(job: $Diff<Job, {| id: string |}>): Promise<Job> {
|
||||
return this._jobs.create(job)
|
||||
async createJob(job: $Diff<Job, {| id: string |}>): Promise<Job> {
|
||||
return (await this._jobs.add(job)).properties
|
||||
}
|
||||
|
||||
async updateJob(job: $Shape<Job>, merge: boolean = true) {
|
||||
@@ -221,7 +179,7 @@ export default class Jobs {
|
||||
job = await this.getJob(id)
|
||||
patch(job, props)
|
||||
}
|
||||
return /* await */ this._jobs.save(job)
|
||||
return /* await */ this._jobs.update(job)
|
||||
}
|
||||
|
||||
registerJobExecutor(type: string, executor: Executor): void {
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class {
|
||||
() => this._pluginsMetadata.get(),
|
||||
plugins =>
|
||||
Promise.all(
|
||||
mapToArray(plugins, plugin => this._pluginsMetadata.save(plugin))
|
||||
mapToArray(plugins, plugin => this._pluginsMetadata.update(plugin))
|
||||
)
|
||||
)
|
||||
})
|
||||
@@ -78,7 +78,7 @@ export default class {
|
||||
;({ autoload, configuration } = metadata)
|
||||
} else {
|
||||
log.info(`[NOTICE] register plugin ${name} for the first time`)
|
||||
await this._pluginsMetadata.save({
|
||||
await this._pluginsMetadata.update({
|
||||
id,
|
||||
autoload,
|
||||
})
|
||||
|
||||
114
yarn.lock
114
yarn.lock
@@ -2,10 +2,10 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/cli@7.1.5", "@babel/cli@^7.0.0", "@babel/cli@^7.1.5":
|
||||
version "7.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.1.5.tgz#4ccf0a8cdabeefdd8ce955384530f050935bc4d7"
|
||||
integrity sha512-zbO/DtTnaDappBflIU3zYEgATLToRDmW5uN/EGH1GXaes7ydfjqmAoK++xmJIA+8HfDw7UyPZNdM8fhGhfmMhw==
|
||||
"@babel/cli@^7.0.0", "@babel/cli@^7.1.5":
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.2.3.tgz#1b262e42a3e959d28ab3d205ba2718e1923cfee6"
|
||||
integrity sha512-bfna97nmJV6nDJhXNPeEfxyMjWnt6+IjUAaDPiYRTBlm8L41n8nvw6UAqUCbvpFfU246gHPxW7sfWwqtF4FcYA==
|
||||
dependencies:
|
||||
commander "^2.8.1"
|
||||
convert-source-map "^1.1.0"
|
||||
@@ -26,27 +26,7 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@babel/core@7.1.5", "@babel/core@^7.0.0", "@babel/core@^7.1.5":
|
||||
version "7.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.5.tgz#abb32d7aa247a91756469e788998db6a72b93090"
|
||||
integrity sha512-vOyH020C56tQvte++i+rX2yokZcRfbv/kKcw+/BCRw/cK6dvsr47aCzm8oC1XHwMSEWbqrZKzZRLzLnq6SFMsg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/generator" "^7.1.5"
|
||||
"@babel/helpers" "^7.1.5"
|
||||
"@babel/parser" "^7.1.5"
|
||||
"@babel/template" "^7.1.2"
|
||||
"@babel/traverse" "^7.1.5"
|
||||
"@babel/types" "^7.1.5"
|
||||
convert-source-map "^1.1.0"
|
||||
debug "^3.1.0"
|
||||
json5 "^0.5.0"
|
||||
lodash "^4.17.10"
|
||||
resolve "^1.3.2"
|
||||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/core@^7.1.0":
|
||||
"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.1.5":
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.0.tgz#248fd6874b7d755010bfe61f557461d4f446d9e9"
|
||||
integrity sha512-Dzl7U0/T69DFOTwqz/FJdnOSWS57NpjNfCwMKHABr589Lg8uX1RrlBIJ7L5Dubt/xkLsx0xH5EBFzlBVes1ayA==
|
||||
@@ -703,49 +683,53 @@
|
||||
core-js "^2.6.5"
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/preset-env@7.1.5", "@babel/preset-env@^7.0.0", "@babel/preset-env@^7.1.5":
|
||||
version "7.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.5.tgz#a28b5482ca8bc2f2d0712234d6c690240b92495d"
|
||||
integrity sha512-pQ+2o0YyCp98XG0ODOHJd9z4GsSoV5jicSedRwCrU8uiqcJahwQiOq0asSZEb/m/lwyu6X5INvH/DSiwnQKncw==
|
||||
"@babel/preset-env@^7.0.0", "@babel/preset-env@^7.1.5":
|
||||
version "7.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.2.tgz#2f5ba1de2daefa9dcca653848f96c7ce2e406676"
|
||||
integrity sha512-OEz6VOZaI9LW08CWVS3d9g/0jZA6YCn1gsKIy/fut7yZCJti5Lm1/Hi+uo/U+ODm7g4I6gULrCP+/+laT8xAsA==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.1.0"
|
||||
"@babel/plugin-proposal-json-strings" "^7.0.0"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.0.0"
|
||||
"@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
|
||||
"@babel/plugin-proposal-unicode-property-regex" "^7.0.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.0.0"
|
||||
"@babel/plugin-syntax-object-rest-spread" "^7.0.0"
|
||||
"@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
|
||||
"@babel/plugin-transform-arrow-functions" "^7.0.0"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.1.0"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.0.0"
|
||||
"@babel/plugin-transform-block-scoping" "^7.1.5"
|
||||
"@babel/plugin-transform-classes" "^7.1.0"
|
||||
"@babel/plugin-transform-computed-properties" "^7.0.0"
|
||||
"@babel/plugin-transform-destructuring" "^7.0.0"
|
||||
"@babel/plugin-transform-dotall-regex" "^7.0.0"
|
||||
"@babel/plugin-transform-duplicate-keys" "^7.0.0"
|
||||
"@babel/plugin-transform-exponentiation-operator" "^7.1.0"
|
||||
"@babel/plugin-transform-for-of" "^7.0.0"
|
||||
"@babel/plugin-transform-function-name" "^7.1.0"
|
||||
"@babel/plugin-transform-literals" "^7.0.0"
|
||||
"@babel/plugin-transform-modules-amd" "^7.1.0"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.1.0"
|
||||
"@babel/plugin-transform-modules-systemjs" "^7.0.0"
|
||||
"@babel/plugin-transform-modules-umd" "^7.1.0"
|
||||
"@babel/plugin-transform-new-target" "^7.0.0"
|
||||
"@babel/plugin-transform-object-super" "^7.1.0"
|
||||
"@babel/plugin-transform-parameters" "^7.1.0"
|
||||
"@babel/plugin-transform-regenerator" "^7.0.0"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.0.0"
|
||||
"@babel/plugin-transform-spread" "^7.0.0"
|
||||
"@babel/plugin-transform-sticky-regex" "^7.0.0"
|
||||
"@babel/plugin-transform-template-literals" "^7.0.0"
|
||||
"@babel/plugin-transform-typeof-symbol" "^7.0.0"
|
||||
"@babel/plugin-transform-unicode-regex" "^7.0.0"
|
||||
browserslist "^4.1.0"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.2.0"
|
||||
"@babel/plugin-proposal-json-strings" "^7.2.0"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.4.0"
|
||||
"@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
|
||||
"@babel/plugin-proposal-unicode-property-regex" "^7.4.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.2.0"
|
||||
"@babel/plugin-syntax-json-strings" "^7.2.0"
|
||||
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
|
||||
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
|
||||
"@babel/plugin-transform-arrow-functions" "^7.2.0"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.4.0"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
|
||||
"@babel/plugin-transform-block-scoping" "^7.4.0"
|
||||
"@babel/plugin-transform-classes" "^7.4.0"
|
||||
"@babel/plugin-transform-computed-properties" "^7.2.0"
|
||||
"@babel/plugin-transform-destructuring" "^7.4.0"
|
||||
"@babel/plugin-transform-dotall-regex" "^7.2.0"
|
||||
"@babel/plugin-transform-duplicate-keys" "^7.2.0"
|
||||
"@babel/plugin-transform-exponentiation-operator" "^7.2.0"
|
||||
"@babel/plugin-transform-for-of" "^7.4.0"
|
||||
"@babel/plugin-transform-function-name" "^7.2.0"
|
||||
"@babel/plugin-transform-literals" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-amd" "^7.2.0"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.4.0"
|
||||
"@babel/plugin-transform-modules-systemjs" "^7.4.0"
|
||||
"@babel/plugin-transform-modules-umd" "^7.2.0"
|
||||
"@babel/plugin-transform-named-capturing-groups-regex" "^7.4.2"
|
||||
"@babel/plugin-transform-new-target" "^7.4.0"
|
||||
"@babel/plugin-transform-object-super" "^7.2.0"
|
||||
"@babel/plugin-transform-parameters" "^7.4.0"
|
||||
"@babel/plugin-transform-regenerator" "^7.4.0"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.2.0"
|
||||
"@babel/plugin-transform-spread" "^7.2.0"
|
||||
"@babel/plugin-transform-sticky-regex" "^7.2.0"
|
||||
"@babel/plugin-transform-template-literals" "^7.2.0"
|
||||
"@babel/plugin-transform-typeof-symbol" "^7.2.0"
|
||||
"@babel/plugin-transform-unicode-regex" "^7.2.0"
|
||||
"@babel/types" "^7.4.0"
|
||||
browserslist "^4.4.2"
|
||||
core-js-compat "^3.0.0"
|
||||
invariant "^2.2.2"
|
||||
js-levenshtein "^1.1.3"
|
||||
semver "^5.3.0"
|
||||
|
||||
Reference in New Issue
Block a user