Making a package or plugin user-configurable
This example demonstrates how to make your package or plugin configurable by a user. To add configuration to your package or plugin, you need to do a few things.
First, you need to declare a configTemplate
in your steamship.json
.
{
"type": "package",
"handle": "a-configurable-package",
...
"configTemplate": {
"name": {
"type": "string",
"description": "The name of the user.",
"default": "you"
},
"favorite_color": {
"type": "string",
"description": "The user's favorite color."
},
"lucky_number": {
"type": "number",
"description": "The user's lucky number"
},
"favorite_true_false_value": {
"type": "string",
"description": "The user's favorite boolean value, true or false."
}
}
}
With this configTemplate
in the steamship.json
, Steamship users will be required to
provide a configuration when instantiating this package:
Steamship.use("a-configurable-package", config={
"name": "Dave",
"favorite_color": "blue",
"lucky_number": 6,
"favorite_true_false_value": False
})
This config will be validated at the time of instance creation for completeness and correct types.
Since we provided a default value for name
in the template, that value can be omitted and "you"
will be used instead.
Now, within the code, you must do a few things. First, you define the inner class that represents the configuration:
class ConfigurableFavoritesPackage(PackageService):
class FavoritesConfig(Config):
"""Configuration required to instantiate this package."""
name: str
favorite_color: str
lucky_number: float
favorite_true_false_value: bool
The names of the fields must align with the names in the configTemplate
.
Next, we tell the Steamship handler how to find our config class:
class ConfigurableFavoritesPackage(PackageService):
...
@classmethod
def config_cls(cls) -> Type[Config]:
return cls.FavoritesConfig
Now when implementing a method, we can use the config fields via self.config.<field_name>
!
@post("my_faves")
def my_faves(self) -> str:
"""Return the user's favorites, in a string."""
return f"""
Hey {self.config.name}!
I can remind you of your favorites.
Your favorite color is {self.config.favorite_color}.
Your lucky number is {self.config.lucky_number}.
Your favorite true/false value is {self.config.favorite_true_false_value}.
Wow, mine too!
"""
When you put it all together, it looks like this:
"""
This package demonstrates how configuration works in Steamship.
"""
from typing import Dict, Any, Type
from steamship import Steamship
from steamship.invocable import PackageService, Config, post
class ConfigurableFavoritesPackage(PackageService):
class FavoritesConfig(Config):
"""Configuration required to instantiate this package."""
name: str
favorite_color: str
lucky_number: float
favorite_true_false_value: bool
def __init__(self, client: Steamship, config: Dict[str, Any] = None, context: InvocationContext = None):
# The superclass init method turns the config param (a Dict)
# into the self.config object (here, a FavoritesConfig)
super().__init__(client, config)
# The config_cls method allows your package to return a class
# that defines its required configuration.
# See Developer Reference -> Accepting Configuration
# for more details. This package uses a few configuration fields
# to record the package user's favorite things.
@classmethod
def config_cls(cls) -> Type[Config]:
return cls.FavoritesConfig
# This method defines the package user's endpoint for adding content
# The @post annotation automatically makes the method available as
# an HTTP Post request. The name in the annotation defines the HTTP
# route suffix, see Packages -> Package Project Structure.
@post("my_faves")
def my_faves(self) -> str:
"""Return the user's favorites, in a string."""
return f"""
Hey {self.config.name}!
I can remind you of your favorites.
Your favorite color is {self.config.favorite_color}.
Your lucky number is {self.config.lucky_number}.
Your favorite true/false value is {self.config.favorite_true_false_value}.
Wow, mine too!
"""