diff --git a/README.md b/README.md index 7b111f0d..68b6ecbf 100644 --- a/README.md +++ b/README.md @@ -51,12 +51,12 @@ Maintenance Scripts * `yarn run build` builds all packages * `yarn run build -- --only` builds a package with specified ``, - e.g. `yarn run build -- xod-core --only` + e.g. `yarn run build -- xod-cli --only` * `yarn run build -- ` builds a package with specified `` and all its dependencies, e.g. `yarn run build -- xod-client-electron` * `yarn run dev -- --only` builds a package with specified `` and stays in watch mode with auto-rebuild when its files change, - e.g. `yarn run dev -- xod-core --only` + e.g. `yarn run dev -- xod-cli --only` * `yarn run dev -- ` builds a package with specified `` and all its dependencies, then stay in watch mode looking for changes in that package or any of its dependencies; diff --git a/packages/xod-core/.babelrc b/packages/xod-core/.babelrc deleted file mode 100644 index c13c5f62..00000000 --- a/packages/xod-core/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015"] -} diff --git a/packages/xod-core/.gitignore b/packages/xod-core/.gitignore deleted file mode 100644 index 5698770b..00000000 --- a/packages/xod-core/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -dist/ -npm-debug.log -fs-temp/ diff --git a/packages/xod-core/README.md b/packages/xod-core/README.md deleted file mode 100644 index e730395c..00000000 --- a/packages/xod-core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# xod-core - -FIXME: write a README diff --git a/packages/xod-core/nodes/meta/and.json5 b/packages/xod-core/nodes/meta/and.json5 deleted file mode 100644 index 8d836dc8..00000000 --- a/packages/xod-core/nodes/meta/and.json5 +++ /dev/null @@ -1,21 +0,0 @@ -{ - label: 'and', - inputs: [{ - key: 'a', - type: 'bool', - description: 'First input' - }, - { - key: 'b', - type: 'bool', - description: 'Second input' - }], - outputs: [{ - key: 'out', - type: 'bool', - description: '"true" if both inputs are "true"', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n return { out: e.inputs.a && e.inputs.b };\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/button.json5 b/packages/xod-core/nodes/meta/button.json5 deleted file mode 100644 index a4128a52..00000000 --- a/packages/xod-core/nodes/meta/button.json5 +++ /dev/null @@ -1,17 +0,0 @@ -{ - category: 'hardware', - outputs: [{ - key: 'state', - type: 'bool', - description: 'Emits `true` when pressed and `false` when released', - }], - properties: [{ - key: 'pin', - label: 'Pin', - type: 'string', - value: 'BTN1', - }], - impl: { - espruino: "\nmodule.exports.setup = function(e) {\n var pin = new Pin(e.props.pin);\n\n setWatch(function(evt) {\n e.fire({ state: !evt.state });\n }, pin, {\n edge: 'both',\n repeat: true,\n debounce: 30\n });\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/buzzer.json5 b/packages/xod-core/nodes/meta/buzzer.json5 deleted file mode 100644 index 3093dd80..00000000 --- a/packages/xod-core/nodes/meta/buzzer.json5 +++ /dev/null @@ -1,20 +0,0 @@ -{ - label: 'Buzzer', - category: 'hardware', - inputs: [{ - key: 'freq', - type: 'number', - pinLabel: 'FREQ', - label: 'Frequency', - description: 'Frequency (Hz)' - }], - properties: [{ - key: 'pin', - label: 'Pin', - type: 'string', - value: 'A3', - }], - impl: { - espruino: "\nmodule.exports.setup = function(e) {\n e.context.pin = new Pin(e.props.pin);\n};\n\nmodule.exports.evaluate = function(e) {\n var f = e.inputs.freq;\n\n if (f === 0) {\n digitalWrite(e.context.pin, false);\n } else {\n analogWrite(e.context.pin, 0.5, { freq: f });\n }\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/clock.json5 b/packages/xod-core/nodes/meta/clock.json5 deleted file mode 100644 index ce7463f7..00000000 --- a/packages/xod-core/nodes/meta/clock.json5 +++ /dev/null @@ -1,18 +0,0 @@ -{ - inputs: [{ - key: 'interval', - pinLabel: 'INT', - label: 'Interval (sec)', - type: 'number', - value: 1, - }], - pure: false, - outputs: [{ - key: 'tick', - type: 'pulse', - description: 'Emits pulse periodically', - }], - impl: { - js: "\nmodule.exports.setup = function(e) {\n e.context.intId = null;\n};\n\nmodule.exports.evaluate = function(e) {\n if (e.context.intId) {\n clearInterval(e.context.intId);\n }\n e.context.intId = setInterval(function() {\n e.fire({ tick: PULSE });\n }, e.inputs.interval * 1000);\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/compare.json5 b/packages/xod-core/nodes/meta/compare.json5 deleted file mode 100644 index df9b5237..00000000 --- a/packages/xod-core/nodes/meta/compare.json5 +++ /dev/null @@ -1,36 +0,0 @@ -{ - inputs: [{ - key: 'a', - pinLabel: 'IN1', - label: 'First value', - type: 'number', - }, - { - key: 'b', - pinLabel: 'IN2', - label: 'Second value', - type: 'number', - } - ], - outputs: [{ - key: 'equal', - type: 'pulse', - pinLabel: '==', - description: 'Pulses if a = b', - }, - { - key: 'less', - type: 'pulse', - pinLabel: '<', - description: 'Pulses if a < b', - }, - { - key: 'greater', - type: 'pulse', - pinLabel: '>', - description: 'Pulses if a > b', - }], - impls: { - js: "\nmodule.exports.evaluate = function(e) {\n var a = e.inputs.a;\n var b = e.inputs.b;\n if (a < b) {\n return { less: PULSE };\n } else if (a > b) {\n return { greater: PULSE };\n } else {\n return { equal: PULSE };\n }\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/constBool.json5 b/packages/xod-core/nodes/meta/constBool.json5 deleted file mode 100644 index a9d382cc..00000000 --- a/packages/xod-core/nodes/meta/constBool.json5 +++ /dev/null @@ -1,25 +0,0 @@ -{ - label: '', - category: 'configuration', - inputs: [{ - key: 'inValue', - type: 'bool', - injected: true, - pinLabel: 'VAL', - label: 'Value', - value: false - }, { - key: 'pulse', - type: 'pulse', - injected: true, - pinLabel: 'PLS', - label: 'Pulse' - }], - outputs: [{ - key: 'value', - type: 'bool', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n e.fire({ value: e.inputs.value });\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/constNumber.json5 b/packages/xod-core/nodes/meta/constNumber.json5 deleted file mode 100644 index 9ef9bb4d..00000000 --- a/packages/xod-core/nodes/meta/constNumber.json5 +++ /dev/null @@ -1,25 +0,0 @@ -{ - label: '', - category: 'configuration', - inputs: [{ - key: 'inValue', - type: 'number', - injected: true, - pinLabel: 'VAL', - label: 'Value', - value: 0 - }, { - key: 'pulse', - type: 'pulse', - injected: true, - pinLabel: 'PLS', - label: 'Pulse' - }], - outputs: [{ - key: 'value', - type: 'number', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n e.fire({ value: e.inputs.value });\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/constString.json5 b/packages/xod-core/nodes/meta/constString.json5 deleted file mode 100644 index 92e55faa..00000000 --- a/packages/xod-core/nodes/meta/constString.json5 +++ /dev/null @@ -1,25 +0,0 @@ -{ - label: '', - category: 'configuration', - inputs: [{ - key: 'inValue', - type: 'string', - injected: true, - pinLabel: 'VAL', - label: 'Value', - value: '' - }, { - key: 'pulse', - type: 'pulse', - injected: true, - pinLabel: 'PLS', - label: 'Pulse' - }], - outputs: [{ - key: 'value', - type: 'string', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n e.fire({ value: e.inputs.value });\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/either.json5 b/packages/xod-core/nodes/meta/either.json5 deleted file mode 100644 index c7dba97a..00000000 --- a/packages/xod-core/nodes/meta/either.json5 +++ /dev/null @@ -1,33 +0,0 @@ -{ - inputs: [{ - key: 'inp', - type: 'bool', - pinLabel: 'IN', - label: 'Value', - description: 'Selector value' - }, { - key: 'trueValue', - type: 'number', - label: 'Value if true', - pinLabel: 'T', - label: 'True output', - value: 1, - description: 'Output if selector is `true`' - }, { - key: 'falseValue', - type: 'number', - label: 'Value if false', - pinLabel: 'F', - label: 'False output', - value: 0, - description: 'Output if selector is `false`' - }], - outputs: [{ - key: 'out', - type: 'number', - description: 'Selected output value', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n var out = e.inputs.inp ? e.inputs.trueValue : e.inputs.falseValue;\n return { out: out };\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/inputBool.json5 b/packages/xod-core/nodes/meta/inputBool.json5 deleted file mode 100644 index e094ef93..00000000 --- a/packages/xod-core/nodes/meta/inputBool.json5 +++ /dev/null @@ -1,15 +0,0 @@ -{ - label: '', - category: 'io', - outputs: [{ - key: 'PIN', - type: 'bool', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/inputNumber.json5 b/packages/xod-core/nodes/meta/inputNumber.json5 deleted file mode 100644 index a9bd9f47..00000000 --- a/packages/xod-core/nodes/meta/inputNumber.json5 +++ /dev/null @@ -1,15 +0,0 @@ -{ - label: '', - category: 'io', - outputs: [{ - key: 'PIN', - type: 'number', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/inputPulse.json5 b/packages/xod-core/nodes/meta/inputPulse.json5 deleted file mode 100644 index 160a9a45..00000000 --- a/packages/xod-core/nodes/meta/inputPulse.json5 +++ /dev/null @@ -1,14 +0,0 @@ -{ - label: '', - category: 'io', - outputs: [{ - key: 'PIN', - type: 'pulse', - }], - properties: [{ - key: 'label', - label: 'Pin label', - type: 'io_label', - defaultValue: 'InP', - }] -} diff --git a/packages/xod-core/nodes/meta/inputString.json5 b/packages/xod-core/nodes/meta/inputString.json5 deleted file mode 100644 index 71430716..00000000 --- a/packages/xod-core/nodes/meta/inputString.json5 +++ /dev/null @@ -1,15 +0,0 @@ -{ - label: '', - category: 'io', - outputs: [{ - key: 'PIN', - type: 'string', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/latch.json5 b/packages/xod-core/nodes/meta/latch.json5 deleted file mode 100644 index b6fd60d3..00000000 --- a/packages/xod-core/nodes/meta/latch.json5 +++ /dev/null @@ -1,30 +0,0 @@ -{ - inputs: [{ - key: 'toggle', - type: 'pulse', - pinLabel: 'TGL', - label: 'Toggle pulse', - description: 'Flips current state to opposite' - }, { - key: 'set', - type: 'pulse', - pinLabel: 'SET', - label: 'Set pulse', - description: 'Sets current state to `true`' - }, { - key: 'reset', - type: 'pulse', - modes: 'pin', - pinLabel: 'RST', - label: 'Reset pulse', - description: 'Sets current state to `false`' - }], - outputs: [{ - key: 'state', - type: 'bool', - description: 'Emits current latch state when changes', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n var inputs = e.inputs;\n var newState;\n\n if (inputs.toggle) {\n newState = !e.context.state;\n } else if (inputs.set) {\n newState = true;\n } else /* if (inputs.reset) */ {\n newState = false;\n }\n\n e.context.state = newState;\n return { state: newState };\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/led.json5 b/packages/xod-core/nodes/meta/led.json5 deleted file mode 100644 index 62d51393..00000000 --- a/packages/xod-core/nodes/meta/led.json5 +++ /dev/null @@ -1,20 +0,0 @@ -{ - label: 'LED', - category: 'hardware', - inputs: [{ - key: 'brightness', - type: 'number', - label: 'Brightness', - value: 0, - description: 'Shine brightness' - }], - properties: [{ - key: 'pin', - label: 'Pin', - type: 'string', - value: 'LED1', - }], - impl: { - espruino: "\nmodule.exports.setup = function(e) {\n e.context.pin = new Pin(e.props.pin);\n};\n\nmodule.exports.evaluate = function(e) {\n var b = e.inputs.brightness;\n\n // Adjust duty cycle as a power function to align brightness\n // perception by human eye\n var duty = b * b * b;\n\n analogWrite(e.context.pin, duty);\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/map.json5 b/packages/xod-core/nodes/meta/map.json5 deleted file mode 100644 index d587ae51..00000000 --- a/packages/xod-core/nodes/meta/map.json5 +++ /dev/null @@ -1,58 +0,0 @@ -{ - inputs: [{ - key: 'inp', - type: 'number', - pinLabel: 'IN', - label: 'Input', - value: 0, - description: 'Input value to map' - }, { - key: 'inA', - type: 'number', - injected: true, - pinLabel: 'As', - label: 'Input range start', - value: 0, - description: 'Input range start' - }, { - key: 'inB', - type: 'number', - injected: true, - pinLabel: 'Bs', - label: 'Input range end', - value: 0, - description: 'Input range end' - }, { - key: 'outA', - type: 'number', - injected: true, - pinLabel: 'At', - label: 'Output range start', - value: 0, - description: 'Output range start' - }, { - key: 'outB', - type: 'number', - injected: true, - pinLabel: 'Bt', - label: 'Output range end', - value: 0, - description: 'Output range end' - }, { - key: 'clip', - type: 'bool', - injected: true, - pinLabel: 'CL', - label: 'Clip', - value: false, - description: 'Clip result to output range' - }], - outputs: [{ - key: 'out', - type: 'number', - description: 'Mapped value', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n var inputs = e.inputs;\n var k = (inputs.inp - inputs.inA) / (inputs.inB - inputs.inA);\n var out = inputs.outA + k * (inputs.outB - inputs.outA);\n\n if (inputs.clip) {\n if (inputs.outB > inputs.outA) {\n out = Math.max(inputs.outA, out);\n out = Math.min(inputs.outB, out);\n } else {\n out = Math.max(inputs.outB, out);\n out = Math.min(inputs.outA, out);\n }\n }\n\n return { out: out };\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/not.json5 b/packages/xod-core/nodes/meta/not.json5 deleted file mode 100644 index b88a66f6..00000000 --- a/packages/xod-core/nodes/meta/not.json5 +++ /dev/null @@ -1,17 +0,0 @@ -{ - label: 'not', - inputs: [{ - key: 'in', - type: 'bool', - label: 'Input', - description: 'Value to be inverted' - }], - outputs: [{ - key: 'out', - type: 'bool', - description: 'Resulting inverted value', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n return { out: !e.inputs.in };\n};", - }, -} diff --git a/packages/xod-core/nodes/meta/or.json5 b/packages/xod-core/nodes/meta/or.json5 deleted file mode 100644 index 931ad36f..00000000 --- a/packages/xod-core/nodes/meta/or.json5 +++ /dev/null @@ -1,21 +0,0 @@ -{ - label: 'or', - inputs: [{ - key: 'a', - type: 'bool', - description: 'First input' - }, - { - key: 'b', - type: 'bool', - description: 'Second input' - }], - outputs: [{ - key: 'out', - type: 'bool', - description: '"true" if a least one of inputs is "true"', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n return { out: e.inputs.a || e.inputs.b };\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/outputBool.json5 b/packages/xod-core/nodes/meta/outputBool.json5 deleted file mode 100644 index d46640b9..00000000 --- a/packages/xod-core/nodes/meta/outputBool.json5 +++ /dev/null @@ -1,16 +0,0 @@ -{ - label: '', - category: 'io', - inputs: [{ - key: 'OUT', - type: 'bool', - label: 'Value', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/outputNumber.json5 b/packages/xod-core/nodes/meta/outputNumber.json5 deleted file mode 100644 index dd80d5b2..00000000 --- a/packages/xod-core/nodes/meta/outputNumber.json5 +++ /dev/null @@ -1,16 +0,0 @@ -{ - label: '', - category: 'io', - inputs: [{ - key: 'OUT', - type: 'number', - label: 'Value', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/outputPulse.json5 b/packages/xod-core/nodes/meta/outputPulse.json5 deleted file mode 100644 index 088c9f3a..00000000 --- a/packages/xod-core/nodes/meta/outputPulse.json5 +++ /dev/null @@ -1,14 +0,0 @@ -{ - label: '', - category: 'io', - inputs: [{ - key: 'PIN', - type: 'pulse', - }], - properties: [{ - key: 'label', - label: 'Pin label', - type: 'io_label', - defaultValue: 'OutB', - }] -} diff --git a/packages/xod-core/nodes/meta/outputString.json5 b/packages/xod-core/nodes/meta/outputString.json5 deleted file mode 100644 index 68352ba2..00000000 --- a/packages/xod-core/nodes/meta/outputString.json5 +++ /dev/null @@ -1,16 +0,0 @@ -{ - label: '', - category: 'io', - inputs: [{ - key: 'OUT', - type: 'string', - label: 'Value', - }], - properties: [{ - key: 'pinLabel', - type: 'string', - widget: 'IOLabel', - label: 'Pin label', - value: '', - }] -} diff --git a/packages/xod-core/nodes/meta/pot.json5 b/packages/xod-core/nodes/meta/pot.json5 deleted file mode 100644 index 8f4980eb..00000000 --- a/packages/xod-core/nodes/meta/pot.json5 +++ /dev/null @@ -1,24 +0,0 @@ -{ - category: 'hardware', - inputs: [{ - key: 'sample', - type: 'pulse', - pinLabel: 'PLS', - label: 'Sample pulse', - description: 'Sample current value', - }], - outputs: [{ - key: 'value', - type: 'number', - description: 'Sampled potentiometer value', - }], - properties: [{ - key: 'pin', - label: 'Pin', - type: 'string', - value: 'A6', - }], - impl: { - espruino: "\nmodule.exports.setup = function(e) {\n e.context.pin = new Pin(e.props.pin);\n};\n\nmodule.exports.evaluate = function(e) {\n return { value: analogRead(e.context.pin) };\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/servo.json5 b/packages/xod-core/nodes/meta/servo.json5 deleted file mode 100644 index 9b569b5f..00000000 --- a/packages/xod-core/nodes/meta/servo.json5 +++ /dev/null @@ -1,34 +0,0 @@ -{ - category: 'hardware', - inputs: [{ - key: 'minPulse', - type: 'number', - injected: true, - pinLabel: 'MIN', - label: 'Min Pulse (μs)', - value: 700 - }, { - key: 'maxPulse', - type: 'number', - injected: true, - pinLabel: 'MAX', - label: 'Max Pulse (μs)', - value: 2300 - }, { - key: 'value', - type: 'number', - pinLabel: 'VAL', - label: 'Value', - value: 1, - description: 'Rotation angle/value' - }], - properties: [{ - key: 'pin', - label: 'Pin', - type: 'string', - value: 'A10', - }], - impl: { - espruino: "\nmodule.exports.setup = function(e) {\n e.context.pin = new Pin(e.props.pin);\n};\n\nmodule.exports.evaluate = function(e) {\n var minPulse = +e.inputs.minPulse;\n var maxPulse = +e.inputs.maxPulse;\n var us = minPulse + (maxPulse - minPulse) * e.inputs.value;\n analogWrite(e.context.pin, us / 20000, { freq: 50 });\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/triggerableNumber.json5 b/packages/xod-core/nodes/meta/triggerableNumber.json5 deleted file mode 100644 index 65e043e3..00000000 --- a/packages/xod-core/nodes/meta/triggerableNumber.json5 +++ /dev/null @@ -1,24 +0,0 @@ -{ - label: 'triggerableNumber', - inputs: [{ - key: 'trigOn', - type: 'pulse', - pinLabel: 'PLS', - label: 'Pulse', - description: 'Pulse to trig on' - }, { - key: 'value', - pinLabel: 'VAL', - label: 'Value', - type: 'number', - value: 0, - }], - outputs: [{ - key: 'out', - type: 'number', - description: 'Output value', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n return { out: e.inputs.value };\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/ultrasonic_HC_SR04.json5 b/packages/xod-core/nodes/meta/ultrasonic_HC_SR04.json5 deleted file mode 100644 index 9ba22b16..00000000 --- a/packages/xod-core/nodes/meta/ultrasonic_HC_SR04.json5 +++ /dev/null @@ -1,45 +0,0 @@ -{ - label: "HC-SR04", - category: 'hardware', - inputs: [{ - key: 'sample', - type: 'pulse', - pinLabel: 'PLS', - label: 'Pulse', - description: 'Sample current value', - }, - { - key: 'units', - pinLabel: 'UNT', - label: 'Units', - type: 'string', - value: 'mm', - }], - outputs: [{ - key: 'value', - type: 'number', - pinLabel: 'DST', - description: 'Sampled distance (mm)', - }, - { - key: 'error', - type: 'string', - pinLabel: 'ERR', - description: 'Operation error', - }], - properties: [{ - key: 'pinTrig', - label: 'Pin trigger', - type: 'string', - value: 'C9', - }, - { - key: 'pinEcho', - label: 'Pin echo', - type: 'string', - value: 'A8', - }], - impl: { - espruino: "\nvar sonic = require('@amperka/ultrasonic');\n\nmodule.exports.setup = function(e) {\n var pinTrig = new Pin(e.props.pinTrig);\n var pinEcho = new Pin(e.props.pinEcho);\n e.context.device = sonic.connect({\n trigPin: pinTrig,\n echoPin: pinEcho\n });\n e.context.units = e.props.units; // FIXME! remove prop in the future\n e.context.isBusy = false;\n};\n\nmodule.exports.evaluate = function(e) {\n if (e.context.isBusy) {\n e.fire({ error: \"busy\" });\n } else {\n e.context.isBusy = true;\n e.context.device.ping(function(err, value) {\n e.context.isBusy = false;\n if (err) {\n e.fire({ error: err.msg });\n } else {\n e.fire({ value: value });\n }\n }, e.context.units);\n }\n};\n", - }, -} diff --git a/packages/xod-core/nodes/meta/valveNumber.json5 b/packages/xod-core/nodes/meta/valveNumber.json5 deleted file mode 100644 index 7cd6bd26..00000000 --- a/packages/xod-core/nodes/meta/valveNumber.json5 +++ /dev/null @@ -1,21 +0,0 @@ -{ - label: 'valveNumber', - inputs: [{ - key: 'cond', - type: 'bool', - description: 'Condition' - }, - { - key: 'in', - type: 'number', - description: 'Input' - }], - outputs: [{ - key: 'out', - type: 'number', - description: 'Output (receives messages from the input if condition is "true")', - }], - impl: { - js: "\nmodule.exports.evaluate = function(e) {\n if (e.inputs.cond) {\n e.fire({ out: e.inputs.in });\n }\n};\n", - }, -} diff --git a/packages/xod-core/package.json b/packages/xod-core/package.json deleted file mode 100644 index 9e830cd2..00000000 --- a/packages/xod-core/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "xod-core", - "version": "0.0.1", - "description": "XOD project: Core", - "scripts": { - "build": "babel src/ -d dist/", - "dev": "yarn run build -- --watch", - "test": "mocha test/**/*.spec.js" - }, - "repository": {}, - "keywords": [], - "author": "", - "license": "MIT", - "main": "dist/index.js", - "dependencies": { - "co": "^4.6.0", - "ramda": "^0.23.0", - "shortid": "^2.2.6", - "uuid": "^2.0.3" - }, - "engines": { - "node": "6.0.0" - }, - "devDependencies": { - "chai": "^3.5.0" - } -} diff --git a/packages/xod-core/src/index.js b/packages/xod-core/src/index.js deleted file mode 100644 index fd26a59f..00000000 --- a/packages/xod-core/src/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import * as Project from './project'; -import * as Utils from './utils'; - -export * from './project'; -export * from './utils'; - -export default Object.assign({}, - Project, - Utils -); diff --git a/packages/xod-core/src/project/constants.js b/packages/xod-core/src/project/constants.js deleted file mode 100644 index 4d450765..00000000 --- a/packages/xod-core/src/project/constants.js +++ /dev/null @@ -1,94 +0,0 @@ -export const LAYER = { - BACKGROUND: 'background', - LINKS: 'links', - NODES: 'nodes', - GHOSTS: 'ghosts', -}; - -export const ENTITY = { - NODE: 'Node', - LINK: 'Link', -}; - -export const NODE_CATEGORY = { - FUNCTIONAL: 'functional', - HARDWARE: 'hardware', - CONFIGURATION: 'configuration', - WATCH: 'watch', - IO: 'io', - PATCHES: 'patch', -}; - -export const PIN_DIRECTION = { - INPUT: 'input', - OUTPUT: 'output', -}; - -export const PIN_TYPE = { - PULSE: 'pulse', - BOOL: 'boolean', - NUMBER: 'number', - STRING: 'string', -}; - -export const PIN_VALIDITY = { - NONE: null, - INVALID: 0, - ALMOST: 1, - VALID: 2, -}; - -export const PROPERTY_TYPE = { - BOOL: 'boolean', - NUMBER: 'number', - STRING: 'string', - PULSE: 'pulse', -}; - -export const PROPERTY_DEFAULT_VALUE = { - BOOL: false, - NUMBER: 0, - STRING: '', - PULSE: false, -}; - -export const SIZE = { - NODE: { - minWidth: 80, - minHeight: 40, - padding: { - x: 2, - y: 25, - }, - }, - PIN: { - radius: 5, - margin: 15, - }, - NODE_TEXT: { - margin: { - x: 15, - y: 5, - }, - }, - LINK_HOTSPOT: { - width: 8, - }, -}; - -export const NODETYPE_ERRORS = { - CANT_DELETE_USED_PIN_OF_PATCHNODE: 'CANT_DELETE_USED_PIN_OF_PATCHNODE', - CANT_DELETE_USED_PATCHNODE: 'CANT_DELETE_USED_PATCHNODE', -}; - -export const LINK_ERRORS = { - SAME_DIRECTION: 'SAME_DIRECTION', - SAME_NODE: 'SAME_NODE', - ONE_LINK_FOR_INPUT_PIN: 'ONE_LINK_FOR_INPUT_PIN', - UNKNOWN_ERROR: 'UNKNOWN_ERROR', - PROP_CANT_HAVE_LINKS: 'PROP_CANT_HAVE_LINKS', -}; - -export const PROPERTY_ERRORS = { - PIN_HAS_LINK: 'PIN_HAS_LINK', -}; diff --git a/packages/xod-core/src/project/index.js b/packages/xod-core/src/project/index.js deleted file mode 100644 index 18f58849..00000000 --- a/packages/xod-core/src/project/index.js +++ /dev/null @@ -1,4 +0,0 @@ - -export * from './constants'; -export * from './selectors'; -export * from './state'; diff --git a/packages/xod-core/src/project/selectors.js b/packages/xod-core/src/project/selectors.js deleted file mode 100644 index f2a9f6c4..00000000 --- a/packages/xod-core/src/project/selectors.js +++ /dev/null @@ -1,828 +0,0 @@ -import R from 'ramda'; - -import { - PIN_DIRECTION, - PROPERTY_TYPE, - SIZE, - NODE_CATEGORY, - NODETYPE_ERRORS, - LINK_ERRORS, -} from './constants'; - -import { deepMerge, localID, isLocalID } from '../utils'; - -export const getUserName = R.always('Bob'); - -/* - Common utils -*/ -export const indexById = R.indexBy(R.prop('id')); -const findByProp = (propName, propVal, from) => R.pipe( - R.values, - R.find(R.propEq(propName, propVal)) -)(from); - -const findById = (id, from) => findByProp('id', id, from); -const findByNodeTypeId = (id, from) => findByProp('typeId', id, from); - -const getProjectState = (state, path) => { - if (path.length > 0 && R.has(path[0], state)) { - return getProjectState( - R.prop(path.shift(), state), - path - ); - } - return state; -}; - -export const getProject = state => R.propOr(state, 'project', state); - -const getPatchStatic = patch => R.propOr(patch, 'static', patch); -const getPatchPresent = patch => R.propOr(patch, 'present', patch); - -export const getPatches = R.pipe( - getProject, - R.prop('patches'), - R.mapObjIndexed(patch => R.merge(getPatchStatic(patch), getPatchPresent(patch))) -); - -export const getPatchById = R.curry((id, projectState) => - R.pipe( - getPatches, - R.prop(id) - )(projectState) -); - -// :: patch -> id -export const getPatchId = R.compose( - R.prop('id'), - getPatchStatic -); - -// :: id -> projectState -> patchStatic -export const getPatchStaticById = id => R.compose( - getPatchStatic, - getPatchById(id) -); - -// :: id -> projectState -> patchPresent -export const getPatchPresentById = id => R.compose( - getPatchPresent, - getPatchById(id) -); - -export const getPatchesByFolderId = (state, folderId) => R.pipe( - getPatches, - R.values, - R.filter(R.propEq('folderId', folderId)) -)(state); - -const getPatchByEntityId = (projectState, id, entityBranch) => R.pipe( - R.prop('patches'), - R.values, - R.find( - R.pipe( - getPatchPresent, - R.prop(entityBranch), - R.has(id) - ) - ) -)(projectState); - -export const getPatchByNodeId = (projectState, nodeId) => - getPatchByEntityId(projectState, nodeId, 'nodes'); - -export const getPatchByLinkId = (projectState, linkId) => - getPatchByEntityId(projectState, linkId, 'links'); - -export const getPatchName = (projectState, patchId) => R.compose( - R.prop('label'), - getPatchStaticById(patchId) -)(projectState); - -export const doesPinHaveLinks = (pin, links) => R.pipe( - R.values, - R.filter(link => ( - (link.pins[0].pinKey === pin.key && link.pins[0].nodeId === pin.nodeId) || - (link.pins[1].pinKey === pin.key && link.pins[1].nodeId === pin.nodeId) - )), - R.length, - R.flip(R.gt)(0) -)(links); - -export const canPinHaveMoreLinks = (pin, links) => ( - ( - pin.direction === PIN_DIRECTION.INPUT && - !doesPinHaveLinks(pin, links) - ) || - pin.direction === PIN_DIRECTION.OUTPUT -); - -export const getAllPinsFromNodes = R.pipe( - R.values, - R.reduce( - (p, cur) => - R.pipe( - R.prop('pins'), - R.values, - R.map(R.assoc('nodeId', cur.id)), - R.concat(p) - )(cur), - [] - ) -); - -export const validatePatches = () => R.pipe( - R.values, - R.all( - R.allPass([ - R.has('id'), - R.has('label'), - R.has('nodes'), - R.has('links'), - ]) - ) -); - -export const isPatchesUpdated = (newPatches, oldPatches) => ( - !R.equals(R.keys(newPatches), R.keys(oldPatches)) -); - -export const validateProject = project => ( - typeof project === 'object' && - R.allPass([ - R.has('patches'), - R.has('nodeTypes'), - R.has('meta'), - ], project) && - ( - R.keys(project.patches).length === 0 || - validatePatches(project.patches) - ) -); - -export const parseProjectJSON = (json) => { - const project = JSON.parse(json); - const patches = R.pipe( - getPatches, - R.values, - R.reduce((p, patch) => R.assoc(getPatchId(patch), patch, p), {}) - )(project); - const projectToLoad = R.assoc('patches', patches, project); - return projectToLoad; -}; - -export const getMeta = R.pipe( - getProject, - R.prop('meta') -); - -export const getName = R.prop('name'); -export const getId = R.prop('id'); - -/* - NodeType selectors -*/ - -export const getNodeTypes = R.pipe( - getProject, - R.prop('nodeTypes') -); - -export const getNodeTypeById = R.curry((state, id) => R.pipe( - getNodeTypes, - R.prop(id) -)(state)); - -/* - Node selectors -*/ - -export const getNodes = R.curry((patchId, state) => R.compose( - R.propOr({}, 'nodes'), - getPatchById(patchId) -)(state)); - -/* - Link selectors -*/ - -export const getLinks = (state, patchId) => R.compose( - R.prop('links'), - getPatchById(patchId) -)(state); - -export const getLinkById = (state, props) => R.pipe( - getLinks, - R.filter(link => link.id === props.id), - R.values, - R.head -)(state, props); - -export const getLinksByPinIdInPatch = (state, props) => { - const patchId = R.prop('patchId', props); - if (!patchId) { return {}; } - - return R.pipe( - R.view(R.lensPath(['patches', patchId, 'present', 'links'])), - R.filter( - link => ( - props.pinIds.indexOf(link.pins[0]) !== -1 || - props.pinIds.indexOf(link.pins[1]) !== -1 - ) - ) - )(state); -}; - -/* - Folders -*/ -export const getFolders = R.pipe( - getProject, - R.prop('folders') -); - -// :: id -> folders -> folder -export const getFolderById = R.pick; - -export const getFoldersByFolderId = (state, folderId) => R.pipe( - getFolders, - R.values, - R.filter(R.propEq('parentId', folderId)) -)(state); - -/* - Tree view (get / parse) -*/ -export const getFoldersPath = (folders, folderId) => { - if (!folderId) { return []; } - const folder = folders[folderId]; - const parentPath = getFoldersPath(folders, folder.parentId); - return R.concat([folderId], parentPath); -}; - -// :: foldersPath -> folders -> 'folder/childFolder/' -export const getPath = (foldersPath, folders) => { - const folderIds = R.reverse(foldersPath); - const folderNames = R.map( - R.pipe( - R.prop(R.__, folders), - R.prop('name') - ), - folderIds - ); - - return R.join('/', folderNames); -}; - -export const getTreeView = (state, patchId) => { - const makeTree = (folders, patches, parentId, curPatchPath) => { - const path = curPatchPath || []; - const foldersAtLevel = R.pipe( - R.values, - R.filter(R.propEq('parentId', parentId)) - )(folders); - const patchesAtLevel = R.pipe( - R.values, - R.filter(R.propEq('folderId', parentId)) - )(patches); - - return R.concat( - R.map( - folder => ({ - id: folder.id, - module: folder.name, - collapsed: (path.indexOf(folder.id) === -1), - children: makeTree(folders, patches, folder.id), - }), - foldersAtLevel - ), - R.map( - patch => ({ - id: getPatchId(patch), - module: patch.label, - leaf: true, - }), - patchesAtLevel - ) - ); - }; - - const folders = getFolders(state); - const patches = getPatches(state); - const curPatchStatic = getPatchStaticById(patchId, state); - const curPatchPath = getFoldersPath(folders, curPatchStatic.folderId); - const projectChildren = makeTree(folders, patches, null, curPatchPath); - const projectName = R.pipe( - getMeta, - getName - )(state); - - return { - id: 0, - module: projectName, - collapsed: false, - children: projectChildren, - }; -}; - -export const parseTreeView = (tree) => { - const resultShape = { - folders: [], - patches: [], - }; - const parseTree = (treePart, parentId) => { - const partResult = R.clone(resultShape); - if (treePart.leaf) { - return R.assoc('patches', R.append({ - id: treePart.id, - folderId: parentId, - }, partResult.patches), partResult); - } - - if (treePart.id) { - partResult.folders = R.append({ - id: treePart.id, - parentId, - }, partResult.folders); - } - - if (treePart.children && treePart.children.length > 0) { - R.pipe( - R.values, - R.forEach((child) => { - const chilParentId = treePart.id || null; - const childResult = parseTree(child, chilParentId); - partResult.folders = R.concat(partResult.folders, childResult.folders); - partResult.patches = R.concat(partResult.patches, childResult.patches); - }) - )(treePart.children); - } - - return partResult; - }; - - return parseTree(tree, null); -}; - -export const getTreeChanges = (oldTree, newTree) => { - const oldTreeParsed = parseTreeView(oldTree); - const newTreeParsed = parseTreeView(newTree); - const result = { - folders: [], - patches: [], - changed: false, - }; - - const sortById = R.sortBy(R.prop('id')); - - oldTreeParsed.folders = sortById(oldTreeParsed.folders); - newTreeParsed.folders = sortById(newTreeParsed.folders); - newTreeParsed.folders.forEach( - (newFolder, i) => { - if ( - newFolder.id !== oldTreeParsed.folders[i].id || - newFolder.parentId !== oldTreeParsed.folders[i].parentId - ) { - result.folders.push(newFolder); - } - } - ); - - oldTreeParsed.patches = sortById(oldTreeParsed.patches); - newTreeParsed.patches = sortById(newTreeParsed.patches); - newTreeParsed.patches.forEach( - (newPatch, i) => { - if ( - newPatch.id !== oldTreeParsed.patches[i].id || - newPatch.folderId !== oldTreeParsed.patches[i].folderId - ) { - result.patches.push(newPatch); - } - } - ); - - if (result.folders.length > 0 || result.patches.length > 0) { - result.changed = true; - } - - return result; -}; - -const filterIOAkaTerminalNodes = R.filter(R.propEq('category', NODE_CATEGORY.IO)); - -export const getPatchIOPin = (node, i) => { - const pin = R.values(node.pins)[0]; - const invertDirection = R.ifElse( - R.equals(PIN_DIRECTION.INPUT), - R.always(PIN_DIRECTION.OUTPUT), - R.always(PIN_DIRECTION.INPUT) - ); - const dir = invertDirection(pin.direction); - - return { - key: node.id, - nodeId: node.id, - pinLabel: node.properties.pinLabel, - label: node.properties.label, - direction: dir, - type: pin.type, - index: i, - }; -}; - -export const getPatchIO = R.pipe( - R.prop('nodes'), - R.values, - filterIOAkaTerminalNodes, - R.groupBy(R.compose(R.prop('direction'), R.prop(0), R.values, R.prop('pins'))), - R.map(R.pipe( - R.sortBy(R.path(['position', 'x'])), - R.addIndex(R.map)(getPatchIOPin) - )), - R.values, - R.merge([[], []]), - R.values, - R.apply(R.concat), - R.values -); - -export const getPatchNode = R.curry((state, patch) => { - const extendNodes = R.map( - node => R.compose( - R.flip(deepMerge)(node), - R.omit(['id']), - getNodeTypeById(state), - R.prop('typeId') - )(node) - ); - - const isItPatchNode = R.pipe( - R.prop('nodes'), - R.values, - filterIOAkaTerminalNodes, - R.length, - R.flip(R.gt)(0) - ); - - const assocNodes = p => R.assoc('nodes', extendNodes(R.prop('nodes', p)), p); - const assocFlag = p => R.assoc('isPatchNode', isItPatchNode(p), p); - const assocIO = p => R.assoc('io', getPatchIO(p), p); - - return R.pipe( - assocNodes, - assocFlag, - assocIO - )(patch); -}); - -export const getPatchNodes = state => R.pipe( - getPatches, - R.map(getPatchNode(state)), - R.pickBy(R.propEq('isPatchNode', true)) -)(state); - -const getPatchNodePath = R.curry( - (patch, project) => { - const folders = getFolders(project); - const patchFolders = getFoldersPath(folders, patch.folderId); - const folderPath = getPath(patchFolders, folders); - const patchLabel = R.prop('label', patch); - - return localID(`${folderPath}${folderPath ? '/' : ''}${patchLabel}`); - } -); - -const isLocalPatch = R.compose( - isLocalID, - getPatchId -); - -export const dereferencedNodeTypes = (state) => { - const patchNodes = getPatchNodes(state); - const patchNodeTypes = R.pipe( - R.values, - R.filter(isLocalPatch), - R.map( - patch => ({ - id: getPatchId(patch), - patchNode: true, - label: R.prop('label', patch), - path: getPatchNodePath(patch, state), - category: NODE_CATEGORY.PATCHES, - properties: [], - pins: R.pipe( - R.values, - R.indexBy(R.prop('key')) - )(patch.io), - }) - ), - R.indexBy(R.prop('id')) - )(patchNodes); - - return R.pipe( - getNodeTypes, - R.flip(R.merge)(patchNodeTypes) - )(state); -}; - -export const getPreparedNodeTypeById = (state, typeId) => R.pipe( - dereferencedNodeTypes, - R.prop(typeId) -)(state); - -export const addPinRadius = position => ({ - x: position.x + SIZE.PIN.radius, - y: position.y + SIZE.PIN.radius, -}); - -export const getNodeLabel = (state, node) => { - const nodeType = getPreparedNodeTypeById(state, node.typeId); - let nodeLabel = node.label || - nodeType.label || - nodeType.id; - - const nodeValue = R.view(R.lensPath(['properties', 'value']), node); - if (nodeValue !== undefined) { - const nodeValueType = nodeType.properties.value.type; - nodeLabel = nodeValue; - if (nodeValue === '' && nodeValueType === PROPERTY_TYPE.STRING) { - nodeLabel = ''; - } - } - - let nodeCustomLabel = R.path(['properties', 'label'], node); - if (nodeCustomLabel === '') { nodeCustomLabel = null; } - - nodeLabel = nodeCustomLabel || nodeLabel; - - return String(nodeLabel); -}; -const getNodePins = (state, typeId) => R.pipe( - dereferencedNodeTypes, - R.pickBy(R.propEq('id', typeId)), - R.values, - R.map(R.prop('pins')), - R.head -)(state); - -export const getLinksConnectedWithPin = R.curry( - (projectState, nodeId, pinKey, patchId) => R.pipe( - R.values, - R.filter( - R.pipe( - R.prop('pins'), - R.find( - R.allPass([ - R.propEq('nodeId', nodeId), - R.propEq('pinKey', pinKey), - ]) - ) - ) - ), - R.map( - R.pipe( - R.prop('id'), - R.toString - ) - ) - )(getLinks(projectState, patchId)) -); - -const isLinkConnected = R.curry(R.compose( - R.gt(R.__, 0), - R.length, - getLinksConnectedWithPin -)); - -export const preparePins = (projectState, node, getIsLinkConnected) => { - const pins = getNodePins(projectState, node.typeId); - - return R.map((pin) => { - const originalPin = R.pathOr({}, ['pins', pin.key], node); // TODO: explain it - const isSelected = { isSelected: false }; - const isConnected = { isConnected: getIsLinkConnected(pin.key) }; - const defaultPin = { value: null, injected: false }; - return R.mergeAll([defaultPin, pin, originalPin, isConnected, isSelected]); - })(pins); -}; - -export const dereferencedNodes = (projectState, patchId) => - R.pipe( - getNodes(patchId), - R.map((node) => { - const label = getNodeLabel(projectState, node); - const nodePins = preparePins( - projectState, - node, - isLinkConnected(projectState, node.id, R.__, patchId) - ); - - return R.merge(node, { - label, - pins: nodePins, - }); - }) - )(projectState); - -export const dereferencedLinks = (projectState, patchId) => { - const nodes = dereferencedNodes(projectState, patchId); - const links = getLinks(projectState, patchId); - - return R.map((link) => { - const pins = R.map(data => R.merge(data, nodes[data.nodeId].pins[data.pinKey]), link.pins); - return R.merge( - link, - { - type: pins[0].type, - } - ); - })(links); -}; - -export const getLinksConnectedWithNode = (projectState, nodeId, patchId) => R.pipe( - R.values, - R.filter( - R.pipe( - R.prop('pins'), - R.find(R.propEq('nodeId', nodeId)) - ) - ), - R.map(R.prop('id')) -)(getLinks(projectState, patchId)); - -const getPinKeyByNodeId = (nodeId, patch) => R.pipe( - R.prop('io'), - R.find( - R.propEq('nodeId', nodeId) - ), - R.propOr(null, 'key') -)(patch); - -export const getNodeTypeToDeleteWithNode = (projectState, nodeId, patchId) => { - const nodes = getNodes(patchId, projectState); - const node = findById(nodeId, nodes); - const nodeTypes = dereferencedNodeTypes(projectState); - const nodeType = findById(node.typeId, nodeTypes); - const isIO = (nodeType.category === NODE_CATEGORY.IO); - - let nodeTypeToDelete = null; - let nodeTypeToDeleteError = false; - - if (isIO) { - const patchNodes = getPatchNodes(projectState); - const patch = patchNodes[patchId]; - const ioNodes = patch.io.length; - const patchNodeType = findById(patchId, nodeTypes); - const patchNode = findByNodeTypeId(patchNodeType.id, nodes); - - if (ioNodes === 1) { - // This is last IO node! It will remove whole PatchNode. - nodeTypeToDelete = patchNodeType.id; - } - - if (patchNode) { - // Get links and check for pins usage - const pinKey = getPinKeyByNodeId(node.id, patch); - const links = getLinks(projectState, patchId); - const patchNodeLinks = R.pipe( - R.values, - R.filter( - link => ( - (link.pins[0].nodeId === patchNode.id && link.pins[0].pinKey === pinKey) || - (link.pins[1].nodeId === patchNode.id && link.pins[1].pinKey === pinKey) - ) - ), - R.length - )(links); - - if (patchNodeLinks > 0) { - // This pin have links - nodeTypeToDeleteError = NODETYPE_ERRORS.CANT_DELETE_USED_PIN_OF_PATCHNODE; - } else if (ioNodes === 1) { - // This patch node is used somewhere! - nodeTypeToDeleteError = NODETYPE_ERRORS.CANT_DELETE_USED_PATCHNODE; - } - } - } - - return { - id: nodeTypeToDelete, - error: nodeTypeToDeleteError, - }; -}; - -const pinComparator = data => R.both( - R.propEq('nodeId', data.nodeId), - R.propEq('key', data.pinKey) -); -const findPin = pins => R.compose( - R.flip(R.find)(pins), - pinComparator -); - -const pinIsInjected = pin => !!pin.injected; - -export const validateLink = (state, linkData) => { - const project = getProject(state); - const patch = getPatchByNodeId(project, linkData[0].nodeId); - const patchId = getPatchStatic(patch).id; - - const nodes = dereferencedNodes(project, patchId); - const pins = getAllPinsFromNodes(nodes); - const linksState = getLinks(project, patchId); - - const getPin = findPin(pins); - - const pin1 = getPin(linkData[0]); - const pin2 = getPin(linkData[1]); - - const sameDirection = pin1.direction === pin2.direction; - const sameNode = pin1.nodeId === pin2.nodeId; - const allPinsEjected = !pinIsInjected(pin1) && !pinIsInjected(pin2); - const pin1CanHaveMoreLinks = canPinHaveMoreLinks(pin1, linksState); - const pin2CanHaveMoreLinks = canPinHaveMoreLinks(pin2, linksState); - - const check = ( - !sameDirection && - !sameNode && - allPinsEjected && - pin1CanHaveMoreLinks && - pin2CanHaveMoreLinks - ); - - let error = null; - - if (!check) { - if (sameDirection) { - error = LINK_ERRORS.SAME_DIRECTION; - } else if (sameNode) { - error = LINK_ERRORS.SAME_NODE; - } else if (!pin1CanHaveMoreLinks || !pin2CanHaveMoreLinks) { - error = LINK_ERRORS.ONE_LINK_FOR_INPUT_PIN; - } else if (!allPinsEjected) { - error = LINK_ERRORS.PROP_CANT_HAVE_LINKS; - } else { - error = LINK_ERRORS.UNKNOWN_ERROR; - } - } - - return error; -}; - -export const validatePin = (state, pin) => { - const project = getProject(state); - const patch = getPatchByNodeId(project, pin.nodeId); - const patchId = getPatchId(patch); - const nodes = dereferencedNodes(project, patchId); - const linksState = getLinks(project, patchId); - const pins = getAllPinsFromNodes(nodes); - - const getPin = findPin(pins); - const pinData = getPin(pin); - - const pinCanHaveMoreLinks = canPinHaveMoreLinks(pinData, linksState); - const pinEjected = !pinIsInjected(pinData); - - const check = ( - pinCanHaveMoreLinks && - pinEjected - ); - - let error = null; - - if (!check) { - if (!pinCanHaveMoreLinks) { - error = LINK_ERRORS.ONE_LINK_FOR_INPUT_PIN; - } else - if (!pinEjected) { - error = LINK_ERRORS.PROP_CANT_HAVE_LINKS; - } else { - error = LINK_ERRORS.UNKNOWN_ERROR; - } - } - - return error; -}; - -export const getProjectPojo = (state) => { - const project = getProject(state); - const patches = R.pipe( - getPatches, - R.values, - indexById - )(project); - - return R.pipe( - R.assoc('patches', patches), - R.assoc('nodeTypes', dereferencedNodeTypes(state)), - R.omit(['counter']) - )(project); -}; - -const prettyJSON = data => JSON.stringify(data, undefined, 2); - -export const getProjectJSON = R.compose( - prettyJSON, - getProjectPojo -); diff --git a/packages/xod-core/src/project/state.js b/packages/xod-core/src/project/state.js deleted file mode 100644 index 6c2fc5c8..00000000 --- a/packages/xod-core/src/project/state.js +++ /dev/null @@ -1,49 +0,0 @@ -import R from 'ramda'; -import { PIN_DIRECTION } from './constants'; - -const mapDirectedNodeTypePins = (direction, collectionKey) => R.compose( - R.indexBy(R.prop('key')), - R.addIndex(R.map)((io, index) => R.merge({ index, direction }, io)), - R.propOr([], collectionKey) -); - -const mapNodeTypePins = meta => R.merge( - mapDirectedNodeTypePins(PIN_DIRECTION.INPUT, 'inputs')(meta), - mapDirectedNodeTypePins(PIN_DIRECTION.OUTPUT, 'outputs')(meta) -); - -// :: (String -> String -> String) -> Object -> Object -export const genNodeTypes = R.compose( - R.indexBy(R.prop('id')), - R.values, - R.mapObjIndexed((meta, id) => R.merge( - R.omit(['inputs', 'outputs'], meta), - { - id, - pins: mapNodeTypePins(meta), - } - )) -); - -export const getInitialState = nodeTypes => ({ - meta: { - name: 'Awesome project', - author: 'Amperka team', - }, - patches: { - '@/1': { - id: '@/1', - label: 'Main', - nodes: {}, - links: {}, - }, - '@/2': { - id: '@/2', - label: 'QUX', - nodes: {}, - links: {}, - }, - }, - nodeTypes, - folders: {}, -}); diff --git a/packages/xod-core/src/utils/gmath.js b/packages/xod-core/src/utils/gmath.js deleted file mode 100644 index 3a68deee..00000000 --- a/packages/xod-core/src/utils/gmath.js +++ /dev/null @@ -1,59 +0,0 @@ - -import R from 'ramda'; - -export function findVertexesWithNoIncomingEdges(vertexes, edges) { - return R.difference( - vertexes, - R.map(R.nth(1), edges) - ); -} - -export function hasIncomingEdges(vertex, edges) { - const edgeIncoming = R.compose(R.equals(vertex), R.nth(1)); - return R.any(edgeIncoming, edges); -} - -export function hasEdgeFrom(n, edges) { - return m => R.contains([n, m], edges); -} - -/** - * Sorts graph vertexes topologically. - * - * @param {Array.} vertexes - * List of graph vertexes with an arbitrary number (ID, for example) as payload. - * @param {Array.>} edges - * List of pairs in the form of `[sourceVertex, destinationVertex] that defines - * graph edges along with their direction. - * - * This is an implementation of Kahn’s algorithm. - * @see https://en.wikipedia.org/wiki/Topological_sorting - */ -export function sortGraph(vertexes, edges) { - let l = []; // Empty list that will contain the sorted elements - let s = findVertexesWithNoIncomingEdges(vertexes, edges); - let edgesLeft = edges; - - const excludeEdgesFrom = n => (m) => { - edgesLeft = R.without([[n, m]], edgesLeft); - if (!hasIncomingEdges(m, edgesLeft)) { - s = R.append(m, s); - } - }; - - while (s.length) { - const n = R.head(s); - s = R.drop(1, s); - l = R.append(n, l); - R.forEach( - excludeEdgesFrom(n), - R.filter(hasEdgeFrom(n, edgesLeft), vertexes) - ); - } - - if (edgesLeft.length) { - throw new Error('Graph has at least one cycle'); - } - - return l; -} diff --git a/packages/xod-core/src/utils/index.js b/packages/xod-core/src/utils/index.js deleted file mode 100644 index 28b4416b..00000000 --- a/packages/xod-core/src/utils/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import { generate } from 'shortid'; - -export * from './gmath'; -export * from './ramda'; - -const removeTrailingSlash = text => text.replace(/\/$/, ''); - -export const localID = sid => `@/${removeTrailingSlash(sid)}`; - -export const generateId = () => generate(); -export const generatePatchSID = () => localID(generateId()); - -export const isLocalID = id => (typeof id === 'string' && id[0] === '@'); diff --git a/packages/xod-core/src/utils/ramda.js b/packages/xod-core/src/utils/ramda.js deleted file mode 100644 index 46396100..00000000 --- a/packages/xod-core/src/utils/ramda.js +++ /dev/null @@ -1,15 +0,0 @@ -import R from 'ramda'; - -// eslint-disable-next-line import/prefer-default-export -export const deepMerge = R.mergeWith( - (o1, o2) => - R.ifElse( - R.is(Object), - R.flip(R.mergeWith(deepMerge))(o2), - R.flip(R.merge)(o2) - )(o1) -); - -export const notNil = R.complement(R.isNil); -export const hasNot = R.complement(R.has); -export const mapIndexed = R.addIndex(R.map); diff --git a/packages/xod-core/test/gmath.spec.js b/packages/xod-core/test/gmath.spec.js deleted file mode 100644 index 46482c5d..00000000 --- a/packages/xod-core/test/gmath.spec.js +++ /dev/null @@ -1,47 +0,0 @@ - -import { expect } from 'chai'; -import { sortGraph } from '../src/utils/gmath'; - -describe('Graph math', () => { - describe('Topological sorting', () => { - it('should return [] for empty graph', () => { - const sorted = sortGraph([], []); - expect(sorted).to.be.eql([]); - }); - - it('should return single vertex for single-vertex graph', () => { - const sorted = sortGraph([42], []); - expect(sorted).to.be.eql([42]); - }); - - it('should return vertexes as is if there are no edges', () => { - const sorted = sortGraph([42, 43, 44], []); - expect(sorted).to.be.eql([42, 43, 44]); - }); - - it('should return vertexes as is if already sorted', () => { - const sorted = sortGraph([42, 43, 44], [[42, 43], [43, 44]]); - expect(sorted).to.be.eql([42, 43, 44]); - }); - - it('should return sorted vertexes if given vertexes are inversed', () => { - const sorted = sortGraph([44, 43, 42], [[42, 43], [43, 44]]); - expect(sorted).to.be.eql([42, 43, 44]); - }); - - it('should throw error for cycled graph', () => { - const sort = () => sortGraph([42, 43, 44], [[42, 43], [43, 42]]); - expect(sort).to.throw(Error, /cycle/); - }); - - it('should sort diamond graph', () => { - const sorted = sortGraph([44, 43, 42, 45], [[42, 43], [42, 44], [43, 45], [44, 45]]); - expect(sorted).to.be.eql([42, 44, 43, 45]); - }); - - it('should sort clusters', () => { - const sorted = sortGraph([44, 43, 42, 45], [[42, 43], [44, 45]]); - expect(sorted).to.be.eql([44, 42, 45, 43]); - }); - }); -}); diff --git a/packages/xod-core/test/mocha.opts b/packages/xod-core/test/mocha.opts deleted file mode 100644 index a5833907..00000000 --- a/packages/xod-core/test/mocha.opts +++ /dev/null @@ -1,2 +0,0 @@ ---require babel-register ---colors diff --git a/packages/xod-core/yarn.lock b/packages/xod-core/yarn.lock deleted file mode 100644 index 6f164fdf..00000000 --- a/packages/xod-core/yarn.lock +++ /dev/null @@ -1,45 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" - -chai@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" - dependencies: - assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" - dependencies: - type-detect "0.1.1" - -ramda@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.23.0.tgz#ccd13fff73497a93974e3e86327bfd87bd6e8e2b" - -shortid@^2.2.6: - version "2.2.8" - resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.8.tgz#033b117d6a2e975804f6f0969dbe7d3d0b355131" - -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - -uuid@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" diff --git a/packages/xod-fs/package.json b/packages/xod-fs/package.json index cb95a2a3..b7c5913f 100644 --- a/packages/xod-fs/package.json +++ b/packages/xod-fs/package.json @@ -18,7 +18,6 @@ "ramda": "^0.23.0", "recursive-readdir": "^2.1.0", "rimraf": "^2.5.4", - "xod-core": "^0.0.1", "xod-project": "^0.0.1", "xod-func-tools": "^0.0.1" }, diff --git a/packages/xod-fs/src/loadLibs.js b/packages/xod-fs/src/loadLibs.js index dca54a60..8870ead8 100644 --- a/packages/xod-fs/src/loadLibs.js +++ b/packages/xod-fs/src/loadLibs.js @@ -1,6 +1,6 @@ import R from 'ramda'; import path from 'path'; -import { hasNot } from 'xod-core'; +import { hasNo } from 'xod-func-tools'; import { toV2, listLibraryPatches } from 'xod-project'; import { readDir, readJSON, readFile } from './read'; import { resolvePath } from './utils'; @@ -63,7 +63,7 @@ const readLibFiles = (libfiles) => { .then((loaded) => { const data = R.assoc('id', `${name}/${getPatchName(patchPath)}`, loaded); - if (hasNot('nodes', data)) { + if (hasNo('nodes', data)) { return R.assoc('impl', {}, data); } diff --git a/packages/xod-fs/src/pack.js b/packages/xod-fs/src/pack.js index fb363919..5a6f4022 100644 --- a/packages/xod-fs/src/pack.js +++ b/packages/xod-fs/src/pack.js @@ -1,6 +1,7 @@ import path from 'path'; import R from 'ramda'; -import { generateId, localID } from 'xod-core'; +import { generateId } from 'xod-project'; +import { localID } from './utils'; const indexById = R.indexBy(R.prop('id')); diff --git a/packages/xod-fs/src/unpack.js b/packages/xod-fs/src/unpack.js index 06003b86..104a830c 100644 --- a/packages/xod-fs/src/unpack.js +++ b/packages/xod-fs/src/unpack.js @@ -1,7 +1,7 @@ import path from 'path'; import R from 'ramda'; import XF from 'xod-func-tools'; -import { hasNot, isLocalID, localID, notNil } from 'xod-core'; +import { isLocalID, localID } from './utils'; // :: "./awesome-project/" -> "main" -> "patch.xodm" -> "./awesome-project/main/patch.xodm" const filePath = (projectPath, patchPath, fileName) => R.pipe( @@ -42,7 +42,7 @@ const foldersPaths = R.pipe( R.values, R.sort( R.allPass([ - notNil, + XF.notNil, R.gte, ]) ), @@ -78,7 +78,7 @@ const extractLibs = R.pipe( // :: patchMeta -> xodball -> patchNodeMeta const margeWithNodeType = (obj, patchId, xodball) => { - if (hasNot(patchId, xodball.nodeTypes)) { return obj; } + if (XF.hasNo(patchId, xodball.nodeTypes)) { return obj; } return R.pipe( R.path(['nodeTypes', patchId]), @@ -132,7 +132,7 @@ const resolvePatchIds = (patches) => { const resolveNode = (node) => { const typeId = node.typeId; - if (hasNot(typeId, pathMapping)) { return node; } + if (XF.hasNo(typeId, pathMapping)) { return node; } return R.assoc('typeId', pathMapping[typeId], node); }; diff --git a/packages/xod-fs/src/utils.js b/packages/xod-fs/src/utils.js index a028c24e..e19df01b 100644 --- a/packages/xod-fs/src/utils.js +++ b/packages/xod-fs/src/utils.js @@ -28,3 +28,9 @@ export const isFileExists = R.tryCatch( ), R.F ); + + +// TODO: remove rudimental utilities +const removeTrailingSlash = text => text.replace(/\/$/, ''); +export const localID = sid => `@/${removeTrailingSlash(sid)}`; +export const isLocalID = id => (typeof id === 'string' && id[0] === '@'); diff --git a/packages/xod-fs/test/unpack.spec.js b/packages/xod-fs/test/unpack.spec.js index baef8015..16544818 100644 --- a/packages/xod-fs/test/unpack.spec.js +++ b/packages/xod-fs/test/unpack.spec.js @@ -1,6 +1,6 @@ import R from 'ramda'; import { expect } from 'chai'; -import { isLocalID } from 'xod-core'; +import { isLocalID } from '../src/utils'; import * as Unpack from '../src/unpack'; import xodball from './fixtures/xodball.json'; import unpacked from './fixtures/unpacked.json'; diff --git a/packages/xod-fs/test/utils.js b/packages/xod-fs/test/utils.js index bdf88d35..7c9ed23c 100644 --- a/packages/xod-fs/test/utils.js +++ b/packages/xod-fs/test/utils.js @@ -1,5 +1,4 @@ import R from 'ramda'; -import { mapIndexed } from 'xod-core'; export const numerateFolders = (initialFolders) => { const accordance = {}; @@ -7,7 +6,7 @@ export const numerateFolders = (initialFolders) => { return R.pipe( R.values, R.sortBy(R.prop('name')), - mapIndexed( + R.mapObjIndexed( (folder, idx) => { accordance[folder.id] = idx; return R.assoc('id', idx, folder); diff --git a/packages/xod-func-tools/src/index.js b/packages/xod-func-tools/src/index.js index 7881328b..f83ad0b0 100644 --- a/packages/xod-func-tools/src/index.js +++ b/packages/xod-func-tools/src/index.js @@ -103,6 +103,7 @@ export const optionalObjOf = def( export const notNil = R.complement(R.isNil); export const notEmpty = R.complement(R.isEmpty); +export const hasNo = R.complement(R.has); /** * Like `R.tap` but works with Promises. @@ -116,6 +117,7 @@ export default Object.assign( explode, explodeMaybe, foldEither, + hasNo, omitNilValues, omitEmptyValues, isAmong, diff --git a/packages/xod-js/package.json b/packages/xod-js/package.json index fb5b2b5b..af1fffd0 100644 --- a/packages/xod-js/package.json +++ b/packages/xod-js/package.json @@ -16,7 +16,6 @@ "hm-def": "^0.1.2", "ramda": "^0.23.0", "ramda-fantasy": "^0.7.0", - "xod-core": "^0.0.1", "xod-project": "^0.0.1", "xod-func-tools": "^0.0.1" }, diff --git a/packages/xod-js/src/transpiler.js b/packages/xod-js/src/transpiler.js index d8930b40..29d5dc72 100644 --- a/packages/xod-js/src/transpiler.js +++ b/packages/xod-js/src/transpiler.js @@ -203,7 +203,7 @@ function transpileImpl(impl) { const itemRef = `impl['${implId}']`; let lines = []; - // TODO: move such predicates to xod-core + // TODO: use functions from xod-project, unhardcode regexes if (/^xod\/core\/input/.test(implId) || /^xod\/core\/output/.test(implId)) { lines = [`${itemRef} = identityNode();`]; } else { diff --git a/packages/xod-js/webpack.config.js b/packages/xod-js/webpack.config.js index f190f524..3439c5b8 100644 --- a/packages/xod-js/webpack.config.js +++ b/packages/xod-js/webpack.config.js @@ -15,7 +15,6 @@ module.exports = { umdNamedDefine: true }, externals: [ - 'xod-core', 'fs', ], module: {