PSDynamoDB.psm1

<#
    Code in this file will be added to the beginning of the .psm1. For example,
    you should place any using statements here.
#>

Function ConvertFrom-AmazonDynamoDBv2AttributeValue {
    [cmdletbinding()]
    param (
        [Amazon.DynamoDBv2.Model.AttributeValue]$Value
    )
    if ($value.S) {
        $Value.S
    } elseif ($value.N) {
        [int]$Value.N
    } else {
        $value
    }
}
Function Get-DdbTableItem {
    [cmdletbinding(
        DefaultParameterSetName = 'Single'
    )]
    param (
        [Parameter(
            Mandatory,
            ParameterSetName = 'Single'
        )]
        [Parameter(
            ParameterSetName = 'IndexQuery'
        )]
        [string]$HashKey,
        [Parameter(
            ParameterSetName = 'Single'
        )]
        [string]$RangeKey,
        [Parameter(
            ParameterSetName = 'IndexQuery'
        )]
        [string]$IndexName,
        [Parameter(
            ParameterSetName = 'IndexQuery'
        )]
        [int]$Limit,
        [Parameter(
            ParameterSetName = 'IndexQuery'
        )]
        [bool]$ScanIndexForward = $true
    )
    if ($PSCmdlet.ParameterSetName -eq 'Single') {
        if ($PSBoundParameters.Keys -contains 'RangeKey' ){
            $task = $table.GetItemAsync([Amazon.DynamoDBv2.DocumentModel.Primitive]::new($HashKey),[Amazon.DynamoDBv2.DocumentModel.Primitive]::new($RangeKey))
        } else {
            $task = $table.GetItemAsync([Amazon.DynamoDBv2.DocumentModel.Primitive]::new($HashKey))
        }
        $task.Wait()
        $htArr = $task.Result
        $ht = @{}
        foreach ($item in $htArr) {
            $ht[$item.Key] = switch ($item.Value.Type) {
                'Numeric' { [int]$item.Value.Value }
                default { $item.Value.Value }
            }
        }
        $ht
    } else {
        # Find the name of the hashkey
        $hashKeyName = ($table.GlobalSecondaryIndexes[$IndexName].KeySchema | ?{$_.KeyType -eq 'HASH'}).AttributeName

        $req = [Amazon.DynamoDBv2.Model.QueryRequest]::new()

        # Really simple condition, hashkey = $hashkey
        # This can be expanded
        $condition = [Amazon.DynamoDBv2.Model.Condition]::new()
        $condition.AttributeValueList.Add($HashKey)
        $condition.ComparisonOperator = [Amazon.DynamoDBv2.ComparisonOperator]::EQ
        $req.KeyConditions.Add($hashKeyName,$condition)

        # Other parameters
        $req.IndexName = $IndexName
        $req.ScanIndexForward = $ScanIndexForward
        $req.Limit = $Limit

        # Since we are using the ddbClient to query, gotta specify tablename
        $req.TableName = $table.TableName

        # Query
        $task = $ddbClient.QueryAsync($req)
        $task.Wait()
        
        # Convert
        foreach ($item in $task.Result.Items) {
            $ht = @{}
            foreach ($key in $item.Keys) {
                $ht[$key] = ConvertFrom-AmazonDynamoDBv2AttributeValue $item[$key]
            }
            $ht
        }
    }
}
Function Initialize-DdbClient {
    [cmdletbinding()]
    param (
        [string]$TableName
    )
    $global:ddbClient = [Amazon.DynamoDBv2.AmazonDynamoDBClient]::new()
    $global:table = [Amazon.DynamoDBv2.DocumentModel.Table]::LoadTable($ddbClient, $TableName)
}
Function New-DdbTableItem {
    [cmdletbinding()]
    param (
        [Parameter(
            ParameterSetName = 'ByJson'
        )]
        [string]$Json,
        [Parameter(
            ParameterSetName = 'ByAttribMap'
        )]
        [hashtable]$AttributeMap
    )
    switch($PSCmdlet.ParameterSetName) {
        'ByJson' {
            $doc = [Amazon.DynamoDBv2.DocumentModel.Document]::FromJson($json)
        }
        'ByAttribMap' {
            $attribMap = New-Object 'System.Collections.Generic.Dictionary[string,Amazon.DynamoDBv2.Model.AttributeValue]'
            foreach ($key in $AttributeMap.Keys) {
                $attribValue = [Amazon.DynamoDBv2.Model.AttributeValue]::new()
                if ($AttributeMap[$key].GetType().Name -like 'Int*') {
                    $attribValue.N = $AttributeMap[$key]
                } else {
                    $attribValue.S = $AttributeMap[$key]
                }
                $attribMap.Add($key,$attribValue)
            }
            $doc = [Amazon.DynamoDBv2.DocumentModel.Document]::FromAttributeMap($attribMap)
        }
    }
    [System.Threading.Tasks.Task]$task = $table.PutItemAsync($doc)
    $task.Wait()
    $task.Result
}
Function Set-DdbTableItem {
    [cmdletbinding()]
    param (
        <#[Parameter(
            ParameterSetName = 'ByJson'
        )]
        [string]$Json,#>

        [Parameter(
            ParameterSetName = 'ByAttribMap'
        )]
        [hashtable]$AttributeMap,
        [string]$Key
    )
    switch($PSCmdlet.ParameterSetName) {
        <#'ByJson' {
            $doc = [Amazon.DynamoDBv2.DocumentModel.Document]::FromJson($json)
        }#>

        'ByAttribMap' {
            $attribUpdates = New-Object 'System.Collections.Generic.Dictionary[string,Amazon.DynamoDBv2.Model.AttributeValueUpdate]'
            foreach ($htkey in $AttributeMap.Keys) {
                $attribValue = [Amazon.DynamoDBv2.Model.AttributeValue]::new()
                # needs support for other value types
                if ($AttributeMap[$htkey] -is [int]) {
                    $attribValue.N = $AttributeMap[$htkey]
                } else {
                    $attribValue.S = $AttributeMap[$htkey]
                }
                
                $attribUpdates.Add($htkey,[Amazon.DynamoDBv2.Model.AttributeValueUpdate]::new($attribValue,'PUT'))
            }
        }
    }

    # Currently only supports tables with a single hash key name
    $keys = New-Object 'System.Collections.Generic.Dictionary[string,Amazon.DynamoDBv2.Model.AttributeValue]'
    $keys.Add($table.HashKeys[0],$Key)
    
    [System.Threading.Tasks.Task]$task = $ddbClient.UpdateItemAsync($table.TableName,$keys,$attribUpdates)
    $task.Wait()
    $task.Result
}
<#
    Code in this file will be added to the end of the .psm1. For example,
    you should set variables or other environment settings here.
#>

#Write-Warning 'This module is in early development. Please use with caution. Contact me @theposhwolf with questions.'