-
Notifications
You must be signed in to change notification settings - Fork 16
Standards
- Standards for FabricTools
- Do Nots
- Naming Convention
- Documentation
- Function Code
- 🔒 Handle results and return
- Default View
- Aliases
- Output
- Try / Catch / Finally
- PSFramework
Remove-functions
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.
- Do not use the built-in write output commands (e.g.
Write-Output,Write-Host,Write-Verbose). UseWrite-Messageprivate cmdlet which uses the PSFramework module for logging and outputting messages. - 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-FabricLakehouseshould not return an error if there are no lakehouses, it should just return nothing.Get-FabricLakehouse -lakehouseName 'MyLakehouse'should not return anything if a Lakehouse does not exist. - Do not use
returnin the code. The last line of the function will be returned automatically. - 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.
| Identifier type | Rules for naming | Example |
|---|---|---|
| Commands (Advanced Functions) | {Approved verb}-{singular nouns} UpperCamelCase | Get-FabricWorkspace |
| Parameters | UpperCamelCase | [guid] $WorkspaceId |
| Variables | lowerCamelCase | $apiEndpointUrl = 'url' |
| Constants | SCREAMING_SNAKE_CASE | int MAX_COUNT = 10 |
Naming Convention: UpperCamelCase
We only utilize the approved verbs in PowerShell. For a list of approved verbs the cmdlet Get-Verb will list them.
On the noun side it can be composed of more than one joined word using Pascal Case (aka Upper Camel Case) and only singular nouns.
The noun part should be singular and descriptive of what the cmdlet operates on. It should be specific enough to understand its purpose but not overly complex.
All of our public commands (aka Advanced Functions) have the Fabric prefix on the noun and are singular in name.
Naming Convention: UpperCamelCase
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.
ℹ️ 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).
ℹ️ This is a work in progress, and we are still working on 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.
ℹ️ This is a work in progress, and we are still working on the piping support.
Naming Convention: lowerCamelCase
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). It requires to be function name in the first line of each function file, before CBH section.
The documentation should be complete and at a minimum include the following sections for CBH (some will repeat):
function New-FabricWorkspace
{
<#
.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
#>
// Code here
}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 (when needed)
- 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
$data = Get-FabricNoun -WorkspaceId 'guid' ....
$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 ....
>> }
#>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 $valueare allowed to be used.
- Use the
Begin,Process, andEndblocks to separate the code into logical sections as defined in Input processing methods. - Each public function should execute
Confirm-TokenStateat the beginning. - Every new public function which accept
-WorkspaceIdparameter, 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:
-
GETis 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 PostWe will gradually remove such code when changes to a function's logic are needed.
- For readability and to avoid small mistakes - we ask to use splatting:
$apiParams = @{
Uri = $apiEndpointUrl
Method = 'Post'
Body = $bodyJson
}
$response = Invoke-FabricRestMethod @apiParamsSplatting is mandatory for executing Invoke-FabricRestMethod function only, not everywhere.
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 documented codes should be handle appropriately.
Since July 2025, the private function (
Test-FabricApiResponse) is developed to handle all returned codes for you. The function is executed when paramHandleResponseis set to$truefor backward compatibility. There is no longer a need to handle response separately in public function code, unless there is a specific reason to do so.
Warning
Do not apply this pattern for new functions.
if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Delete Workspace"))
{
# Step 3: Make the API request
$response = Invoke-FabricRestMethod `
-Uri $apiEndpointUrl `
-Method Delete
}
# Step 4: 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 "Error Code: $($response.errorCode)" -Level Error
return $null
}
Write-Message -Message "Workspace '$WorkspaceId' deleted successfully!" -Level Info
return $nullUsing Invoke-FabricRestMethod with HandleResponse supports the following features:
- Call API
- Handles Status Code from a response (200, 201, 202)
- Supports LRO (Long-Running Operations) - code 202
- Pagination (automatically detected when continuation token exists in api response)
- Standard messages (this feature is being tested)
Note
Use this pattern for any new function.
# Step: Make the API request & validate response
if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Delete Deployment Pipeline"))
{
$apiParameters = @{
Uri = $apiEndpointUrl
Method = 'DELETE'
HandleResponse = $true
TypeName = "deployment pipeline"
ObjectIdOrName = $DeploymentPipelineId
}
$response = Invoke-FabricRestMethod @apiParameters
}
# Step: Handle results
$responseNew functions with LRO on API will implement NoWait switch parameter that enables user to avoid waiting for response when not needed.
Take a look at this example: New-FabricSQLDatabase.ps1
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-FabricEventhousefunction.
Avoid using the return keyword in your functions. Just place the object variable on its own.
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-FabricEventhousefunction.
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?
a. WorkspaceId - Alias: 'Id' is permitted only if there are no other parameters named 'Id' to prevent ambiguity.
b. WorkspaceName - Alias: 'Name' is permitted only if there are no other parameters named 'Name'.
c. DisplayName - Alias: 'Name' is allowed only in New or Update functions.
d. Description - No alias allowed; use full parameter name.
Note
Always use the full parameter name as the primary identifier.
Aliases should only be introduced when necessary and safe to avoid confusion or coding mistakes.
This is OK:
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[Alias("Id")]
[guid]$WorkspaceId,
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$WorkspaceName
)In this case, the Id alias is not allowed:
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[guid]$WorkspaceId,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[guid]$LakehouseId
)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 -
valueshould 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
-Explodeswitch parameter, the function should flatten (unfold) these nested structures into separate objects or properties for easier consumption.
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
Always use CmdletBinding attribute.
Any public (advanced) 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-FabricEventstreamfunction.