Skip to content

Standards

Kamil Nowinski edited this page Jun 19, 2025 · 20 revisions

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.

Standards for FabricTools

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 Nots

  1. Do not depend on or incorporate commands from external modules unless you have explicit permissions/approval (via an issue) from the module owner.
  2. 🔒#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.)
  3. Do not use any backticks for line continuation.
  4. 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.
  5. 🔒#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.
  6. 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.
  7. 🔒#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.)

Naming Convention

Commands

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

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

Variables

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.

Documentation

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.

Examples

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.

Examples Formatting

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.

Function Code

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:

  1. Use 4 spaces for indentation (no tabs).
  2. Formatting strings: both "$value" and "{0}" -f $value are allowed to be used.

Begin/Process/End Blocks

  1. Use the Begin, Process, and End blocks to separate the code into logical sections as defined in Input processing methods.
  2. Each public function should execute Confirm-TokenState at the beginning.
  3. Every new public function which accept -WorkspaceId parameter, should also handle pipeline for workspaces.

Execute API

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:

  1. GET is optional and defult parameter for Method, however we recommend to provide it for readability.
  2. 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.

  1. For readability and to avoid small mistakes - we ask to use splatting:
    $apiParams = @{
        Uri    = $apiEndpointUrl
        Method = 'Post'
        Body   = $bodyJson
    }
    $response = Invoke-FabricRestMethod @apiParams

Validate response

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 is Test-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
    }

Handling statusCode 201 and 202 (LRO)

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.

Pagination and adding data to response

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.

🔒 Handle results and return

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.

Default View

Aliases

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

Output

Each public function should return the result from API.
Ideally, the result should be return like-to-like, with exceptions when:

  1. Result contains "value" element as a wrapper for the major data - value should be return.
  2. 🔒 Error details should be return when error returned from API. By default it contains the following columns: x, y, z
  3. 🔒 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

OutputType

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.

try/catch/finally

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.

PSFramework

🔒 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

Remove- functions

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.

Templates

Tests

Testing/QA

FabricTools

  • Unfold the pages links above to navigate the wiki.

Coding Standards

GitHub and Git

Clone this wiki locally