Compare commits
8 Commits
xen-api-v0
...
complex-ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ab028ad6 | ||
|
|
9fc6013934 | ||
|
|
8a02d557f4 | ||
|
|
bdddea2e29 | ||
|
|
be4ca0eede | ||
|
|
316d71b34d | ||
|
|
b3bc9a2edd | ||
|
|
90369acb63 |
@@ -1,11 +1,12 @@
|
||||
const { NODE_ENV = 'development' } = process.env
|
||||
const dependencies = require('./package').dependencies || {}
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
const __PROD__ = NODE_ENV === 'production'
|
||||
const __TEST__ = NODE_ENV === 'test'
|
||||
|
||||
module.exports = {
|
||||
comments: !__PROD__,
|
||||
compact: __PROD__,
|
||||
ignore: __TEST__ ? undefined : [ /\.spec\.js$/ ],
|
||||
ignore: __TEST__ ? undefined : [/\.spec\.js$/],
|
||||
plugins: ['lodash'],
|
||||
presets: [
|
||||
[
|
||||
@@ -20,7 +21,7 @@ module.exports = {
|
||||
node: '4',
|
||||
}
|
||||
: { node: 'current' },
|
||||
useBuiltIns: 'usage',
|
||||
useBuiltIns: '@babel/polyfill' in dependencies && 'usage',
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "complex-matcher",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.0",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
@@ -24,7 +24,6 @@
|
||||
"node": ">=4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "7.0.0-beta.37",
|
||||
"lodash": "^4.17.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -37,9 +36,10 @@
|
||||
},
|
||||
"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": "rimraf dist/",
|
||||
"predev": "npm run prebuild",
|
||||
"prepublishOnly": "npm run build"
|
||||
"prebuild": "yarn run clean",
|
||||
"predev": "yarn run clean",
|
||||
"prepublishOnly": "yarn run build"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as CM from './'
|
||||
|
||||
export const pattern = 'foo !"\\\\ \\"" name:|(wonderwoman batman) hasCape?'
|
||||
export const pattern =
|
||||
'foo !"\\\\ \\"" name:|(wonderwoman batman) hasCape? age:32'
|
||||
|
||||
export const ast = new CM.And([
|
||||
new CM.String('foo'),
|
||||
@@ -10,4 +11,5 @@ export const ast = new CM.And([
|
||||
new CM.Or([new CM.String('wonderwoman'), new CM.String('batman')])
|
||||
),
|
||||
new CM.TruthyProperty('hasCape'),
|
||||
new CM.Property('age', new CM.Number(32)),
|
||||
])
|
||||
|
||||
@@ -141,6 +141,23 @@ export class Not extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
export class NumberNode extends Node {
|
||||
constructor (value) {
|
||||
super()
|
||||
|
||||
this.value = value
|
||||
}
|
||||
|
||||
match (value) {
|
||||
return value === this.value
|
||||
}
|
||||
|
||||
toString () {
|
||||
return String(this.value)
|
||||
}
|
||||
}
|
||||
export { NumberNode as Number }
|
||||
|
||||
export class Property extends Node {
|
||||
constructor (name, child) {
|
||||
super()
|
||||
@@ -159,9 +176,10 @@ export class Property extends Node {
|
||||
}
|
||||
|
||||
const escapeChar = char => '\\' + char
|
||||
const formatString = value => isRawString(value)
|
||||
? value
|
||||
: `"${value.replace(/\\|"/g, escapeChar)}"`
|
||||
const formatString = value =>
|
||||
Number.isNaN(+value)
|
||||
? isRawString(value) ? value : `"${value.replace(/\\|"/g, escapeChar)}"`
|
||||
: `"${value}"`
|
||||
|
||||
export class StringNode extends Node {
|
||||
constructor (value) {
|
||||
@@ -214,14 +232,15 @@ export class TruthyProperty extends Node {
|
||||
|
||||
// terms = null || term+
|
||||
// *null = /$/
|
||||
// term = ws (and | or | not | property | truthyProperty | string) ws
|
||||
// term = ws (and | or | not | property | truthyProperty | numberOrString) ws
|
||||
// ws = ' '*
|
||||
// *and = "(" terms ")"
|
||||
// *or = "|" ws "(" terms ")"
|
||||
// *not = "!" term
|
||||
// *property = string ws ":" term
|
||||
// *truthyProperty = string ws "?"
|
||||
// *string = quotedString | rawString
|
||||
// numberOrString = string
|
||||
// string = quotedString | rawString
|
||||
// quotedString = "\"" ( /[^"\]/ | "\\\\" | "\\\"" )+
|
||||
// rawString = /[a-z0-9-_.]+/i
|
||||
export const parse = invoke(() => {
|
||||
@@ -263,7 +282,7 @@ export const parse = invoke(() => {
|
||||
parseNot() ||
|
||||
parseProperty() ||
|
||||
parseTruthyProperty() ||
|
||||
parseString()
|
||||
parseNumberOrString()
|
||||
if (child) {
|
||||
parseWs()
|
||||
return child
|
||||
@@ -308,16 +327,27 @@ export const parse = invoke(() => {
|
||||
input[i++] === ':' &&
|
||||
(child = parseTerm())
|
||||
) {
|
||||
return new Property(name.value, child)
|
||||
return new Property(name, child)
|
||||
}
|
||||
})
|
||||
const parseNumberOrString = () => {
|
||||
let str = parseQuotedString()
|
||||
if (str !== undefined) {
|
||||
return new StringNode(str)
|
||||
}
|
||||
str = parseRawString()
|
||||
if (str !== undefined) {
|
||||
const asNum = +str
|
||||
return Number.isNaN(asNum) ? new StringNode(str) : new NumberNode(asNum)
|
||||
}
|
||||
}
|
||||
const parseString = () => {
|
||||
let value
|
||||
if (
|
||||
(value = parseQuotedString()) !== undefined ||
|
||||
(value = parseRawString()) !== undefined
|
||||
) {
|
||||
return new StringNode(value)
|
||||
return value
|
||||
}
|
||||
}
|
||||
const parseQuotedString = backtrace(() => {
|
||||
@@ -350,7 +380,7 @@ export const parse = invoke(() => {
|
||||
const parseTruthyProperty = backtrace(() => {
|
||||
let name
|
||||
if ((name = parseString()) && parseWs() && input[i++] === '?') {
|
||||
return new TruthyProperty(name.value)
|
||||
return new TruthyProperty(name)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -24,6 +24,20 @@ describe('parse', () => {
|
||||
it('supports an empty string', () => {
|
||||
expect(parse('')).toEqual(new Null())
|
||||
})
|
||||
|
||||
it('differentiate between numbers and numbers in strings', () => {
|
||||
let node
|
||||
|
||||
node = parse('32')
|
||||
expect(node.match(32)).toBe(true)
|
||||
expect(node.match('32')).toBe(false)
|
||||
expect(node.toString()).toBe('32')
|
||||
|
||||
node = parse('"32"')
|
||||
expect(node.match(32)).toBe(false)
|
||||
expect(node.match('32')).toBe(true)
|
||||
expect(node.toString()).toBe('"32"')
|
||||
})
|
||||
})
|
||||
|
||||
describe('setPropertyClause', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xen-api",
|
||||
"version": "0.16.1",
|
||||
"version": "0.16.3",
|
||||
"license": "ISC",
|
||||
"description": "Connector to the Xen API",
|
||||
"keywords": [
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
isInteger,
|
||||
isObject,
|
||||
map,
|
||||
mapValues,
|
||||
noop,
|
||||
omit,
|
||||
reduce,
|
||||
@@ -153,7 +152,17 @@ const prepareParam = param => {
|
||||
return param
|
||||
}
|
||||
|
||||
return (isArray(param) ? map : mapValues)(param, prepareParam)
|
||||
if (isArray(param)) {
|
||||
return map(param, prepareParam)
|
||||
}
|
||||
|
||||
const values = {}
|
||||
forEach(param, (value, key) => {
|
||||
if (value !== undefined) {
|
||||
values[key] = prepareParam(value)
|
||||
}
|
||||
})
|
||||
return values
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -226,6 +235,8 @@ export class Xapi extends EventEmitter {
|
||||
// Memoize this function _addObject().
|
||||
this._getPool = () => this._pool
|
||||
|
||||
this._nTasks = 0
|
||||
|
||||
const objects = this._objects = new Collection()
|
||||
objects.getKey = getKey
|
||||
|
||||
@@ -761,7 +772,22 @@ export class Xapi extends EventEmitter {
|
||||
|
||||
if (type === 'pool') {
|
||||
this._pool = object
|
||||
|
||||
const eventWatchers = this._eventWatchers
|
||||
if (eventWatchers !== undefined) {
|
||||
forEach(object.other_config, (_, key) => {
|
||||
const eventWatcher = eventWatchers[key]
|
||||
if (eventWatcher !== undefined) {
|
||||
delete eventWatchers[key]
|
||||
eventWatcher(object)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (type === 'task') {
|
||||
if (prev === undefined) {
|
||||
++this._nTasks
|
||||
}
|
||||
|
||||
const taskWatchers = this._taskWatchers
|
||||
const taskWatcher = taskWatchers[ref]
|
||||
if (
|
||||
@@ -771,16 +797,18 @@ export class Xapi extends EventEmitter {
|
||||
delete taskWatchers[ref]
|
||||
}
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
_removeObject (ref) {
|
||||
_removeObject (type, ref) {
|
||||
const byRefs = this._objectsByRefs
|
||||
const object = byRefs[ref]
|
||||
if (object !== undefined) {
|
||||
this._objects.unset(object.$id)
|
||||
delete byRefs[ref]
|
||||
|
||||
if (type === 'task') {
|
||||
--this._nTasks
|
||||
}
|
||||
}
|
||||
|
||||
const taskWatchers = this._taskWatchers
|
||||
@@ -792,26 +820,12 @@ export class Xapi extends EventEmitter {
|
||||
}
|
||||
|
||||
_processEvents (events) {
|
||||
const eventWatchers = this._eventWatchers
|
||||
|
||||
forEach(events, event => {
|
||||
let object
|
||||
const { ref } = event
|
||||
const { class: type, ref } = event
|
||||
if (event.operation === 'del') {
|
||||
this._removeObject(ref)
|
||||
this._removeObject(type, ref)
|
||||
} else {
|
||||
const type = event.class
|
||||
object = this._addObject(type, ref, event.snapshot)
|
||||
|
||||
if (eventWatchers !== undefined && type === 'pool') {
|
||||
forEach(object.other_config, (_, key) => {
|
||||
const eventWatcher = eventWatchers[key]
|
||||
if (eventWatcher !== undefined) {
|
||||
delete eventWatchers[key]
|
||||
eventWatcher(object)
|
||||
}
|
||||
})
|
||||
}
|
||||
this._addObject(type, ref, event.snapshot)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -823,10 +837,24 @@ export class Xapi extends EventEmitter {
|
||||
60 + 0.1, // Force float.
|
||||
]).then(onSuccess, onFailure)
|
||||
|
||||
const onSuccess = ({token, events}) => {
|
||||
const onSuccess = ({ events, token, valid_ref_counts: { task } }) => {
|
||||
this._fromToken = token
|
||||
this._processEvents(events)
|
||||
|
||||
if (task !== this._nTasks) {
|
||||
forEach(this.objects.all, object => {
|
||||
if (object.$type === 'task') {
|
||||
this._removeObject('task', object.$ref)
|
||||
}
|
||||
})
|
||||
|
||||
this._sessionCall('task.get_all_records').then(tasks => {
|
||||
forEach(tasks, (task, ref) => {
|
||||
this._addObject('task', ref, task)
|
||||
})
|
||||
}).catch(noop)
|
||||
}
|
||||
|
||||
const debounce = this._debounce
|
||||
return debounce != null
|
||||
? pDelay(debounce).then(loop)
|
||||
|
||||
Reference in New Issue
Block a user