feat(schema): typed CLI properties for extends-based formae#546
Draft
naxty wants to merge 1 commit into
Draft
Conversation
Forma files can now extend the base module and declare CLI properties as a
plain typed class:
extends "@formae/forma.pkl"
properties: Props
class Props {
/// The name to deploy
name: String = "pel"
port: Int(this > 0) = 8080
}
Member name = flag, declared default = default, doc comment = help text, and
pkl type constraints validate CLI input. Property access is statically typed,
so editors resolve properties.name instead of flagging it as unresolved.
Mechanics: forma.pkl's output now self-injects - on first evaluation the
module amends itself with a properties instance filled from external prop:
values (reflect members, read, coerce by declared type, fall back to declared
defaults, validate via toTyped), then evaluates the amended module's output.
Late binding carries the injected values into all resources. This mirrors how
pkl:Command's runtime injects options (synthesize a module that amends the
command module). The manifest renders Value from the instance so manifest and
resources always agree.
Backward compatible: properties is widened to Any?, legacy properties{} blocks
pass through the render unchanged, amends-based formae keep working against
the now-open module, and their serialized JSON is byte-identical. Stray module
properties never render (output serializes FormaRender only).
Not included yet: unknown-property validation throw, scaffold/testdata
migration, docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
extends "@formae/forma.pkl"and declare CLI properties as a plain typed class (properties: Props+class Props { name: String = "pel" }). Member name = flag, declared default = default, doc comment = help text, pkl type constraints validate CLI input (-p port=-5fails theInt(this > 0)constraint).properties.nameinstead of flagging it as an unresolved reference, which is the biggest source of red squiggles in forma files today.forma.pkl: the output amends the module once with a properties instance filled from externalprop:values, then renders normally — late binding carries injected values into all resources. Same mechanism pkl's ownpkl:Commandruntime uses. Plainpkl eval -p name=test forma.pklworks unchanged; no evaluator/Go changes.propertieswidens toAny?, legacyproperties {}blocks pass through the render untouched,amends-based formae keep working against the now-open module.Verification
make test-pklandgo test ./internal/schema/pkl/...green with the existing (unmigrated) testdata.testdata/forma/extends_props_test.pkl: defaults,-pinjection into resources and manifest, constraint violations.Clouds = …) never reach the rendered output — onlyFormaRenderserializes.Deliberately not in this PR
form {}currently vanishes silently — same follow-up as the design discussion).--help, typed flags).