-
Notifications
You must be signed in to change notification settings - Fork 5
Standards
This documentation is based on the solid foundation of the dbatools project and is intended to provide a consistent and maintainable approach to developing and contributing to the FabricTools PowerShell module. The standards outlined here are subject to change as the project evolves, and contributions are welcome to help improve and refine these practices.
This document outlines the standards and practices for contributing to the FabricTools PowerShell module. It is intended to ensure consistency, maintainability, and quality across the codebase.
There are MANY things that are not currently consistent across the module at the current time. This document contains the standards for the expected state and shall be used as the guidance for future development and contributions.
❗ Important |
---|
Having said that, we do not expect you to follow (as of now) any guidance listed below and marked with 🔒 icon. |
In general, if not specified here the standards will follow the Powershell Community Standards as outlined in the PowerShell and Best Practice Style Guide as the guideline for the code. If not specified there then the PowerShell documentation shall be taken as the standard.
- Do not depend on or incorporate commands from external modules unless you have explicit permissions/approval (via an issue) from the module owner.
- 🔒#84 Do not use the built-in write output commands (e.g.
Write-Output
,Write-Host
,Write-Verbose
). Use the PSFramework module for logging and outputting messages and for configuration. (NOTE: This is a work in progress, and we are still working on the PSFramework integration.) - Do not use any backticks for line continuation.
- Do not return an error, a warning or any information message if there is nothing to return. For example -
Get-FabricLakehouse
should not return an error if there are no lakehouses, it should just return nothing.Get-FabricLakehouse -lakehouseName 'MyLakehouse'
should not return anything if the lakehouse does not exist. - 🔒#134 Do not use
return
in the code. The last line of the function will be returned automatically. # We should not be using the return keyword. - Do not use aliases in the code. All function calls should use the full function name. This is to ensure that the code is readable and understandable by all users, and also to avoid any confusion with other aliases that may be defined in the user's environment.
- 🔒#84 Do not use
Write-Message
. Use the PSFramework module for logging and outputting messages. (NOTE: This is a work in progress, and we are still working on implementing the PSFramework integration.)
All of our public commands have the Fabric
prefix on the noun and are singular in name.
We only utilize the approved verbs in PowerShell.
Parameters, referring to inputs for the commands, are to use camel caps where each word is capitalized (e.g. SqlInstance
).
Unless circumstances dictate otherwise any command should support multiple objects being passed as input and support piping.(NOTE: This is a work in progress, and we are still working on the piping support.)
Mandatory should only be specified on the parameter if it is being set $true, since $false is the default.
When a command requires a Workspace, the parameter should be named Workspace
and should accept multiple workspaces.
When a command requires a resource name, the parameter should be named Name
and should accept multiple names. The parameter should also support piping from other commands that return that resource type eg Set-FabricLakehouse
should accept piping from Get-FabricLakehouse
.
When a command requires an ID, the parameter should be named Id
and should accept multiple IDs. The parameter should also support piping from other commands that return that resource type (e.g. Get-FabricLakehouse
). (NOTE: This is a work in progress, and we are still working on the naming as well as the piping support.)
The exception to these rules are when there are greater than one resource type. In this scenario, the parameter Name
shall be used for the resource first in the function name and all other parameters shall be named ResourceTypeName
(e.g. LakehouseName
, WarehouseName
, DataPipelineName
, etc.). The same rules apply for the parameter Id. (NOTE: This is a work in progress, and we are still working on the naming as well as the piping support.)
When referencing the parameters/inputs within code they should use the camel caps (e.g. $Lakehouses
) but other processing variables should utilize camel casing such as $lakehouseName
.
This refers to the comment-based help (CBH) that is required for each command. All public commands in the module are required to have CBH (we test for this in PR processing). The documentation should be complete and at a minimum include the following sections for CBH (some will repeat):
<#
.SYNOPSIS
Short description of the function.
.DESCRIPTION
This section should be more descriptive and longer than above one.
.PARAMETER
This will be one for each parameter input the command utilizes
.NOTES
Tags: SqlDatabase, deployment
Author: First LastName (@twitterHandle), YourWebSite.net
Website: https://fabrictools.io
Copyright: (c) 2025 by FabricTools, licensed under MIT
License: MIT https://opensource.org/licenses/MIT
.EXAMPLE
#>
The NOTES section will be required to contain the website, copyright and license information as well as the Initial author and changelog.
TODO: Ensure that there can be a LINK section for the help.
The examples provide a way for users to see how the command can be used for various scenarios or combinations of parameters/inputs. A good start of examples to provide are given below:
- Splatting
- Piping input from other commands (e.g.
Get-FabricNoun ... | Set-FabricNoun ...
) - Passing in multiple values to a given parameter (where supported)
- Outputting only certain properties, or otherwise manipulating output for a certain purpose
- All strings should be enclosed in single quotes unless there is a need for variable expansion or special characters, in which case string formatting should be used.
The format of the examples should include a view as if you are on an interactive prompt running the command. So a sample where you may have multiple calls:
<#
.EXAMPLE
PS C:\> $data = Get-FabricNoun -WorkspaceId 'guid' ....
PS C:\> $data | Set-FabricNoun ...
#>
Where you may do a multi-line call on the command line you will include the >>
just as the PowerShell prompt would:
<#
.EXAMPLE
PS C:\> $files = Get-ChildItem C:\temp
PS C:\> foreach ($f in $files) {
>> Verb-FabricNoun -WorkspaceId 'guid' -Name $f ....
>> }
#>
🔒#87
If an example uses more than two/three parameters, or if including all parameters in a single line would make the example difficult to read, the parameters should be presented in a splatting format. Splatting involves creating a hash table of parameters and passing it to the command using the @
symbol. This improves readability and maintainability of the examples.
<#
.EXAMPLE
Verb-FabricNoun -WorkspaceId 'guid' -Name $objectName
.EXAMPLE
$params = @{
Workspace = 'WorkspaceName'
SetId = 'xxxx-yyyy'
Format = 'json'
}
Verb-FabricNoun @params
#>
If only one or two parameters are used and the example remains clear and concise, parameters may be specified directly in the command line.
The code for the function should be formatted in a way that is easy to read and understand.
The following are some guidelines for formatting the code:
- Use 4 spaces for indentation (no tabs).
- Formatting strings: both
"$value"
and"{0}" -f $value
are allowed to be used.
- Use the
Begin
,Process
, andEnd
blocks to separate the code into logical sections as defined in Input processing methods. - Each public function should execute
Confirm-TokenState
at the beginning. - Every new public function which accept
-WorkspaceId
parameter, should also handle pipeline for workspaces.
Each public function must use Invoke-FabricRestMethod
to communicate with Fabric or Power BI api endpoint and retrieve outcome to $response
variable.
Please bear in mind:
-
GET
is optional and defult parameter forMethod
, however we recommend to provide it for readability. - Do not use backticks to create multiline parameters:
# DO NOT use backticks (`) moving forward:
$response = Invoke-FabricRestMethod `
-Uri $apiEndpointUrl `
-Method Post
We will be gradually removing such code when changes to a function logic is needed.
- For readability and to avoid small mistakes - we ask to use splatting:
$apiParams = @{
Uri = $apiEndpointUrl
Method = 'Post'
Body = $bodyJson
}
$response = Invoke-FabricRestMethod @apiParams
Function Invoke-FabricRestMethod
sets additional variables (script scope) when receiving the API response. They are:
- $script:statusCode = $statusCode
- $script:responseHeader = $responseHeader
Try to use them for read-only purposes.
Validate block must validate the response. Sometimes only statusCode = 200 is expected, in other cases a function can return more codes. All documened codes should be handle appropriately.
🔒#132
Currently, the private function is being developed to handle all returned codes for you. The function isTest-FabricApiResponse
, but it's under development and review process to ensure it covers all cases and can be use for all public functions moving forward. Until then, use the following approach to handle the API result.
# Step X: Validate the response code
if ($statusCode -ne 200) {
Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error
Write-Message -Message "Error: $($response.message)" -Level Error
Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error
Write-Message "Error Code: $($response.errorCode)" -Level Error
return $null
}
Take a look at this code to see how currently we handle LRO (Long-Running Operations): New-FabricLakehouse.ps1
New functions with LRO on API will implement NoWait
switch parameter that enables user to avoid waiting for response when not needed.
When pagination is available for an API function, it is strongly recommended to implement correct handling of the paginated response (i.e., handling $continuationToken) to ensure all data is retrieved:
ℹ️ There are few blocks of code needed to handle pagination. For an example - please take a look at code from
Get-FabricEventhouse
function.
TODO. We need an agreement for new functions.
Currently it looks like below:
# Step 9: Handle results
if ($eventhouse) {
Write-Message -Message "Eventhouse found in the Workspace '$WorkspaceId'." -Level Debug
return $eventhouse
} else {
Write-Message -Message "No Eventhouse found matching the provided criteria." -Level Warning
return $null
}
ℹ️ The above example comes from
Get-FabricEventhouse
function.
Function and Parameter aliases must be kept for at least two major versions to ensure that backward compatibility is maintained. However, new commands should not have aliases created for them.
🔒 KN: Can we introduce this since version 1.0, as the module is new and has never been promoted as production-ready?
Input Parameters & aliases naming convention:
a. WorkspaceId
- Alias 'Id' allowed only if there is no other "Id" parameters
b. WorkspaceName
- Alias 'Name' allowed only if there is no other "Name" parameters
c. DisplayName
- Alias 'Name' is allowed for New
or Update
functions
d. Description
Each public function should return the result from API.
Ideally, the result should be return like-to-like, with exceptions when:
- Result contains "value" element as a wrapper for the major data -
value
should be return. - 🔒 Error details should be return when error returned from API. By default it contains the following columns: x, y, z
- 🔒 If the API response includes properties with nested objects or arrays, and the user specifies the
-Explode
switch parameter, the function should flatten (unfold) these nested structures into separate objects or properties for easier consumption.
Example:
Suppose the API returns the following response:
{
"value": [
{
"Id": "1",
"Name": "Item1",
"Details": {
"Type": "A",
"Status": "Active"
}
},
{
"Id": "2",
"Name": "Item2",
"Details": {
"Type": "B",
"Status": "Inactive"
}
}
]
}
With the -Explode
switch, the function should output:
Id | Name | Type | Status |
---|---|---|---|
1 | Item1 | A | Active |
2 | Item2 | B | Inactive |
There should be an OutputType
attribute on the function to indicate what type of object is returned by the command. This is important for users to know what to expect when using the command and for PowerShell to provide IntelliSense and other features.
Use try/catch/finally
blocks to handle errors and exceptions in the code. This is important for ensuring that the code is robust and can handle unexpected situations gracefully.
Do not use try/catch for code logic or workflow control. Use it only for error handling.
🔒 Note: This is a work in progress, and we are still working on the PSFramework integration.
Use the PSFramework module for configuration, logging and outputting messages. This is important for ensuring that the code is consistent and can be easily maintained. The PSFramework module provides a consistent way to log messages and output information, and it also provides a way to configure the logging behavior and enables logging to a number of different targets (e.g. file, event log, database, KQL etc.).
TODO: Example of usage
Any public function that removes resources (i.e., functions with the Remove-
verb) must implement the following pattern to ensure safe and user-confirmed operations:
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
This ensures that the function supports PowerShell's -WhatIf
and -Confirm
parameters, allowing users to preview changes and require confirmation before performing high-impact actions. Setting ConfirmImpact = 'High'
prompts for confirmation by default, which is appropriate for operations that delete or remove resources.
ℹ️ For example:
Remove-FabricEventstream
function.
- Unfold the pages links above to navigate the wiki.