SPACEPORT DOCS

Class Enhancements

Spaceport enhances standard Groovy classes with many additional methods designed to make common frontend and backend tasks easier. These utilities provide powerful and convenient shortcuts for data manipulation, web content handling, serialization, and formatting, streamlining the development of web applications.

Becoming a Groovy Luminary will teach you how you can make your own class enhancements, providing a powerful way to tailor your application to your specific needs.

# Quick Reference

This section provides a comprehensive overview of all available class enhancements organized by type. For detailed explanations, examples, and usage patterns, see the Enhancement Concerns section below.

## String Methods

Method Returns Description
clean() String Sanitizes HTML based on cleanType property ('none', 'simpleText', 'simple', 'basic', 'relaxed')
surroundWith(String prefix, String suffix) String Wraps string with prefix and suffix
surroundWith(String fix) String Wraps string with HTML tag (auto-generates closing tag)
escape() String Converts HTML special characters to entities
unescape() String Converts HTML entities back to characters
quote() String Wraps string in double quotes and escapes internal quotes
strip(String regex) String Removes all occurrences of regex pattern
encode() String URL-encodes the string (UTF-8)
decode() String URL-decodes the string (UTF-8)
toBase64() String Encodes string to Base64
fromBase64() String Decodes Base64 string
kebab() String Converts to kebab-case (e.g., "myURLAddress" → "my-url-address")
snake() String Converts to snake_case (e.g., "HelloWorld" → "hello_world")
slugify() String Converts to URL-friendly slug (removes special chars, transliterates)
phone() String Formats 10 or 11-digit number as US phone number
money() BigDecimal Parses currency string (e.g., "$1,234.56") to BigDecimal
time() Long Parses datetime-local form string to epoch milliseconds
jsonList() List Parses JSON array string to List
jsonMap() Map Parses JSON object string to Map
js() String Wraps string in <script type='text/javascript'> tags
if(Closure c) String Returns string if closure evaluates true, empty string otherwise
roll() Integer Evaluates dice notation (e.g., "2d6+3") and returns roll result
cdata() String Wraps string content in CDATA tags for safe embedding

## Number Methods

Method Returns Description
money() String Formats number as currency using default Locale (e.g., "$1,299.95")
ordinal() String Returns ordinal representation (e.g., 1 → "1st", 22 → "22nd")
hours() Long Converts number to milliseconds (hours × 60 × 60 × 1000)
minutes() Long Converts number to milliseconds (minutes × 60 × 1000)
seconds() Long Converts number to milliseconds (seconds × 1000)
days() Long Converts number to milliseconds (days × 24 × 60 × 60 × 1000)
time() String Formats epoch milliseconds as "hh:mm:ss a" (12-hour with AM/PM)
date() String Formats epoch milliseconds as "MMMM dd, yyyy"
dateRaw() String Formats epoch milliseconds as "MM/dd/yyyy"
dateTime() String Formats epoch milliseconds as "MMMM dd, yyyy hh:mm a z"
dateTimeRaw() String Formats epoch milliseconds as "MM/dd/yyyy hh:mm a z"
relativeTime() String Returns human-friendly relative time (e.g., "5 minutes ago", "in 2 hours")
formTime() String Formats epoch milliseconds for HTML datetime-local input ("yyyy-MM-dd'T'HH:mm")

## Integer-Specific Methods

Method Returns Description
random() Integer Returns random integer between 0 (inclusive) and the number (exclusive)
randomID() String Generates random hex ID of specified length (1-32), starting with letter a-f

## List Methods

Method Returns Description
clean() List Cleans String items in list based on cleanType property (modifies in place)
snap(Integer time, Object obj) List Temporarily adds item(s) for specified milliseconds, then removes
random() Object Returns random item from list
combine(Closure c) String Collects items using closure and joins into string
combine(Closure sort, Closure collect) String Sorts using first closure, collects with second, joins into string
including(Object obj) List Adds item or items from another list, returns modified list for chaining
json() String Serializes list to JSON string
if(Closure c) Object Returns first element if closure evaluates true, second element otherwise

