🔌 Extensibility
KodiScript is designed to be extensible. You can enrich the language by adding your own native functions, allowing scripts to interact with your system while maintaining full control over what’s exposed.
Why Extensibility?
The built-in native functions cover common use cases, but your application likely has unique requirements:
- Database access: Let scripts fetch users, orders, or any data
- Notifications: Send emails, push notifications, SMS from scripts
- Business logic: Calculate discounts, validate rules, process workflows
- External APIs: Call third-party services securely
- File operations: Read/write files with proper permissions
How It Works
Each SDK provides a registerFunction method that lets you add custom functions callable from KodiScript:
val result = KodiScript.builder("""
let user = fetchUser(123)
let discount = calculateDiscount(user.tier, 100)
print("Discount: " + discount + "%")
""")
.registerFunction("fetchUser") { args ->
// Call your database
mapOf("id" to args[0], "name" to "Alice", "tier" to "gold")
}
.registerFunction("calculateDiscount") { args ->
val tier = args[0] as String
when (tier) {
"gold" -> 20
"silver" -> 10
else -> 5
}
}
.execute()Real-World Example: E-commerce Rules Engine
Imagine letting your business team define discount rules without deploying code:
// Script stored in database, editable by admins
let user = getUser(userId)
let cart = getCart(cartId)
let discount = 0
// Gold members get 20% off
if (user.tier == "gold") {
discount = 20
}
// Extra 5% for orders over $100
if (cart.total > 100) {
discount = discount + 5
}
// Holiday special
if (isHolidaySeason()) {
discount = min(discount + 10, 50) // Cap at 50%
}
// Apply and notify
let finalPrice = cart.total * (1 - discount / 100)
sendNotification(user.email, "Your discount: " + discount + "%")
return { discount: discount, finalPrice: finalPrice }Your backend exposes only the functions you choose:
KodiScript.builder(adminScript)
.withVariable("userId", request.userId)
.withVariable("cartId", request.cartId)
.registerFunction("getUser") { userService.findById(it[0] as Long) }
.registerFunction("getCart") { cartService.findById(it[0] as Long) }
.registerFunction("isHolidaySeason") { holidayService.isActive() }
.registerFunction("sendNotification") { notificationService.send(it[0], it[1]) }
.execute()Security Best Practices
When exposing functions to scripts:
- Validate inputs - Never trust script arguments blindly
- Limit scope - Only expose what’s necessary
- Rate limit - Prevent abuse of expensive operations
- Audit logs - Track what scripts execute
- Sandbox - Scripts can’t access anything you don’t explicitly provide
// ✅ Good: Scoped, validated function
.registerFunction("getUser") { args ->
val id = (args[0] as? Number)?.toLong()
?: throw IllegalArgumentException("Invalid user ID")
userService.findById(id)?.toSafeMap() // Only expose safe fields
}
// ❌ Bad: Too permissive
.registerFunction("query") { args ->
database.executeRaw(args[0] as String) // SQL injection risk!
}Use Cases
| Use Case | Custom Functions |
|---|---|
| E-commerce | getUser, getCart, applyDiscount, sendEmail |
| Workflow Engine | approve, reject, escalate, notify |
| Data Processing | fetchRecord, transform, validate, save |
| IoT/Automation | readSensor, setDevice, scheduleTask |
| Gaming | getPlayer, giveReward, checkAchievement |
Next Steps
- Explore the SDK Reference for your platform
- Check Native Functions for built-in capabilities
- See Variables for injecting context