New-CDBDocument.psm1

$FunctionScriptName = "New-CDBDocument"
Write-Verbose "Import-Start| [$($FunctionScriptName)]"

#* Dependencies
# New-CDBAuthHeader

#todo: check for conflict -> $_.Exception.Response.StatusCode = "Conflict" | $x.Exception.Response.Statuscode.value__ = 409
#todo: Add error handling
#todo: Add socket throttling check

function New-CDBDocument {
    <#
        .SYNOPSIS
            Creates a new document in the database
         
        .DESCRIPTION
            Creates a new document in the database
            Pkey value must match value in the entity/pipe!
 
            Used by SQL/Core REST API
         
        .PARAMETER Config
            Config array
            Accepts the following values: DatabaseID / CollectionID / AuthKey / keyType / CosmosDBEndpoint / KeyType
            All required values can be set directly. Directly set values have precedent.
            Not all values may be required.
         
        .PARAMETER DatabaseID
            Can be set via -Config value
            Name of the CosmosDB Database
         
        .PARAMETER CollectionId
            Can be set via -Config value
            Name of the CosmosDB Collection
         
        .PARAMETER AuthKey
            Can be set via -Config value
            Key value to authenticate against cosmosDB
         
        .PARAMETER KeyType
            Can be set via -Config value
            Type of AuthKey provided.
            Default value: "master"
         
        .PARAMETER PartitionKey
            Value of the Partition. Not the Name of the Key itself!
         
        .PARAMETER Entity
            The Document itself.
            Must contain a partition-unique "id" value
            Must contain the defined partitionkey with the same value as the "PartitionKey" parameter
 
            The PartitionKey itself is configured in the database collection.
 
        .PARAMETER pipe
            Used automatically insted of "Entity" while using a Pipeline.
            Do not use Entity if a Pipeline is used!
         
        .PARAMETER DocumentUpsert
            Default: TRUE
            Sets the "x-ms-documentdb-is-upsert" header
            True = Overwrites existing document if exists. Create if new.
            False = Throws error if document exists. Create if new.
 
        .PARAMETER enablecrosspartition
            Default: FALSE
            Sets the "x-ms-documentdb-query-enablecrosspartition" header
            True = Scopes multiple partitions. The primary one still needs to be defined.
            False = Only uses the defined partition. Increases the performance.
         
        .EXAMPLE
            New-CDBDocument -Config $Config -PartitionKey $PKEY -Entity $Document
         
        .NOTES
            AUTHOR: Ken Dobrunz // Ken.Dobrunz@Skaylink.com
            LASTEDIT: 05.08.2022 - Version: 1.0
        #>

    [cmdletbinding()]
    Param(
        #* Active data
        # Config or direct values needed
        [Parameter()]$Config,
        [Parameter()][string]$DatabaseID,
        [Parameter()][Alias('col')][string]$CollectionId,
        [Parameter()][Alias('key')][string]$AuthKey,
        [Parameter()][Alias('type')][string]$KeyType = "master",
        [Parameter()][Alias('uri')][string]$CosmosDBEndpoint,
        
        # Entity
        [parameter()]$Entity,
        [parameter(ValueFromPipeline = $True)]$pipe,
        [parameter()][Alias('pkey')][string]$PartitionKey,
        
        [parameter()][Alias('upsert')][bool]$DocumentUpsert = $true,
        [parameter()][bool]$enablecrosspartition = $false,
        [parameter()][bool]$ReuseAuthHeader = $false
    )
    Begin {
        $SelfIdentifier = "New-CDBDocument"
        
        # Check Config / Set Variables
        $DatabaseID = if ($DatabaseID) { $DatabaseID }elseif ($Config.DatabaseID) { $Config.DatabaseID }else { Write-Error "[$($SelfIdentifier)] No DatabaseID provided" }
        $CollectionId = if ($CollectionId) { $CollectionId }elseif ($Config.CollectionId) { $Config.CollectionId }else { Write-Error "[$($SelfIdentifier)] No CollectionId provided" }
        $AuthKey = if ($AuthKey) { $AuthKey }elseif ($Config.AuthKey) { $Config.AuthKey }else { Write-Error "[$($SelfIdentifier)] No AuthKey provided" }
        $KeyType = if ($KeyType) { $KeyType }elseif ($Config.KeyType) { $Config.KeyType }else { Write-Error "[$($SelfIdentifier)] No KeyType provided" }
        $CosmosDBEndpoint = if ($CosmosDBEndpoint) { $CosmosDBEndpoint }elseif ($Config.CosmosDBEndpoint) { $Config.CosmosDBEndpoint }else { Write-Error "[$($SelfIdentifier)] No CosmosDBEndpoint provided" }
        
        $CosmosURI = "$CosmosDBEndPoint/dbs/$DatabaseId/colls/$CollectionId/docs"

        if (!$PartitionKey) { throw "[$($SelfIdentifier)] No PartitionKey [$($PartitionKey)]" }
        
        if ($ReuseAuthHeader) {
            $dateTime = [DateTime]::UtcNow.ToString("r")
            Write-Debug "[$($SelfIdentifier)] Reusing header for all requests - Datetime [$($dateTime)]"
            Write-Warning "[$($SelfIdentifier)] Static header may timeout before completion of all entities!"
            
            $header = New-CDBAuthHeader -DatabaseID $DatabaseID -CollectionID $CollectionId -AuthKey $AuthKey -keytype $KeyType -HTTPverb "POST" -DocumentUpsert $DocumentUpsert -enablecrosspartition $enablecrosspartition -PartitionKey $PartitionKey
        }
        
        $functionverbosecount = 0
    }
    Process { 
        if ($Entity) { $pipe = $Entity }
        
        # Auth Header
        if (!$ReuseAuthHeader) {
            $header = New-CDBAuthHeader -DatabaseID $DatabaseID -CollectionID $CollectionId -AuthKey $AuthKey -keytype $KeyType -HTTPverb "POST" -DocumentUpsert $DocumentUpsert -enablecrosspartition $enablecrosspartition -PartitionKey $PartitionKey
        }
        Write-Verbose "[$($SelfIdentifier)] Creating document for id [$($pipe.id)] @ [$($PartitionKey)]"
        Invoke-RestMethod -Method POST -Uri $CosmosURI -Headers $header -Body ($pipe | ConvertTo-Json -Depth 20) -ContentType application/json
        $functionverbosecount++
    
    }
    End {
        if ($functionverbosecount -gt 1) { Write-Verbose "[$($SelfIdentifier)] Updated $($functionverbosecount) entries" }
    }
} #v0.1.1

Export-ModuleMember -Function *
Write-Verbose "Import-END| [$($FunctionScriptName)]"