## Map Methods

Method Returns Description
snap(Integer time, String key, Object obj) Map Temporarily adds key-value pair(s) for specified milliseconds, then removes
combine(Closure c) String Collects entries using closure and joins into string
combine(Closure sort, Closure collect) String Sorts using first closure, collects with second, joins into string
including(Map map) Map Adds all entries from another map, returns modified map for chaining
random() Map.Entry Returns random key-value entry from map
json() String Serializes map to JSON string

## Collection Methods

Method Returns Description
json() String Serializes any collection to JSON string

## Object Methods

Method Returns Description
isPresent(Collection c) Boolean Fluent alternative to collection.contains(object)
_update() void Triggers reactive updates for all bound connections
_forceUpdate() void Forces reactive update regardless of value changes
cdata() String Wraps object (or its JSON representation) in CDATA tags

# Enhancement Concerns

The enhancements can be grouped into several categories, each addressing specific development needs. While they can be used throughout your codebase, some are particularly useful in specific contexts, such as within Launchpad templates or when processing user input.

## String Manipulation and Formatting

Spaceport provides powerful tools for transforming strings. Case conversions handle a variety of inputs intelligently:

// Case and format conversions
"hello_world".kebab()      // Returns "hello-world"
"HelloWorld".kebab()       // Returns "hello-world"
"Hello World".snake()      // Returns "hello_world"
"Hello World!".slugify()   // Returns "hello-world"

The kebab() and snake() methods intelligently handle CamelCase, spaces, hyphens, and underscores while trimming excess whitespace. The slugify() method goes further by removing or transliterating non-ASCII characters and stripping most punctuation.

The versatile surroundWith() method wraps strings with prefix and suffix. When given a single argument that looks like an HTML tag (even with attributes), it intelligently creates the corresponding closing tag:

"test".surroundWith("->", "<-") // Returns "->test<-"
"content".surroundWith("<div class='main'>") 
// Returns "<div class='main'>content</div>"

Additional utilities include quote() for wrapping in quotes with internal escaping, strip(regex) for removing pattern matches, and phone() for formatting 10 or 11-digit numbers into standard US phone format.

## HTML, Web, and Security

The clean() method sanitizes HTML to prevent XSS attacks. Set the cleanType property to control behavior:

For manual escaping, escape() converts HTML characters to entities, while unescape() reverts them. URL handling is simplified with encode() and decode() for safe parameter inclusion. The js() method wraps JavaScript in proper script tags.

The cdata() method wraps content in CDATA tags for safe embedding in XML contexts, automatically converting non-string objects to JSON:

"<script>alert('test')</script>".cdata()
// Returns <!--<![CDATA[<script>alert('test')</script>]]>--!>

[name: "Test", value: 123].cdata()
// Returns <!--<![CDATA[{"name":"Test","value":123}]]>--!>

## Data Serialization and Conversion

Convert between data formats effortlessly. The universal json() method serializes any Collection or Map:

[name: "Groovy", version: 4].json() 
// Returns '{"name":"Groovy","version":4}'

Parse JSON with jsonMap() for objects or jsonList() for arrays:

'{"name":"Groovy"}'.jsonMap()  // Returns [name: "Groovy"]
'[1, 2, 3]'.jsonList()         // Returns [1, 2, 3]

Base64 encoding is available through toBase64() and fromBase64(). Parse formatted currency strings into BigDecimal with String.money():

'$1,234.56'.money()  // Returns 1234.56 as BigDecimal

The roll() method evaluates tabletop dice notation, perfect for games or simulations:

"2d6+3".roll()  // Returns result of rolling 2 six-sided dice plus 3
"d20".roll()    // Returns result of rolling 1 twenty-sided die

## Collection Handling

The snap() method temporarily adds items with automatic removal after a specified duration—ideal for flash messages or temporary flags:

