Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
CommandBox functions as a package manager which means you can use it to locate and install code packages for you. This gives you a consistent and scriptable method to install the libraries you need in a simple manner.
By default, the list of available packages is on ForgeBox, our CFML code sharing site. Additional endpoints such as Git, HTTP/HTTPS, and local file/folder are also available. When a package is installed, all of its dependencies are automatically installed for you for quick, easy experience.
You can easily create your own packages and register them on ForgeBox so the whole community can start using them.
There are several factors that determine where a package gets installed to. Here are the ways CommandBox determines the install location in order of importance.
The value of the directory
parameter passed into the install
command by the user.
The value of the installPaths.packageName
property set in the project's main box.json by the user. Where packageName
is the name of the package you are installing like logbox
.
The value of the directory
property in the package's box.json by the package author. Note, this must be a path relative to the current working directory (CWD).
Based on the package type convention if the package is a command, coldbox module, commandbox module, plugin, or interceptor.
If the package being installed is of type lucee-extensions
and if the current working directory is found to have a Lucee server in it, the lex file will instead be installed to the server context's deploy folder.
The current working directory (CWD)
Once the installation directory is determined, a folder is created that matches the package's slug which is where the package is finally copied to. If the package's createPackageDirectory property is set to false in the box.json, the package will be copied to the root of the installation directory. An example of this would be a complete application that needs to go in the web root.
There are several options you can use to control how a package is installed.
By default, any package you install will be saved as a dependency. To save it as a development dependency instead, use the --saveDev
flag.
If you DON'T want the package you're installing to be saved as a dependency pass save=false
or negate the save flag as --!save
.
When you install a package, all dependencies will be installed. If you want to skip development dependencies, use the --production
flag. This will also cause CommandBox to obey the package's ignoreList property in its box.json.
If you're a glutton for information, or perhaps you just want to debug what's going on, set the --verbose
flag to get extra debugging information out of the install command including a list of every file that's installed.
If CommandBox sees the directory that it was going to install into already exists with a newer or equal version of the package inside, it will decline to install again since it would be overwriting what's already there. If you want to install anyway, use the --force
flag.
In the CFML world, there are no global conventions for where to install things to nor where to store dependencies. Therefore, CommandBox for the most part will just stick packages in the root of your site unless you tell it otherwise. It may not be pretty, but it's as good as stock CFML apps can get. That means a lot of the cool things other package managers like NPM can do simply won't be available to you.
If you're using the ColdBox MVC Platform, congratulation! You just unlocked advanced mode! ColdBox uses conventions that tells you where to put stuff, and most importantly it has modularity as a first class citizen. Not only that, but modules can be nested infinitely to nicely encapsulate dependencies and WireBox will automatically find and register each module's models for your application to use.
Modules are basically smart packages and when CommandBox installs or uninstalls modules it will behave a bit differently to take advantage of the functionality only available to the CFML world via the ColdBox Platform.
When installing a module, it will be placed in the modules/ directory. That means the cbvalidation module will install here:
The cbvalidation module has dependencies of its own but it is an island unto itself and will encapsulate these. Therefore the cbi18n module will be installed in a modules/ folder inside cbvalidation.
You'll be able to see a nice representation of this when you use the list
command.
What this opens the door for is more than one module to depend on different versions of the same second module. Both can be installed and nested under the respective parent. In the near future, WireBox will be smart enough to present these nested modules only to their parents so they are fully encapsulated.
The idea is that a module can "see" and use another module installed at the same level or higher in the hierarchy, but not lower. That makes dependencies a bit of a black box to their parents. This also allows us to bypass some redundancy. For instance, when installing a module, if a satisfying version of that module already exists at a higher level, we skip the installation. Consider this example:
We know that cbvaliation requires cbi18n, but since it is already installed in the root modules folder, we won't install it again under cbvalidation.
The last way modules are better than sliced papusas is in how they uninstall. We talked about how non-modules install-- just littered in the web root in a jumble of dependencies. When uninstalling a non-module package, CommandBox will recursively go through the dependencies and remove them as well. However, when uninstalling a module, that module's folder is simply deleted and that's it. Since all dependencies are contained in the "black box", there's no need to go hunting for them.
The install command is used to tell CommandBox what you want. Here we ask for the stable release of the ColdBox MVC Platform. "coldbox" is the name of the ForgeBox slug.
Packages should always have a box.json
descriptor file inside them. This is especially true of packages installed from endpoints other than Forgebox since they don't have any other metadata available. CommandBox will install any zip file even if it doesn't have a box.json
, but this isn't ideal since the name, version, and type of the package must be guessed in that instance.
If you find a package on the internet that doesn't have a box.json
, please contact the maintainer and request that they add one or submit a pull request!
ForgeBox supports semantic version ranges for installing packages. Here are some examples:
When you install a package, here are the steps that are taken. Most all of this should be evident by the output streamed to the console during the install process. To get even more juicy details, use the --verbose
flag while installing.
CommandBox inspects the ID passed to the install
command to determine the endpoint to use.
The matching endpoint is asked to fetch the package represented by the ID.
For example, the ForgeBox endpoint checks the local artifact cache and possibly downloads the package.
If ForgeBox is offline, the best match package will be looked for in your artifacts.
The package is unzipped and its box.json
is read
Installation directory is finalized
Contents of package are copied based on the ignoreList
and --production
flag
The package is saved as a dependency in the root box.json
The package's dependencies are installed
For CommandBox to be able to install packages for you it needs to connect to package registry where packages are stored so it can download them for installation. CommandBox integrates seamlessly with ForgeBox, our community of ColdFusion (CFML) projects. CommandBox also integrates with HTTP(S), local file/folder, and Git endpoints.
Here is a list of the package endpoints currently supported by CommandBox.
ForgeBox - Cloud-based packages
HTTP(S) - Point to a hosted zip file containing a package
File - A local file containing a package
Folder - A local folder containing a package
Git - Any Git repo containing a package
Java - Install OpenJDK for your servers
Jar - A jar file hosted via HTTP that's not contained in a zip file
Lex- A Lucee Extension hosted via HTTP that's not contained in a zip file
S3 - A package zip stored in a private S3 bucket
CFLib - UDFs posted on CFLib.org
Gist - A package hosted as a Gist from gist.github.com
ForgeBox allows you to publish packages that only you can see and install. You'll be able to view your private package from the CLI, in the ForgeBox.io search, and in your ForgeBox.io profile, but these packages will now show up for any other users.
To create a private package, set the private
property to true
in your box.json
prior to publishing.
Replace forgeBoxUser
with your actual ForgeBox username. When you install the package, you'll need to use the full slug like so:
You can install specific versions or version ranges as you would expect:
Private packages will be a paid feature for ForgeBox Pro subscribers, though the feature is currently available to all users for free.
Entire Git repos that represent a package can be installed via the Git endpoint. This can be a public Git server like GitHub or Bitbucket, or a private Git repo behind your firewall.
Make sure the root of your Git repo has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the name of the repo will be used as the package name.
To install a package from a Git repo, use the URL like so:
You can target a specific branch
, tag
, or commit
by adding a "commit-ish" to the end of the URL.
If the repo you wish to install is located on Github.com, you can use this shortcut to specifying the package.
You can specify packages from folder endpoints as dependencies in your box.json
in this format. Remember, JSON requires that backslashes be escaped.
Git repos that allow anonymous pulls do not require any additional configuration for authentication. CommandBox's Git endpoint supports SSH authentication via public/private keys by using the git+ssh://
protocol.
Some Git endpoints (like private Github repos) need a user before the site name in the url string like below:
Info Note the git+ssh URL is a little different than a HTTP(S) URL. There is a colon (
:
) after the host instead of a forward slash (/
).
The git+ssh
endpoint will look for a private SSH key in your ~/.ssh
directory named id_rsa
, id_dsa
, or identity
. If you are using a multi-key setup with a ~/.ssh/config
file, it will be read, and the appropriate key will be used for the host. The matching public key needs to be registered in the Git server.
Info If you are deploying to a server and you have not previously logged into the Git server from the new machine you will need to make sure the Git server is added to your
known_hosts
file. The quickest way to do this is to usegit clone git@github.com/user/repo.git
from the terminal OR add the line from your local machine to the server.
You can authenticate to a Git repo over HTTP using a username/password combination or a personal access token. The format looks like this:
Github personal access tokens can be specified as either
or just the personal access token like
and they both appear to work the same. It appears that a private Github repo requires the “repo” scope selected for the personal access token.
GitLab seems to want a username, but it doesn’t seem to matter what the username is.
You can use environment variables from the CLI or in your box.json to protect sensitive information like passwords and keys.
We also support the NetRC file format. Just create a files in your user's home directory called ~/.netrc
or ~/_netrc
with the following format:
CommandBox will find this file, match the hostname to the Git repo being cloned, and use the username and password as specified.
We do not support any of these username/password options over HTTP as it just seems unwise. Please use HTTPS.
The Java endpoint is capable of downloading and installing any version of Java in the AdoptOpenJDK API. Use the java search
command to search the API to find what Java versions are available. The endpoint will use the local artifacts cache.
The installation ID consists of a series of identifiers separated by underscores that describe the Java version, type, JVM, etc that you want installed.
An example utilizing every option would be
However, everything is optional except the major version. These are also valid installation IDs
Here are the possible options for each section of the ID.
version - openjdk8, openjdk9, openjdk10, etc...
type - jdk, jre
arch - x64, x32, ppc64, s390x, ppc64le, aarch64
os - windows, linux, mac
jvm-implementation - hotspot, openj9
release - latest, jdk8u172, jdk8u172-b00, etc...
For items not specified in the endpoint ID, the endpoint will default as follows:
type - jre
arch - Whatever the current OS arch is
os - Whatever the current OS is
JVM-implementation - hotspot
release - latest
When java is installed as a package endpoint, the name of the folder that it is installed into will mirror the ID you use. This means two different installation IDs that resolve to the exact same Java version may end up in different folders. We do this for a couple reasons. One of which is simplicity, the other is that if you have configuration expecting a specific folder name, Mac users and Windows users may get a different download, but if the id is simple java:openjdk8_jdk
, they would both install into a folder called openjdk8_jdk
.
This endpoint will NOT edit your registry, create any symlinks, or add environment variables. It will simply drop the Java installation into a folder so you can point servers at it. You are free to use one of these Java installations in such a manner, but we don't do this by default so you can install as many java versions as you like and they don't fight with each other.
NOTE: If you simply want to start a server with a given version of OpenJDK, you don't need to use this endpoint directly, You can and it will handle the installation for you as well as re-using identical Java installs across servers. For example:
Dependencies are other packages that are required by another package for it to run. A simple package may have no dependencies, or it may have many. There are two types of dependencies: a regular dependency or a development dependency. Regular dependencies are ones required for operation of the main package. Development dependencies are optional and only necessary if you plan on making changes to the package you're installing. Dev dependencies would include testing frameworks or build tools.
When a package is installed, CommandBox will read its dependencies (from the box.json) and recursively install them as well. This encourages developers to write small, reusable libraries for everyone to use. When installing via a package manager, you don't have to worry about getting all the pieces installed.
Dependencies and development dependencies are stored in an object with the slug for the key and a version range for the value. The are several options available for these version ranges and more information can be found in the section on Semantic versioning.
When you install a dependency , it will be automatically added to your box.json. Use the --saveDev
flag to save a development dependency. Uninstalling a dependency will remove it from your box.json unless you set the save
parameter to false.
When you distribute a package for others to use, you should omit it dependencies. This will reduce the size of your repository and will prevent you from having to mess with the 3rd party code. As long as they are saved in your box.json, you're good.
When someone installs your package, CommandBox will automatically get the latest dependencies for them. If you're sharing an entire project that other people will download or clone from GitHub, they can simply run the install
command with no parameters.
This basically installs the root box.json as the current package, which means all dependencies that don't exist already will be installed. Now your project should be assembled and ready to run!