{"_id":"54dd27e0db3b362100131294","__v":6,"parentDoc":null,"version":{"_id":"54d5635532d98b0d00384afb","project":"54d53c7b23010a0d001aca0c","__v":10,"forked_from":"54d53c7c23010a0d001aca0f","createdAt":"2015-02-07T00:59:01.934Z","releaseDate":"2015-02-07T00:59:01.934Z","categories":["54d5635632d98b0d00384afc","54d5635632d98b0d00384afd","54d5635632d98b0d00384afe","54d5635632d98b0d00384aff","54d5635632d98b0d00384b00","54d5635632d98b0d00384b01","54d5635632d98b0d00384b02","54d652097e05890d006f153e","54dd1315ca1e5219007e9daa","54e21e2b22de1c230094b147","54e68e62a43fe13500db3879","54fa1d3fe7a0ba2f00306309","551c453a23a1ee190034d19a","551df586e52a0b23000c62b6","551f39be6886f8230055f02a","55a6720751457325000e4d97"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"0.1.0","version":"0.1"},"project":"54d53c7b23010a0d001aca0c","category":{"_id":"54d5635632d98b0d00384afe","__v":19,"version":"54d5635532d98b0d00384afb","pages":["54d5635732d98b0d00384b12","54d5635732d98b0d00384b13","54d5635732d98b0d00384b14","54d847c125e90a0d00db551f","54d995416a09052100a6b6d7","54d995534c49f40d00dff98a","54d9956b4c49f40d00dff98c","54dbce210e553a0d00dc1d09","54dcdf7bac05560d00335a15","54dd133c08f6b61700a691f7","54dd136108f6b61700a691fa","54dd27e0db3b362100131294","54dd2838ca1e5219007e9dcb","54dd28c8db3b362100131296","54deb1133a91410d001b1791","54deb134c4a3570d009d4a60","54dec5c0c2b4b70d009c3f05","54ded495e8e35a0d007551a0","54ded57d8e7b000d007c7f31","551447a90edb420d0050016e","551c4369ff892b3700d1c616"],"project":"54d53c7b23010a0d001aca0c","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-06T23:44:18.708Z","from_sync":false,"order":4,"slug":"api-plugins","title":"API Plugins"},"user":"54cfa8e1a8a4fd0d00b7fd1d","updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-02-12T22:23:28.719Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":4,"body":"Plugins often want to interact with files, processes and network within the user's workspace. Because all Cloud9 plugins run in the browser and there is a network between the browser and the user's workspace we looked for an API that would work asynchronously. The Node.js APIs were an obvious match and so we based our Filesystem (`fs`), Process (`proc`) and Network (`net`) APIs on Node's fs, child_process and net modules.\n\n# Getting a reference to the plugin\n\nThe following examples show how to gain access to the `fs` APIs. \n\nFirst, make sure to add \"fs\" to your list of plugins you depend on like so:\n\n```\nmain.consumes = [\"Plugin\", \"fs\"];\n```\n\nAnd then get a reference to the plugin in the main function:\n\n```\nfunction main(options, imports, register) {\n    var fs = imports.fs;\n```\n\n# Filesystem\n\n*For a complete reference to all the methods and events of the `fs` plugin check out the [fs api reference](https://docs.c9.io/api/#!/api/fs).*\n\nThe following table lists of all the methods supported by the `fs` plugin. \n[block:html]\n{\n  \"html\": \"<table>\\n<tr><th>appendFile</th><td>Appends a file in the workspace</td></tr>\\n<tr><th>chmod</th><td>Change the mode of a file within the workspace</td></tr>\\n<tr><th>copy</th><td>Copy a file within the workspace</td></tr>\\n<tr><th>exists</th><td>Tests if a file or directory exists</td></tr>\\n<tr><th>metadata</th><td>Set metadata for a file.</td></tr>\\n<tr><th>mkdir</th><td>Create a directory at path.</td></tr>\\n<tr><th>mkdirP</th><td>Creates all non-existing directories of the path.</td></tr>\\n<tr><th>readFile</th><td>Reads the entire contents from a file in the workspace.</td></tr>\\n<tr><th>readFileWithMetadata</th><td>Read the contents of a file including the metadata</td></tr>\\n<tr><th>readdir</th><td>Read the contents of a directory as an array of stat objects.</td></tr>\\n<tr><th>rename</th><td>Rename/move a file or directory.</td></tr>\\n<tr><th>rmdir</th><td>Delete a directory at path</td></tr>\\n<tr><th>rmfile</th><td>Delete a file at path.</td></tr>\\n<tr><th>stat</th><td>Loads the stat information for a single path entity.</td></tr>\\n<tr><th>symlink</th><td>Create a special symlink file at path.</td></tr>\\n<tr><th>unlink</th><td>Delete a file at path</td></tr>\\n<tr><th>unwatch</th><td>Stop watching for changes on a file or directory</td></tr>\\n<tr><th>watch</th><td>Watches for changes on a file or directory</td></tr>\\n<tr><th>writeFile</th><td>Write the contents of a file</td></tr>\\n</table>\"\n}\n[/block]\nThe following examples show some of the most common use cases dealing with the file system. The paths are always relative to the workspace directory. One exception are paths that are in the home dir of the owner. These can be accessed by prefixing paths with `~/`.\n\nGetting a directory listing:\n```\nfs.readdir(\"/plugins\", function(err, list){\n    if (err) return console.error(err);\n    \n    list.forEach(function(stat){\n        console.log(\"Name:\", stat.name, \"Size:\", stat.size);\n    });\n});\n```\n\nReading a file:\n```\nfs.readFile(\"/README.md\", function(err, content){\n    if (err) return console.error(err);\n\n    console.log(\"Contents of the file:\", content);\n});\n```\n\nWriting to a file:\n```\nfs.writeFile(\"/empty.json\", \"{}\", function(err){\n    if (err) return console.error(err);\n\n    console.log(\"File is written\");\n});\n```\n\nRemoving a directory tree:\n```\nfs.rmdir(\"/plugins\", { recursive: true }, function(err){\n    if (err) return console.error(err);\n\n    console.log(\"The directory and all it's children are deleted\");\n});\n```\n\n## Events\n\nThe `fs` plugin provides events before and after each method call. This allows your plugin to hook into and interact with filesystem changes before they happen or after they have occurred. The before events are cancelable.\n\n```\nfs.on(\"beforeWriteFile\", function(e){\n    console.log(\"Path:\", e.path, \"Args:\", e.args);\n    \n    return false; // Cancels this action\n});\n```\n\n## File Watchers\n\nWe advice not to use the `fs.watch()` and `fs.unwatch()` methods. If every plugin would set watchers on the same files there would be extra overhead. Instead use the `watcher` plugin to watch files.\n\n```\nwatcher.watch(\"/example.css\");\nwatcher.on(\"change\", function(e){\n    if (e.path == \"/example.css\")\n        console.log(\"example.css is updated. New file size: \", e.stat.size);\n});\n```\n\n*See the [watcher api reference](https://docs.c9.io/api/#!/api/watcher). for more information*\n\n# Latency Considerations\n\nBecause the code of your plugin is running in the user's browser it takes time to go from there to the user's workspace and back. We are continuously adding new servers and locations and our aim is to get worldwide latency down to 30ms or less. The truth is that seeing latency between 50ms - 100ms is not unusual. For most operations this is fine. However, it is important to realize that if you are writing a script that is going to deal with a large number of files, it is often best to create a small Node.js or Bash script. Simply use the process APIs to execute such a script instead of using the file system APIs.","excerpt":"","slug":"the-filesystem-api","type":"basic","title":"The Filesystem API"}

The Filesystem API


Plugins often want to interact with files, processes and network within the user's workspace. Because all Cloud9 plugins run in the browser and there is a network between the browser and the user's workspace we looked for an API that would work asynchronously. The Node.js APIs were an obvious match and so we based our Filesystem (`fs`), Process (`proc`) and Network (`net`) APIs on Node's fs, child_process and net modules. # Getting a reference to the plugin The following examples show how to gain access to the `fs` APIs. First, make sure to add "fs" to your list of plugins you depend on like so: ``` main.consumes = ["Plugin", "fs"]; ``` And then get a reference to the plugin in the main function: ``` function main(options, imports, register) { var fs = imports.fs; ``` # Filesystem *For a complete reference to all the methods and events of the `fs` plugin check out the [fs api reference](https://docs.c9.io/api/#!/api/fs).* The following table lists of all the methods supported by the `fs` plugin. [block:html] { "html": "<table>\n<tr><th>appendFile</th><td>Appends a file in the workspace</td></tr>\n<tr><th>chmod</th><td>Change the mode of a file within the workspace</td></tr>\n<tr><th>copy</th><td>Copy a file within the workspace</td></tr>\n<tr><th>exists</th><td>Tests if a file or directory exists</td></tr>\n<tr><th>metadata</th><td>Set metadata for a file.</td></tr>\n<tr><th>mkdir</th><td>Create a directory at path.</td></tr>\n<tr><th>mkdirP</th><td>Creates all non-existing directories of the path.</td></tr>\n<tr><th>readFile</th><td>Reads the entire contents from a file in the workspace.</td></tr>\n<tr><th>readFileWithMetadata</th><td>Read the contents of a file including the metadata</td></tr>\n<tr><th>readdir</th><td>Read the contents of a directory as an array of stat objects.</td></tr>\n<tr><th>rename</th><td>Rename/move a file or directory.</td></tr>\n<tr><th>rmdir</th><td>Delete a directory at path</td></tr>\n<tr><th>rmfile</th><td>Delete a file at path.</td></tr>\n<tr><th>stat</th><td>Loads the stat information for a single path entity.</td></tr>\n<tr><th>symlink</th><td>Create a special symlink file at path.</td></tr>\n<tr><th>unlink</th><td>Delete a file at path</td></tr>\n<tr><th>unwatch</th><td>Stop watching for changes on a file or directory</td></tr>\n<tr><th>watch</th><td>Watches for changes on a file or directory</td></tr>\n<tr><th>writeFile</th><td>Write the contents of a file</td></tr>\n</table>" } [/block] The following examples show some of the most common use cases dealing with the file system. The paths are always relative to the workspace directory. One exception are paths that are in the home dir of the owner. These can be accessed by prefixing paths with `~/`. Getting a directory listing: ``` fs.readdir("/plugins", function(err, list){ if (err) return console.error(err); list.forEach(function(stat){ console.log("Name:", stat.name, "Size:", stat.size); }); }); ``` Reading a file: ``` fs.readFile("/README.md", function(err, content){ if (err) return console.error(err); console.log("Contents of the file:", content); }); ``` Writing to a file: ``` fs.writeFile("/empty.json", "{}", function(err){ if (err) return console.error(err); console.log("File is written"); }); ``` Removing a directory tree: ``` fs.rmdir("/plugins", { recursive: true }, function(err){ if (err) return console.error(err); console.log("The directory and all it's children are deleted"); }); ``` ## Events The `fs` plugin provides events before and after each method call. This allows your plugin to hook into and interact with filesystem changes before they happen or after they have occurred. The before events are cancelable. ``` fs.on("beforeWriteFile", function(e){ console.log("Path:", e.path, "Args:", e.args); return false; // Cancels this action }); ``` ## File Watchers We advice not to use the `fs.watch()` and `fs.unwatch()` methods. If every plugin would set watchers on the same files there would be extra overhead. Instead use the `watcher` plugin to watch files. ``` watcher.watch("/example.css"); watcher.on("change", function(e){ if (e.path == "/example.css") console.log("example.css is updated. New file size: ", e.stat.size); }); ``` *See the [watcher api reference](https://docs.c9.io/api/#!/api/watcher). for more information* # Latency Considerations Because the code of your plugin is running in the user's browser it takes time to go from there to the user's workspace and back. We are continuously adding new servers and locations and our aim is to get worldwide latency down to 30ms or less. The truth is that seeing latency between 50ms - 100ms is not unusual. For most operations this is fine. However, it is important to realize that if you are writing a script that is going to deal with a large number of files, it is often best to create a small Node.js or Bash script. Simply use the process APIs to execute such a script instead of using the file system APIs.