ballerina-spec
ballerina-spec copied to clipboard
Add support for Package Types
For some use cases in tooling and Choreo we need a concept of a package type. A package type is a package that is constrained to have only a given set of language constructs.
Usecase: We need to define a package type for data transformation. Here the package should contain only functions and there should be one or more public expression bodied functions.
Here the constraining of a package can be done with a compiler plugin but when it comes to BC and other tooling we need a way to figure out the package type without needing to compile
Possible solution Add “type” attribute to “package” in Ballerina.toml
[package]
org = "jo"
name = "ikman"
version = "0.1.0"
type= "ballerinax/transformer"
Here the type attribute can be the name of the Ballerina package that include the compiler plugin that restrict the package. If the above attribute is specified and if the package has a compiler plugin it will be engaged during the package build.
We can use this feature to create a real "low code" editing experience for Choreo as well by creating another way to edit a single strand function body with restricted constructs, which is what low code is.
Compiler plugins (analyzers) enforce constraints on packages. Here are some sample constraints:
- No service declarations are allowed
- No Listeners are allowed
- All public functions must be expression-bodied functions
The above list contains only syntax-level constraints. Similarly, there can be semantics-related constraints such as:
- Public function parameter types and the return type should be a subtype of
anydata
It is not straightforward to define these constraints in a machine-processable way. Therefore I would let each compiler plugin implement constraints.
Some other use cases:
- a data mapper package which has one module and only public symbols are functions with a particular signature
- similar thing for a low code composition experience and where the body of the function is not free-for-all either (not defined yet .. new idea)
Compiler plugins (analyzers) enforce constraints on packages. Here are some sample constraints:
- No service declarations are allowed
- No Listeners are allowed
- All public functions must be expression-bodied functions
The above list contains only syntax-level constraints. Similarly, there can be semantics-related constraints such as:
- Public function parameter types and the return type should be a subtype of
anydataIt is not straightforward to define these constraints in a machine-processable way. Therefore I would let each compiler plugin implement constraints.
These are all constraints relating to the code itself isn't it? What about constraints that one may want to impose on the package structure itself? e.g., modules other than the default module within the package not allowed
I suppose these can also be enforced through a compiler plugin as well. But might need an additional type of diagnostics for these since the diagnostics usually point to a location in a particular source file.
There's a requirement for package types in supporting custom mediations in Choreo. Specifically for the mediation policies. Those will be written and packaged as Ballerina packages and pushed to Central. But need to be able to identify these as mediation policies when querying for these and need to be able to push these with some associated metadata about these (arbitrary key-value pairs).
Possible solution Add “type” attribute to “package” in Ballerina.toml
[package] org = "jo" name = "ikman" version = "0.1.0" type= "ballerinax/transformer"
We discussed to have the following attribute under the [[package]] table in the Ballerina.toml
[package]
org = "jo"
name = "ikman"
version = "0.1.0"
constraint= "ballerinax/transformer"
is there a way to mark a particular module as a constraint module like "ballerinax/transformer? Or what are the criteria?
I guess One of them is the constraint module should have at least one compiler plugin.
is there a way to mark a particular module as a constraint module like "ballerinax/transformer? Or what are the criteria?
I guess One of them is the constraint module should have at least one compiler plugin.
For Update 3, we thought of treating it as just another library package. It will be published in Ballerina Central and also will be visible like any other package.
@hasithaa yes we can write a validator package to validate if it is a valid constraint package. The rule would be to have only a compiler plugin.
Then the Ballerina.toml of the "ballerinax/transformer" package would be
[package]
org = "ballerinax"
name = "transformer"
version = "1.0.0"
constraint= "ballerina/validator"
Also it will be useful to reuse some of the constraints in others ie. a transformer package should only be a library and should not contain executable. It would be worth while to define a generic validator plugin called "ballerina/library" and reuse it in "ballerinax/transformer". One option is to allow inclusion of other validators when writing a validator package.
[package]
org = "ballerinax"
name = "transformer"
version = "1.0.0"
constraint= "ballerina/validator"
[constraint]
include=["ballerina/library"]
Should the user be able to specify a version for the constraint package?
eg :-
constraint= "ballerina/validator:5.3.4"
As per this comment, compiler plugins, especially code analyzers, enforce constraints on the Ballerina package. Therefore without introducing a new concept here, can we use compiler plugins to achieve the package type requirement?
As per the compiler plugin design, there are two ways to engage a compiler plugin.
- Import a package that contains a compiler plugin.
- Specify the compiler plugin in
Ballerina.toml(Not yet implemented)
What if we add the capability to specify one or more compiler plugins in Ballerina.tom?.
- Any Ballerina package specifies the "ballerina/datatransformer" compiler plugin is a data transformer.
- Any package with the "Choreo/Trigger" is a trigger
We agreed to go ahead with the proposal in this comment.