diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..657ce1b
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,29 @@
+{
+ "env": {
+ "browser": true
+ },
+ "extends": "eslint:recommended",
+ "rules": {
+ "indent": [
+ "error",
+ 4,
+ {
+ "SwitchCase": 1
+ }
+ ],
+ "linebreak-style": [
+ "error",
+ "unix"
+ ],
+ "quotes": [
+ "error",
+ "double"
+ ],
+ "semi": [
+ "error",
+ "always"
+ ],
+ "no-unused-vars": "warn",
+ "no-console": "warn"
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..60179b4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.gradle/
+.vscode/
+build/
+zip/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f79b5d5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,65 @@
+# Thingworx Monaco Code Editor
+
+ The purpose of this project is to replace the script editor in Thinworx Composer with a better one.
+ The new code editor is based on [Monaco Editor](https://microsoft.github.io/monaco-editor/index.html), the same editor used in [Visual Studio Code](https://code.visualstudio.com/).
+
+## Features
+### Basic code editor features
+
+As it's based on the Visual Studio Code, most basic code editor features are inherited from there. See the [official page](https://code.visualstudio.com/docs/editor/codebasics) for a list of keyboard shortcuts, as well as detailed explanations of other features like:
+#### Multiple selections (multi-cursor)
+
+VS Code supports multiple cursors for fast simultaneous edits. You can add secondary cursors (rendered thinner) with `Alt+Click`. Each cursor operates independently based on the context it sits in. A common way to add more cursors is with `Ctrl+Alt+Down` or `Ctrl+Alt+Up` that insert cursors below or above.
+
+
+
+`Ctrl+D` selects the word at the cursor, or the next occurrence of the current selection.
+
+
+
+> **Tip:** You can also add more cursors with `kb(editor.action.selectHighlights)`, which will add a selection at each occurrence of the current selected text.
+#### Column (box) selection
+
+Hold `Shift` and `Alt` while dragging to do column selection:
+
+
+#### Folding
+
+You can fold regions of source code using the folding icons on the gutter between line numbers and line start. Move the mouse over the gutter to fold and unfold regions. The folding regions are evaluated based on the indentation of lines. A folding region starts when a line has a smaller indent than one or more following lines, and ends when there is a line with the same or smaller indent.
+### IntelliSense
+
+IntelliSense is a general term for a variety of code editing features including: code completion, parameter info, quick info, and member lists. IntelliSense features are sometimes called by other names such as "code completion", "content assist", and "code hinting."
+
+You can trigger IntelliSense in any editor by typing `Ctrl+Space` or by typing a trigger character (such as the dot character (.) in JavaScript).
+
+#### Function autocompletion
+
+All the function definitions are availbe for autocomplete. For example:
+
+
+#### Entity autocompletion
+Metadata about the current entity is used in autocompletion.
+
+
+We also autocomplete entity names for all entity collections, as well as service parameters. The completion also includes the descriptions available.
+
+
+In the case of services that return infotables, or infotable properties with known datashapes, we offer advanced intellisense for the datashape fields
+
+
+### Keyboard Shortcuts
+* Quick actions: Save (CTRL+S), Cancel (CTRL+Q), Test (CTRL+Y), Save and Close (CTRL+ENTER)
+* Diff editor: view changes since you started editing (CTRL+K)
+
+
+### Other Features
+* Thingworx snippets (iterate infotable, create infotable, iterate infotable fields)
+
+* Theme support (F1 -> select "Change Theme" option )
+* Support for SQL services
+
+## Known issues:
+ * Intellisense sometimes fails when multiple editors are open at the same time.
+
+## Download the latest prebuild binary from here:
+ftp://rostorage.ptcnet.ptc.com/SHARE/Petrisor/monaco/MonacoEditor_widget.zip (guest1:guest for auth)
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..06d058b
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,111 @@
+import org.apache.http.entity.mime.MultipartEntity
+import org.apache.http.entity.mime.HttpMultipartMode
+import org.apache.http.entity.mime.content.FileBody
+import groovyx.net.http.HTTPBuilder
+import static groovyx.net.http.Method.*
+import static groovyx.net.http.ContentType.*
+
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath 'org.apache.httpcomponents:httpmime:4.5.2'
+ classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
+ }
+}
+
+// set the properties accordingly
+project.ext {
+ baseDir = projectDir
+ uiDir = "${baseDir}/ui"
+ libDir = "${baseDir}/lib"
+ configDir = "${baseDir}/metadata.xml"
+ entitiesDir = "${baseDir}/Entities"
+ zipDir = "${baseDir}/zip"
+ packageVendor = "ThingWorx Customer Service"
+ thingworxServerRoot = "http://localhost:8011"
+ thingworxUser = "Administrator"
+ thingworxPass = "admin"
+}
+
+task increaseVersionNumber() {
+ doLast {
+ def file = "${baseDir}/metadata.xml"
+ def parser = new groovy.util.XmlParser(false,true);
+ def xml = parser.parse(file)
+
+ def currentVersion = xml.ExtensionPackages.ExtensionPackage.@packageVersion[0];
+
+ def versionComponents = currentVersion.split('\\.');
+
+ def minorVersion = ++Integer.parseInt(versionComponents[versionComponents.length - 1]);
+
+ versionComponents[versionComponents.length - 1] = String.valueOf(minorVersion);
+
+ xml.ExtensionPackages.ExtensionPackage.@packageVersion = String.join('.', versionComponents);
+ // xml.ExtensionPackages.ExtensionPackage.get(0).attributes().put('packageVersion', String.join(',', versionComponents));
+
+ println 'Updated to version ' + String.join('.', versionComponents)
+ println xml.ExtensionPackages.ExtensionPackage.@packageVersion[0];
+
+ PrintWriter pw = new PrintWriter(new File(file))
+ pw.write(groovy.xml.XmlUtil.serialize(xml))
+ pw.close()
+
+ }
+}
+
+task prepPackage(dependsOn: increaseVersionNumber) {
+ doLast {
+ delete project.ext.zipDir
+ // add the configuration
+ copy {
+ from "${project.ext.configDir}"
+ into "${buildDir}/zip/"
+ }
+ // add the ui files
+ copy {
+ from uiDir
+ into "${buildDir}/zip/ui/"
+ }
+ // add the entities
+ copy {
+ from entitiesDir
+ into "${buildDir}/zip/Entities/"
+ }
+ }
+}
+
+task packageExtension(type: Zip, dependsOn: prepPackage, overwrite: true) {
+ archiveName = "${project.name}.zip"
+ destinationDir = new File(project.ext.zipDir)
+ from "${buildDir}/zip/"
+}
+
+task upload(dependsOn: packageExtension) {
+ doLast{
+ def http = new HTTPBuilder("${thingworxServerRoot}/Thingworx/")
+ http.auth.basic thingworxUser, thingworxPass
+
+ def extZip = file("${baseDir}/zip/${project.name}.zip")
+
+ http.request(POST) { req ->
+ uri.path = 'ExtensionPackageUploader'
+ uri.query = ['purpose': 'import']
+ headers."X-XSRF-TOKEN" = "TWX-XSRF-TOKEN-VALUE"
+ requestContentType = 'multipart/form-data'
+ MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE)
+ entity.addPart('file', new FileBody(extZip))
+ req.setEntity(entity)
+ response.success = {resp ->
+ println("Upload successful!")
+ }
+
+ response.failure = {resp ->
+ println(resp.statusLine)
+ throw new StopExecutionException("Thingworx upload failed! See server response above")
+ }
+ }
+ }
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..9594cf1
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d2226f6
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Mar 02 11:34:17 EET 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4453cce
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/metadata.xml b/metadata.xml
new file mode 100644
index 0000000..a800a6b
--- /dev/null
+++ b/metadata.xml
@@ -0,0 +1,22 @@
+
+