{"_id":"grab-bag","_rev":"48-210a1582abf8840c2b960665565740c6","name":"grab-bag","description":"Easily loads and stores system resources","dist-tags":{"latest":"0.1.1"},"versions":{"0.0.1":{"name":"grab-bag","version":"0.0.1","description":"A place where system properties are stored","keywords":["properties","json","configuration","settings"],"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"},"engines":{"node":"*"},"dependencies":{"error-provider":"*","properties":"*"},"devDependencies":{"mocha-runner":"*"},"licenses":[{"type":"MIT","url":"http://www.opensource.org/licenses/mit-license.html"}],"main":"lib/grab-bag","readme":"grab-bag\r\n========\r\n\r\n_Node.js project_\r\n\r\n#### A place where system properties are stored ####\r\n\r\nVersion: 0.0.1","readmeFilename":"README.md","_id":"grab-bag@0.0.1","dist":{"shasum":"19e0457f272674ad72007cf6ff2a45028c533c5f","tarball":"https://registry.npmjs.org/grab-bag/-/grab-bag-0.0.1.tgz","integrity":"sha512-/WkPHikvJVx3pB86Xx6+skKtRlpV1EcWZAwkaRdytP0lML0dd7mkWuXuknFFiVwNMzl4RE3pUbu/a37+BBctvQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICMDEHGirWpALSDJOGH98MMuGt70xvX3DPz+Y65geOaGAiBRqG2hSGUJYFJ9bNyjlzeJm5cjn2AqzW6NqMbu4YYkhA=="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"Gagle","email":"gaglekas@gmail.com"},"maintainers":[{"name":"Gagle","email":"gaglekas@gmail.com"}],"directories":{},"deprecated":"see seraphim"},"0.0.2":{"name":"grab-bag","version":"0.0.2","description":"Easily loads and stores system resources","keywords":["properties","json","configuration","settings","resources"],"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"},"engines":{"node":"*"},"dependencies":{"error-provider":"*","properties":"*"},"licenses":[{"type":"MIT","url":"http://www.opensource.org/licenses/mit-license.html"}],"main":"lib/grab-bag","readme":"grab-bag\r\n========\r\n\r\n_Node.js project_\r\n\r\n#### Easily loads and stores system resources ####\r\n\r\nVersion: 0.0.2\r\n\r\nThis module can be used to ease the loading and storing process for system resources without the need to worry about how they are loaded and stored and how you save them in namespaces. A resource is anything you save in configuration files.\r\n\r\n#### Instalation ####\r\n\r\n```\r\nnpm install grab-bag\r\n```\r\n\r\n#### Example ####\r\n\r\nYou need to load a directory named `conf`, a place where you put all your system configuration files. Inside it you have two files named `a.json` and `b.properties`. By default, you can only have json, key-value properties (.properties and INI files) and JavaScript modules but you can extend and overwrite the list defining your own readers and writers. Then you only need to do (assuming `conf` is inside `.`):\r\n\r\n```javascript\r\nvar gb = require (\"grab-bag\");\r\n\r\n//Loads recursively all the files inside conf\r\ngb.load (\"conf\", function (error){\r\n\tif (error) return handleError (error);\r\n\t\r\n\tvar conf = gb.get (\"conf\");\r\n\t//a.json file\r\n\tvar a = conf[\"a.json\"];\r\n\t//b.properties file\r\n\tvar b = conf[\"b.properties\"];\r\n\t\r\n\t/*\r\n\tAnother way to get resources is through paths\r\n\tvar a = gb.get (\"conf/a.json\");\r\n\tvar b = gb.get (\"conf/b.properties\");\r\n\t*/\r\n\t\r\n\t//Modifies in-memory a.json and b.properties\r\n\tdoSomething (conf);\r\n\t\r\n\t//Stores all the loaded resources to their files\r\n\tgb.store (function (error){\r\n\t\tif (error) return handleError (error);\r\n\t});\r\n});\r\n```\r\n\r\n#### Methods and Properties ####\r\n\r\n- [gb.define(extensions[, reader][, writer])](#define)\r\n- [gb.extensions](#ext)\r\n- [gb.get([resource])](#get)\r\n- [gb.load(resource, callback)](#load)\r\n- [gb.store([resource], callback)](#store)\r\n- [gb.types](#types)\r\n\r\n<a name=\"define\"></a>\r\n__gb.define(extensions[, reader][, writer])__  \r\nDefines a new parser/stringifier for every extension.\r\n\r\nThe \"extensions\" parameter is an array of strings with all the extensions that will be used with the given reader and writer functions.\r\n\r\nThe \"reader\" and \"writer\" parameters are callbacks that are executed when you load or store the files.\r\n\r\nThe reader receives the path of the file that needs to be parsed, the extension of this file and a callback to execute when the file is loaded. This callback expects an error and the loaded data as parameters.\r\n\r\nThe writer receives the path of the file that needs to be stored, the extension of this file, the data to store and a callback to execute when the file is loaded. This callback expects an error as parameter.\r\n\r\nFor example, we need to add support for YAML files. We're going to use the [yaml.js](#https://github.com/jeremyfa/yaml.js) moule to parse and stringify properties. Also, we want to parse/stringify the files as .properties files when the file has no extension.\r\n\r\n```javascript\r\nvar yaml = require (\"yamljs\");\r\nvar gb = requir (\"grab-bag\");\r\nvar fs = require (\"fs\");\r\n\r\nvar reader = function (file, extension, cb){\r\n\tfs.readFile (file, \"utf8\", function (error, data){\r\n\t\tif (error) return cb (error, null);\r\n\t\ttry{\r\n\t\t\tcb (null, yaml.parse (data));\r\n\t\t}catch (e){\r\n\t\t\tcb (e, null);\r\n\t\t}\r\n\t});\r\n};\r\n\r\nvar writer = function (file, extension, data, cb){\r\n\tfs.writeFile (file, yaml.stringify (data, 2), \"utf8\", cb);\r\n};\r\n\r\n//Defines a new parser/stringifier\r\ngb.define ([\"yml\", \"yaml\"], reader, writer);\r\n\r\n//Uses the buil-in .properties parser/stringifier to read/write files with no extension\r\ngb.define ([\"\"], gb.types.PROPERTIES.reader, gb.types.PROPERTIES.writer);\r\n```\r\n\r\nIf you don't need to stringify yaml properties, ignore the writer function:\r\n\r\n```javascript\r\ngb.define ([\"yml\", \"yaml\"], reader);\r\n```\r\n\r\nYou can also re-define existing extensions, for example, we want to replace the json parser/stringifier:\r\n\r\n```javascript\r\nvar reader = function (file, extension, cb){\r\n\t//...\r\n};\r\n\r\nvar writer = function (file, extension, data, cb){\r\n\t//...\r\n};\r\n\r\ngb.define ([\"json\"], reader, writer);\r\n```\r\n\r\nAdditionally, you can remove extensions from the set of extensions bound to a parser/stringifier. For example, we don't want to parse/stringify files with extension `conf`. Both reader and writer functions must be ignored to remove the extension.\r\n\r\n```javascript\r\ngb.define ([\"conf\"]);\r\n```\r\n\r\nNow, if a file with `conf` extension is found you'll get an error when loading the files, `FILE_TYPE_NOT_SUPPORTED`. The loading or storing process are not finished, they continue until completion.\r\n\r\nThe reader must be given if a writer is passed, that is, before writing to a file, the data has to be loaded with the reader function.\r\n\r\nTo know what extensions are bound to default parsers/stringifiers, see [gb.ext](#ext) and [gb.types](#types).\r\n\r\n<a name=\"ext\"></a>\r\n__gb.extensions__  \r\nContains all the supported extensions and their associated parser/stringifier. By default the .properties parser/stringifier accepts \"properties\", \"ini\" and \"conf\" extensions, the json parser/stringifier, \"json\", and the JavaScript modules, \"js\".\r\n\r\n- gb.extensions.properties === gb.types.PROPERTIES;\r\n- gb.extensions.ini === gb.types.PROPERTIES;\r\n- gb.extensions.conf === gb.types.PROPERTIES;\r\n- gb.extensions.json === gb.types.JSON;\r\n- gb.extensions.js === gb.types.JS;\r\n\r\n<a name=\"get\"></a>\r\n__gb.get([resource])__  \r\nReturns the given resource. The \"resource\" parameter is a path. If no path is passed the function returns all the loaded data:\r\n\r\n```\r\n./\r\n\ta/\r\n\t\ta.json\r\n\t\tb/\r\n\t\t\tb.json\r\n\t\tc/\r\n\t\t\tc.properties\r\n\t\t\td/\r\n\te.json\r\n```\r\n\r\n```\r\n//a.json\r\n{\r\n\t\"a\": 1\r\n}\r\n```\r\n\r\n```\r\n//b.json\r\n{\r\n\t\"b\": 2\r\n}\r\n```\r\n\r\n```\r\n//c.json\r\n{\r\n\t\"c\": 3\r\n}\r\n```\r\n\r\n```\r\n//e.json\r\n{\r\n\t\"d\": 4\r\n}\r\n```\r\n\r\n```javascript\r\ngb.load ([\"a\", \"e.json\"], function (error){\r\n\tif (error) return handleError (error);\r\n\t\r\n\tconsole.log (gb.get (\"a/b/b.json\").a); //Prints: 2\r\n\tconsole.log (gb.get ().a.b[\"b.json\"].a); //Prints: 2\r\n\tconsole.log (gb.get (\"e.json\").d); //Prints: 4\r\n\tconsole.log (require (\"util\").inspect (gb.get (), true, null));\r\n\t\r\n\t/*\r\n\tPrints:\r\n\t\r\n\t{\r\n\t\ta: {\r\n\t\t\t\"a.json\": {\r\n\t\t\t\ta: 1\r\n\t\t\t},\r\n\t\t\tb: {\r\n\t\t\t\t\"b.json\": {\r\n\t\t\t\t\tb: 2\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tc: {\r\n\t\t\t\t\"c.json\": {\r\n\t\t\t\t\tc: 3\r\n\t\t\t\t},\r\n\t\t\t\td: {}\r\n\t\t\t}\r\n\t\t},\r\n\t\t\"e.json\": {\r\n\t\t\td: 4\r\n\t\t}\r\n\t}\r\n\t*/\r\n});\r\n```\r\n\r\n<a name=\"load\"></a>\r\n__gb.load(resource, callback)__  \r\nLoads resources into memory. The \"resource\" parameters can be a string with the path to a file or directory or an array of strings. If an array is passed all the resources are loaded in parallel. If the path points to a directory, the directory is read recursively and all the files found are loaded. The callback with an error parameter is executed on completion.\r\n\r\n<a name=\"store\"></a>\r\n__gb.store([resource], callback)__  \r\nStores resources into their files. The \"resource\" parameters can be a string with the path to a file or directory or an array of strings. If an array is passed all the resources are stored in parallel. If the path points to a directory, all the resources that has been loaded into memory previously that belongs to this path will be stored recursively, that is, if an in-memory directory is found, all the properties are stored to their files. The callback with an error parameter is executed on completion, if any. If \"resource\" is not passed, stores all the loaded resources.\r\n\r\n<a name=\"types\"></a>\r\n__gb.types__  \r\nContains the default parsers/stringifiers. Every parser/stringifier has a \"reader\" and \"writer\" functions used to parse and store properties.\r\n\r\n- gb.types.PROPERTIES.reader, gb.types.PROPERTIES.writer\r\n- gb.types.JSON.reader, gb.types.JSON.writer\r\n- gb.types.JS.reader, gb.types.JS.writer\r\n\r\nThe .properties parser/stringifier type uses the [properties](#https://github.com/Gagle/Node-Properties) module, the json one uses the built-in json parser/stringifier and the JavaScript uses `require` to load the file, that is, the script file need to export an object.\r\n\r\nThe custom parser/stringifier defined with [gb.define()](#define) will be stored here with the name `CUSTOMX`, where `X` is an incremental number that starts at 0.\r\n\r\nThe extensions that are associated with each parser/stringifier can be found at [gb.ext](#ext).","readmeFilename":"README.md","_id":"grab-bag@0.0.2","dist":{"shasum":"46afbab87ed526a5ac70fd5afcfdc11c4f4775a7","tarball":"https://registry.npmjs.org/grab-bag/-/grab-bag-0.0.2.tgz","integrity":"sha512-fRs7TsCYwsy1OnbwLG3vdpX1huLixGw2Bc+x1ZaGoluqmtT/MzfPDrlogXbfKZTx0RgvUVVJzosGCGxYLizj0Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5qoUdX6mXiMH+znOPTQm+lQo+Q1OGWhyTHjtu0CXl7AiAAjo8WmVMy1/VgqvNOp2MNhMwd2gybkygGJjiNg4UZug=="}]},"_npmVersion":"1.1.69","_npmUser":{"name":"Gagle","email":"gaglekas@gmail.com"},"maintainers":[{"name":"Gagle","email":"gaglekas@gmail.com"}],"directories":{},"deprecated":"see seraphim"},"0.0.3":{"name":"grab-bag","version":"0.0.3","description":"Easily loads and stores system resources","keywords":["properties","json","configuration","settings","resources"],"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"},"engines":{"node":"*"},"dependencies":{"error-provider":"*","properties":"*"},"licenses":[{"type":"MIT","url":"http://www.opensource.org/licenses/mit-license.html"}],"main":"lib/grab-bag","readme":"grab-bag\r\n========\r\n\r\n_Node.js project_\r\n\r\n#### Easily loads and stores system resources ####\r\n\r\nVersion: 0.0.3\r\n\r\nThis module can be used to ease the loading and storing process for system resources without the need to worry about how they are loaded and stored and how you save them in namespaces. A resource is anything you save in configuration files.\r\n\r\n#### Installation ####\r\n\r\n```\r\nnpm install grab-bag\r\n```\r\n\r\n#### Example ####\r\n\r\nYou need to load a directory named `conf`, a place where you put all your system configuration files. Inside it you have two files named `a.json` and `b.properties`. By default, you can only have json, key-value properties (.properties and INI files) and JavaScript modules but you can extend and overwrite the list defining your own readers and writers. Then you only need to do (assuming `conf` is inside `.`):\r\n\r\n```javascript\r\nvar gb = require (\"grab-bag\");\r\n\r\n//Loads recursively all the files inside conf\r\ngb.load (\"conf\", function (error){\r\n\tif (error) return handleError (error);\r\n\t\r\n\tvar conf = gb.get (\"conf\");\r\n\t//a.json file\r\n\tvar a = conf[\"a.json\"];\r\n\t//b.properties file\r\n\tvar b = conf[\"b.properties\"];\r\n\t\r\n\t/*\r\n\tAnother way to get resources is through paths\r\n\tvar a = gb.get (\"conf/a.json\");\r\n\tvar b = gb.get (\"conf/b.properties\");\r\n\t*/\r\n\t\r\n\t//Modifies in-memory a.json and b.properties\r\n\tdoSomething (conf);\r\n\t\r\n\t//Stores all the loaded resources to their files\r\n\tgb.store (function (error){\r\n\t\tif (error) return handleError (error);\r\n\t});\r\n});\r\n```\r\n\r\n#### Methods and Properties ####\r\n\r\n- [gb.define(extensions[, reader][, writer])](#define)\r\n- [gb.extensions](#ext)\r\n- [gb.get([resource])](#get)\r\n- [gb.load(resource, callback)](#load)\r\n- [gb.store([resource], callback)](#store)\r\n- [gb.types](#types)\r\n\r\n<a name=\"define\"></a>\r\n__gb.define(extensions[, reader][, writer])__  \r\nDefines a new parser/stringifier for every extension.\r\n\r\nThe \"extensions\" parameter is an array of strings with all the extensions that will be used with the given reader and writer functions.\r\n\r\nThe \"reader\" and \"writer\" parameters are callbacks that are executed when you load or store the files.\r\n\r\nThe reader receives the path of the file that needs to be parsed, the extension of this file and a callback to execute when the file is loaded. This callback expects an error and the loaded data as parameters.\r\n\r\nThe writer receives the path of the file that needs to be stored, the extension of this file, the data to store and a callback to execute when the file is loaded. This callback expects an error as parameter.\r\n\r\nFor example, we need to add support for YAML files. We're going to use the [yaml.js](#https://github.com/jeremyfa/yaml.js) module to parse and stringify properties. Also, we want to parse/stringify files with no extension as INI files.\r\n\r\n```javascript\r\nvar yaml = require (\"yamljs\");\r\nvar gb = requir (\"grab-bag\");\r\nvar fs = require (\"fs\");\r\n\r\nvar reader = function (file, extension, cb){\r\n\tfs.readFile (file, \"utf8\", function (error, data){\r\n\t\tif (error) return cb (error, null);\r\n\t\ttry{\r\n\t\t\tcb (null, yaml.parse (data));\r\n\t\t}catch (e){\r\n\t\t\tcb (e, null);\r\n\t\t}\r\n\t});\r\n};\r\n\r\nvar writer = function (file, extension, data, cb){\r\n\tfs.writeFile (file, yaml.stringify (data, 2), \"utf8\", cb);\r\n};\r\n\r\n//Defines a new parser/stringifier\r\ngb.define ([\"yml\", \"yaml\"], reader, writer);\r\n\r\n//Uses the buil-in .ini parser/stringifier to read/write files with no extension\r\ngb.define ([\"\"], gb.types.INI.reader, gb.types.INI.writer);\r\n```\r\n\r\nIf you don't need to store yaml objects, ignore the writer function:\r\n\r\n```javascript\r\ngb.define ([\"yml\", \"yaml\"], reader);\r\n```\r\n\r\nYou can also re-define existing extensions, for example, we want to replace the INI parser/stringifier with the [ini](#https://github.com/isaacs/ini) module:\r\n\r\n```javascript\r\nvar ini = require (\"ini\");\r\nvar gb = requir (\"grab-bag\");\r\nvar fs = require (\"fs\");\r\n\r\nvar reader = function (file, extension, cb){\r\n\tfs.readFile (file, \"utf8\", function (error, data){\r\n\t\tif (error) return cb (error, null);\r\n\t\tcb (null, ini.parse (data));\r\n\t});\r\n};\r\n\r\nvar writer = function (file, extension, data, cb){\r\n\tfs.writeFile (file, ini.stringify (data), \"utf8\", cb);\r\n};\r\n\r\ngb.define ([\"ini\"], reader, writer);\r\n```\r\n\r\nAdditionally, you can remove extensions from the set of extensions bound to a parser/stringifier. For example, we don't want to parse/stringify files with extension `js`. Both reader and writer functions must be ignored to remove the extension.\r\n\r\n```javascript\r\ngb.define ([\"conf\"]);\r\n```\r\n\r\nNow, if a file with `conf` extension is found it won't be parsed.\r\n\r\nThe reader must be given if a writer is passed, that is, before writing to a file, the data has to be loaded with the reader function.\r\n\r\nTo know what extensions are bound to default parsers/stringifiers, see [gb.ext](#ext) and [gb.types](#types).\r\n\r\n<a name=\"ext\"></a>\r\n__gb.extensions__  \r\nContains all the supported extensions and their associated parser/stringifier. By default the .properties parser/stringifier accepts \"properties\", \"ini\" and \"conf\" extensions, the json parser/stringifier, \"json\", and the JavaScript modules, \"js\".\r\n\r\n- gb.extensions.properties === gb.types.PROPERTIES;\r\n- gb.extensions.ini === gb.types.INI;\r\n- gb.extensions.json === gb.types.JSON;\r\n- gb.extensions.js === gb.types.JS;\r\n\r\n<a name=\"get\"></a>\r\n__gb.get([resource])__  \r\nReturns the given resource. The \"resource\" parameter is a path. If no path is passed the function returns all the loaded data:\r\n\r\n```\r\n./\r\n\ta/\r\n\t\ta.json\r\n\t\tb/\r\n\t\t\tb.json\r\n\t\tc/\r\n\t\t\tc.properties\r\n\t\t\td/\r\n\te.json\r\n```\r\n\r\n```\r\n//a.json\r\n{\r\n\t\"a\": 1\r\n}\r\n```\r\n\r\n```\r\n//b.json\r\n{\r\n\t\"b\": 2\r\n}\r\n```\r\n\r\n```\r\n//c.json\r\n{\r\n\t\"c\": 3\r\n}\r\n```\r\n\r\n```\r\n//e.json\r\n{\r\n\t\"d\": 4\r\n}\r\n```\r\n\r\n```javascript\r\ngb.load ([\"a\", \"e.json\"], function (error){\r\n\tif (error) return handleError (error);\r\n\t\r\n\tconsole.log (gb.get (\"a/b/b.json\").a); //Prints: 2\r\n\tconsole.log (gb.get ().a.b[\"b.json\"].a); //Prints: 2\r\n\tconsole.log (gb.get (\"e.json\").d); //Prints: 4\r\n\tconsole.log (require (\"util\").inspect (gb.get (), true, null));\r\n\t\r\n\t/*\r\n\tPrints:\r\n\t\r\n\t{\r\n\t\ta: {\r\n\t\t\t\"a.json\": {\r\n\t\t\t\ta: 1\r\n\t\t\t},\r\n\t\t\tb: {\r\n\t\t\t\t\"b.json\": {\r\n\t\t\t\t\tb: 2\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tc: {\r\n\t\t\t\t\"c.json\": {\r\n\t\t\t\t\tc: 3\r\n\t\t\t\t},\r\n\t\t\t\td: {}\r\n\t\t\t}\r\n\t\t},\r\n\t\t\"e.json\": {\r\n\t\t\td: 4\r\n\t\t}\r\n\t}\r\n\t*/\r\n});\r\n```\r\n\r\n<a name=\"load\"></a>\r\n__gb.load(resource, callback)__  \r\nLoads resources into memory. The \"resource\" parameters can be a string with the path to a file or directory or an array of strings. If an array is passed all the resources are loaded in parallel. If the path points to a directory, the directory is read recursively and all the files found are loaded. The callback with an error parameter is executed on completion.\r\n\r\n<a name=\"store\"></a>\r\n__gb.store([resource], callback)__  \r\nStores resources into their files. The \"resource\" parameters can be a string with the path to a file or directory or an array of strings. If an array is passed all the resources are stored in parallel. If the path points to a directory, all the resources that has been loaded into memory previously that belongs to this path will be stored recursively, that is, if an in-memory directory is found, all the properties are stored to their files. The callback with an error parameter is executed on completion, if any. If \"resource\" is not passed, stores all the loaded resources.\r\n\r\n<a name=\"types\"></a>\r\n__gb.types__  \r\nContains the default parsers/stringifiers. Every parser/stringifier has a \"reader\" and \"writer\" functions used to parse and store properties.\r\n\r\n- gb.types.PROPERTIES.reader, gb.types.PROPERTIES.writer\r\n- gb.types.INI.reader, gb.types.INI.writer\r\n- gb.types.JSON.reader, gb.types.JSON.writer\r\n- gb.types.JS.reader, gb.types.JS.writer\r\n\r\nThe PROPERTIES type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables feature enabled.\r\nThe INI type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables and sections features enabled.\r\nThe JSON type uses the built-in json parser/stringifier.\r\nThe JS type uses the `require` function to load the file, the script file need to export an object. Take into account that `require` is synchronous and therefore it will block the entire event loop.\r\n\r\nThe custom parser/stringifier defined with [gb.define()](#define) will be stored here with the name `CUSTOMX`, where `X` is an incremental number that starts at 0.\r\n\r\nThe extensions that are associated with each parser/stringifier can be found at [gb.ext](#ext).","readmeFilename":"README.md","_id":"grab-bag@0.0.3","dist":{"shasum":"58ab3eb6492a050cef8c53f035d2bde6a6b37a11","tarball":"https://registry.npmjs.org/grab-bag/-/grab-bag-0.0.3.tgz","integrity":"sha512-qJ59C6mPDLic0dQsEkN1Atqi+1NrqIlTzbyEJplHKXCl4WHHmUBB4KrmleBHmnAS30sMGDjLXHvV1mbYOTCvSA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCu10N5WePZTCZI+Zcx5/dKfLgbQOV8KO0OwOno7aGOQwIhALCJqtLqUQunlqj1UxqDv+/cfnk+KyJuEk1cisTwrxio"}]},"_npmVersion":"1.1.69","_npmUser":{"name":"Gagle","email":"gaglekas@gmail.com"},"maintainers":[{"name":"Gagle","email":"gaglekas@gmail.com"}],"directories":{},"deprecated":"see seraphim"},"0.1.0":{"name":"grab-bag","version":"0.1.0","description":"Easily loads and stores system resources","keywords":["properties","json","configuration","settings","resources","namespace","file"],"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"},"engines":{"node":"*"},"dependencies":{"error-provider":"*","properties":"*"},"licenses":[{"type":"MIT","url":"http://www.opensource.org/licenses/mit-license.html"}],"main":"lib/grab-bag","readme":"grab-bag\n========\n\n_Node.js project_\n\n#### Easily loads and stores system resources ####\n\nVersion: 0.1.0\n\nThe main goal of this module is to ease the loading and storing process of system resources without the need to worry about how they are loaded and stored and where they are saved into memory, configure the I/O calls once and just load and store. A resource is anything you save in files, typically configuration data. A grab bag, or simply a box, provides a centralized and well organized place that grants to you a better control over your files.\n\nBecause encapsulation and abstraction is an art this module is the glue between your application and your configuration files. Useful when you have to load, update and store a lot of files with the minimum dependencies (loosely coupled).\n\nPut it simply, you need to work with localized strings and you need to load, update and store some configuration files. You need to save them somewhere for a later use. You could create a module called \"i18n\" holding and managing all your language files. That's fine. Furthermore, your application needs to externalize some configuration properties so you could create another module called \"conf\" trying to encapsulate the way you load and store your files, or simply you could just load and store the configuration properties when you need to do so if encapsulation is not one of your strengths.\n\nHave you thought the format of the properties? You have to decide a format because you need to load and store them to files. Typically you'll use a json, ini or yaml file. Perhaps you don't need a complex format and you simply store the information in different lines. These methods are highly coupled with a lot of dependencies. If you need to change how you load and store the properties there's a big risk to break your code accidentally. With a grab bag you must define once how the files are loaded and stored and then you can abstract from this and just call to [load()](#load) or [store()](#store).\n\n\n#### Installation ####\n\n```\nnpm install grab-bag\n```\n\n#### Example ####\n\nYou need to load a directory named `conf`, a place where you put all your system configuration files. Inside it you have two files named `a.json` and `b.properties`. By default, you can only have json, key-value properties (.properties and INI files) and JavaScript modules but you can extend and overwrite the list defining your own readers and writers. Then you only need to do (assuming `conf` is inside `.`):\n\n```javascript\nvar gb = require (\"grab-bag\");\n\nvar box = gb.create (\"system\");\n\n//Loads recursively all the files inside conf\nbox.load (\"conf\", function (error){\n\tif (error) return console.log (error);\n\t\n\tvar conf = box.get (\"conf\");\n\t//a.json file\n\tvar a = conf[\"a.json\"];\n\t//b.properties file\n\tvar b = conf[\"b.properties\"];\n\t\n\t/*\n\tAnother way to get resources is through paths\n\tvar a = gb.get (\"conf/a.json\");\n\tvar b = gb.get (\"conf/b.properties\");\n\t*/\n\t\n\t//Modifies a.json and b.properties\n\tdoSomething (conf);\n\t\n\t//Stores all the loaded resources to their files\n\tbox.store (function (error){\n\t\tif (error) return console.log (error);\n\t});\n});\n```\n\n#### Methods and Properties ####\n\n- [gb.create(name)](#create)\n- [gb.define(extensions, io)](#define)\n- [gb.remove(extensions)](#remove-gb)\n- [gb.types](#types)\n- [GrabBag#get([path])](#get)\n- [GrabBag#ignore(paths)](#ignore)\n- [GrabBag#load(path[, type], callback)](#load)\n- [GrabBag#name()](#name)\n- [GrabBag#remove([paths])](#remove)\n- [GrabBag#set(path, obj[, type])](#set)\n- [GrabBag#store([paths], callback)](#store)\n\n<a name=\"create\"></a>\n__gb.create([name])__  \nCreates a new GrabBag with an optional name.\n\n<a name=\"define\"></a>\n__gb.define(extensions, io)__  \nDefines a new parser/stringifier for every extension.\n\nThe \"extensions\" parameter is an array of strings with all the extensions that will be used with the given reader and writer functions.\n\nThe \"reader\" and \"writer\" parameters are callbacks that are executed when you load or store the files.\n\nThe reader receives the path of the file that needs to be parsed, the extension of this file and a callback to execute when the file is loaded. This callback expects an error and the loaded data as parameters.\n\nThe writer receives the path of the file that needs to be stored, the extension of this file, the data to store and a callback to execute when the file is loaded. This callback expects an error as parameter.\n\nDefault extensions and their associated parser/stringifier are:\n\n- \"properties\": gb.types.PROPERTIES\n- \"ini\": gb.types.INI\n- \"json\": gb.types.JSON\n- \"js\": gb.types.JS\n\nFor example, we need to add support for YAML files. We're going to use the [yaml.js](#https://github.com/jeremyfa/yaml.js) module to parse and stringify properties. Furthermore, we want to parse/stringify files with no extension as INI files.\n\n```javascript\nvar yaml = require (\"yamljs\");\nvar gb = require (\"grab-bag\");\nvar fs = require (\"fs\");\n\nvar reader = function (file, extension, cb){\n\tfs.readFile (file, \"utf8\", function (error, data){\n\t\tif (error) return cb (error, null);\n\t\ttry{\n\t\t\tcb (null, yaml.parse (data));\n\t\t}catch (e){\n\t\t\tcb (e, null);\n\t\t}\n\t});\n};\n\nvar writer = function (file, extension, data, cb){\n\tfs.writeFile (file, yaml.stringify (data, 2), \"utf8\", cb);\n};\n\n//Defines a new parser/stringifier\ngb.define ([\"yml\", \"yaml\"], {\n\treader: reader,\n\twriter: writer\n});\n\n//Uses the buil-in ini parser/stringifier to read/write files with no extension\ngb.define ([\"\"], gb.types.INI);\n```\n\nIf you don't need to store yaml objects, ignore the writer function:\n\n```javascript\ngb.define ([\"yml\", \"yaml\"], {\n\treader: reader\n});\n```\n\nYou can also re-define existing extensions, for example, we want to replace the INI parser/stringifier with the [ini](#https://github.com/isaacs/ini) module:\n\n```javascript\nvar ini = require (\"ini\");\nvar gb = requir (\"grab-bag\");\nvar fs = require (\"fs\");\n\nvar reader = function (file, extension, cb){\n\tfs.readFile (file, \"utf8\", function (error, data){\n\t\tif (error) return cb (error, null);\n\t\tcb (null, ini.parse (data));\n\t});\n};\n\nvar writer = function (file, extension, data, cb){\n\tfs.writeFile (file, ini.stringify (data), \"utf8\", cb);\n};\n\ngb.define ([\"ini\"], {\n\treader: reader,\n\twriter: writer\n});\n```\n\n<a name=\"remove-gb\"></a>\n__gb.remove(extensions)__  \nRemoves extensions from the set of extensions bound to a parser/stringifier. For example, we don't want to parse/stringify files with extension `js`.\n\n```javascript\ngb.remove ([\"js\"]);\n```\n\nNow, if a file with `js` extension is found it will be ignored.\n\n<a name=\"types\"></a>\n__gb.types__  \nContains the default parsers/stringifiers. Every parser/stringifier has a \"reader\" and \"writer\" function that are used to load and store properties from disk.\n\n- gb.types.PROPERTIES.reader, gb.types.PROPERTIES.writer\n- gb.types.INI.reader, gb.types.INI.writer\n- gb.types.JSON.reader, gb.types.JSON.writer\n- gb.types.JS.reader, gb.types.JS.writer\n\nThe PROPERTIES type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables feature enabled.  \nThe INI type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables and sections features enabled.  \nThe JSON type uses the built-in json parser/stringifier.  \nThe JS type uses the `require` function to load the file, the script needs to export an object. Take into account that `require` is synchronous and therefore it will block the entire event loop.\n\nThe custom parser/stringifier defined with [gb.define()](#define) will be stored here with the name `CUSTOMX`, where `X` is an incremental number that starts at 0.\n\nDefault extensions and their associated parser/stringifier are:\n\n- \"properties\": gb.types.PROPERTIES\n- \"ini\": gb.types.INI\n- \"json\": gb.types.JSON\n- \"js\": gb.types.JS\n\n<a name=\"get\"></a>\n__GrabBag#get([path])__  \nReturns a resource given a path. If no path is given the function returns all the resources:\n\n```\n./\n\ta/\n\t\ta.json\n\t\tb/\n\t\t\tb.json\n\t\tc/\n\t\t\tc.properties\n\t\t\td/\n\te.json\n```\n\n```\n//a.json\n{\n\t\"a\": 1\n}\n```\n\n```\n//b.json\n{\n\t\"b\": 2\n}\n```\n\n```\n//c.json\n{\n\t\"c\": 3\n}\n```\n\n```\n//e.json\n{\n\t\"d\": 4\n}\n```\n\n```javascript\nvar box = gb.create ();\n\nbox.load ([\"a\", \"e.json\"], function (error){\n\tif (error) return console.log (error);\n\t\n\tconsole.log (box.get (\"a/b/b.json\").a); //Prints: 2\n\tconsole.log (box.get ().a.b[\"b.json\"].a); //Prints: 2\n\tconsole.log (box.get (\"e.json\").d); //Prints: 4\n\tconsole.log (require (\"util\").inspect (box.get (), true, null));\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\ta: {\n\t\t\t\"a.json\": {\n\t\t\t\ta: 1\n\t\t\t},\n\t\t\tb: {\n\t\t\t\t\"b.json\": {\n\t\t\t\t\tb: 2\n\t\t\t\t}\n\t\t\t},\n\t\t\tc: {\n\t\t\t\t\"c.json\": {\n\t\t\t\t\tc: 3\n\t\t\t\t},\n\t\t\t\td: {}\n\t\t\t}\n\t\t},\n\t\t\"e.json\": {\n\t\t\td: 4\n\t\t}\n\t}\n\t*/\n});\n```\n\n<a name=\"ignore\"></a>\n__GrabBag#ignore(paths)__  \nIgnores the given resources when loading or storing. The \"paths\" parameter is an array of paths. The paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().ignore ([\"a\", \"b/c\"]);\n//This is not valid\ngb.create ().ignore ([\"./a\", \"../b\"]);\n```\n\nFor example, we have the following directory and we want to load `f1.json` and `f2.ini`.\n\n```\n./\n\ta/\n\t\tf1.json\n\t\tf2.ini\n\t\tf3.properties\n```\n\nWe can load indivual files:\n\n```javascript\ngb.create ().load ([\"a/f1.json\", \"a/f2.ini\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nOr we can ignore `f3.properties` and load the entire directory:\n\n```javascript\nvar box = gb.create ();\nbox.ignore (\"a/f3.properties\");\nbox.load (\"a\", function (error){\n\tif (error) return console.log (error);\n});\n```\n\n<a name=\"load\"></a>\n__GrabBag#load(path[, type], callback)__  \nLoads resources into memory. The \"path\" parameter can be a string with the path to a file or directory or an array of paths. If a path points to a directory, the directory is read recursively and all the sub-directories and supported files are loaded. The callback with an error parameter is executed on completion. See [get()](#get) example.\n\nHow can we load files with no extension without loading other specific files, for example readme files?\n\n```\n./\n\tconf/\n\t\tfile1\n\t\tfile2\n\t\tREADME1\n\tsystem/\n\t\tboot.properties\n\t\tREADME2\n\t\tREADME3\n```\n\nPut it simply, define a new type and load both directories:\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.load ([\"conf\", \"system\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nHere we have a problem because the three README files should not be parsed but because we have included the empty extension as a valid extension, they are parsed.\n\nA good solution is to define the empty extension and load files individually.\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.load ([\"conf/file1\", \"conf/file2\", \"system/boot.properties\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nBut this has a problem because if you need to load a lot of files you have to include them in the array.\n\nA better solution consists of using the [ignore()](#ignore) function. Just ignore the files that you don't want to load or store:\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.ignore ([\"conf/README1\", \"system/README2\", \"system/README3\"]);\nbox.load ([\"conf\", \"system\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nThe optional \"type\" parameter is the type of the content of the file or files if the path is a directory. This parameter is typically used when you want to load a file that has an extension that is not found in the set of default extensions but you don't want to define a new type because you have multiple files with the same extension but with different format, like the previous scenario.\n\nFor example, we want to load a file with a txt extension that has a custom format (line separated values).\n\n```\n//users.txt\nBroderick Distilo\nEllsworth Deperte\nWillian Garzone\nMarcellus Hoysock\nIesha Calvelo\n```\n\n```javascript\nvar type = {\n\treader: function (file, extension, cb){\n\t\tfs.readFile (file, \"utf8\", function (error, data){\n\t\t\tif (error) return cb (error, null);\n\t\t\tcb (null, data.split (/\\r\\n|\\n/));\n\t\t});\n\t}\n};\n\nvar box = gb.create ();\nbox.load (\"users.txt\", type, function (error){\n\tif (error) return console.log (error);\n\tconsole.log (box.get ());\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\t\"users.txt\": [\"Broderick Distilo\", \"Ellsworth Deperte\", \"Willian Garzone\", \"Marcellus Hoysock\", \"Iesha Calvelo\"]\n\t}\n\t*/\n});\n```\n\nYou can also use a predefined type:\n\n```javascript\n//file will be parsed as a .properties file\nvar box = gb.create ();\nbox.load (\"file\", gb.types.PROPERTIES, function (error){\n\tif (error) return console.log (error);\n});\n```\n\n<a name=\"name\"></a>\n__GrabBag#name()__  \nReturns the name of the grab bag.\n\n<a name=\"remove\"></a>\n__GrabBag#remove([paths])__  \nRemoves a resource or resources if the path points to a directory. The \"paths\" parameter can be a string or an array of paths. Take into account that the resource (JavaScript object) won't be freed if you have a reference pointing to it. In fact, this function calls to `delete` to remove the resource. Be aware of this if you don't want memory leaks.\n\n\n```\n./\n\ta/\n\t\ta.json\n\t\tb/\n\t\t\tb.json\n\t\tc/\n\t\t\tc.properties\n\t\t\td/\n\te.json\n```\n\n```\n//e.json\n{\n\t\"d\": 4\n}\n```\n\n```javascript\nvar box = gb.create ();\n\nbox.load ([\"a\", \"e.json\"], function (error){\n\tif (error) return console.log (error);\n\t\n\tbox.remove (\"a\");\n\t\n\tconsole.log (require (\"util\").inspect (box.get (), true, null));\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\t\"e.json\": {\n\t\t\td: 4\n\t\t}\n\t}\n\t*/\n});\n```\n\nThe paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().remove ([\"a\", \"b/c\"]);\n//This is not valid\ngb.create ().remove ([\"./a\", \"../b\"]);\n```\n\n<a name=\"set\"></a>\n__GrabBag#set(path, obj[, type])__  \nSaves an object into the set of resources. Instead of loading a file to populate the set of resources you can populate it with in-memory objects. Make sure to not to save a reference to the object in you application because if you want to free the object you'll produce a memory leak.\n\nThe path is relative to the current working directory but it must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().set (\"a.ini\", { p: 1 });\n//This is not valid\ngb.create ().set (\"./a.ini\", { p: 1 });\ngb.create ().set (\"../a.ini\", { p: 1 });\n```\n\n<a name=\"store\"></a>\n__GrabBag#store([paths], callback)__  \nStores resources into their files. The \"paths\" parameters can be a string with the path to a file or directory or an array of paths. If an array is passed all the resources are stored in parallel. If the path points to a directory, all the resources that has been loaded into memory previously that belongs to this path will be stored recursively, that is, if an in-memory directory is found, all the properties are stored to their files. The callback with an error parameter is executed on completion, if any. If \"paths\" is not passed, stores all the loaded resources.\n\nThe paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().store (\"a.ini\", function (error){});\n//This is not valid\ngb.create ().set (\"./a.ini\", function (error){});\ngb.create ().set (\"../a.ini\", function (error){});\n","readmeFilename":"README.md","_id":"grab-bag@0.1.0","dist":{"shasum":"86cd8bc1ccecef86afa298b29c6b88a52fa33f88","tarball":"https://registry.npmjs.org/grab-bag/-/grab-bag-0.1.0.tgz","integrity":"sha512-bbuidCcZBymOgwWkvF7nnC6D9HV1r0lEMYvFt0NLjoRY93uo6oDQR2AlY76wITPUCrjnFjlTHiSThJ9cdjIRKg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAsyPniKW1yLNV12Vl0lNAFIJqlkLjAxmspjSvHCd2G5AiB6YnCEh025TyZBxINqTWFW7w34KwYipiFT6A4JRqCE+A=="}]},"_from":".","_npmVersion":"1.2.2","_npmUser":{"name":"Gagle","email":"gaglekas@gmail.com"},"maintainers":[{"name":"Gagle","email":"gaglekas@gmail.com"}],"directories":{},"deprecated":"see seraphim"},"0.1.1":{"name":"grab-bag","version":"0.1.1","description":"Easily loads and stores system resources","keywords":["properties","json","configuration","settings","resources","namespace","file"],"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"},"engines":{"node":"*"},"dependencies":{"error-provider":"*","properties":"*"},"licenses":[{"type":"MIT","url":"http://www.opensource.org/licenses/mit-license.html"}],"main":"lib/grab-bag","readme":"grab-bag\n========\n\n_Node.js project_\n\n#### Easily loads and stores system resources ####\n\nVersion: 0.1.1\n\nThe main goal of this module is to ease the loading and storing process of system resources without the need to worry about how they are loaded and stored and where they are saved into memory, configure the I/O calls once and just load and store. A resource is anything you save in files, typically configuration data. A grab bag, or simply a box, provides a centralized and well organized place that grants to you a better control over your files.\n\nBecause encapsulation and abstraction is an art this module is the glue between your application and your configuration files. Useful when you have to load, update and store a lot of files with the minimum dependencies (loosely coupled). If you only want to load a couple of files this module is not made for you, it was thought for big projects with a lot of externalized data to provide an abstraction layer between the data and the way it is accessed.\n\nPut it simply, you need to work with localized strings and you need to load, update and store some configuration files. You need to save them somewhere for a later use. You could create a module called \"i18n\" holding and managing all your language files. That's fine. Furthermore, your application needs to externalize some configuration properties so you could create another module called \"conf\" trying to encapsulate the way you load and store your files, or simply you could just load and store the configuration properties when you need to do so if encapsulation is not one of your strengths.\n\nHave you thought the format of the data? You have to decide a format because you need to load and store them into files. Typically you'll use a json, ini or yaml file. Perhaps you don't need a complex format and you simply store the information in different lines. These methods are highly coupled with a lot of dependencies. If you need to change how you load and store the properties there's a big risk to break your code accidentally.\n\nThis is the way a grab bag works:\n\n<p align=\"center\">\n\t<img src=\"http://image.gxzone.com/images/7/a/7ae3a2a19c6.png\" alt=\"diagram\"/>\n</p>\n\nInstead of calling the parser/stringifier or just read/write the files you talk directly with the grab bag. To fill it you can load the files from disk ([load()](#load)) or just save in-memory objects ([set()](#set)). Then, you can retrieve and use them in your application ([get()](#get)) and persist the changes if you modify them ([store()](#store)).\n\nThe best part of this is that you configure how the data is loaded and stored into disk only once, so if you need to change anything related with the format it's very easy and safe to do the changes without affecting the whole application, therefore reducing the refactoring potential damage.\n\n\n#### Installation ####\n\n```\nnpm install grab-bag\n```\n\n#### Example ####\n\nYou need to load a directory named `conf`, a place where you put all your system configuration files. Inside it you have two files named `a.json` and `b.properties`. By default, you can only have .json, .properties and .ini files but you can extend and overwrite the list defining your own readers and writers. Then you only need to do (assuming `conf` is inside `.`):\n\n```javascript\nvar gb = require (\"grab-bag\");\n\nvar box = gb.create (\"system\");\n\n//Loads recursively all the files inside conf\nbox.load (\"conf\", function (error){\n\tif (error) return console.log (error);\n\t\n\tvar conf = box.get (\"conf\");\n\t//a.json file\n\tvar a = conf[\"a.json\"];\n\t//b.properties file\n\tvar b = conf[\"b.properties\"];\n\t\n\t/*\n\tAnother way to get resources is through paths\n\tvar a = box.get (\"conf/a.json\");\n\tvar b = box.get (\"conf/b.properties\");\n\t*/\n\t\n\t//Modifies a.json and b.properties\n\tdoSomething (conf);\n\t\n\t//Stores all the loaded resources to their files (overwriting them)\n\tbox.store (function (error){\n\t\tif (error) return console.log (error);\n\t});\n});\n```\n\n#### Methods and Properties ####\n\n- [gb.create(name)](#create)\n- [gb.define(extensions, io)](#define)\n- [gb.remove(extensions)](#remove-gb)\n- [gb.types](#types)\n- [GrabBag#get([path])](#get)\n- [GrabBag#ignore(paths)](#ignore)\n- [GrabBag#load(paths[, type], callback)](#load)\n- [GrabBag#name()](#name)\n- [GrabBag#remove([paths])](#remove)\n- [GrabBag#set(path[, type], obj)](#set)\n- [GrabBag#store([paths], callback)](#store)\n\n<a name=\"create\"></a>\n__gb.create([name])__  \nCreates a new GrabBag with an optional name.\n\n<a name=\"define\"></a>\n__gb.define(extensions, io)__  \nDefines a new parser/stringifier for every given extension.\n\nThe \"extensions\" parameter is an array of strings with all the extensions that will be used with the given reader and writer functions.\n\nThe \"io\" parameter is an object with the properties \"reader\" and \"writer\". This properties are the callbacks that are executed when you load or store the files. They are optional.\n\nThe reader receives the path of the file that needs to be parsed, the extension of this file and a callback to execute when the file is loaded. This callback expects an error and the loaded data as parameters.\n\nThe writer receives the path of the file that needs to be stored, the extension of this file, the data to store and a callback to execute when the file is loaded. This callback expects an error as parameter.\n\nDefault extensions and their associated parser/stringifier are:\n\n- \"properties\": gb.types.PROPERTIES\n- \"ini\": gb.types.INI\n- \"json\": gb.types.JSON\n\nFor example, we need to add support for YAML files. We're going to use the [yaml.js](#https://github.com/jeremyfa/yaml.js) module to parse and stringify properties. Furthermore, we want to parse/stringify files with no extension as INI files.\n\n```javascript\nvar yaml = require (\"yamljs\");\nvar gb = require (\"grab-bag\");\nvar fs = require (\"fs\");\n\nvar reader = function (file, extension, cb){\n\tfs.readFile (file, \"utf8\", function (error, data){\n\t\tif (error) return cb (error, null);\n\t\ttry{\n\t\t\tcb (null, yaml.parse (data));\n\t\t}catch (e){\n\t\t\tcb (e, null);\n\t\t}\n\t});\n};\n\nvar writer = function (file, extension, data, cb){\n\tfs.writeFile (file, yaml.stringify (data, 2), \"utf8\", cb);\n};\n\n//Defines a new parser/stringifier\ngb.define ([\"yml\", \"yaml\"], {\n\treader: reader,\n\twriter: writer\n});\n\n//Uses the built-in ini parser/stringifier to read/write files with no extension\ngb.define ([\"\"], gb.types.INI);\n```\n\nIf you don't need to store yaml objects, ignore the writer function:\n\n```javascript\ngb.define ([\"yml\", \"yaml\"], {\n\treader: reader\n});\n```\n\nYou can also re-define existing extensions, for example, we want to replace the INI parser/stringifier with the [ini](#https://github.com/isaacs/ini) module:\n\n```javascript\nvar ini = require (\"ini\");\nvar gb = requir (\"grab-bag\");\nvar fs = require (\"fs\");\n\nvar reader = function (file, extension, cb){\n\tfs.readFile (file, \"utf8\", function (error, data){\n\t\tif (error) return cb (error, null);\n\t\tcb (null, ini.parse (data));\n\t});\n};\n\nvar writer = function (file, extension, data, cb){\n\tfs.writeFile (file, ini.stringify (data), \"utf8\", cb);\n};\n\ngb.define ([\"ini\"], {\n\treader: reader,\n\twriter: writer\n});\n```\n\n<a name=\"remove-gb\"></a>\n__gb.remove(extensions)__  \nRemoves extensions from the set of extensions bound to a parser/stringifier. For example, we don't want to parse/stringify files with `ini` extension.\n\n```javascript\ngb.remove ([\"ini\"]);\n```\n\nNow, if a file with a `ini` extension is found it will be ignored.\n\n<a name=\"types\"></a>\n__gb.types__  \nContains the default parsers/stringifiers. Every parser/stringifier has a \"reader\" and \"writer\" function that are used to load and store properties from disk.\n\n- gb.types.PROPERTIES.reader, gb.types.PROPERTIES.writer\n- gb.types.INI.reader, gb.types.INI.writer\n- gb.types.JSON.reader, gb.types.JSON.writer\n\nThe PROPERTIES type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables feature enabled.  \nThe INI type uses the [properties](#https://github.com/Gagle/Node-Properties) module with the variables and sections features enabled.  \nThe JSON type uses the Node.js built-in json parser/stringifier.  \n\nThe custom parser/stringifier defined with [gb.define()](#define) will be stored here with the name `CUSTOMX`, where `X` is an incremental number that starts at 0.\n\nDefault extensions and their associated type are:\n\n- \"properties\": gb.types.PROPERTIES\n- \"ini\": gb.types.INI\n- \"json\": gb.types.JSON\n\n<a name=\"get\"></a>\n__GrabBag#get([path])__  \nReturns a resource given a path. If no path is given the function returns all the resources.\n\nExample:\n\n```\n./\n\ta/\n\t\ta.json\n\t\tb/\n\t\t\tb.json\n\t\tc/\n\t\t\tc.properties\n\t\t\td/\n\te.json\n```\n\n```\n//a.json\n{\n\t\"a\": 1\n}\n```\n\n```\n//b.json\n{\n\t\"b\": 2\n}\n```\n\n```\n//c.json\n{\n\t\"c\": 3\n}\n```\n\n```\n//e.json\n{\n\t\"e\": 4\n}\n```\n\n```javascript\nvar box = gb.create ();\n\nbox.load ([\"a\", \"e.json\"], function (error){\n\tif (error) return console.log (error);\n\t\n\tconsole.log (box.get (\"a/b/b.json\").a); //Prints: 2\n\tconsole.log (box.get ().a.b[\"b.json\"].a); //Prints: 2\n\tconsole.log (box.get (\"e.json\").e); //Prints: 4\n\tconsole.log (require (\"util\").inspect (box.get (), true, null));\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\ta: {\n\t\t\t\"a.json\": {\n\t\t\t\ta: 1\n\t\t\t},\n\t\t\tb: {\n\t\t\t\t\"b.json\": {\n\t\t\t\t\tb: 2\n\t\t\t\t}\n\t\t\t},\n\t\t\tc: {\n\t\t\t\t\"c.json\": {\n\t\t\t\t\tc: 3\n\t\t\t\t},\n\t\t\t\td: {}\n\t\t\t}\n\t\t},\n\t\t\"e.json\": {\n\t\t\te: 4\n\t\t}\n\t}\n\t*/\n});\n```\n\nThe paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().get (\"a\");\ngb.create ().get (\"b/c\");\n//This is not valid\ngb.create ().get (\"./a\");\ngb.create ().get (\"../a\");\n```\n\n<a name=\"ignore\"></a>\n__GrabBag#ignore(paths)__  \nIgnores the given resources when loading or storing. The \"paths\" parameter is an array of paths. The paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().ignore ([\"a\", \"b/c\"]);\n//This is not valid\ngb.create ().ignore ([\"./a\", \"../b\"]);\n```\n\nFor example, we have the following directory and we want to load `f1.json` and `f2.ini`.\n\n```\n./\n\ta/\n\t\tf1.json\n\t\tf2.ini\n\t\tf3.properties\n```\n\nWe can load indivual files:\n\n```javascript\ngb.create ().load ([\"a/f1.json\", \"a/f2.ini\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nOr we can ignore `f3.properties` and load the entire directory:\n\n```javascript\nvar box = gb.create ();\nbox.ignore (\"a/f3.properties\");\nbox.load (\"a\", function (error){\n\tif (error) return console.log (error);\n});\n```\n\n<a name=\"load\"></a>\n__GrabBag#load(paths[, type], callback)__  \nLoads resources from disk. The \"path\" parameter can be a string with the path to a file or directory or an array of paths. If a path points to a directory, the directory is read recursively and all the sub-directories and supported files are loaded. The callback receives an error parameter and is executed on completion. See [get()](#get) example.\n\nHow can we load files with no extension without loading other specific files, for example readme files?\n\n```\n./\n\tconf/\n\t\tfile1\n\t\tfile2\n\t\tREADME1\n\tsystem/\n\t\tboot.properties\n\t\tREADME2\n\t\tREADME3\n```\n\nPut it simply, define a new type and load both directories:\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.load ([\"conf\", \"system\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nHere we have a problem because the three README files should not be parsed but because we have included the empty extension as a valid extension, they are parsed.\n\nA good solution is to define the empty extension and load files individually.\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.load ([\"conf/file1\", \"conf/file2\", \"system/boot.properties\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nBut this has a problem because if you need to load a lot of files you have to include them manually in the array and they could have a different format so you can't load them with the same parser.\n\nA better solution consists of using the [ignore()](#ignore) function. Just ignore the files that you don't want to load or store:\n\n```javascript\ngb.define ([\"\"], gb.types.PROPERTIES);\n\nvar box = gb.create ();\nbox.ignore ([\"conf/README1\", \"system/README2\", \"system/README3\"]);\nbox.load ([\"conf\", \"system\"], function (error){\n\tif (error) return console.log (error);\n});\n```\n\nThe optional \"type\" parameter is the type of the content of the file, or files if the path is a directory. This parameter is typically used when you want to load a file that has an extension that is not found in the set of default extensions but you don't want to define a new type because you have multiple files with the same extension but with different format, like the previous scenario.\n\nFor example, we want to load a file with a txt extension that has a custom format (line separated values).\n\n```\n//users.txt\nBroderick Distilo\nEllsworth Deperte\nWillian Garzone\nMarcellus Hoysock\nIesha Calvelo\n```\n\n```javascript\nvar type = {\n\treader: function (file, extension, cb){\n\t\tfs.readFile (file, \"utf8\", function (error, data){\n\t\t\tif (error) return cb (error, null);\n\t\t\tcb (null, data.split (/\\r\\n|\\n/));\n\t\t});\n\t}\n};\n\nvar box = gb.create ();\nbox.load (\"users.txt\", type, function (error){\n\tif (error) return console.log (error);\n\tconsole.log (box.get ());\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\t\"users.txt\": [\"Broderick Distilo\", \"Ellsworth Deperte\", \"Willian Garzone\", \"Marcellus Hoysock\", \"Iesha Calvelo\"]\n\t}\n\t*/\n});\n```\n\nYou can also use a predefined type:\n\n```javascript\n//file will be parsed as a .properties file\nvar box = gb.create ();\nbox.load (\"file\", gb.types.PROPERTIES, function (error){\n\tif (error) return console.log (error);\n});\n```\n\nLoading multiple files at once each of them with a different parser/stringifier is also possible:\n\n```javascript\nvar box = gb.create ();\n\nvar type1 = {\n\treader: function (file, extension, cb){\n\t\t//...\n\t}\n};\n\nvar files = {\n\t\"a/file1\": gb.types.PROPERTIES, //file1 loaded/stored as a .properties file\n\t\"a/file2\": type1, //file2 loaded with the custom reader\n\t\"file3.json\": null, //file3 is loaded/stored as a .json file because it has a .json extension\n\t\"file4\": null, //file4 is ignored because it has no extension and the empty extension has not been defined as a type\n\t\"b/dir1\": null //The dir1 directory is read\n};\n\nbox.load (files, function (error){\n\tif (error) return console.log (error);\n});\n```\n\n<a name=\"name\"></a>\n__GrabBag#name()__  \nReturns the name of the grab bag.\n\n<a name=\"remove\"></a>\n__GrabBag#remove([paths])__  \nRemoves a resource, or resources if the path points to a directory. The \"paths\" parameter can be a string or an array of paths. Take into account that the resource (JavaScript object) won't be freed if you have a reference pointing to it. In fact, this function calls to `delete` to remove the resource. Be aware of this if you don't want memory leaks.\n\n\n```\n./\n\ta/\n\t\ta.json\n\t\tb/\n\t\t\tb.json\n\t\tc/\n\t\t\tc.properties\n\t\t\td/\n\te.json\n```\n\n```\n//e.json\n{\n\t\"e\": 4\n}\n```\n\n```javascript\nvar box = gb.create ();\n\nbox.load ([\"a\", \"e.json\"], function (error){\n\tif (error) return console.log (error);\n\t\n\tbox.remove (\"a\");\n\t\n\tconsole.log (require (\"util\").inspect (box.get (), true, null));\n\t\n\t/*\n\tPrints:\n\t\n\t{\n\t\t\"e.json\": {\n\t\t\te: 4\n\t\t}\n\t}\n\t*/\n});\n```\n\nThe paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().remove ([\"a\", \"b/c\"]);\n//This is not valid\ngb.create ().remove ([\"./a\", \"../a\"]);\n```\n\n<a name=\"set\"></a>\n__GrabBag#set(path[, type], obj)__  \nSaves an object into the grab bag. Instead of loading a file from disk to fill the grab bag you can populate it with in-memory objects. Make sure to not to maintain a reference to the object you want to put in the grab bag because if you want to free the object you'll produce a memory leak. Reminder: an object is garbage collected if it is not referenced by any variable.\n\nThe path is relative to the current working directory but it must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().set (\"a.ini\", { p: 1 });\n//This is not valid\ngb.create ().set (\"./a.ini\", { p: 1 });\ngb.create ().set (\"../a.ini\", { p: 1 });\n```\n\n<a name=\"store\"></a>\n__GrabBag#store([paths], callback)__  \nStores the resources into their files. The \"paths\" parameters can be a string with the path to a file or directory or an array of paths. If an array is passed all the resources are stored in parallel. If the path points to a directory, all the resources that has been previously loaded into memory that belongs to this path will be stored recursively. The callback with an error parameter is executed on completion, if any. If \"paths\" is not passed, stores all the loaded resources.\n\nExample:\n\n\n```\n./\n\ta/\n\t\ta.json\n\t\tb/\n\t\t\tb.json\n\t\t\tc/\n\t\t\t\tc.properties\n```\n\n```javascript\nvar box = gb.create ();\n\nbox.load (\"a\", function (error){\n\tif (error) return console.log (error);\n\t\n\tbox.store (\"a/b\", function (error){\n\t\tif (error) return console.log (error);\n\t\t\n\t\t//\"b\" points to a directory so b.json and c.properties have been stored\n\t});\n});\n```\n\n\nThe paths are relative to the current working directory but they must not begin with `.` or `..`.\n\n```javascript\n//This is valid\ngb.create ().store (\"a.ini\", function (error){});\n//This is not valid\ngb.create ().set (\"./a.ini\", function (error){});\ngb.create ().set (\"../a.ini\", function (error){});\n","readmeFilename":"README.md","_id":"grab-bag@0.1.1","dist":{"shasum":"73ec672e0f1084b8819b8200a073b2402b878863","tarball":"https://registry.npmjs.org/grab-bag/-/grab-bag-0.1.1.tgz","integrity":"sha512-TUf9VNx0nLKbNE3VGEUolwWyhR7LrAzrrWeIlgHxa5oVCHhC9vBljkIcmpEtW+LMs6l9K+vx2OL72kTI80WSGg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFBJaNu1pC3oY6FZ8TFywdTYFwVrvdRKj182G2LhfcvSAiEAyVMQxvmxHGELuzw8IrFe+u/nNawp+mr9Nu5D+ju8S4s="}]},"_from":".","_npmVersion":"1.2.11","_npmUser":{"name":"Gagle","email":"gaglekas@gmail.com"},"maintainers":[{"name":"Gagle","email":"gaglekas@gmail.com"}],"directories":{},"deprecated":"see seraphim"}},"readme":"grab-bag\r\n========\r\n\r\n_Node.js project_\r\n\r\n#### A place where system properties are stored ####\r\n\r\nVersion: 0.0.1","maintainers":[{"name":"gagle","email":"gabriel_llamas_llopis@yahoo.es"}],"time":{"modified":"2022-06-18T13:44:47.197Z","created":"2013-01-05T15:23:08.945Z","0.0.1":"2013-01-05T15:23:11.886Z","0.0.2":"2013-01-06T23:13:02.120Z","0.0.3":"2013-01-07T19:54:06.844Z","0.1.0":"2013-01-20T14:43:26.845Z","0.1.1":"2013-02-21T09:09:06.239Z"},"author":{"name":"Gabriel Llamas","email":"gaglekas@gmail.com"},"repository":{"type":"git","url":"git://github.com/Gagle/Node-GrabBag.git"}}