CommandBox
repository·development·Indexed 41 days ago
https://github.com/ortus-solutions/commandboxA comprehensive CLI, package manager, and embedded server for ColdFusion (CFML) development designed to streamline the CFML lifecycle. It functions as a multi-purpose toolset including a REPL and provides various system modules such as Globber for file system path pattern matching, JMESPath for querying JSON and CFML data, JSONPrettyPrint for formatting JSON, and PropertyFile for managing Java property files.
What's inside CommandBox
- CacheBox is an enterprise caching engine, aggregator, and API designed specifically for ColdFusion (CFML) applications. It provides a unified interface to manage and interact with various caching mechanisms.
Overview of CommandBox
developmentCommandBox is a multi-purpose toolset for ColdFusion (CFML) development. It functions as a Command Line Interface (CLI), a Package Manager, an Embedded CFML Server, and a REPL (Read-Eval-Print Loop).Use the PropertyFile utility for CFML
developmentPropertyFileis a library designed to load, modify, and store Java property files directly from CFML using a fluent API. It encapsulates the behavior of a Java properties file within a single CFC, allowing you to manage properties without writing Java code.getInstance( 'propertyFile' ) .load( myPath ) .set( 'myProp', 'myValue' ) .store();Chain PropertyFile methods
developmentMost methods in the
PropertyFileobject that do not return an explicit value returnthis, enabling a fluent interface for chaining operations like loading, setting, and storing in a single statement.getInstance( 'propertyFile' ) .load( myPath ) .set( 'myProp', 'myValue' ) .set( 'myOtherProp', 'myOtherValue' ) .store();Use the Lucee 5 formatter on Adobe ColdFusion
developmentOn Lucee 5, the library uses an alternate formatter that deserializes JSON to ordered structs, providing a significant performance boost while preserving key order and data types.
Adobe ColdFusion does not preserve key order and (prior to ACF 2018) may inaccurately serialize data types. If you are using ColdFusion and want the performance boost of the Lucee 5 formatter—and you are willing to accept the loss of key order or potential data type inaccuracies—you can inject the specific formatter using the
@JSONPrettyPrintalias.component { // Inject the Lucee 5 formatter specifically property name='JSONPrettyPrint' inject="CFMLPrinter@JSONPrettyPrint"; function writeJSON( required JSON, required path ) { fileWrite( path, JSONPrettyPrint.formatJSON( JSON ) ); } }Use Special Keys and Expressions in JMESPath
developmentJMESPath supports several special characters to control how expressions and values are evaluated:
@(Current Node): Refers to the current number, string, array, or object being evaluated.&(Expression): Used to denote a function or a keyname (e.g.,&to_number()or&keyname). This is required when passing functions as arguments to other functions.!(NOT): Negates an expression.&&(AND): Logical AND expression.||(OR): Logical OR expression.`{'ab':true}`(Literal Expressions): Used to define literals, which are converted to JSON.'foo'(Raw String Literals): Single quotes are used for raw strings that should not be evaluated.
JMESPath expression features and syntax
developmentThis implementation supports a wide range of JMESPath features for querying data:
Basic Access & Wildcards
- Nested values:
foo.bar - Wildcards:
*.bar - Array projection:
foo[*].bar[1]
Slicing, Pipes, and Indices
- Slicing:
foo[start:end:step](e.g.,foo[10:0:-1]) - Pipes: Use
|to pass the result of one expression to another (e.g.,foo[*].bar[*] | [0][0]) - Indices: Supports positive, negative, and out-of-bounds indices (out-of-bounds returns
null).
Multiselect
- List projection:
foo.[bar, baz[0]]returns an array of values. - Object projection:
foo.{bar: bar, buz: buz}returns a new object with specified keys.
Current Node Reference
- Use
@to refer to the current node (e.g.,@.baror@.foo[0]).
Filters
- Use
[? <expression>]to filter arrays. Expressions can use comparison operators like==,!=,>,>=,<,<=. Note that literals in filters should be enclosed in backticks (e.g.,[?age >25]).
// Example: Filtering var data = { foo: [{ age: 20 }, { age: 25 }, { age: 30 }] }; JMESPath.search(data, 'foo[?age > `25`]'); // returns [32m[{"age":30}][0m // Example: Multiselect Object var data = { foo: { bar: 1, baz: [2, 3, 4], buz: 2 } }; JMESPath.search(data, 'foo.{bar: bar, buz: buz}'); // returns {"bar":1,"buz":2}- Nested values:
Install the jmespath module via Commandbox
developmentTo add the JMESPath implementation to your Commandbox environment, use the
box installcommand.$ box install jmespathInject JSONPrettyPrint into a component
developmentJSONPrettyPrintis a threadsafe singleton and is designed to be injected using WireBox.component { property name='JSONPrettyPrint' inject; function writeJSON( required JSON, required path ) { fileWrite( path, JSONPrettyPrint.formatJSON( JSON ) ); } }Query JSON documents from disk
developmentYou can pass file paths or raw JSON strings as the data argument to
JMESPath.search.// Using a file path via expandPath JMESPath.search(expression, expandPath('/path/to/data.json')); // Using file content directly fileContent = fileRead(expandPath('./path/to/data.json'), 'utf-8'); JMESPath.search(expression, fileContent);Load a property file
developmentTo initialize the utility with an existing file, create an instance using
getInstance( 'propertyFile' )and call theload()method with the absolute path to the file.var propertyFile = getInstance( 'propertyFile' ).load( expandPath( 'myFile.properties' ) );Install JSONPrettyPrint
developmentInstall the
JSONPrettyPrintmodule via the CommandBox CLI to enable pretty-printing of JSON objects with human-readable indentation and line breaks.CommandBox> install JSONPrettyPrint