Banana howto

This howto breaks down the different parts that make up a banana.

banana.json

Within the root of a banana's directory a banana.json file (when markup.data.yaml is implemented and bootstrapped into banana, banana.yaml may also be supported) defines an object with data defining the banana.

There are 3 required keys.

As a simple explanation the name is used as a display name to the user, the shortname as a short easy to use identifier when using things like banana install foo and the namespace acts as the absolute unique identifier of the banana. A namespace should either follow category rules or use the reverse domain name technique.

Another important one is the components key. At it's most verbose it is an array of objects with at minimum each object having a type key (js or jar currently) and a file key with the filename relative to the banana root which may not use . or .., different types of componenets may have other component specific keys they may use.

This components list may be shortened down. Rather than an object, for simple things you can simply define a string with what you would define as the file key in the object. If the filename ends in .js it will be considered the same as { type: "js", file: component } and if the filename ends in .jar it will be considered the same as { type: "jar", file: component }, otherwise a full object is needed.

A banana should also define a version key which will be used when versioning bananas, and may define extra keys such as description, author, license, and so on as information metadata about the banana.

The optional depends and recommends keys define a list of banana namespace queries that act as a list of dependencies on other bananas. If a banana uses banana(q) inside the banana code it MUST define that same q as a dependency in banana.json. MonkeyScript will throw an error if a banana attempts to include a banana it does not define as a dependency. This is done to make it possible to keep proper track of dependencies.

The difference between depends and recommends is in the meaning and purpose of the dependency. A dependency defined in depends is a requirement, when banana install is used all depends dependencies will be installed as well. A dependency defined in recommends will merely be a recommendation which installation is suggested to the user. The purpose of a recommendation is for things like a library recommending that a readline style shell library be installed so it can support extra shell abilities, or something using configuration files recommending yaml support be installed so that it can support yaml config files as well as json config files (which would be supported natively by the native JSON support).

The depends key supports a multi-level definition of dependencies. In this case it may be an array of arrays in alternating and/or forms starting with and. Basically if you define { ... "depends": ["foo.bar", "bar.baz", "baz.splat" ] ... } the banana will either require that the "foo.bar" package be installed as well as either the "bar.baz" banana or the "baz.splat" banana. This is useful for meta packages such as markup.data.yaml where there may be multiple yaml implementations like markup.data.yaml.libyaml using a libyaml C library, and markup.data.yaml.jsyaml a pure-js implementation both sharing the same api. In this case markup.data.yaml can define { ... "depends": ["markup.data.yaml.libyaml", "markup.data.yaml.jsyaml ] ... } and require that at least one of either the libyaml backed library or the jsyaml library be installed.

There are two other highly optional special keys, onevesion and monkeypatch.

Oneversion is a special key which may be set with a value of true to indicate that banana should not permit any more than one version of a banana to be loaded at any one time. ie: If someone uses banana('foov=1'); and another uses banana('foov=2'); and foo defines oneversion: true, then the second call will throw an error because foo does not permit other versions. This would normally be used in combination with an absent version if a banana is merely a proxy to a native MonkeyScript api which cannot be versioned.

Monkeypatch is another special key, to use it oneversion should also be specified to avoid gotchas where multiple versions are included and conflict with prototypes. This key doesn't mean anything programically but indicates that the banana may monkeypatch globals or classes in other bananas. It is best to only monkeypatch bananas that use oneversion.

*.js

JavaScript files defined inside components as type:"js" will be executed to populate an exports object for the banana which will be returned by banana(q) calls.

JS files for bananas are run in their own private functional scope, variables defined within one will not be available inside of sister files in the same banana.

Within a JS file executed for a banana there are a few special variables it has access to:

It might be worth noting that the banana function inside of a banana itself is not the same as the global banana function, practically speaking it is the same, it's just technically a different function inheriting from the global banana that does the same thing except it restricts the banana's ability to include bananas to only bananas it has defined as dependencies or recommends.

_native.js

(MonkeyScript Lite specific)

*.jar

(MonkeyScript Lite specific)