Description
Plaster is a good platform to scaffold content, and I have used it for building module templates. But recently I have been using it to scaffold application configuration data.
One shortcoming I have found is that Plaster uses constrained runspaces to perform the scaffolding. Correct me if I'm wrong, but this was to provide safety around what is essentially Invoke-Expression. The difficulty comes from trying to write clean code and turn comma separated strings into properly formatted output.
Example template files:
Test.json.txt
(This is the simplest way I could think to join comma separated strings into a JSON array.)
{
"Key": "Value",
"Array": [
""
<%
if ($PLASTER_PARAM_Param1) {
$PLASTER_PARAM_Param1.split(",").trim().foreach({",`"$_`""})
}
%>
]
}
The resulting file is not well formatted, and has a blank element in the first position of the array:
Test.json
{
"Key": "Value",
"Array": [
""
,"Test"
,"Testing"
]
}
Another option is to use .Replace
, and replace commas with newlines(`n) and double quotes ("). But newlines are not interpolated in the constrained runspace. So this doesn't work:
"`"$($PLASTER_PARAM_Param1.replace(",", "`"`n,`""))`""
Possible Solutions
One solution that I would like to see, is a configuration file that can be placed in a user directory (like $PROFILE), or in the module folder itself. This file contains a list of allowable cmdlets in the scaffolding process, and Invoke-Plaster
adds these cmdlets to the runspace. This would provide the extensibility, without having to rebuild the module with a custom list of cmdlets. It also puts the security onus on the user that adds the commands. Either the installing user can add a config file, or only the current user's config file is used during scaffolding.
Another solution, is adding a parameter to the Invoke-Plaster
function, like -AllowedCmdlets
to add a list of cmdlets to be used during scaffolding. This makes it a little easier for the user to scaffold with the cmdlets they need, but on the flip-side it makes it easier to pass cmdlets required for command injection. So this provides a little less control when scaffolding content.
Either of these solutions would allow the code to be cleaner, like so:
{
"Key": "Value",
"Array": [
<%
if ($PLASTER_PARAM_Param1) {
$output = $PLASTER_PARAM_Param1 -split ",") -join "`",`n`""
"`"$output`""
} else {
"`"`""
}
%>
]
}