import * as azure from "@pulumi/azure" ; import * as cloud from "@pulumi/cloud" ; import * as pulumi from "@pulumi/pulumi" ; import { RunError } from "@pulumi/pulumi/errors" ; import * as shared from "./shared" ; import * as azureStorage from "azure-storage" ; export class Table extends pulumi . ComponentResource implements cloud . Table { public readonly table : azure . storage . Table ; public readonly primaryKey : pulumi . Output < string > ; public readonly primaryKeyType : pulumi . Output < string > ; public get : ( query : Object ) => Promise < any > ; public insert : ( item : Object ) => Promise < void > ; public delete : ( query : Object ) => Promise < void > ; public update : ( query : Object , updates : Object ) => Promise < void > ; public scan : { ( ) : Promise < any [ ] > ; ( callback ) : Promise < void > ; } ; constructor ( name , primaryKey ? , primaryKeyType ? , opts ? ) { if ( primaryKey === undefined ) { primaryKey = "id" ; } if ( primaryKeyType === undefined ) { primaryKeyType = "string" ; } if ( primaryKeyType !== "string" ) { throw new RunError ( "Only [string] is supported for [primaryKeyType] for an Azure [cloud.Table]." ) ; } super ( "cloud:table:Table" , name , { } , opts ) ; this . primaryKey = pulumi . output ( primaryKey ) ; this . primaryKeyType = pulumi . output ( primaryKeyType ) ; const primaryKeyOutput = this . primaryKey ; const storageAccount = shared . getGlobalStorageAccount ( ) ; const acceptableName = name . replace ( /[^A-Za-z0-9]/g , "" ) ; this . table = new azure . storage . Table ( acceptableName , { storageAccountName : storageAccount . name , } , { parent : this } ) ; const tableName = this . table . name ; this . get = async ( query ) => { const key = query [ primaryKeyOutput . get ( ) ] ; if ( ! key ) { throw new Error ( `[query] must have a value specified for [${ primaryKeyOutput . get ( ) }]` ) ; } const tableService = azureStorage . createTableService ( storageAccount . primaryConnectionString . get ( ) ) ; const result = await new Promise ( ( resolve , reject ) => { tableService . retrieveEntity < any > ( tableName . get ( ) , key , "" , ( err , result ) => { if ( err ) { return reject ( err ) ; } resolve ( result ) ; } ) ; } ) ; return deserialize ( result ) ; } ; this . insert = async ( obj ) => { const primaryKey = primaryKeyOutput . get ( ) ; const key = obj [ primaryKey ] ; if ( ! key ) { throw new Error ( `[obj] must have a value specified for [${ primaryKeyOutput . get ( ) }]` ) ; } const tableService = azureStorage . createTableService ( storageAccount . primaryConnectionString . get ( ) ) ; const descriptor = convertToDescriptor ( obj , primaryKey , key , azureStorage ) ; await new Promise ( ( resolve , reject ) => { tableService . insertOrReplaceEntity < any > ( tableName . get ( ) , descriptor , ( err , result ) => { if ( err ) { return reject ( err ) ; } resolve ( result ) ; } ) ; } ) ; } ; this . delete = async ( query ) => { const primaryKey = primaryKeyOutput . get ( ) ; const key = query [ primaryKey ] ; if ( ! key ) { throw new Error ( `[query] must have a value specified for [${ primaryKeyOutput . get ( ) }]` ) ; } const tableService = azureStorage . createTableService ( storageAccount . primaryConnectionString . get ( ) ) ; const descriptor = convertToDescriptor ( { } , primaryKey , key , azureStorage ) ; await new Promise ( ( resolve , reject ) => { tableService . deleteEntity ( tableName . get ( ) , descriptor , ( err , result ) => { if ( err ) { return reject ( err ) ; } resolve ( result ) ; } ) ; } ) ; } ; this . update = async ( query , updates ) => { const primaryKey = primaryKeyOutput . get ( ) ; const key = query [ primaryKey ] ; if ( ! key ) { throw new Error ( `[query] must have a value specified for [${ primaryKeyOutput . get ( ) }]` ) ; } const tableService = azureStorage . createTableService ( storageAccount . primaryConnectionString . get ( ) ) ; const obj = { ... query , ... updates } ; const descriptor = convertToDescriptor ( obj , primaryKey , key , azureStorage ) ; await new Promise ( ( resolve , reject ) => { tableService . insertOrMergeEntity < any > ( tableName . get ( ) , descriptor , ( err , result ) => { if ( err ) { return reject ( err ) ; } resolve ( result ) ; } ) ; } ) ; } ; this . scan = < any > ( async ( callback ? ) => { let items ; if ( callback === undefined ) { items = [ ] ; callback = ( page ) => { items ! . push ( ... page ) ; return Promise . resolve ( true ) ; } ; } const tableService = azureStorage . createTableService ( storageAccount . primaryConnectionString . get ( ) ) ; const query = new azureStorage . TableQuery ( ) ; let continuationToken = null ; do { const entries = await new Promise < any [ ] > ( ( resolve , reject ) => { tableService . queryEntities ( tableName . get ( ) , query , continuationToken ! , ( err , result , response ) => { if ( err ) { reject ( err ) ; } continuationToken = result . continuationToken ; resolve ( result . entries ) ; } ) ; } ) ; const cont = await callback ( entries . map ( deserialize ) ) ; if ( ! cont ) { break ; } } while ( continuationToken ) ; if ( items !== undefined ) { return items ; } else { return ; } } ) ; this . registerOutputs ( { primaryKey : this . primaryKey , primaryKeyType : this . primaryKeyType , table : this . table , } ) ; } } function convertToDescriptor ( obj , primaryKey , partitionKey , mod ) { const descriptor = { ... obj , PartitionKey : partitionKey , RowKey : "" , } ; for ( const key in descriptor ) { if ( descriptor . hasOwnProperty ( key ) ) { descriptor [ key ] = translate ( key , descriptor [ key ] , mod ) ; } } return descriptor ; } function translate ( key , value , mod ) { const entGen = mod . TableUtilities . entityGenerator ; if ( Buffer . isBuffer ( value ) ) { return entGen . Binary ( value ) ; } if ( value instanceof Date ) { return entGen . DateTime ( value ) ; } switch ( typeof value ) { case "string" : return entGen . String ( value ) ; case "number" : return entGen . Double ( value ) ; case "boolean" : return entGen . Boolean ( value ) ; default : throw new Error ( `value[${ key }] was not a supported type.  Supported types are: string | number | boolean | Date | Buffer` ) ; } } function deserialize ( value ) { const result = { ... value , } ; delete result [ "PartitionKey" ] ; delete result [ "RowKey" ] ; delete result [ "Timestamp" ] ; delete result [ ".metadata" ] ; for ( const key in result ) { if ( result . hasOwnProperty ( key ) ) { result [ key ] = result [ key ] [ "_" ] ; } } return result ; }