2023-01-24 17:06:06 -05:00
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
2024-10-16 11:53:18 -04:00
import { fileURLToPath } from "node:url" ;
2023-01-24 17:06:06 -05:00
// snippet-start:[javascript.v3.support.scenarios.basic]
import {
AddAttachmentsToSetCommand ,
AddCommunicationToCaseCommand ,
CreateCaseCommand ,
DescribeAttachmentCommand ,
DescribeCasesCommand ,
DescribeCommunicationsCommand ,
DescribeServicesCommand ,
DescribeSeverityLevelsCommand ,
ResolveCaseCommand ,
SupportClient ,
} from "@aws-sdk/client-support" ;
2024-04-30 16:36:13 -04:00
import * as inquirer from "@inquirer/prompts" ;
import { retry } from "@aws-doc-sdk-examples/lib/utils/util-timers.js" ;
2023-01-24 17:06:06 -05:00
const wrapText = ( text , char = "=" ) => {
const rule = char . repeat ( 80 ) ;
return ` ${ rule } \n ${ text } \n ${ rule } \n ` ;
} ;
const client = new SupportClient ( { region : "us-east-1" } ) ;
// Verify that the account has a Support plan.
export const verifyAccount = async ( ) => {
const command = new DescribeServicesCommand ( { } ) ;
try {
await client . send ( command ) ;
} catch ( err ) {
if ( err . name === "SubscriptionRequiredException" ) {
throw new Error (
2024-04-30 16:36:13 -04:00
"You must be subscribed to the AWS Support plan to use this feature." ,
2023-01-24 17:06:06 -05:00
) ;
}
2024-10-16 11:53:18 -04:00
throw err ;
2023-01-24 17:06:06 -05:00
}
} ;
2024-04-30 16:36:13 -04:00
/**
* Select a service from the list returned from DescribeServices.
*/
2023-01-24 17:06:06 -05:00
export const getService = async ( ) => {
const { services } = await client . send ( new DescribeServicesCommand ( { } ) ) ;
2024-04-30 16:36:13 -04:00
const selectedService = await inquirer . select ( {
2023-01-24 17:06:06 -05:00
message :
"Select a service. Your support case will be created for this service. The list of services is truncated for readability." ,
choices : services . slice ( 0 , 10 ) . map ( ( s ) => ( { name : s . name , value : s } ) ) ,
} ) ;
return selectedService ;
} ;
2024-04-30 16:36:13 -04:00
/**
* @param {{ categories: import('@aws-sdk/client-support').Category[]}} service
*/
2023-01-24 17:06:06 -05:00
export const getCategory = async ( service ) => {
2024-04-30 16:36:13 -04:00
const selectedCategory = await inquirer . select ( {
2023-01-24 17:06:06 -05:00
message : "Select a category." ,
choices : service . categories . map ( ( c ) => ( { name : c . name , value : c } ) ) ,
} ) ;
return selectedCategory ;
} ;
// Get the available severity levels for the account.
export const getSeverityLevel = async ( ) => {
const command = new DescribeSeverityLevelsCommand ( { } ) ;
const { severityLevels } = await client . send ( command ) ;
2024-04-30 16:36:13 -04:00
const selectedSeverityLevel = await inquirer . select ( {
2023-01-24 17:06:06 -05:00
message : "Select a severity level." ,
choices : severityLevels . map ( ( s ) => ( { name : s . name , value : s } ) ) ,
} ) ;
return selectedSeverityLevel ;
} ;
2024-04-30 16:36:13 -04:00
/**
* Create a new support case
* @param {{
* selectedService: import('@aws-sdk/client-support').Service
* selectedCategory: import('@aws-sdk/client-support').Category
* selectedSeverityLevel: import('@aws-sdk/client-support').SeverityLevel
* }} selections
* @returns
*/
2023-01-24 17:06:06 -05:00
export const createCase = async ( {
selectedService ,
selectedCategory ,
selectedSeverityLevel ,
} ) => {
const command = new CreateCaseCommand ( {
subject : "IGNORE: Test case" ,
communicationBody : "This is a test. Please ignore." ,
serviceCode : selectedService . code ,
categoryCode : selectedCategory . code ,
severityCode : selectedSeverityLevel . code ,
} ) ;
const { caseId } = await client . send ( command ) ;
return caseId ;
} ;
// Get a list of open support cases created today.
export const getTodaysOpenCases = async ( ) => {
const d = new Date ( ) ;
const startOfToday = new Date ( d . getFullYear ( ) , d . getMonth ( ) , d . getDate ( ) ) ;
const command = new DescribeCasesCommand ( {
includeCommunications : false ,
afterTime : startOfToday . toISOString ( ) ,
} ) ;
const { cases } = await client . send ( command ) ;
if ( cases . length === 0 ) {
throw new Error (
2024-04-30 16:36:13 -04:00
"Unexpected number of cases. Expected more than 0 open cases." ,
2023-01-24 17:06:06 -05:00
) ;
}
return cases ;
} ;
// Create an attachment set.
export const createAttachmentSet = async ( ) => {
const command = new AddAttachmentsToSetCommand ( {
attachments : [
{
fileName : "example.txt" ,
data : new TextEncoder ( ) . encode ( "some example text" ) ,
} ,
] ,
} ) ;
const { attachmentSetId } = await client . send ( command ) ;
return attachmentSetId ;
} ;
export const linkAttachmentSetToCase = async ( attachmentSetId , caseId ) => {
const command = new AddCommunicationToCaseCommand ( {
attachmentSetId ,
caseId ,
communicationBody : "Adding attachment set to case." ,
} ) ;
await client . send ( command ) ;
} ;
// Get all communications for a support case.
export const getCommunications = async ( caseId ) => {
const command = new DescribeCommunicationsCommand ( {
caseId ,
} ) ;
const { communications } = await client . send ( command ) ;
return communications ;
} ;
2024-04-30 16:36:13 -04:00
/**
* @param {import('@aws-sdk/client-support').Communication[]} communications
*/
2023-01-24 17:06:06 -05:00
export const getFirstAttachment = ( communications ) => {
const firstCommWithAttachment = communications . find (
2024-04-30 16:36:13 -04:00
( c ) => c . attachmentSet . length > 0 ,
2023-01-24 17:06:06 -05:00
) ;
return firstCommWithAttachment ? . attachmentSet [ 0 ] . attachmentId ;
} ;
// Get an attachment.
export const getAttachment = async ( attachmentId ) => {
const command = new DescribeAttachmentCommand ( {
attachmentId ,
} ) ;
const { attachment } = await client . send ( command ) ;
return attachment ;
} ;
// Resolve the case matching the given case ID.
export const resolveCase = async ( caseId ) => {
2024-04-30 16:36:13 -04:00
const shouldResolve = await inquirer . confirm ( {
2023-01-24 17:06:06 -05:00
message : ` Do you want to resolve ${ caseId } ? ` ,
} ) ;
if ( shouldResolve ) {
const command = new ResolveCaseCommand ( {
caseId : caseId ,
} ) ;
await client . send ( command ) ;
return true ;
}
return false ;
} ;
2024-04-30 16:36:13 -04:00
/**
* Find a specific case in the list of provided cases by case ID.
* If the case is not found, and the results are paginated, continue
* paging through the results.
* @param {{
* caseId: string,
* cases: import('@aws-sdk/client-support').CaseDetails[]
* nextToken: string
* }} options
* @returns
*/
2023-01-24 17:06:06 -05:00
export const findCase = async ( { caseId , cases , nextToken } ) => {
const foundCase = cases . find ( ( c ) => c . caseId === caseId ) ;
if ( foundCase ) {
return foundCase ;
}
if ( nextToken ) {
const response = await client . send (
new DescribeCasesCommand ( {
nextToken ,
includeResolvedCases : true ,
2024-04-30 16:36:13 -04:00
} ) ,
2023-01-24 17:06:06 -05:00
) ;
return findCase ( {
caseId ,
cases : response . cases ,
nextToken : response . nextToken ,
} ) ;
}
throw new Error ( ` ${ caseId } not found. ` ) ;
} ;
// Get all cases created today.
export const getTodaysResolvedCases = async ( caseIdToWaitFor ) => {
const d = new Date ( "2023-01-18" ) ;
const startOfToday = new Date ( d . getFullYear ( ) , d . getMonth ( ) , d . getDate ( ) ) ;
const command = new DescribeCasesCommand ( {
includeCommunications : false ,
afterTime : startOfToday . toISOString ( ) ,
includeResolvedCases : true ,
} ) ;
const { cases , nextToken } = await client . send ( command ) ;
await findCase ( { cases , caseId : caseIdToWaitFor , nextToken } ) ;
return cases . filter ( ( c ) => c . status === "resolved" ) ;
} ;
const main = async ( ) => {
let caseId ;
try {
console . log ( wrapText ( "Welcome to the AWS Support basic usage scenario." ) ) ;
// Verify that the account is subscribed to support.
await verifyAccount ( ) ;
// Provided a truncated list of services and prompt the user to select one.
const selectedService = await getService ( ) ;
// Provided the categories for the selected service and prompt the user to select one.
const selectedCategory = await getCategory ( selectedService ) ;
// Provide the severity available severity levels for the account and prompt the user to select one.
const selectedSeverityLevel = await getSeverityLevel ( ) ;
// Create a support case.
console . log ( "\nCreating a support case." ) ;
caseId = await createCase ( {
selectedService ,
selectedCategory ,
selectedSeverityLevel ,
} ) ;
console . log ( ` Support case created: ${ caseId } ` ) ;
// Display a list of open support cases created today.
const todaysOpenCases = await retry (
{ intervalInMs : 1000 , maxRetries : 15 } ,
2024-04-30 16:36:13 -04:00
getTodaysOpenCases ,
2023-01-24 17:06:06 -05:00
) ;
console . log (
2024-04-30 16:36:13 -04:00
` \n Open support cases created today: ${ todaysOpenCases . length } ` ,
2023-01-24 17:06:06 -05:00
) ;
console . log ( todaysOpenCases . map ( ( c ) => ` ${ c . caseId } ` ) . join ( "\n" ) ) ;
// Create an attachment set.
console . log ( "\nCreating an attachment set." ) ;
const attachmentSetId = await createAttachmentSet ( ) ;
console . log ( ` Attachment set created: ${ attachmentSetId } ` ) ;
// Add the attachment set to the support case.
console . log ( ` \n Adding attachment set to ${ caseId } ` ) ;
await linkAttachmentSetToCase ( attachmentSetId , caseId ) ;
console . log ( ` Attachment set added to ${ caseId } ` ) ;
// List the communications for a support case.
console . log ( ` \n Listing communications for ${ caseId } ` ) ;
const communications = await getCommunications ( caseId ) ;
console . log (
communications
. map (
( c ) =>
2024-04-30 16:36:13 -04:00
` Communication created on ${ c . timeCreated } . Has ${ c . attachmentSet . length } attachments. ` ,
2023-01-24 17:06:06 -05:00
)
2024-04-30 16:36:13 -04:00
. join ( "\n" ) ,
2023-01-24 17:06:06 -05:00
) ;
// Describe the first attachment.
console . log ( ` \n Describing attachment ${ attachmentSetId } ` ) ;
const attachmentId = getFirstAttachment ( communications ) ;
const attachment = await getAttachment ( attachmentId ) ;
console . log (
` Attachment is the file ' ${
attachment . fileName
2024-04-30 16:36:13 -04:00
} ' with data: \n ${ new TextDecoder ( ) . decode ( attachment . data ) } ` ,
2023-01-24 17:06:06 -05:00
) ;
// Confirm that the support case should be resolved.
const isResolved = await resolveCase ( caseId ) ;
if ( isResolved ) {
// List the resolved cases and include the one previously created.
// Resolved cases can take a while to appear.
console . log (
2024-04-30 16:36:13 -04:00
"\nWaiting for case status to be marked as resolved. This can take some time." ,
2023-01-24 17:06:06 -05:00
) ;
const resolvedCases = await retry (
{ intervalInMs : 20000 , maxRetries : 15 } ,
2024-04-30 16:36:13 -04:00
( ) => getTodaysResolvedCases ( caseId ) ,
2023-01-24 17:06:06 -05:00
) ;
console . log ( "Resolved cases:" ) ;
console . log ( resolvedCases . map ( ( c ) => c . caseId ) . join ( "\n" ) ) ;
}
} catch ( err ) {
console . error ( err ) ;
}
} ;
// snippet-end:[javascript.v3.support.scenarios.basic]
// Invoke main function if this file was run directly.
if ( process . argv [ 1 ] === fileURLToPath ( import . meta . url ) ) {
main ( ) ;
}