ballerina-spec icon indicating copy to clipboard operation
ballerina-spec copied to clipboard

Add support for Package Types

Open hevayo opened this issue 3 years ago • 11 comments

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.

hevayo avatar Jun 08 '22 05:06 hevayo

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.

sanjiva avatar Jun 08 '22 07:06 sanjiva

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.

sameerajayasoma avatar Jun 22 '22 21:06 sameerajayasoma

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)

sanjiva avatar Jun 23 '22 01:06 sanjiva

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.

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).

pubudu91 avatar Jun 24 '22 10:06 pubudu91

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"

azinneera avatar Aug 01 '22 18:08 azinneera

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.

hasithaa avatar Aug 02 '22 03:08 hasithaa

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.

azinneera avatar Aug 02 '22 18:08 azinneera

@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"]

hevayo avatar Aug 11 '22 19:08 hevayo

Should the user be able to specify a version for the constraint package? eg :-

constraint= "ballerina/validator:5.3.4"

gayaldassanayake avatar Aug 16 '22 06:08 gayaldassanayake

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.

  1. Import a package that contains a compiler plugin.
  2. 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

sameerajayasoma avatar Oct 06 '22 22:10 sameerajayasoma

We agreed to go ahead with the proposal in this comment.

sameerajayasoma avatar Oct 12 '22 23:10 sameerajayasoma