zellfaze/dnd-generator — pull request #32 by zellfaze (2014-09-09 13:10:27+00:00)
Title: Implements Frictionless Open Data Packaging

This pull request implements frictionless open data packaging support into the D&D Character Sheet generator, resolving #28. This allows for data to be stored in "packages" that can be easily added and removed from the software. Data about different things (such as classes) can be stored across different packages or even different files within the same package. The extras directory has been renamed to data.

Most of the code is lazy loaded, which is to say that the assets for the package aren't actually loaded until the first time that they are used. This should cut back on loading times for the program as our data volume grows, but it does mean that the browser will have to periodically load more data in. This shouldn't be a problem on most computers and most Internet connections though.

To use this system you begin by creating a packageFileList object, which can be instantiated with a parameter telling it where to load for its loading file. If it is not passed such a parameter, it will load from data/load.json. The load.json file contains a simple array that lists which folders contain packages that need to be loaded. Each folder listed should have a datapackage.json file containing metadata about the package and a list of the package's data files. The packageFileList object's constructor, using the data from load.json, attempts to create a packageFile object for each package. Those that are successfully created are stored in an array. You can access this array using the getLoadedPackages method, which returns a promise that is resolved as soon as the packageFileList object is finished loading.

Each packageFile has, once it has loaded, a series of read-only properties allowing you to access the package's metadata. The resources property though in particular is noteworthy as it returns an array of dataFile objects.

Each dataFile object has properties for all of its metadata along with a method called getData. The json file containing the data for the dataFile object is lazy loaded when getData is called for the first time. getData always returns a promise that is resolved once the data file is loaded.

Generally you will not access dataFiles or packageFiles directly, but instead will work through dataStore objects. There is a dataStore class for each type of data file (class, feats, skills, etc.). Once instantiated a dataStore object can be passed either individual dataFile objects, or a packageFile object from which they will load any valid dataFiles for them. You can then use methods on the dataStore object to query all of the dataFiles it knows about for the data that you need. dataStore objects always return promises for their queries because it is impossible to know if all of the needed dataFile objects have loaded their data yet. After the first use of a dataStore object most promises should resolve close to instantly.

Lines 12-19 of base.js are example code showing the process of creating a packageFileList and passing its packages on to instantiate a namesDataStore object.