This commit is contained in:
Mark Eibes 2020-01-26 12:32:19 +01:00
parent 4e7334be70
commit 4a3f8f821f
10 changed files with 319 additions and 1641 deletions

20
client/dist/bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -85,6 +85,15 @@ mkContainerContent = do
]
}
, element header {}
, R.div { className: classes.content, children: [ element editor {} ] <> children }
, R.div { className: classes.content, children: [ element editor { initialCode } ] <> children }
]
}
initialCode :: String
initialCode =
"""module Main where
import Batteries
main :: Effect Unit
main ="""

View File

@ -1,4 +1,4 @@
{
"editor.formatOnSave": true,
"purescript.buildCommand": "spago build --purs-args '--json-errors'"
"purescript.buildCommand": "npx spago build --purs-args '--json-errors'"
}

View File

@ -5377,12 +5377,12 @@
}
},
"execa": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/execa/-/execa-2.0.4.tgz",
"integrity": "sha512-VcQfhuGD51vQUQtKIq2fjGDLDbL6N1DTQVpYzxZ7LPIXw3HqTuIz6uxRmpV1qf8i31LHf2kjiaGI+GdHwRgbnQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz",
"integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==",
"dev": true,
"requires": {
"cross-spawn": "^6.0.5",
"cross-spawn": "^7.0.0",
"get-stream": "^5.0.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
@ -5391,6 +5391,49 @@
"p-finally": "^2.0.0",
"signal-exit": "^3.0.2",
"strip-final-newline": "^2.0.0"
},
"dependencies": {
"cross-spawn": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
"integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"expand-brackets": {
@ -5758,9 +5801,9 @@
}
},
"filesize": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-4.2.0.tgz",
"integrity": "sha512-bdS2UP98MZzLyTZzhuSH5ctAWyDt81n5xMti9BSdmgPXjjENLDz5Bmbk2R7ATVw/HRysZzWA2JIPgcSAOimWpw==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-4.2.1.tgz",
"integrity": "sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA==",
"dev": true
},
"fill-range": {
@ -6088,25 +6131,29 @@
"dependencies": {
"abbrev": {
"version": "1.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true,
"optional": true
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"bundled": true,
"resolved": false,
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"dev": true,
"optional": true,
"requires": {
@ -6116,13 +6163,15 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"optional": true,
"requires": {
@ -6132,37 +6181,43 @@
},
"chownr": {
"version": "1.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
"dev": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true,
"optional": true
},
"debug": {
"version": "4.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"optional": true,
"requires": {
@ -6171,25 +6226,29 @@
},
"deep-extend": {
"version": "0.6.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true,
"optional": true
},
"delegates": {
"version": "1.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true,
"optional": true
},
"detect-libc": {
"version": "1.0.3",
"bundled": true,
"resolved": false,
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"dev": true,
"optional": true
},
"fs-minipass": {
"version": "1.2.5",
"bundled": true,
"resolved": false,
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"dev": true,
"optional": true,
"requires": {
@ -6198,13 +6257,15 @@
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true,
"optional": true
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"resolved": false,
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true,
"optional": true,
"requires": {
@ -6220,7 +6281,8 @@
},
"glob": {
"version": "7.1.3",
"bundled": true,
"resolved": false,
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"optional": true,
"requires": {
@ -6234,13 +6296,15 @@
},
"has-unicode": {
"version": "2.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"dev": true,
"optional": true
},
"iconv-lite": {
"version": "0.4.24",
"bundled": true,
"resolved": false,
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"optional": true,
"requires": {
@ -6249,7 +6313,8 @@
},
"ignore-walk": {
"version": "3.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"dev": true,
"optional": true,
"requires": {
@ -6258,7 +6323,8 @@
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"resolved": false,
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"optional": true,
"requires": {
@ -6268,19 +6334,22 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
"bundled": true,
"resolved": false,
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"optional": true,
"requires": {
@ -6289,13 +6358,15 @@
},
"isarray": {
"version": "1.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true,
"optional": true
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"optional": true,
"requires": {
@ -6304,13 +6375,15 @@
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"resolved": false,
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"dev": true,
"optional": true,
"requires": {
@ -6320,7 +6393,8 @@
},
"minizlib": {
"version": "1.2.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
"dev": true,
"optional": true,
"requires": {
@ -6329,7 +6403,8 @@
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"optional": true,
"requires": {
@ -6338,13 +6413,15 @@
},
"ms": {
"version": "2.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true,
"optional": true
},
"needle": {
"version": "2.3.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==",
"dev": true,
"optional": true,
"requires": {
@ -6355,7 +6432,8 @@
},
"node-pre-gyp": {
"version": "0.12.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==",
"dev": true,
"optional": true,
"requires": {
@ -6373,7 +6451,8 @@
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"dev": true,
"optional": true,
"requires": {
@ -6383,13 +6462,15 @@
},
"npm-bundled": {
"version": "1.0.6",
"bundled": true,
"resolved": false,
"integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
"dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==",
"dev": true,
"optional": true,
"requires": {
@ -6399,7 +6480,8 @@
},
"npmlog": {
"version": "4.1.2",
"bundled": true,
"resolved": false,
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"optional": true,
"requires": {
@ -6411,19 +6493,22 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true,
"optional": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"optional": true,
"requires": {
@ -6432,19 +6517,22 @@
},
"os-homedir": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true,
"optional": true
},
"osenv": {
"version": "0.1.5",
"bundled": true,
"resolved": false,
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"dev": true,
"optional": true,
"requires": {
@ -6454,19 +6542,22 @@
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"optional": true
},
"process-nextick-args": {
"version": "2.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true,
"optional": true
},
"rc": {
"version": "1.2.8",
"bundled": true,
"resolved": false,
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dev": true,
"optional": true,
"requires": {
@ -6478,7 +6569,8 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true,
"optional": true
}
@ -6486,7 +6578,8 @@
},
"readable-stream": {
"version": "2.3.6",
"bundled": true,
"resolved": false,
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"optional": true,
"requires": {
@ -6501,7 +6594,8 @@
},
"rimraf": {
"version": "2.6.3",
"bundled": true,
"resolved": false,
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"optional": true,
"requires": {
@ -6510,43 +6604,50 @@
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"resolved": false,
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
"bundled": true,
"resolved": false,
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"optional": true
},
"sax": {
"version": "1.2.4",
"bundled": true,
"resolved": false,
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true,
"optional": true
},
"semver": {
"version": "5.7.0",
"bundled": true,
"resolved": false,
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"resolved": false,
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true,
"optional": true
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"optional": true,
"requires": {
@ -6557,7 +6658,8 @@
},
"string_decoder": {
"version": "1.1.1",
"bundled": true,
"resolved": false,
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"optional": true,
"requires": {
@ -6566,7 +6668,8 @@
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"optional": true,
"requires": {
@ -6575,13 +6678,15 @@
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true,
"resolved": false,
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true,
"optional": true
},
"tar": {
"version": "4.4.8",
"bundled": true,
"resolved": false,
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"dev": true,
"optional": true,
"requires": {
@ -6596,13 +6701,15 @@
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true,
"optional": true
},
"wide-align": {
"version": "1.1.3",
"bundled": true,
"resolved": false,
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"dev": true,
"optional": true,
"requires": {
@ -6611,13 +6718,15 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"resolved": false,
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"resolved": false,
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true,
"optional": true
}
@ -7685,9 +7794,9 @@
}
},
"is-plain-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.0.0.tgz",
"integrity": "sha512-EYisGhpgSCwspmIuRHGjROWTon2Xp8Z7U03Wubk/bTL5TTRC5R1rGVgyjzBrk9+ULdH6cRD06KRcw/xfqhVYKQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"is-plain-object": {
@ -8532,9 +8641,9 @@
"dev": true
},
"minipass": {
"version": "2.8.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.8.6.tgz",
"integrity": "sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.2",
@ -8542,12 +8651,12 @@
}
},
"minizlib": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.2.tgz",
"integrity": "sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ==",
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
"dev": true,
"requires": {
"minipass": "^2.2.1"
"minipass": "^2.9.0"
}
},
"mississippi": {
@ -8826,9 +8935,9 @@
},
"dependencies": {
"path-key": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz",
"integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
}
}
@ -9874,9 +9983,9 @@
"dev": true
},
"purescript": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/purescript/-/purescript-0.13.3.tgz",
"integrity": "sha512-YFznjWSFrl6pbds0JxWXJ/ztzyGgUsR5pvdF/wH1i1BqSqxpFtWgREUIOCCkzmuc+X9U2Ntf5DMQ56RxawE3gQ==",
"version": "0.13.6",
"resolved": "https://registry.npmjs.org/purescript/-/purescript-0.13.6.tgz",
"integrity": "sha512-PC93xqr0zDs5l5xnfTlptKzv5jBWbML+dwtpDCZkOOH7h9wgLusQfU4PNfHvdwrSmsBntalGm+Cbd6VrokN7Sg==",
"dev": true,
"requires": {
"purescript-installer": "^0.2.0"
@ -11720,12 +11829,12 @@
"dev": true
},
"spago": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/spago/-/spago-0.10.0.tgz",
"integrity": "sha512-hcyAVObO+ZgXZaqy0EMCZgw8+Yr+PAGpYfV77C1EuL5gcSaly4snCY6dFBIdcUq0/vYhkCuUpBUGi6Dx+rnxiw==",
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/spago/-/spago-0.13.1.tgz",
"integrity": "sha512-cfxhWEIbPDcPoTHZbAdtmPRui70dzUo4JZlybrGiWo9A+HpWrfkefzjhn6AcOWY/2tmtmOhYJirtsQzxvO4VnQ==",
"dev": true,
"requires": {
"follow-redirects": "^1.7.0",
"request": "^2.88.0",
"tar": "^4.4.8"
}
},
@ -13475,9 +13584,9 @@
}
},
"zen-observable": {
"version": "0.8.14",
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.14.tgz",
"integrity": "sha512-kQz39uonEjEESwh+qCi83kcC3rZJGh4mrZW7xjkSQYXkq//JZHTtKo+6yuVloTgMtzsIWOJrjIrKvk/dqm0L5g==",
"version": "0.8.15",
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
"integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==",
"dev": true
}
}

View File

@ -48,11 +48,11 @@
"deep-equal": "^1.1.0",
"jsdom": "^15.1.1",
"jsdom-global": "^3.0.2",
"purescript": "^0.13.3",
"purescript": "^0.13.6",
"purescript-psa": "^0.7.3",
"purs-loader": "^3.6.0",
"react-svg-loader": "^3.0.3",
"spago": "^0.10.0",
"spago": "^0.13.1",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.8.1",

View File

@ -61,7 +61,7 @@ mkCompileEditor = do
res <- compileAndRun { code }
liftEffect
$ setCompileResult case res of
Left cr -> (cr.result.errors <#> _.message # intercalate "/n")
Left cr -> (cr.result <#> _.message # intercalate "/n")
Right r -> r.stdout
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
{
"name": "playground",
"version": "1.0.0",
"description": "",
"main": "run.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"purescript": "^0.13.6",
"spago": "^0.13.1"
}
}

View File

@ -38,9 +38,9 @@ import Node.Process (lookupEnv)
import Playground.Playground (Folder(..), copy)
import PscIdeClient (PscIdeConnection, compileCode, getFolder, mkConnection)
import Shared.Json (readAff)
import Shared.Models.Body (CompileRequest, RunResult)
import Shared.Models.Body (CompileRequest, RunResult, CompileResult)
import Shared.Models.Body as Body
import Simple.JSON (read_, write)
import Simple.JSON (readJSON, read_, write)
toBody ∷ ∀ r m. MonadEffect m => { stdout ∷ Buffer, stderr ∷ Buffer | r } -> m RunResult
toBody result =
@ -58,43 +58,6 @@ type ErrorWithCode
asErrorWithCode ∷ ∀ a. a -> Maybe ErrorWithCode
asErrorWithCode = read_ <<< unsafeToForeign
-- compileCode ∷ JobId -> Folder -> Int -> String -> Aff PursResult
-- compileCode jobId folder port code = do
-- saveMainFile folder code
-- { stderr } <- execCommand folder "node_modules/spago/spago build --purs-args \"--json-errors\""
-- strResult <- liftEffect $ Buffer.toString UTF8 stderr
-- case checkOutput strResult of
-- Just r -> do
-- pure r
-- Nothing -> do
-- liftEffect $ throw $ "No result in " <> strResult
-- where
-- checkOutput output =
-- head do
-- line <- lines output
-- let
-- (parseable :: Maybe PursResult) = JSON.readJSON_ line
-- fromFoldable parseable
-- compileCodeOld ∷ JobId -> Folder -> String -> Aff PursResult
-- compileCodeOld jobId folder code = do
-- saveMainFile folder code
-- { stderr } <- execCommand folder "node_modules/spago/spago build --purs-args \"--json-errors\""
-- strResult <- liftEffect $ Buffer.toString UTF8 stderr
-- case checkOutput strResult of
-- Just r -> do
-- pure r
-- Nothing -> do
-- liftEffect $ throw $ "No result in " <> strResult
-- where
-- checkOutput output =
-- head do
-- line <- lines output
-- let
-- (parseable :: Maybe PursResult) = JSON.readJSON_ line
-- fromFoldable parseable
runCode ∷ Folder -> Aff ExecResult
runCode folder = execCommand folder "node run.js"
@ -109,14 +72,19 @@ execCommand folder command =
compileAndRunJob ∷ CompileRequest -> (Handler -> Aff Unit) -> NewJob PscIdeConnection
compileAndRunJob json handle =
NewJob \jobId conn -> do
compileResult <- compileCode json.code conn
if compileResult.resultType == "error" then do
handle $ setStatus 422
handle $ Response.send $ write compileResult
else do
runResult <- runCode (getFolder conn)
resultBody <- toBody runResult
handle $ Response.send $ write (resultBody ∷ Body.RunResult)
responseString <- compileCode json.code conn
case ((readJSON responseString) :: _ _ CompileResult) of
Right res | res.resultType == "error" -> do
handle $ setStatus 422
handle $ Response.send $ write res
Right res -> do
runResult <- runCode (getFolder conn)
resultBody <- toBody runResult
handle $ Response.send $ write (resultBody ∷ Body.RunResult)
Left errs -> do
handle $ setStatus 500
log $ "Could not decode: " <> responseString <> "\nErrors: " <> show errs
handle $ Response.send $ write {}
compileAndRunHandler ∷ Queue PscIdeConnection -> Handler
compileAndRunHandler queue = do
@ -153,7 +121,7 @@ main = do
mkFolder = Folder <<< (destFolder <> _) <<< show
connections <- sequential $ for (0 .. poolSize) \n -> parallel do
connections <- for (0 .. poolSize) \n -> do
let folder = mkFolder n
port = 14100 + n
copy srcFolder (un Folder folder)
@ -163,7 +131,7 @@ main = do
q <-
Q.mkQueue
{ maxSize: 50
, timeout: 60.0 # Seconds # fromDuration
, timeout: 10.0 # Seconds # fromDuration
}
pool
serverSetup (makeApp q)

View File

@ -2,50 +2,29 @@ module PscIdeClient where
import Prelude
import Control.Monad.Rec.Class (untilJust)
import Data.Array (foldMap)
import Data.Array as Array
import Data.Array.NonEmpty as NEA
import Data.Either (Either(..))
import Data.Foldable (for_, intercalate)
import Data.Int (fromString)
import Data.Map (Map)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Either (Either(..), either)
import Data.Foldable (intercalate)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype, un, unwrap)
import Data.Posix.Signal (Signal(..))
import Data.Semigroup.Foldable (intercalateMap)
import Data.String as Str
import Data.String.Utils (lines)
import Data.Time.Duration (Milliseconds(..), Seconds(..), fromDuration)
import Data.Traversable (for)
import Data.UUID as UUID
import Data.String.Utils (endsWith)
import Debug.Trace (spy)
import Effect (Effect)
import Effect.Aff (Aff, Canceler(..), Fiber, delay, effectCanceler, launchAff, launchAff_, makeAff, nonCanceler)
import Effect.Aff.Class (liftAff)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Class.Console (info, log, logShow)
import Effect.Class.Console as Console
import Effect.Exception (Error, throw)
import Effect.Aff (Aff, Canceler, effectCanceler, makeAff)
import Effect.Class (liftEffect)
import Effect.Class.Console (log)
import Effect.Exception (message)
import Effect.Ref (Ref)
import Effect.Ref as Ref
import Foreign (renderForeignError, unsafeToForeign)
import JobQueue (EnqueueResult(..), JobId(..), NewJob(..), Queue, ResourcePool(..))
import JobQueue as Q
import Middleware.JsonBodyParser (jsonBodyParser)
import Foreign (renderForeignError)
import Node.Buffer as Buf
import Node.ChildProcess (ChildProcess, defaultExecOptions)
import Node.ChildProcess (ChildProcess)
import Node.ChildProcess as CP
import Node.Encoding (Encoding(..))
import Node.Express.Handler (HandlerM(..), Handler)
import Node.Express.Middleware.Static (static)
import Node.Express.Request (getBody')
import Node.FS.Aff (readTextFile, writeTextFile)
import Node.HTTP (Server)
import Node.FS.Aff (writeTextFile)
import Node.Net.Socket (Socket)
import Node.Net.Socket as Socket
import Node.OS (numCpus)
import Node.Process (lookupEnv)
import Playground.Playground (Folder(..))
import Shared.Models.Body (CompileResult)
import Simple.JSON (readJSON, writeJSON)
@ -60,72 +39,41 @@ type BuildCommand
buildCommand ∷ BuildCommand
buildCommand =
{ "command": "rebuild"
, "params": { "file": "/Users/mark/code/psfp/playground/src/Main.purs" }
, "params": { "file": "src/Main.purs" }
}
closeSocketCanceller :: Socket -> Canceler
closeSocketCanceller Socket -> Canceler
closeSocketCanceller s =
effectCanceler $
unlessM
(Socket.destroyed s) do
effectCanceler
$ unlessM
(Socket.destroyed s) do
-- Socket.end s (pure unit)
log $ "Destroying socket..."
Socket.destroy s Nothing
createConnectionTCP ∷ Int -> Aff Socket
createConnectionTCP port =
makeAff \callback -> do
socket <- Socket.createConnectionTCP port "localhost" mempty
Socket.onReady socket (callback (Right socket))
pure $ closeSocketCanceller socket
startIdeServer ∷ Folder -> Int -> Aff ChildProcess
startIdeServer folder port = do
log
$ "Spawning ide server in folder "
<> un Folder folder
<> " on port "
<> show port
cp <- spawnProcess folder ("npx purs ide server -p " <> show port)
log
$ "Spawned ide server in folder "
<> un Folder folder
<> " on port "
<> show port
pure cp
splitter :: Ref String -> String -> Effect (Array String)
splitter chunkRef str = case NEA.fromArray splitAtNewlines of
Nothing -> pure []
Just newChunks -> do
chunk <- Ref.read chunkRef
let
{ init, last } = NEA.unsnoc newChunks
newTail = Array.drop 1 init
oldChunkAndNewFirst = NEA.head newChunks <> chunk
Ref.write last chunkRef
pure (Array.cons oldChunkAndNewFirst newTail)
where
splitAtNewlines = Str.split (Str.Pattern "\n") str
writeString :: String -> Socket -> Aff Unit
writeString str socket =
makeAff \callback -> do
void $ Socket.writeString socket str UTF8 (callback (Right unit))
pure $ closeSocketCanceller socket
onError :: (Error -> Effect Unit) -> Socket -> Effect Unit
onError = flip Socket.onError
onData ∷ Socket -> (String -> Effect Unit) -> Effect Unit
onData socket callback = do
chunkRef <- Ref.new ""
Socket.onData socket case _ of
Left buffer -> do
response <- Buf.toString UTF8 buffer
results <- splitter chunkRef response
for_ results callback
Right response -> do
results <- splitter chunkRef response
for_ results callback
startIdeServer :: Folder -> Int -> Aff ChildProcess
startIdeServer folder port =
spawnProcess folder ("npx purs ide server -p " <> show port)
restartIdeServer :: _ -> _ -> _ -> Aff Unit
restartIdeServer ∷ Folder -> Int -> Ref ChildProcess -> Aff Unit
restartIdeServer folder port processRef = do
cp <- Ref.read processRef # liftEffect
CP.kill SIGKILL cp # liftEffect
newCp <- startIdeServer folder port
Ref.write newCp processRef # liftEffect
spawnProcess :: Folder -> String -> Aff ChildProcess
spawnProcess ∷ Folder -> String -> Aff ChildProcess
spawnProcess folder command =
makeAff \callback -> do
let
@ -134,70 +82,57 @@ spawnProcess folder command =
callback (Right childProcess)
pure $ effectCanceler ((log $ "Killing " <> show (CP.pid childProcess)) *> CP.kill SIGKILL childProcess)
newtype PscIdeConnection = PscIdeConnection
{ serverProcess :: ChildProcess
, socket :: Socket
, port :: Int
, folder :: Folder
, answersRef :: Ref (Array CompileResult)
newtype PscIdeConnection
= PscIdeConnection
{ serverProcess ∷ ChildProcess
, port ∷ Int
, folder ∷ Folder
}
derive instance ntPscIdeConnection :: Newtype PscIdeConnection _
instance eqPscIdeConnection :: Eq PscIdeConnection where
eq c1 c2 = (unwrap c1).port == (unwrap c2).port
compileCode :: String -> PscIdeConnection -> Aff CompileResult
compileCode code conn@(PscIdeConnection { serverProcess, socket, port, folder, answersRef }) = do
saveMainFile folder code
writeString (writeJSON buildCommand <> "\n") socket
untilJust do
delay (50.0 # Milliseconds)
popOldestAnswer conn # liftEffect
saveMainFile ∷ Folder -> String -> Aff Unit
saveMainFile folder code = writeTextFile UTF8 (un Folder folder <> "/src/Main.purs") code
popOldestAnswer :: PscIdeConnection -> Effect (Maybe CompileResult)
popOldestAnswer (PscIdeConnection { answersRef }) = do
result <- Ref.read answersRef <#> Array.head
Ref.modify_ (Array.drop 1) answersRef
pure result
getFolder :: PscIdeConnection -> Folder
getFolder ∷ PscIdeConnection -> Folder
getFolder (PscIdeConnection { folder }) = folder
mkConnection :: Folder -> Int -> Aff PscIdeConnection
compileCode ∷ String -> PscIdeConnection -> Aff String
compileCode code (PscIdeConnection { port, folder }) = do
saveMainFile folder code
makeAff \affCb -> do
log $
"Compiling code in " <> (un Folder folder) <> " on port " <> show port
socket <- Socket.createConnectionTCP port "localhost" mempty
-- maybe timeout?
Socket.onError socket (affCb <<< Left)
resultRef <- Ref.new ""
Socket.onData socket \dataFromServer -> do
str <- dataFromServer # either (Buf.toString UTF8) pure
newStr <- resultRef # Ref.modify (_ <> str)
when (newStr # endsWith "\n") do
Socket.endString socket "" UTF8 mempty
liftEffect
$ Socket.onClose socket case _ of
true -> mempty -- should be covered in onError
false -> do
res <- Ref.read resultRef
affCb (Right res)
let
command = writeJSON buildCommand <> "\n"
Socket.onReady socket (void $ Socket.writeString socket command UTF8 mempty)
pure (closeSocketCanceller socket)
mkConnection ∷ Folder -> Int -> Aff PscIdeConnection
mkConnection folder port = do
serverProcess <- startIdeServer folder port
delay (2.0 # Seconds # fromDuration)
socket <- createConnectionTCP port
answersRef <- Ref.new [] # liftEffect
onData socket (parseAndAppend answersRef) # liftEffect
pure $ PscIdeConnection
{ serverProcess, socket, port, folder, answersRef }
-- onClose ???
where
parseAndAppend :: _ -> String -> Effect Unit
parseAndAppend answersRef string =
case readJSON (spy "shit" string) of
Left errs -> log $ intercalate "\n" (errs <#> renderForeignError)
Right more -> Ref.modify_ (_ <> [more]) answersRef
-- testRun ∷ Effect Unit
-- testRun = do
-- socket <- Socket.createConnectionTCP 14189 "localhost" mempty
-- Socket.onReady socket do
-- log "Ready"
-- log $ "Sending " <> writeJSON buildCommand
-- void $ Socket.writeString socket (writeJSON buildCommand <> "\n") UTF8 mempty
-- Socket.onData socket (onData socket)
-- where
-- onData socket = case _ of
-- Left buffer -> do
-- bufferString <- Buffer.toString UTF8 buffer
-- logShow { _message: "Converted to a `String`", bufferString }
-- Right string -> do
-- logShow { _message: "Received some data", string }
liftEffect $ CP.onError serverProcess \e ->
log $ "Server process on port " <> show port <> " got error " <> show e
pure
$ PscIdeConnection
{ serverProcess
, port
, folder
}