{
  "swagger" : "2.0",
  "info" : {
    "description" : "Restful API for Webida clients to use server's data & features",
    "version" : "0.7.1",
    "title" : "Webida Restful API",
    "license" : {
      "name" : "Apache 2.0",
      "url" : "http://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "basePath" : "/api",
  "consumes" : [ "application/json" ],
  "produces" : [ "application/json", "application/octet-stream" ],
  "paths" : {
    "/aliass/{aliasId}" : {
      "get" : {
        "tags" : [ "alias" ],
        "description" : "get alias objects. set aliasId to '*' to find all aliases in some workspace. If alias id is given, only 0 or 1 matched alias object will be returned, ignoring workspaceId and srcPath. To get an alias object of some wfs path, set srcPath value to some path, and to find all aliases in a workspace, set it to '*' (empty value is not allowed by definition)",
        "operationId" : "findAliases",
        "parameters" : [ {
          "name" : "aliasId",
          "in" : "path",
          "description" : "url path fragment alias id. should have no '/' as well as any 'unsafe' chars for url path.  especially, '*' is reserved for finding operations or some other special case.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "webida workspace id in query part",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "srcPath",
          "in" : "query",
          "description" : "source data path of some operations, without have heading /",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "alias list",
            "schema" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/definitions/Alias"
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/alias/findAliasesjs"
      },
      "put" : {
        "tags" : [ "alias" ],
        "description" : "create, or update an alias.",
        "operationId" : "putAlias",
        "parameters" : [ {
          "name" : "aliasId",
          "in" : "path",
          "description" : "url path fragment alias id. should have no '/' as well as any 'unsafe' chars for url path.  especially, '*' is reserved for finding operations or some other special case.",
          "required" : true,
          "type" : "string"
        }, {
          "in" : "body",
          "name" : "body",
          "description" : "alias object to write. should have same id to aliasId parameter.",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/Alias"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK.",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/alias/putAlias.js"
      },
      "delete" : {
        "tags" : [ "alias" ],
        "description" : "remove alias. targeting rule is same to findAliases() operation.",
        "operationId" : "removeAliases",
        "parameters" : [ {
          "name" : "aliasId",
          "in" : "path",
          "description" : "url path fragment alias id. should have no '/' as well as any 'unsafe' chars for url path.  especially, '*' is reserved for finding operations or some other special case.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "webida workspace id in query part",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "srcPath",
          "in" : "query",
          "description" : "source data path of some operations, without have heading /",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK.",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/alias/removeAlias.js"
      }
    },
    "/auth/info" : {
      "get" : {
        "tags" : [ "auth" ],
        "description" : "Gets user information of that can be identified with current access token. Implementations should provide a more restful api based on domain data model, not extending this operation. (e.g. GET,PUT and DELETE on /Users/{userId} to read, update and delete user)\n",
        "operationId" : "getInfo",
        "parameters" : [ ],
        "responses" : {
          "200" : {
            "description" : "user information",
            "schema" : {
              "$ref" : "#/definitions/User"
            }
          },
          "401" : {
            "description" : "auth failed",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/auth/getInfo.js"
      }
    },
    "/auth/login" : {
      "post" : {
        "tags" : [ "auth" ],
        "description" : "A \"VERY\" basic authentication, required to use webida-simple-auth security scheme.\n\nService / Product implementations who need better security, should override this operation or add their own login api or some other specs like OAuth2. Simple auth is not suitable for large-sacle, multi-tennant service, for the scheme assumes a single, trusted user only.\n\nLogging-in with master token, the generated access token inherits all restriction from it. On the other hand, normal log-in with login id & password creates an unrestricted access token, with reasonably short expiration time.\n\nEvery client should spawn another access token with issueToken API before current access token expires, inheriting session id from current token. To save remote access info, client should create a (restricted but long-ttl) master token to start IDE from remote. The remote client should not use the unrestricted acccess token from login to use any other perpose than finding available workspaces, and should not refresh the token. (Let user log-in again)\n\nLogin API does not force any encryption. Server should provide secure transport channel, usually https, to provide remote access, always.\n",
        "operationId" : "login",
        "parameters" : [ {
          "in" : "body",
          "name" : "body",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/Credential"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "login success",
            "schema" : {
              "$ref" : "#/definitions/Token"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "x-handler" : "handlers/auth/login.js"
      }
    },
    "/auth/token" : {
      "post" : {
        "tags" : [ "auth" ],
        "description" : "Creates new token from current access token, inheriting workspace id & session id. The duration of generated token is not (and should not be) parameterizable. Server should set proper duration, respecting \"reconnect\" period of socket.io clients. Remember that most of socket.io client implementations (including official js client) do not provide any ways to change connection parameters (header or query) while reconnecting to server.\n\nLike login API, this endpoint does not provide any encryption. Server should not set any data to harm security in the token & should provide some signinig/encryption mechanism to protect token. Simple JSON Web Token with HMAC-SHA will do.\n",
        "operationId" : "issueToken",
        "parameters" : [ {
          "name" : "type",
          "in" : "query",
          "required" : true,
          "type" : "string",
          "enum" : [ "MASTER", "ACCESS" ]
        }, {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "Clients to save some remote access info should issue a MASTER type token restricted to specific workspace id.",
          "required" : false,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "new token generated",
            "schema" : {
              "$ref" : "#/definitions/Token"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/auth/issueToken.js"
      }
    },
    "/remotes" : {
      "get" : {
        "tags" : [ "remotes" ],
        "description" : "Get all access informations See RemoteWorkspaceAccess definition for details (no fancy find / search feature yet)",
        "operationId" : "findRemoteAccesses",
        "parameters" : [ ],
        "responses" : {
          "200" : {
            "description" : "Array of remote workspaces",
            "schema" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/definitions/RemoteAccess"
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/remotes/findRemoteAccesses.js"
      },
      "put" : {
        "tags" : [ "remotes" ],
        "description" : "Ceates or updates a remote workspace access information",
        "operationId" : "putRemoteAccess",
        "parameters" : [ {
          "in" : "body",
          "name" : "body",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/RemoteAccess"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ]
      },
      "delete" : {
        "tags" : [ "remotes" ],
        "description" : "Removes remote workspace access information",
        "operationId" : "removeRemoteAccess",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "workspace Id of remote workspace",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "removed remote workspace access info",
            "schema" : {
              "$ref" : "#/definitions/RemoteAccess"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ]
      }
    },
    "/sessions/{sessionId}" : {
      "get" : {
        "tags" : [ "session" ],
        "description" : "Finds webida sessions established to server. if session id is given, matched session info will be returned and workspace id  parameter will be ignored. To find all sessions of some workspace, set session id to '*' and specify workspace id.\n\nThis operation requires proper accsss rights.\n  1) To find all sessions, an unrestricted token is required.\n  2) To find some workspace sesions, token should have proper access right on the workspace.\n",
        "operationId" : "findSessions",
        "parameters" : [ {
          "name" : "sessionId",
          "in" : "path",
          "description" : "webida session id (usually different from socket id from sock.io)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "webida workspace id in query part",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "array of sessions",
            "schema" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/definitions/Session"
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/session/findSessions.js"
      },
      "delete" : {
        "tags" : [ "session" ],
        "description" : "Closes session with timeout. Targets are selected by same rule to findSessions() op. While targeting multiple sessions, this operation requires same access rights with findSessions(). Closing a single session requires 'same session id' or 'unrestricted workspace acceess'.",
        "operationId" : "closeSessions",
        "parameters" : [ {
          "name" : "sessionId",
          "in" : "path",
          "description" : "webida session id (usually different from socket id from sock.io)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "workspaceId",
          "in" : "query",
          "description" : "webida workspace id in query part",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "closeAfter",
          "in" : "query",
          "description" : "Waiting time before actual closing, to let client save files and prevent reconnecting.\n",
          "required" : true,
          "type" : "integer"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK.",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/session/closeSession.js"
      }
    },
    "/wfs/{wfsId}/any/{wfsPath}" : {
      "get" : {
        "tags" : [ "wfs" ],
        "description" : "Get stats of given path. (stat() returns stats object in node and POSIX system). This API should be called only when stats of some file system path is stale for unknown reason (e.g. losting change events). Use dirTree operation and session events to detect stats, if possible. This API can be used to check a path is valid, existing one, but it's not recommended to check existence of individual paths by API. Clients should use dirTree and session events to synchorize some in-app file system with webida file system.",
        "operationId" : "stat",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "dummyFor404",
          "in" : "query",
          "description" : "When true, operation ignore ENOENT error and returns DUMMY stats object instead of 404 error.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "stats object.",
            "schema" : {
              "$ref" : "#/definitions/Stats"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/stat.js"
      },
      "post" : {
        "tags" : [ "wfs" ],
        "description" : "Moves source resource to given path. Follows same rule to deal with existing path. So, this operation works like rename rather than mv. Just like copy(), this operations creates paraent dirs if needed and does not roll-back. Symbolic link and timestamp values will be moved without touching.",
        "operationId" : "move",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "srcPath",
          "in" : "query",
          "description" : "source data path of some operations, without have heading /",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "noOverwrite",
          "in" : "query",
          "description" : "does not overwrites any existing file while copying or moving",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/move.js"
      },
      "put" : {
        "tags" : [ "wfs" ],
        "description" : "Creates a copy of source to given path. Unlike cp command, wfsPath always denotes an exact path of the resource to be created.\n\nSo, When destination path exists already,\n  1) copying file to file : follows noOverwrite flag. (does not return error)\n  2) copying file to dir : returns 409 error\n  3) copying dir to file : returns 409 error\n  4) copying dir to dir : merge srcPath/* to wfsPath, following noOverwite flag.\n\nThis operation creates the parents dir of destination path always, and does not roll-back the creation when operation failed. So, clients should roll-back if needed.\n",
        "operationId" : "copy",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "srcPath",
          "in" : "query",
          "description" : "source data path of some operations, without have heading /",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "noOverwrite",
          "in" : "query",
          "description" : "does not overwrites any existing file while copying or moving",
          "required" : false,
          "type" : "boolean",
          "default" : false
        }, {
          "name" : "followSymbolicLinks",
          "in" : "query",
          "description" : "dereference symlinks in source.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        }, {
          "name" : "preserveTimestamps",
          "in" : "query",
          "description" : "keep mtime/atime of source file(s) in destination.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/copy.js"
      },
      "delete" : {
        "tags" : [ "wfs" ],
        "description" : "delete file or directory",
        "operationId" : "remove",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "noRecursive",
          "in" : "query",
          "description" : "if set, deleting non-empty directory will return 409 error.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/remove.js"
      }
    },
    "/wfs/{wfsId}/dir/{wfsPath}" : {
      "get" : {
        "tags" : [ "wfs" ],
        "description" : "Returns a directory tree of given path, the errors while building sub-tree will be ignored and result will not include the path that has errors. Client may have to stat some suspicious paths manually, if listing is not complete.",
        "operationId" : "dirTree",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "maxDepth",
          "in" : "query",
          "description" : "Maximum depth of tree. -1 to build a full tree, 0 to stat, 1 to plain list.",
          "required" : true,
          "type" : "integer"
        } ],
        "responses" : {
          "200" : {
            "description" : "A DirEntry, root of the tree, for given path and depth.",
            "schema" : {
              "$ref" : "#/definitions/DirEntry"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/dirTree.js"
      },
      "put" : {
        "tags" : [ "wfs" ],
        "description" : "Creates a directory at the path. When the path is found to be a directory, this api does not return error and does not care it's empty or not. Always creates parent directories if needed.",
        "operationId" : "createDir",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/createDir.js"
      }
    },
    "/wfs/{wfsId}/file/{wfsPath}" : {
      "get" : {
        "tags" : [ "wfs" ],
        "description" : "read file data on path",
        "operationId" : "readFile",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "If-Modified-Since",
          "in" : "header",
          "description" : "Usual if-modified-since header. So, should be RFC-1123(same to RFC-822) format, not RFC-3339 (same to ISO-8601).",
          "required" : false,
          "type" : "string"
        }, {
          "name" : "If-None-Match",
          "in" : "header",
          "description" : "Usual if-non-match header, allowing only 1 e-tag value from previous readFile response. The value of this header can have weak prefix and quotation chars. This header value precedes the value of if-modified-since header. Server should ignore if-modified-since header when if-none-match header exists, as RFC-2616.",
          "required" : false,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "File contents. Content-Type is application/octet-stream or follows file name extension.",
            "schema" : {
              "type" : "file"
            },
            "headers" : {
              "ETag" : {
                "type" : "string",
                "description" : "usual etag header in HTTP 1.1"
              },
              "Last-Modified" : {
                "type" : "integer",
                "description" : "usual last-modified header, in RFC-1123 format."
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/readFile.js"
      },
      "put" : {
        "tags" : [ "wfs" ],
        "description" : "Creates / updates file with body data. Server should write the file in atomic manner nd should not write down request body into final destination path directly. In other words,  wheather writeFile() succeeds or not, the contents of the file should not be corrupted nor half-written.",
        "operationId" : "writeFile",
        "consumes" : [ "multipart/form-data" ],
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPath",
          "in" : "path",
          "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
          "required" : true,
          "type" : "string",
          "pattern" : ".*"
        }, {
          "name" : "ensureParents",
          "in" : "query",
          "description" : "A flag to create all parent directories to create file or dir, like mkdir -p. This parameter does not create entire path, but ensures 'parent directory' of the wfsPath parameter",
          "required" : false,
          "type" : "boolean",
          "default" : false
        }, {
          "name" : "data",
          "in" : "formData",
          "description" : "file contents to write.",
          "required" : true,
          "type" : "file"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/writeFile.js"
      }
    },
    "/wfs/{wfsId}/ops/replace" : {
      "post" : {
        "tags" : [ "wfs" ],
        "description" : "replace file contents with regex matching",
        "operationId" : "replace",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPathList",
          "in" : "query",
          "description" : "array of wfsPath, without heading /.",
          "required" : true,
          "type" : "array",
          "items" : {
            "type" : "string"
          },
          "collectionFormat" : "multi"
        }, {
          "name" : "pattern",
          "in" : "query",
          "description" : "regex pattern to match in search or replace. In replace operation, pattern should be same to the parttern in search operation",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "ignoreCase",
          "in" : "query",
          "description" : "regex matching option to ignore case. In replace operation, this option should be same to one used in search operation",
          "required" : false,
          "type" : "boolean",
          "default" : false
        }, {
          "name" : "replaceTo",
          "in" : "query",
          "description" : "string to replace with",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "done",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/replace.js"
      }
    },
    "/wfs/{wfsId}/ops/search" : {
      "get" : {
        "tags" : [ "wfs" ],
        "description" : "search files in some path, with given pattern",
        "operationId" : "search",
        "parameters" : [ {
          "name" : "wfsId",
          "in" : "path",
          "description" : "webida file system id (same to workspace id) to access.",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "wfsPathList",
          "in" : "query",
          "description" : "array of wfsPath, without heading /.",
          "required" : true,
          "type" : "array",
          "items" : {
            "type" : "string"
          },
          "collectionFormat" : "multi"
        }, {
          "name" : "pattern",
          "in" : "query",
          "description" : "regex pattern to match in search or replace. In replace operation, pattern should be same to the parttern in search operation",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "ignoreCase",
          "in" : "query",
          "description" : "regex matching option to ignore case. In replace operation, this option should be same to one used in search operation",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "search",
            "schema" : {
              "type" : "object",
              "additionalProperties" : {
                "type" : "array",
                "items" : {
                  "$ref" : "#/definitions/Match"
                }
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/wfs/search.js"
      }
    },
    "/workspaces/{workspaceId}" : {
      "get" : {
        "tags" : [ "workspace" ],
        "description" : "Finds workspaces with given id or parameters. if workspaceId = '*', all workspaces in server are returned. No empty workspace id is allowed for it's a path parameter. When workspaceId is not '*', server should return empty array, not 404 Not Found error.\n",
        "operationId" : "findWorkspaces",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "includeEphemeral",
          "in" : "query",
          "description" : "flag to include ephemeral workspaces or not, when workspaceId is '*'. if workspace id is specified, then this flag will be ignored.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        } ],
        "responses" : {
          "200" : {
            "description" : "array of local workspaces found",
            "schema" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/definitions/Workspace"
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/workspace/findWorkspaces.js"
      },
      "post" : {
        "tags" : [ "workspace" ],
        "description" : "Creates a new workspace with given local path. Requires an unrestricted access token. the workspace id parameter is ignored and will be replaced by new, unique value by server. it's recommended to set the value to simple, bogus one, like '*' or '-' (since it's path  parameter, empty value is not allowed. excludedPath property is initialized with  default values (usually .git/, .node_modules/, ./bower_components) by server.\n\nNeeds an unrestricted access token.\n",
        "operationId" : "createWorkspace",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "localPath",
          "in" : "query",
          "description" : "a real, local path of the system (not unixified)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "name",
          "in" : "query",
          "description" : "workspace name property",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "description",
          "in" : "query",
          "description" : "workspace name property",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "newly created local workspace",
            "schema" : {
              "$ref" : "#/definitions/Workspace"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/workspace/createWorkspace.js"
      },
      "put" : {
        "tags" : [ "workspace" ],
        "description" : "Updates workspace. Some protected properties will not be changed by this op. If server cannot apply changed properties before returning workspace, such properties should not be updated with this operation. Clients should not rely on request body for further works, and should always check response to see what's changed actually.\n\nRequires proper access rights.\n",
        "operationId" : "updateWorkspace",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "in" : "body",
          "name" : "body",
          "description" : "workspace object that contains updates",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/Workspace"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "updated Workspace object. some properties may different from input.",
            "schema" : {
              "$ref" : "#/definitions/Workspace"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/workspace/updateWorkspace.js"
      },
      "delete" : {
        "tags" : [ "workspace" ],
        "description" : "Removes a workspace. If no sessions are connected, this api 'works' before returning result. if some sesions are, workspace will be removed when\n  1) all sessions are closed for request (will be notified by server)\n  2) exceeded time limit value in closeAfter parameter\n  3) server stops after accepting remove request\nand willBeRemoved value is set. So, client may 'find' the workspace to be removed after calling this operation.\n\nRequires \"unrestricted\" access rights.\n",
        "operationId" : "removeWorkspace",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "closeAfter",
          "in" : "query",
          "description" : "Time in seconds to wait for all sessions save & close their data.",
          "required" : false,
          "type" : "integer",
          "default" : 0
        }, {
          "name" : "removeDir",
          "in" : "query",
          "description" : "flag to delete directory in real file system when removing workspace. Usually, this value should not be set true for user can handle directory persistence manually. Clients need to get explicit confirmation from user.",
          "required" : false,
          "type" : "boolean"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK. removed",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/workspace/removeWorkspace.js"
      }
    },
    "/workspaces/{workspaceId}/procs" : {
      "get" : {
        "tags" : [ "workspace" ],
        "description" : "Gets process info on this workspace. To find all child processes, set id to '*'. This op does not returns error when no procs found but empty result array. Child process can be created by exec operation and by some other means.\n",
        "operationId" : "findProcs",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "execId",
          "in" : "query",
          "description" : "the id from execution request (different from pid!)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "includeForeground",
          "in" : "query",
          "description" : "flag to include 'foreground processes' in result. foreground processes can be created by and only by exec operation without async opetion. normally, this flag will not be used except debugging or diagnostics. foreground processes has 'foreground' property, set to true, always.",
          "required" : false,
          "type" : "boolean"
        } ],
        "responses" : {
          "200" : {
            "description" : "the child processes found. result does not include 'exited' procs.",
            "schema" : {
              "type" : "array",
              "items" : {
                "$ref" : "#/definitions/ChildProcess"
              }
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "x-handler" : "handlers/workspace/findProcs.js"
      },
      "post" : {
        "tags" : [ "workspace" ],
        "description" : "Executes a shell command (foreground process) or spawns a background process on this workspace. Requires proper access rights.",
        "operationId" : "execute",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "async",
          "in" : "query",
          "description" : "Spawns a background process for given command and returns the created child proc info. Actual output (stream of message) will be delivered to web socket channel, using execution id.",
          "required" : false,
          "type" : "boolean",
          "default" : false
        }, {
          "in" : "body",
          "name" : "body",
          "description" : "the process to be executed or spawned.",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/Execution"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "Execution result with all captured standard ouput and error. If execution is completed without error, the error property in result object should be a falsy value. If some error has happened, then it will be an error message, without stack. A plain RestError will be returned with 4xx or 5xx error code (e.g. insufficient/invalid arguments) when it's found before creating process. So, clients should handle the 'invocation error' and 'errors from the command' differently.",
            "schema" : {
              "$ref" : "#/definitions/ExecutionResult"
            }
          },
          "201" : {
            "description" : "Spawned process infomation created by async execution. If server could not create a child process, error event will be sent to client via socket channel but RestError will not be ruturned from this operation. When a client has got 'error' event from the socket channel, the client should close the channel wheather it receives subsequent exit event or not (with some proper timeout if needed). Server should not send the errors related to 'killing' child processes.",
            "schema" : {
              "$ref" : "#/definitions/ChildProcess"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ],
        "x-handler" : "handlers/workspace/execute.js"
      },
      "delete" : {
        "tags" : [ "workspace" ],
        "description" : "Cancels executions, killing the spawned processes. To terminate all spawned processes, set execId to '*'. Requires proper access rights. Since killing a process usually takes a little bit long time, this api does not returns actual result but works in async manner. (So, client should listen to web socket channels for the processes). This operation Requires same access rights to execute operation. Server should reject to cancel any forground processes and processes is being killed or has exited already.",
        "operationId" : "cancel",
        "parameters" : [ {
          "name" : "workspaceId",
          "in" : "path",
          "description" : "webida workspace id (usually same to file system id, wfsId)",
          "required" : true,
          "type" : "string"
        }, {
          "name" : "execId",
          "in" : "query",
          "description" : "the id from execution request (different from pid!)",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/RestOK"
            }
          },
          "default" : {
            "description" : "Error",
            "schema" : {
              "$ref" : "#/definitions/RestError"
            }
          }
        },
        "security" : [ {
          "webida-simple-auth" : [ ]
        } ]
      }
    }
  },
  "securityDefinitions" : {
    "webida-simple-auth" : {
      "type" : "apiKey",
      "name" : "Authorization",
      "in" : "header",
      "x-authorize" : "webida-simple-auth.js"
    }
  },
  "definitions" : {
    "RestOK" : {
      "type" : "object",
      "properties" : {
        "message" : {
          "type" : "string",
          "description" : "additional text from server. Clients may use this value to debugging or logging, but should not rely on the value of this property, for server can omit to set message for performance."
        }
      }
    },
    "RestError" : {
      "type" : "object",
      "required" : [ "message" ],
      "properties" : {
        "code" : {
          "type" : "string"
        },
        "message" : {
          "type" : "string"
        },
        "errno" : {
          "type" : "string",
          "description" : "errno code for some internal errors in server. Since service implementation can use many different platform api & runtime, client should avoid relying on errno code. If server provides errno code, it should be translated into human readable string like ENOENT or ENOMEM, not pure integer value."
        },
        "stack" : {
          "type" : "string",
          "description" : "stack trace for this error. Server should not include stack trace in production and client should not print or show this stack to user. This property should be used in 'developer mode' only, for debugging."
        }
      },
      "description" : "Error object with code and message. code is bound to status code, but not always same to standard HTTP status text. For example, some 409 error may have code \"Invalid Argument\" instead of \"Conflic\". So, Client should read message property to know what happend exactly, when an error is returned from server. And, some 500 errors can have system errno instead of useless \"internal\". Like other errors, details are hidden in message."
    },
    "Token" : {
      "type" : "object",
      "required" : [ "expiresAt", "issuedAt", "text", "tokenType" ],
      "properties" : {
        "text" : {
          "type" : "string",
          "description" : "actual token text that should be shipped in header or query"
        },
        "tokenType" : {
          "type" : "string",
          "description" : "MASTER : used to create an access token from clients, without login credential\nACCESS : protects api access. should be unique for each ide session\n\nNote that here\"s no REFRESH token, nor LOGIN token. The login api will create unrestricted access token & master token pair. Desktop app has a side-way to create an unrestricted master token before starting IDE instances.\n",
          "enum" : [ "MASTER", "ACCESS" ]
        },
        "expiresAt" : {
          "type" : "string",
          "format" : "date-time"
        },
        "issuedAt" : {
          "type" : "string",
          "format" : "date-time"
        },
        "sessionId" : {
          "type" : "string",
          "description" : "mandatory for ACCESS token, identifying client instance"
        },
        "workspaceId" : {
          "type" : "string",
          "description" : "If truthy, access rights are restricted to specified workspace only."
        }
      },
      "description" : "a json webtoken and accessible data"
    },
    "Credential" : {
      "type" : "object",
      "required" : [ "loginId", "loginPassword" ],
      "properties" : {
        "loginId" : {
          "type" : "string"
        },
        "loginPassword" : {
          "type" : "string"
        },
        "masterToken" : {
          "type" : "string",
          "description" : "A master token is issued when user wants to access webida api without id/password from remote or local desktop app. When masterToken is set, client should put some bogus id/password for login, non-empty. the values can be used to identify client type."
        }
      },
      "description" : "User credential to login. Use https to protect credential. master token can replace actual id/password pair."
    },
    "User" : {
      "type" : "object",
      "properties" : {
        "id" : {
          "type" : "string",
          "description" : "unique id per user (email is also unique)"
        },
        "email" : {
          "type" : "string"
        },
        "name" : {
          "type" : "string"
        }
      },
      "description" : "Any services/products should define some admin apis to manage users in the system and expose what should be exposed to client app. So, no properties are mandatory. Currently, the properties are defined for compatiblity with legacy clients."
    },
    "Stats" : {
      "type" : "object",
      "required" : [ "birthtime", "mode", "mtime", "nlink", "size", "type" ],
      "properties" : {
        "type" : {
          "type" : "string",
          "description" : "All types except 'DUMMY' come from fs.Stats is*** methods results. (e.g. if isFile() is true, then type will be 'FILE') If type is not decidable by the methods, default type is 'FILE', for everything on the file system is basically a file. 'DUMMY' type means that some object 'does not exist for now'. Client may use 'DUMMY' type to mark something dangling, not written or created on real file system yet but visible to user.",
          "enum" : [ "FILE", "DIRECTORY", "BLOCK_DEVICE", "CHARACTER_DEVICE", "LINK", "FIFO", "SOCKET", "DUMMY" ]
        },
        "birthtime" : {
          "type" : "string",
          "format" : "date-time"
        },
        "mtime" : {
          "type" : "string",
          "format" : "date-time"
        },
        "mode" : {
          "type" : "integer"
        },
        "size" : {
          "type" : "integer"
        },
        "nlink" : {
          "type" : "integer"
        }
      },
      "description" : "simplified/augmented fs.Stats class - see node.js doc for all properties"
    },
    "DirEntry" : {
      "type" : "object",
      "required" : [ "children", "name", "stats" ],
      "properties" : {
        "name" : {
          "type" : "string"
        },
        "stats" : {
          "$ref" : "#/definitions/Stats"
        },
        "children" : {
          "type" : "array",
          "items" : {
            "$ref" : "#/definitions/DirEntry"
          }
        }
      },
      "description" : "a directory entry (file or directory) with children that represents a (sub) tree"
    },
    "Match" : {
      "type" : "object",
      "required" : [ "line", "text" ],
      "properties" : {
        "line" : {
          "type" : "integer"
        },
        "text" : {
          "type" : "string"
        }
      },
      "description" : "search result for a file"
    },
    "Workspace" : {
      "type" : "object",
      "required" : [ "createdAt", "description", "excludedPaths", "id", "name", "offlineCachePaths", "workspacePath" ],
      "properties" : {
        "id" : {
          "type" : "string",
          "description" : "the id of a workspace. usually same to file system id"
        },
        "name" : {
          "type" : "string",
          "description" : "display text of this workspace for UI"
        },
        "description" : {
          "type" : "string",
          "description" : "human readable description on this workspace"
        },
        "createdAt" : {
          "type" : "string",
          "format" : "date-time",
          "description" : "the time when this workspace is created (registered from local file system)"
        },
        "accessedAt" : {
          "type" : "string",
          "format" : "date-time",
          "description" : "the time when the last session on this workspace was made. (optional)"
        },
        "workspacePath" : {
          "type" : "string",
          "description" : "absolute path of this workspace in server. Server may not expose this property to some untrusted clients."
        },
        "ephemeral" : {
          "type" : "boolean",
          "description" : "If set, workspace is ephemeral - Server will drop registration when it stops working. Ususally, side-loaded workspace via desktop app is ephemeral. Client with proper access right can flip this flag to declare the workspace should be persist, after rebooting.\n"
        },
        "excludedPaths" : {
          "type" : "array",
          "description" : "Ignore patterns to exclude from watch service and search-and-replace operations.\n\nPattern follows '.gitignore' syntax, 1 item per line. It should work as a .gitignore file in the workspace directory. Server should remove all comment items (any item that begins with '#') and blank items. Escaping with '\\' char for the beginning '!' and ending white-spaces shoule be supported, too.\n\nTo exclude a directory, client may have to put '/' at the end of the item to exclude everything underneath it. When a dir path is excluded with 'ending /', watch service  may not deliver unlinkDir/addDir events for the path and client should manually check the existence or stats.\n",
          "items" : {
            "type" : "string"
          }
        },
        "offlineCachePaths" : {
          "type" : "array",
          "description" : "Any paths (including excluded paths) to be cached in remote clients.\n\nBrowser client should respect offline cache paths always. Desktop-app client may not use off-line cache for local (embedded) server but shall use cache for any remote servers, even for same host. All caches should be partitioned with workspace id, globally unique value through time and space.\n\nClient should pre-fetch the contents of offline cache paths when it start IDE sessions on a workspace to use for off-line state. When client goes to off-line, after losing connection to server, it can use cached data as reply of some WFS operations and can write some data to cache to save workspace data & metadata. The changes should be persistent on client side safely. C\n\nWhen a client recovers connectivity to server, it should check the stats of files and  dirs to upload if it has got some changes in offline state. If server has more recents contents, client should drop chagnes and refill the cache with fresher data. Client may have some 'time-tolerance' to accept server's data is fresher than client's, smaller than serveral seconds. If server has more recent contents, client should drop the changes and refill the cache with fresher data. If not, client should replay the changes 1 by 1.\n\nSame protocol should be applied when client application starts with some 'unuploaded change' evertime. That means, client should save 'change history' with 'changed data' too, to process it later, when starting app again in normal condition.\n\nAll Clients should not replay any 'delete' operations while replaying changes on client's cache, to protect from more serious problems with skewed timer or unexpected behaviors. And, of course, client should not rely on cached data while connection state is healthy.\n",
          "items" : {
            "type" : "string"
          }
        }
      },
      "description" : "A workspace in server"
    },
    "RemoteAccess" : {
      "type" : "object",
      "required" : [ "masterToken", "name", "serverUrl", "workspaceId" ],
      "properties" : {
        "name" : {
          "type" : "string",
          "description" : "display text of remote workspace. can be different from original name."
        },
        "serverUrl" : {
          "type" : "string",
          "description" : "the url of remote server. Should have no path/query parameters, even \"/\" in path."
        },
        "workspaceId" : {
          "type" : "string",
          "description" : "the id of remote workspace, read from remote server"
        },
        "workspacePath" : {
          "type" : "string",
          "description" : "Full path of remote workspace, read from remote server. this property will be removed when clients are able to work without \"named root directory\" in workspace fs tree."
        },
        "masterToken" : {
          "type" : "string",
          "description" : "master token to access service, issued from remote server"
        }
      },
      "description" : "Access information of remote workspace in remote server"
    },
    "Session" : {
      "type" : "object",
      "required" : [ "clientAddress", "connectedAt", "id", "name", "state" ],
      "properties" : {
        "id" : {
          "type" : "string",
          "description" : "the id of a session. usually same to socket id."
        },
        "name" : {
          "type" : "string",
          "description" : "human readable name, usually derived from workspace name."
        },
        "state" : {
          "type" : "string",
          "description" : "NORMAL = connected, normally working.\nCLOSING = server requested client to disconnect. Connection will be closed soon.\nTERMINATED = disconnected. server will remove this session from registry ASAP.\n",
          "enum" : [ "NORMAL", "CLOSING", "TERMINATED" ]
        },
        "workspaceId" : {
          "type" : "string",
          "description" : "the id of workspace that this sessions is working on. If falsy, then this session is not belonged to any workpsace. Usually, dashboard / monitoring app will create a session without workspace id."
        },
        "clientAddress" : {
          "type" : "string",
          "description" : "the peer address of session connection. not always"
        },
        "connectedAt" : {
          "type" : "string",
          "format" : "date-time",
          "description" : "the time when socket connection is established"
        },
        "willCloseAt" : {
          "type" : "string",
          "format" : "date-time",
          "description" : "when state becomes CLOSING, server sets this time as deadline."
        }
      },
      "description" : "an application session per ide instance. bound to access token"
    },
    "Execution" : {
      "type" : "object",
      "required" : [ "args", "command" ],
      "properties" : {
        "id" : {
          "type" : "string",
          "description" : "unique identifier of execution, to demux response stream or cancel request. Server should reject an async exec request without id."
        },
        "command" : {
          "type" : "string",
          "description" : "The command to run. Server may not support pipe, redirection nor shell variables in command. Client should not assume any specific shell provider in server and should not using the shell features for portability.\nIn windows system with unix sh (e.g. cygwin or mingw from git-for-windows), usually a shell script in PATH may work as command but probably allocates console window while running the command. Implementations (both of server & client) should avoid allocating any  console instances while running services, for costs and UX, and should provide a portable way to invoke commands. Shortly, when a service/product embeds some .sh file to run, it must provide .cmd file doing same thing, always."
        },
        "args" : {
          "type" : "array",
          "description" : "The arguments array. Server can join this args to command with proper white-space char, when underlying platform api (e.g. child_process#exec() in node.js) does not support additional arguments vector. It's recommended to use args vector than making a long command, to find & see child processes easily with this Rest API. So, args should be always provided, even empty array.\n\nWhen some arguments has a white space (e.g. C:\\Program Files\\webida), usually invoking command understands escaping or quotation, but not always. Client should add proper escaping or quotation chars to args vector manually. server should not change any command or arguments.\n",
          "items" : {
            "type" : "string"
          }
        },
        "cwd" : {
          "type" : "string",
          "description" : "Current working directory of spawned process, relative to workspace root. If abscent, cwd will be the workspace directory. Does not accept any evaluatable form like $HOME, %USERPROFILE%. path should be unixified. Server may reject an absolute cwd path."
        },
        "timeout" : {
          "type" : "integer",
          "description" : "The value which In 'miliseconds' the maximum amount of time the child is allowed to run. (not idle time of stdout / stderr stream) for sync exec. Server should not apply default value for async exec, when omitted. The child process spawned by async       execution should be killed when 1) server goes down 2) process exits by self 3) cancel operation is invoked"
        },
        "maxBuffer" : {
          "type" : "integer",
          "description" : "Largest amount of data (in bytes) allowed on stdout or stderr for sync exec. Server should not apply this limit to async execution. In sync exec, server may kill a child process that has exceeded limit. default value is 512KB, large enough."
        }
      },
      "description" : "execution request, simlilar to node.js exec()/spawn(). see node.js documentation for  details of each properties. some properties are not configurable for portability\n * encoding : fixed to utf-8\n * shell : fixed to system defaults. (so, cmd.exe will be invoked in Windows OS, not sh or bash in git-for-windows even they are available.)\n * killSignal : fixed to SIGTERM. If process does not die, server can send SIGKILL or invoke taskkill, to ensure chlid process is killed.\n * uid & gid : will not be set for security\n * stdio : all streams are handled by server. no options are avaliable to client.\n * detached : always false\n"
    },
    "ExecutionResult" : {
      "type" : "object",
      "required" : [ "stderr", "stdout" ],
      "properties" : {
        "error" : {
          "type" : "string",
          "description" : "error message when execution failed."
        },
        "stdout" : {
          "type" : "string",
          "description" : "standard out of child process."
        },
        "stderr" : {
          "type" : "string",
          "description" : "standard error of child process."
        }
      },
      "description" : "execution response"
    },
    "ChildProcess" : {
      "type" : "object",
      "required" : [ "args", "command", "execId", "foreground", "pid", "startedAt", "state" ],
      "properties" : {
        "pid" : {
          "type" : "integer",
          "description" : "child process pid"
        },
        "command" : {
          "type" : "string",
          "description" : "execution command in execution request"
        },
        "args" : {
          "type" : "array",
          "description" : "arguments of command in execution request",
          "items" : {
            "type" : "string"
          }
        },
        "execId" : {
          "type" : "string",
          "description" : "execution id from execution request"
        },
        "state" : {
          "type" : "string",
          "description" : "State of process. Where\n  CREATED - process is just created. no event has arrived yet.\n  WORKING - some output on stdout/stderr is arrived.\n  KILLING - sent kill signal, by cancel operation or some critical error event from the process. Invoking cancel operation to a process being killed should return error.\n  EXITED  - This process has exited already. Server is cleaning up the resources and not complete yet. Client should not expect that every exited process can be found with findProcs(). As KILLING state, cancellation will be rejected.\n",
          "enum" : [ "CREATED", "WORKING", "KILLING", "EXITED" ]
        },
        "foreground" : {
          "type" : "boolean",
          "description" : "if is true, this process is created from synchronous exec request. Som"
        },
        "startedAt" : {
          "type" : "string",
          "format" : "date-time",
          "description" : "the time when this process is spawned"
        },
        "exitCode" : {
          "type" : "integer",
          "description" : "the exit code of child process. available with EXITED procs only."
        },
        "exitSignal" : {
          "type" : "string",
          "description" : "the signal named that killed this child process.(not always available)"
        }
      },
      "description" : "a process in execution, spawned by exec or other means."
    },
    "Alias" : {
      "type" : "object",
      "required" : [ "id", "sourcePath", "workspaceId" ],
      "properties" : {
        "id" : {
          "type" : "string",
          "description" : "id, and the path-fragment to access. Since this id is a path-fragment, any unsafe chars for file system path should not be included. Windows OS prohibits following characters.\n < (less than)\n > (greater than)\n : (colon)\n \" (double quote)\n / (forward slash)\n \\ (backslash)\n | (vertical bar or pipe)\n ? (question mark)\n * (asterisk)\n"
        },
        "workspaceId" : {
          "type" : "string",
          "description" : "id of the workspace that contains source of alias"
        },
        "sourcePath" : {
          "type" : "string",
          "description" : "the source of alias, relative path to workspace root directory."
        }
      },
      "description" : "alias to access file system using git or direct http(s) requests who can't call swagger api with proper tokens. Implemenations may provide some concrent url formats. Alias may be invalidated when the workspace it belongs is removed. Any removed alias will result 404 error or equivalent."
    }
  },
  "parameters" : {
    "wfsId" : {
      "name" : "wfsId",
      "in" : "path",
      "description" : "webida file system id (same to workspace id) to access.",
      "required" : true,
      "type" : "string"
    },
    "wfsPath" : {
      "name" : "wfsPath",
      "in" : "path",
      "description" : "webida file system path to access. without heading /. should be placed at the end of path arguments",
      "required" : true,
      "type" : "string",
      "pattern" : ".*"
    },
    "srcPath" : {
      "name" : "srcPath",
      "in" : "query",
      "description" : "source data path of some operations, without have heading /",
      "required" : true,
      "type" : "string"
    },
    "wfsPathList" : {
      "name" : "wfsPathList",
      "in" : "query",
      "description" : "array of wfsPath, without heading /.",
      "required" : true,
      "type" : "array",
      "items" : {
        "type" : "string"
      },
      "collectionFormat" : "multi"
    },
    "ensureParents" : {
      "name" : "ensureParents",
      "in" : "query",
      "description" : "A flag to create all parent directories to create file or dir, like mkdir -p. This parameter does not create entire path, but ensures 'parent directory' of the wfsPath parameter",
      "required" : false,
      "type" : "boolean",
      "default" : false
    },
    "noOverwrite" : {
      "name" : "noOverwrite",
      "in" : "query",
      "description" : "does not overwrites any existing file while copying or moving",
      "required" : false,
      "type" : "boolean",
      "default" : false
    },
    "pattern" : {
      "name" : "pattern",
      "in" : "query",
      "description" : "regex pattern to match in search or replace. In replace operation, pattern should be same to the parttern in search operation",
      "required" : true,
      "type" : "string"
    },
    "ignoreCase" : {
      "name" : "ignoreCase",
      "in" : "query",
      "description" : "regex matching option to ignore case. In replace operation, this option should be same to one used in search operation",
      "required" : false,
      "type" : "boolean",
      "default" : false
    },
    "workspaceId" : {
      "name" : "workspaceId",
      "in" : "path",
      "description" : "webida workspace id (usually same to file system id, wfsId)",
      "required" : true,
      "type" : "string"
    },
    "workspaceIdQuery" : {
      "name" : "workspaceId",
      "in" : "query",
      "description" : "webida workspace id in query part",
      "required" : true,
      "type" : "string"
    },
    "execId" : {
      "name" : "execId",
      "in" : "query",
      "description" : "the id from execution request (different from pid!)",
      "required" : true,
      "type" : "string"
    },
    "sessionId" : {
      "name" : "sessionId",
      "in" : "path",
      "description" : "webida session id (usually different from socket id from sock.io)",
      "required" : true,
      "type" : "string"
    },
    "aliasId" : {
      "name" : "aliasId",
      "in" : "path",
      "description" : "url path fragment alias id. should have no '/' as well as any 'unsafe' chars for url path.  especially, '*' is reserved for finding operations or some other special case.",
      "required" : true,
      "type" : "string"
    }
  }
}