diff --git a/ask-sdk-model/index.ts b/ask-sdk-model/index.ts index 5882b67..68a51b4 100644 --- a/ask-sdk-model/index.ts +++ b/ask-sdk-model/index.ts @@ -1,428 +1,428 @@ -export namespace services { - /** - * Represents the interface between ApiClient and a Service Client. - * @export - * @interface ApiClientMessage - */ - export interface ApiClientMessage { - headers : Array<{key : string, value : string}>; - body? : string; - } - - /** - * Represents a request sent from Service Clients to an ApiClient implementation. - * @export - * @interface ApiClientRequest - * @extends {ApiClientMessage} - */ - export interface ApiClientRequest extends ApiClientMessage { - url : string; - method : string; - } - - /** - * Represents a response returned by ApiClient implementation to a Service Client. - * @export - * @interface ApiClientResponse - * @extends {ApiClientMessage} - */ - export interface ApiClientResponse extends ApiClientMessage { - /** - * Result code of the attempt to satisfy the request. Normally this - * corresponds to the HTTP status code returned by the server. - */ - statusCode : number; - } - - /** - * Represents a response with parsed body. - * @export - * @interface ApiResponse - */ - export interface ApiResponse { - headers : Array<{key : string, value : string}>; - body? : any; - statusCode : number; - } - - /** - * Represents a basic contract for API request execution - * @export - * @interface ApiClient - */ - export interface ApiClient { - /** - * Dispatches a request to an API endpoint described in the request. - * An ApiClient is expected to resolve the Promise in the case an API returns a non-200 HTTP - * status code. The responsibility of translating a particular response code to an error lies with the - * caller to invoke. - * @param {ApiClientRequest} request request to dispatch to the ApiClient - * @returns {Promise} Response from the ApiClient - * @memberof ApiClient - */ - invoke(request : ApiClientRequest) : Promise; - } - - /** - * Represents an interface that provides API configuration options needed by service clients. - * @interface ApiConfiguration - */ - export interface ApiConfiguration { - /** - * Configured ApiClient implementation - */ - apiClient : ApiClient; - /** - * Authorization value to be used on any calls of the service client instance - */ - authorizationValue : string; - /** - * Endpoint to hit by the service client instance - */ - apiEndpoint : string; - } - - /** - * Class to be used as the base class for the generated service clients. - */ - export abstract class BaseServiceClient { - private static isCodeSuccessful( responseCode : number ) : boolean { - return responseCode >= 200 && responseCode < 300; - } - - private static buildUrl( - endpoint : string, - path : string, - queryParameters : Array<{ key : string, value : string }>, - pathParameters : Map, - ) : string { - const processedEndpoint : string = endpoint.endsWith('/') ? endpoint.substr(0, endpoint.length - 1) : endpoint; - const pathWithParams : string = this.interpolateParams(path, pathParameters); - const isConstantQueryPresent : boolean = pathWithParams.includes('?'); - const queryString : string = this.buildQueryString(queryParameters, isConstantQueryPresent); - - return processedEndpoint + pathWithParams + queryString; - } - - private static interpolateParams(path : string, params : Map) : string { - if (!params) { - return path; - } - - let result : string = path; - - params.forEach((paramValue : string, paramName : string) => { - result = result.replace('{' + paramName + '}', encodeURIComponent(paramValue)); - }); - - return result; - } - - private static buildQueryString(params : Array<{ key : string, value : string }>, isQueryStart : boolean) : string { - if (!params) { - return ''; - } - - const sb : string[] = []; - - if (isQueryStart) { - sb.push('&'); - } else { - sb.push('?'); - } - - params.forEach((obj) => { - sb.push(encodeURIComponent(obj.key)); - sb.push('='); - sb.push(encodeURIComponent(obj.value)); - sb.push('&'); - }); - sb.pop(); - - return sb.join(''); - } - - /** - * ApiConfiguration instance to provide dependencies for this service client - */ - protected apiConfiguration : ApiConfiguration; - - private requestInterceptors : Array<(request : ApiClientRequest) => void | Promise> = []; - private responseInterceptors : Array<(response : ApiClientResponse) => void | Promise> = []; - - /** - * Creates new instance of the BaseServiceClient - * @param {ApiConfiguration} apiConfiguration configuration parameter to provide dependencies to service client instance - */ - protected constructor(apiConfiguration : ApiConfiguration) { - this.apiConfiguration = apiConfiguration; - } - - /** - * Sets array of functions that is going to be executed before the request is send - * @param {Function} requestInterceptor request interceptor function - * @returns {BaseServiceClient} - */ - public withRequestInterceptors(...requestInterceptors : Array<(request : ApiClientRequest) => void | Promise>) : BaseServiceClient { - for ( const interceptor of requestInterceptors ) { - this.requestInterceptors.push(interceptor); - } - - return this; - } - - /** - * Sets array of functions that is going to be executed after the request is send - * @param {Function} responseInterceptor response interceptor function - * @returns {BaseServiceClient} - */ - public withResponseInterceptors(...responseInterceptors : Array<(response : ApiClientResponse) => void | Promise>) : BaseServiceClient { - for ( const interceptor of responseInterceptors ) { - this.responseInterceptors.push(interceptor); - } - - return this; - } - - /** - * Invocation wrapper to implement service operations in generated classes - * @param method HTTP method, such as 'POST', 'GET', 'DELETE', etc. - * @param endpoint base API url - * @param path the path pattern with possible placeholders for path parameters in form {paramName} - * @param pathParams path parameters collection - * @param queryParams query parameters collection - * @param headerParams headers collection - * @param bodyParam if body parameter is present it is provided here, otherwise null or undefined - * @param errors maps recognized status codes to messages - * @param nonJsonBody if the body is in JSON format - */ - protected async invoke( - method : string, - endpoint : string, - path : string, - pathParams : Map, - queryParams : Array<{ key : string, value : string }>, - headerParams : Array<{ key : string, value : string }>, - bodyParam : any, - errors : Map, - nonJsonBody? : boolean, - ) : Promise { - const request : ApiClientRequest = { - url : BaseServiceClient.buildUrl(endpoint, path, queryParams, pathParams), - method, - headers : headerParams, - }; - if (bodyParam != null) { - request.body = nonJsonBody ? bodyParam : JSON.stringify(bodyParam); - } - - const apiClient = this.apiConfiguration.apiClient; - let response : ApiClientResponse; - try { - for (const requestInterceptor of this.requestInterceptors) { - await requestInterceptor(request); - } - response = await apiClient.invoke(request); - for (const responseInterceptor of this.responseInterceptors) { - await responseInterceptor(response); - } - } catch (err) { - err.message = `Call to service failed: ${err.message}`; - - throw err; - } - - let body; - - try { - const contentType = response.headers.find((h) => h.key === 'content-type'); - // json if no content type or content type is application/json - const isJson = !contentType || contentType.value.includes('application/json'); - body = response.body && isJson ? JSON.parse(response.body) : response.body; - // converting to undefined if empty string - body = body || undefined; - } catch (err) { - throw new SyntaxError(`Failed trying to parse the response body: ${response.body}`); - } - - if (BaseServiceClient.isCodeSuccessful(response.statusCode)) { - const apiResponse : ApiResponse = { - headers : response.headers, - body, - statusCode : response.statusCode, - }; - - return apiResponse; - } - - const err = new Error('Unknown error'); - err.name = 'ServiceError'; - err['statusCode'] = response.statusCode; // tslint:disable-line:no-string-literal - err['response'] = body; // tslint:disable-line:no-string-literal - if (errors && errors.has(response.statusCode)) { - err.message = errors.get(response.statusCode); - } - - throw err; - } - } - - /** - * Represents a Login With Amazon(LWA) access token - */ - export interface AccessToken { - token : string; - expiry : Number; - } - - /** - * Represents a request for retrieving a Login With Amazon(LWA) access token - */ - export interface AccessTokenRequest { - clientId : string; - clientSecret : string; - scope? : string; - refreshToken? : string; - } - - /** - * Represents a response returned by LWA containing a Login With Amazon(LWA) access token - */ - export interface AccessTokenResponse { - access_token : string; - expires_in : number; - scope : string; - token_type : string; - } - - /** - * Represents the authentication configuration for a client ID and client secret - */ - export interface AuthenticationConfiguration { - clientId : string; - clientSecret : string; - refreshToken? : string; - authEndpoint? : string; - } - - /** - * Class to be used to call Amazon LWA to retrieve access tokens. - */ - export class LwaServiceClient extends BaseServiceClient { - protected static EXPIRY_OFFSET_MILLIS : number = 60000; - protected static REFRESH_ACCESS_TOKEN : string = 'refresh_access_token'; - protected static CLIENT_CREDENTIALS_GRANT_TYPE : string = 'client_credentials'; - protected static LWA_CREDENTIALS_GRANT_TYPE : string = 'refresh_token'; - protected static AUTH_ENDPOINT : string = 'https://api.amazon.com'; - - protected authenticationConfiguration : AuthenticationConfiguration; - protected tokenStore : {[cacheKey : string] : AccessToken}; - protected grantType : string; - - constructor(options : { - apiConfiguration : ApiConfiguration, - authenticationConfiguration : AuthenticationConfiguration, - grantType? : string, - }) { - super(options.apiConfiguration); - if (options.authenticationConfiguration == null) { - throw new Error('AuthenticationConfiguration cannot be null or undefined.'); - } - this.grantType = options.grantType ? options.grantType : LwaServiceClient.CLIENT_CREDENTIALS_GRANT_TYPE; - this.authenticationConfiguration = options.authenticationConfiguration; - this.tokenStore = {}; - } - - public async getAccessTokenForScope(scope : string) : Promise { - if (scope == null) { - throw new Error('Scope cannot be null or undefined.'); - } - - return this.getAccessToken(scope); - } - - public async getAccessToken(scope? : string) : Promise { - const cacheKey : string = scope ? scope : LwaServiceClient.REFRESH_ACCESS_TOKEN; - const accessToken = this.tokenStore[cacheKey]; - - if (accessToken && accessToken.expiry > Date.now() + LwaServiceClient.EXPIRY_OFFSET_MILLIS) { - return accessToken.token; - } - - const accessTokenRequest : AccessTokenRequest = { - clientId : this.authenticationConfiguration.clientId, - clientSecret : this.authenticationConfiguration.clientSecret, - }; - if (scope && this.authenticationConfiguration.refreshToken) { - throw new Error('Cannot support both refreshToken and scope.'); - } else if (scope == null && this.authenticationConfiguration.refreshToken == null) { - throw new Error('Either refreshToken or scope must be specified.'); - } else if (scope == null) { - accessTokenRequest.refreshToken = this.authenticationConfiguration.refreshToken; - } else { - accessTokenRequest.scope = scope; - } - - const accessTokenResponse : AccessTokenResponse = await this.generateAccessToken(accessTokenRequest); - - this.tokenStore[cacheKey] = { - token : accessTokenResponse.access_token, - expiry : Date.now() + accessTokenResponse.expires_in * 1000, - }; - - return accessTokenResponse.access_token; - } - - protected async generateAccessToken(accessTokenRequest : AccessTokenRequest) : Promise { - const authEndpoint = this.authenticationConfiguration.authEndpoint || LwaServiceClient.AUTH_ENDPOINT; - - if (accessTokenRequest == null) { - throw new Error(`Required parameter accessTokenRequest was null or undefined when calling generateAccessToken.`); - } - - const queryParams : Array<{ key : string, value : string }> = []; - - const headerParams : Array<{key : string, value : string}> = []; - headerParams.push({key : 'Content-type', value : 'application/x-www-form-urlencoded'}); - - const pathParams : Map = new Map(); - - const paramInfo = this.grantType === LwaServiceClient.LWA_CREDENTIALS_GRANT_TYPE ? `&refresh_token=${accessTokenRequest.refreshToken}` : `&scope=${accessTokenRequest.scope}`; - const bodyParams : string = `grant_type=${this.grantType}&client_secret=${accessTokenRequest.clientSecret}&client_id=${accessTokenRequest.clientId}` + paramInfo; - - const errorDefinitions : Map = new Map(); - errorDefinitions.set(200, 'Token request sent.'); - errorDefinitions.set(400, 'Bad Request'); - errorDefinitions.set(401, 'Authentication Failed'); - errorDefinitions.set(500, 'Internal Server Error'); - - const apiResponse : ApiResponse = await this.invoke( - 'POST', - authEndpoint, - '/auth/O2/token', - pathParams, - queryParams, - headerParams, - bodyParams, - errorDefinitions, - true, - ); - - return apiResponse.body as AccessTokenResponse; - } - } -} - -/** - * function creating an AskSdk user agent. - * @param packageVersion - * @param customUserAgent - */ -export function createUserAgent(packageVersion : string, customUserAgent : string) : string { - const customUserAgentString = customUserAgent ? (' ' + customUserAgent) : ''; - - return `ask-node-model/${packageVersion} Node/${process.version}` + customUserAgentString; -} +export namespace services { + /** + * Represents the interface between ApiClient and a Service Client. + * @export + * @interface ApiClientMessage + */ + export interface ApiClientMessage { + headers : Array<{key : string, value : string}>; + body? : string; + } + + /** + * Represents a request sent from Service Clients to an ApiClient implementation. + * @export + * @interface ApiClientRequest + * @extends {ApiClientMessage} + */ + export interface ApiClientRequest extends ApiClientMessage { + url : string; + method : string; + } + + /** + * Represents a response returned by ApiClient implementation to a Service Client. + * @export + * @interface ApiClientResponse + * @extends {ApiClientMessage} + */ + export interface ApiClientResponse extends ApiClientMessage { + /** + * Result code of the attempt to satisfy the request. Normally this + * corresponds to the HTTP status code returned by the server. + */ + statusCode : number; + } + + /** + * Represents a response with parsed body. + * @export + * @interface ApiResponse + */ + export interface ApiResponse { + headers : Array<{key : string, value : string}>; + body? : any; + statusCode : number; + } + + /** + * Represents a basic contract for API request execution + * @export + * @interface ApiClient + */ + export interface ApiClient { + /** + * Dispatches a request to an API endpoint described in the request. + * An ApiClient is expected to resolve the Promise in the case an API returns a non-200 HTTP + * status code. The responsibility of translating a particular response code to an error lies with the + * caller to invoke. + * @param {ApiClientRequest} request request to dispatch to the ApiClient + * @returns {Promise} Response from the ApiClient + * @memberof ApiClient + */ + invoke(request : ApiClientRequest) : Promise; + } + + /** + * Represents an interface that provides API configuration options needed by service clients. + * @interface ApiConfiguration + */ + export interface ApiConfiguration { + /** + * Configured ApiClient implementation + */ + apiClient : ApiClient; + /** + * Authorization value to be used on any calls of the service client instance + */ + authorizationValue : string; + /** + * Endpoint to hit by the service client instance + */ + apiEndpoint : string; + } + + /** + * Class to be used as the base class for the generated service clients. + */ + export abstract class BaseServiceClient { + private static isCodeSuccessful( responseCode : number ) : boolean { + return responseCode >= 200 && responseCode < 300; + } + + private static buildUrl( + endpoint : string, + path : string, + queryParameters : Array<{ key : string, value : string }>, + pathParameters : Map, + ) : string { + const processedEndpoint : string = endpoint.endsWith('/') ? endpoint.substr(0, endpoint.length - 1) : endpoint; + const pathWithParams : string = this.interpolateParams(path, pathParameters); + const isConstantQueryPresent : boolean = pathWithParams.includes('?'); + const queryString : string = this.buildQueryString(queryParameters, isConstantQueryPresent); + + return processedEndpoint + pathWithParams + queryString; + } + + private static interpolateParams(path : string, params : Map) : string { + if (!params) { + return path; + } + + let result : string = path; + + params.forEach((paramValue : string, paramName : string) => { + result = result.replace('{' + paramName + '}', encodeURIComponent(paramValue)); + }); + + return result; + } + + private static buildQueryString(params : Array<{ key : string, value : string }>, isQueryStart : boolean) : string { + if (!params) { + return ''; + } + + const sb : string[] = []; + + if (isQueryStart) { + sb.push('&'); + } else { + sb.push('?'); + } + + params.forEach((obj) => { + sb.push(encodeURIComponent(obj.key)); + sb.push('='); + sb.push(encodeURIComponent(obj.value)); + sb.push('&'); + }); + sb.pop(); + + return sb.join(''); + } + + /** + * ApiConfiguration instance to provide dependencies for this service client + */ + protected apiConfiguration : ApiConfiguration; + + private requestInterceptors : Array<(request : ApiClientRequest) => void | Promise> = []; + private responseInterceptors : Array<(response : ApiClientResponse) => void | Promise> = []; + + /** + * Creates new instance of the BaseServiceClient + * @param {ApiConfiguration} apiConfiguration configuration parameter to provide dependencies to service client instance + */ + protected constructor(apiConfiguration : ApiConfiguration) { + this.apiConfiguration = apiConfiguration; + } + + /** + * Sets array of functions that is going to be executed before the request is send + * @param {Function} requestInterceptor request interceptor function + * @returns {BaseServiceClient} + */ + public withRequestInterceptors(...requestInterceptors : Array<(request : ApiClientRequest) => void | Promise>) : BaseServiceClient { + for ( const interceptor of requestInterceptors ) { + this.requestInterceptors.push(interceptor); + } + + return this; + } + + /** + * Sets array of functions that is going to be executed after the request is send + * @param {Function} responseInterceptor response interceptor function + * @returns {BaseServiceClient} + */ + public withResponseInterceptors(...responseInterceptors : Array<(response : ApiClientResponse) => void | Promise>) : BaseServiceClient { + for ( const interceptor of responseInterceptors ) { + this.responseInterceptors.push(interceptor); + } + + return this; + } + + /** + * Invocation wrapper to implement service operations in generated classes + * @param method HTTP method, such as 'POST', 'GET', 'DELETE', etc. + * @param endpoint base API url + * @param path the path pattern with possible placeholders for path parameters in form {paramName} + * @param pathParams path parameters collection + * @param queryParams query parameters collection + * @param headerParams headers collection + * @param bodyParam if body parameter is present it is provided here, otherwise null or undefined + * @param errors maps recognized status codes to messages + * @param nonJsonBody if the body is in JSON format + */ + protected async invoke( + method : string, + endpoint : string, + path : string, + pathParams : Map, + queryParams : Array<{ key : string, value : string }>, + headerParams : Array<{ key : string, value : string }>, + bodyParam : any, + errors : Map, + nonJsonBody? : boolean, + ) : Promise { + const request : ApiClientRequest = { + url : BaseServiceClient.buildUrl(endpoint, path, queryParams, pathParams), + method, + headers : headerParams, + }; + if (bodyParam != null) { + request.body = nonJsonBody ? bodyParam : JSON.stringify(bodyParam); + } + + const apiClient = this.apiConfiguration.apiClient; + let response : ApiClientResponse; + try { + for (const requestInterceptor of this.requestInterceptors) { + await requestInterceptor(request); + } + response = await apiClient.invoke(request); + for (const responseInterceptor of this.responseInterceptors) { + await responseInterceptor(response); + } + } catch (err) { + err.message = `Call to service failed: ${err.message}`; + + throw err; + } + + let body; + + try { + const contentType = response.headers.find((h) => h.key === 'content-type'); + // json if no content type or content type is application/json + const isJson = !contentType || contentType.value.includes('application/json'); + body = response.body && isJson ? JSON.parse(response.body) : response.body; + // converting to undefined if empty string + body = body || undefined; + } catch (err) { + throw new SyntaxError(`Failed trying to parse the response body: ${response.body}`); + } + + if (BaseServiceClient.isCodeSuccessful(response.statusCode)) { + const apiResponse : ApiResponse = { + headers : response.headers, + body, + statusCode : response.statusCode, + }; + + return apiResponse; + } + + const err = new Error('Unknown error'); + err.name = 'ServiceError'; + err['statusCode'] = response.statusCode; // tslint:disable-line:no-string-literal + err['response'] = body; // tslint:disable-line:no-string-literal + if (errors && errors.has(response.statusCode)) { + err.message = errors.get(response.statusCode); + } + + throw err; + } + } + + /** + * Represents a Login With Amazon(LWA) access token + */ + export interface AccessToken { + token : string; + expiry : Number; + } + + /** + * Represents a request for retrieving a Login With Amazon(LWA) access token + */ + export interface AccessTokenRequest { + clientId : string; + clientSecret : string; + scope? : string; + refreshToken? : string; + } + + /** + * Represents a response returned by LWA containing a Login With Amazon(LWA) access token + */ + export interface AccessTokenResponse { + access_token : string; + expires_in : number; + scope : string; + token_type : string; + } + + /** + * Represents the authentication configuration for a client ID and client secret + */ + export interface AuthenticationConfiguration { + clientId : string; + clientSecret : string; + refreshToken? : string; + authEndpoint? : string; + } + + /** + * Class to be used to call Amazon LWA to retrieve access tokens. + */ + export class LwaServiceClient extends BaseServiceClient { + protected static EXPIRY_OFFSET_MILLIS : number = 60000; + protected static REFRESH_ACCESS_TOKEN : string = 'refresh_access_token'; + protected static CLIENT_CREDENTIALS_GRANT_TYPE : string = 'client_credentials'; + protected static LWA_CREDENTIALS_GRANT_TYPE : string = 'refresh_token'; + protected static AUTH_ENDPOINT : string = 'https://api.amazon.com'; + + protected authenticationConfiguration : AuthenticationConfiguration; + protected tokenStore : {[cacheKey : string] : AccessToken}; + protected grantType : string; + + constructor(options : { + apiConfiguration : ApiConfiguration, + authenticationConfiguration : AuthenticationConfiguration, + grantType? : string, + }) { + super(options.apiConfiguration); + if (options.authenticationConfiguration == null) { + throw new Error('AuthenticationConfiguration cannot be null or undefined.'); + } + this.grantType = options.grantType ? options.grantType : LwaServiceClient.CLIENT_CREDENTIALS_GRANT_TYPE; + this.authenticationConfiguration = options.authenticationConfiguration; + this.tokenStore = {}; + } + + public async getAccessTokenForScope(scope : string) : Promise { + if (scope == null) { + throw new Error('Scope cannot be null or undefined.'); + } + + return this.getAccessToken(scope); + } + + public async getAccessToken(scope? : string) : Promise { + const cacheKey : string = scope ? scope : LwaServiceClient.REFRESH_ACCESS_TOKEN; + const accessToken = this.tokenStore[cacheKey]; + + if (accessToken && accessToken.expiry > Date.now() + LwaServiceClient.EXPIRY_OFFSET_MILLIS) { + return accessToken.token; + } + + const accessTokenRequest : AccessTokenRequest = { + clientId : this.authenticationConfiguration.clientId, + clientSecret : this.authenticationConfiguration.clientSecret, + }; + if (scope && this.authenticationConfiguration.refreshToken) { + throw new Error('Cannot support both refreshToken and scope.'); + } else if (scope == null && this.authenticationConfiguration.refreshToken == null) { + throw new Error('Either refreshToken or scope must be specified.'); + } else if (scope == null) { + accessTokenRequest.refreshToken = this.authenticationConfiguration.refreshToken; + } else { + accessTokenRequest.scope = scope; + } + + const accessTokenResponse : AccessTokenResponse = await this.generateAccessToken(accessTokenRequest); + + this.tokenStore[cacheKey] = { + token : accessTokenResponse.access_token, + expiry : Date.now() + accessTokenResponse.expires_in * 1000, + }; + + return accessTokenResponse.access_token; + } + + protected async generateAccessToken(accessTokenRequest : AccessTokenRequest) : Promise { + const authEndpoint = this.authenticationConfiguration.authEndpoint || LwaServiceClient.AUTH_ENDPOINT; + + if (accessTokenRequest == null) { + throw new Error(`Required parameter accessTokenRequest was null or undefined when calling generateAccessToken.`); + } + + const queryParams : Array<{ key : string, value : string }> = []; + + const headerParams : Array<{key : string, value : string}> = []; + headerParams.push({key : 'Content-type', value : 'application/x-www-form-urlencoded'}); + + const pathParams : Map = new Map(); + + const paramInfo = this.grantType === LwaServiceClient.LWA_CREDENTIALS_GRANT_TYPE ? `&refresh_token=${accessTokenRequest.refreshToken}` : `&scope=${accessTokenRequest.scope}`; + const bodyParams : string = `grant_type=${this.grantType}&client_secret=${accessTokenRequest.clientSecret}&client_id=${accessTokenRequest.clientId}` + paramInfo; + + const errorDefinitions : Map = new Map(); + errorDefinitions.set(200, 'Token request sent.'); + errorDefinitions.set(400, 'Bad Request'); + errorDefinitions.set(401, 'Authentication Failed'); + errorDefinitions.set(500, 'Internal Server Error'); + + const apiResponse : ApiResponse = await this.invoke( + 'POST', + authEndpoint, + '/auth/O2/token', + pathParams, + queryParams, + headerParams, + bodyParams, + errorDefinitions, + true, + ); + + return apiResponse.body as AccessTokenResponse; + } + } +} + +/** + * function creating an AskSdk user agent. + * @param packageVersion + * @param customUserAgent + */ +export function createUserAgent(packageVersion : string, customUserAgent : string) : string { + const customUserAgentString = customUserAgent ? (' ' + customUserAgent) : ''; + + return `ask-node-model/${packageVersion} Node/${process.version}` + customUserAgentString; +} /* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -513,6 +513,11 @@ export interface Context { * Provides the current experimentation state */ 'Experimentation'?: interfaces.alexa.experimentation.ExperimentationState; + /** + * Provides the customer's advertising ID and preference for receiving interest-based ads + */ + 'Advertising'?: interfaces.alexa.advertising.Advertising; + } /** @@ -1134,6 +1139,26 @@ export namespace events.skillevents { } } +export namespace interfaces.alexa.advertising { + /** + * A map that provides the customer's advertising ID and preference for receiving interest-based ads. + * @interface + */ + export interface Advertising { + /** + * The customer's advertising ID. + * Customer-resettable, unique identifier that maps to the ifa attribute of the OpenRTB API specification. + * Formatted as a version 4 UUID string separated by dashes (8-4-4-4-12). + */ + 'advertisingId': string; + /** + * Indicates whether the customer wants to receive interest-based ads. Set to true when the customer opts out of interest-based ads and tracking. + * Maps to the lmt attribute of the OpenRTB API specification. + */ + 'limitAdTracking': boolean; + } + } + export namespace interfaces.alexa.comms.messagingcontroller { /** * A map whose key is the new status and value is the message ID list. The status of the messages whose IDs are in the list will be updated to the new status from the key.