def messages = []
messages.snap(5000, "This message disappears in 5 seconds.")

def userFlags = [:]
userFlags.snap(1.minutes(), 'isNew', true)

The including() method fluently adds items while returning the collection for chaining:

def list = [1, 2, 3].including(4).including([5, 6])
// Returns [1, 2, 3, 4, 5, 6]

Retrieve random items with random(), which returns a random element from a List or a random Map.Entry from a Map.

The powerful combine() method aggregates collections into strings:

def list = [5, 3, 1, 4, 2]
// Sorts the list, then joins the items into a string
list.combine({ it }, { it }) // Returns "12345"

def map = [c: 3, a: 1]
// Sorts by key, then combines the values
map.combine({ it.key }, { it.value }) // Returns "13"

## Time and Date Operations

Working with dates and times (represented as epoch milliseconds) is dramatically simplified. Convert numbers into durations:

def fiveHoursThirtyMinutes = 5.hours() + 30.minutes()
def deadline = System.currentTimeMillis() + 2.days()

Format epoch milliseconds into human-readable strings:

def timestamp = System.currentTimeMillis()

timestamp.date()         // "October 28, 2025"
timestamp.time()         // "02:30:45 PM"
timestamp.dateTime()     // "October 28, 2025 02:30 PM EDT"
timestamp.dateRaw()      // "10/28/2025"
timestamp.dateTimeRaw()  // "10/28/2025 02:30 PM EDT"
timestamp.relativeTime() // "just now" or "in 5 minutes"
timestamp.formTime()     // "2025-10-28T14:30" (for datetime-local inputs)

The relativeTime() method provides human-friendly descriptions like "just now", "5 minutes ago", "in 2 hours", "3 days ago", etc., automatically choosing appropriate units.

Parse form datetime strings back to epoch milliseconds:

"2025-10-28T14:30".time()  // Returns epoch milliseconds

## Numeric Utilities and Generation

Format numbers as currency using the default JVM Locale:

1299.95.money()  // Returns "$1,299.95" (in US Locale)

Get ordinal representations:

1.ordinal()   // Returns "1st"
22.ordinal()  // Returns "22nd"
103.ordinal() // Returns "103rd"

Generate random integers:

10.random()  // Returns random number from 0 to 9

Create random IDs suitable for HTML IDs and CSS class names with randomID(). It generates hexadecimal strings guaranteed to start with a letter (a-f), with lengths between 1 and 32 characters:

8.randomID()   // Returns random 8-character hex like "e4b1a0c9"
16.randomID()  // Returns random 16-character hex like "a3f8d9c2b1e4567f"

## General and Conditional Utilities

The if() method provides concise conditional string production:

// Only show the admin link if the user is an admin
def adminLink = "<a href='/admin'>Admin</a>".if { user.isAdmin() }

For lists, if() enables conditional selection between two values:

def message = ["Success!", "Failed"].if { operation.succeeded() }
// Returns "Success!" if true, "Failed!" if false

Check object presence with readable syntax:

5.isPresent([1, 3, 5])  // Returns true
'x'.isPresent(['a', 'b'])  // Returns false

## Reactive System Methods

> Note: These methods are primarily for internal use by Spaceport's reactivity system. Understanding them can be > helpful for advanced scenarios, but most applications won't need to call them directly.

The _update() method triggers reactive updates for all connections bound to an object. When you modify a reactive variable, this method notifies all connected clients:

// Usually called automatically, but can be triggered manually
myReactiveList.add("new item")
myReactiveList._update()  // Notify all connected clients

The _forceUpdate() method forces an update regardless of whether values actually changed, useful when you need to refresh client state:

// Force refresh even if no changes detected
myObject._forceUpdate()

These methods work behind the scenes with Launchpad's reactive features. See Launchpad and Server Elements for more information on building reactive components.

# Next Steps

Explore the various modules of Spaceport to see how these class enhancements can be applied in real-world scenarios: