The Project Provisioning Protocol is used between a project creation tool (the server) and an interface (the client) where a developer wishes to generate a new project. Messages are sent between the client and the server to inform the project creation tool how the user wishes to generate the project, and inform the user what options are available to them. The following diagram illustrates the communications between a tool and an interface through the process of creating a new project.
- Reason For This Protocol
- Contributing
- Message Overview
- Base Protocol
- Project Provisioning Protocol
- Protocol Objects
- Example Interactions
- License
Coders are do-ers, so when they wish to learn a new language or technology jumping into a new project is one of the first things they do. This allows coders to be exposed to simple ideas, syntaxes, and confirms that all the required technologies they will need are properly configured.
However, without a common protocol for creating projects not all technologies offer such a feature to users, leaving them behind in the orientation process of that technology. This is caused by valid reasons. Generating the support for new project creation across multiple interfaces (such as IDEs, web sites, or CLIs) is costly to developers and if they do create project provisioners, it is not ensured that they will be made in such a way that helps new users, also updates to all the different interfaces would be costly, leading to outdated tools only confusing new users more.
With a common protocol for project creation (or provisioning), technology developers only create one provisioning tool and any interface would be able to implement it, and these provisioning tools will be held to a higher standard and as a community we can decided what are the features that will most help with onboarding developers to new technologies.
The Project Provisioning Protocol is in its beginning stages, if this project sparks ideas that you think would add value to the project, create an issue so we can discuss it.
Create the connection between an interface and the provisioner
- ➡️ Initialize
- ⬅️ Result
Validate a potential input for project provisioning and to notify the user of required changes
- ➡️ Validation
- ⬅️ Result
Preview to the user what will happen if provisioning is requested
Provision the project and notify the client of the new project location
Instruct the client what actions will be required to provision the project, used when the server is unable to do so itself
- ➡️ ProvisionInstructions
- ⬅️ Result
The communication between the interface and the provisioner uses JSON RCP v2.0. The descirption of the base protocol is that same as the one for the Language Server Protocol and can be found in the "Base Protocol" section of the Language Server Protocol specification.
(Client -> Server) A request to begin the project provisioner parameter generation process, this opens and keeps open a connection to a server for future messages
Method: projectProvisioning/initialize
Initialize {
supportMarkdown: Boolean,
allowFileCreation: Boolean
}
supportMarkdown
: Informs the server if the client is capable of displaying markdown strings or if text that is intended to be displayed should be limited to raw StringsallowFileCreation
: Informs the server if it is able to generate the project itself and only inform the client where it has generated the project or if the files necessary for creation and their contents should be sent to the client on provisioning
(Server -> Client) A response to inform the client what the server's capabilities are and what the default parameter values are
InitializeResult {
versionRequired: Boolean,
validationSupported: Boolean,
previewSupported: Boolean,
templates: Template[],
componentVersions: ComponentVersion[],
defaultProvisioningParameters: ProvisioningParameters | null
}
versionRequired
: Whether the server need the user to define a project version before creationvalidationSupported
: Whether the server is capable of responding to validation requests, informing the client if a set of parameters are validpreviewSupported
: Whether the server is capable of previewing what will be done to provision the projecttemplates
: A list of Template objects defining the template projects available from this provisionercomponentVersions
: A list of ComponentVersion objects listing all the components required for this project creation and the versions availabledefaultProvisioningParameters
: Either a ProvisioningParameters object or null if there are no default values for the interface
(Client -> Server) A request to validate a set of parameters for project provisioning
Method: projectProvisioning/validation
The message contents is the Provisioning-parameters object.
(Server -> Client) Whether the parameters are valid or the errors with the parameters
ValidationResult {
errorMessage: String | null,
erroneousParameters: ErroneousParameter[]
}
errorMessage
: If there is an error with the parameters, this is either an overarching error message or an error message that does not relate to any one specific parameter
erroneousParameters
: If there is an error with the parameters, A list of ErroneousParameter objects listing parameter specific errors
If errorMessage
is null
and erroneousParameters
is empty, then the given parameters are valid for provisioning
(Client -> Server) A request to preview the effects a set of parameters would have if used for project provisioning
Method: projectProvisioning/preview
The message contents is the ProvisioningParameters object.
(Server -> Client) A preview of the effects a set of parameters would have if used for project provisioning or the errors stopping the preview from being generated
PreviewResult {
errorMessage: String | null,
erroneousParameters: ErroneousParameter[],
message: String | null
}
errorMessage
: If there is an error with the parameters, this is either an overarching error message or an error message that does not relate to any one specific parameter
erroneousParameters
: If there is an error with the parameters, A list of ErroneousParameter objects listing parameter specific errors
message
: If errorMessage
is null
and erroneousParameters
is empty, then a message explaining what will happen when the project is provisioned. If supportMarkdown
in the Initialize message was true then the message will be interpreted as markdown by the client
(Client -> Server) A request to provision a project with a set of given parameters.
Method: projectProvisioning/provision
The message contents is the ProvisioningParameters object.
(Server -> Client) The resulting effects of provisioning the project or the errors stopping the provisioning
ProvisionResult: {
errorMessage: String | null,
erroneousParameters: ErroneousParameter[],
location: String,
openFiles: String[]
}
errorMessage
: If there is an error with the parameters, this is either an overarching error message or an error message that does not relate to any one specific parametererroneousParameters
: If there is an error with the parameters, A list of ErroneousParameter objects listing parameter specific errorslocation
: The path to the location that the project was madeopenFiles
: A list of location relative paths to files that should be displayed to the user through the client, to show that the project has been provisioned
(Client -> Server)A request to generate a list of files and their contents to provision a project from a set of given parameters
Method: projectProvisioning/provisionInstructions
The message contents is the ProvisioningParameters object.
(Server -> Client) A list of files and their contents to provision a project from a set of given parameters or the errors stopping this list from being generated
ProvisionInstructionsResult: {
errorMessage: String | null,
erroneousParameters: ErroneousParameter[],
message: String | null,
name: String,
newFiles: Instruction[],
openFiles: String[]
}
errorMessage
: If there is an error with the parameters, this is either an overarching error message or an error message that does not relate to any one specific parametererroneousParameters
: If there is an error with the parameters, A list of ErroneousParameter objects listing parameter specific errorsmessage
: An optional message explaining any extra steps the user will have to take to initializes the project from the files given. Is interpreted as markdown ifInitialize.supportMarkdown == True
name
: The name of the project to be created to be used in generaing the new porject's directory if needednewFiles
: A list of Instruction objects that instruct the client on the files that need to be created for project provisioningopenFiles
: A list of relative paths to files that should be displayed to the user through the client, to show that the project has been provisioned
Template {
id: String,
title: String,
caption: String | null,
componentVersions: ComponentVersion[]
}
id
: ID of the template projecttitle
: UI name of the template projectcaption
: Short description of the template to be used by the UI, such as a tooltipcomponentVersions
: A list of ComponentVersion objects listing all the components required for this template creation and the versions available
Used by:
ComponentVersion {
id: String,
title: String,
caption: String | null,
versions: Version[]
}
id
: ID of the componenttitle
: UI name of the component that requires a version selectioncaption
: Short description of the component to be used by the UI, such as a tooltipversions
: A list of Version objects listing all the available versions of this component
Used by:
Version {
id: String,
title: String,
caption: String | null
}
id
: ID of the versiontitle
: UI name of the versioncaption
: Short description of the version to be used by the UI, such as a tooltip
Used by:
ProvisioningParameters {
name: String,
location: String | null, //Is always null if InitializeRequest->allowFileCreation == false
version: String | null,
templateSelection: TemplateSelection | null,
componentVersionSelections: ComponentVersionSelection[ ],
}
name
: Name of the project to be createdlocation
: Relative path to the location to provision the projectversion
: Version to define the project attemplateSelection
: A TemplateSelection object to use during provisioningcomponentVersionSelections
: A list of ComponentVersionSelection objects to define which versions of each component will be used during provisioning
Used by:
ComponentVersionSelection {
id: String,
versionId: String | null
}
id
: ID of the component requiring a version selectionversionId
: ID of the component's version
Used by:
TemplateSelection {
id: String,
componentVersions: ComponentVersion[]
}
id
: ID of the templateversionId
: A list of ComponentVersion objects listing all the component versions selected for this template
Used by:
ErroneousParameter {
parameterType: String, // (name, location, version, template, templateComponentVersion, componentVersion)
message: String,
componentVersionId: String | null
}
parameterType
: Name of the parameter which is causing the errormessage
: UI message describing the errorcomponentVersionId
: ID of the component version causing the error, only necessary if it is a component version causing the error
Used by:
Instruction: {
path: String,
content: String
}
path
: A relative path including the file name for the file to be createdcontent
: The content of the file to be created
Used by:
The user opens the IDE and wishes to create a new Rust project. They then open the New Project Wizard.
Method: projectProvisioning/initialize
Direction: Client -> Server
Message:
{
supportMarkdown: true,
allowFileCreation: true
}
Method: projectProvisioning/initialize
Direction: Server -> Client
Message:
{
versionRequired: false,
validationSupported: true,
previewSupported: true,
templates: [{
id: 'hello_world',
title: 'Hello World Project',
caption: 'A basic Rust project that outputs \'Hello World\' to the console',
componentVersions: []
},{
id: 'crates',
title: 'External Crate Example Project',
caption: 'Cargo project that depends on the `rand` external crate',
componentVersions: [{
id: 'rand_version',
title: 'rand Version',
caption: 'The version of the `rand` crate that will be used',
versions: [{
id: '0.5.0',
title: '0.5.0',
caption: null
}{
id: '0.4.2',
title: '0.4.2',
caption: null
}]
}]
}],
componentVersions: [],
defaultProvisioningParameters: {
name: 'new_rust_project',
location: '/new_rust_project',
version: null,
templateSelection: {
id: 'hello_world',
componentVersions: []
},
componentVersionSelections: []
}
}
The returned information is then used by the client to build the wizard for the user to fill in. As the user fills in the various fields, the inputed parameters are validated.
Method: projectProvisioning/validation
Direction: Client -> Server
Message:
{
name: 'my_rust_project',
location: 'invalid/path/my_rust_project
version: null,
templateSelection: {
id: 'hello_world',
componentVersions: []
},
componentVersionSelections: []
}
Method: projectProvisioning/validation
Direction: Server -> Client
Message:
{
errorMessage: 'Unable to create a new folder in the given location',
erroneousParameters: [{
parameterType: 'location'
message: 'Unable to create a new folder in the given location',
componentVersionId: null
}]
}
After all the errors are addressed, the user wishes to review their inputs before creating the project, so they press "Next" in the wizard.
Method: projectProvisioning/preview
Direction: Client -> Server
Message:
{
name: 'my_rust_project',
location: 'path/to/workspace/rust_projects/my_rust_project
version: null,
templateSelection: {
id: 'hello_world',
componentVersions: []
},
componentVersionSelections: []
}
Method: projectProvisioning/preview
Direction: Server -> Client
Message:
{
errorMessage: null,
erroneousParameters: [],
message: '# Steps that will be take to create the project
- A new directory named `my_rust_project` will be created in `path/to/workspace/rust_projects/`
- `mkdir path/to/workspace/rust_projects/my_rust_project`
- This directory will contain a new directory called `src` which will contain `main.rs`
- `touch path/to/workspace/rust_projects/my_rust_project/main.rs`
- `main.rs` will contain the required Rust code to output "Hello World"
- `echo "fn main() { println!(\"Hello, world!\"); }" > path/to/workspace/rust_projects/my_rust_project/main.rs`'
}
The user is now confident in what will happen when they confirm the provisioning and press "Finish".
Method: projectProvisioning/provision
Direction: Client -> Server
Message:
{
name: 'my_rust_project',
location: 'path/to/workspace/rust_projects/my_rust_project
version: null,
templateSelection: {
id: 'hello_world',
componentVersions: []
},
componentVersionSelections: []
}
Method: projectProvisioning/provision
Direction: Server -> Client
Message:
{
errorMessage: null,
erroneousParameters: [],
newFiles: ['path/to/workspace/rust_projects/my_rust_project/main.rs'],
openFiles: ['path/to/workspace/rust_projects/my_rust_project/main.rs']
}
The user is now presented with the main.rs
file and can begin working.
// TODO
// TODO