UNPKG

@aws-cdk/aws-apigateway

Version:

The CDK Construct Library for AWS::ApiGateway

654 lines 76.7 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.EndpointType = exports.ApiKeySourceType = exports.RestApi = exports.SpecRestApi = exports.RestApiBase = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const cloudwatch = require("@aws-cdk/aws-cloudwatch"); const iam = require("@aws-cdk/aws-iam"); const core_1 = require("@aws-cdk/core"); const api_key_1 = require("./api-key"); const apigateway_canned_metrics_generated_1 = require("./apigateway-canned-metrics.generated"); const apigateway_generated_1 = require("./apigateway.generated"); const deployment_1 = require("./deployment"); const domain_name_1 = require("./domain-name"); const gateway_response_1 = require("./gateway-response"); const model_1 = require("./model"); const requestvalidator_1 = require("./requestvalidator"); const resource_1 = require("./resource"); const stage_1 = require("./stage"); const usage_plan_1 = require("./usage-plan"); const RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApiBase'); /** * Base implementation that are common to various implementations of IRestApi */ class RestApiBase extends core_1.Resource { constructor(scope, id, props = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiBaseProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, RestApiBase); } throw error; } const restApiName = props.restApiName ?? id; super(scope, id, { physicalName: restApiName, }); this.restApiName = restApiName; Object.defineProperty(this, RESTAPI_SYMBOL, { value: true }); } /** * Checks if the given object is an instance of RestApiBase. * @internal */ static _isRestApiBase(x) { return x !== null && typeof (x) === 'object' && RESTAPI_SYMBOL in x; } /** * API Gateway deployment that represents the latest changes of the API. * This resource will be automatically updated every time the REST API model changes. * This will be undefined if `deploy` is false. */ get latestDeployment() { return this._latestDeployment; } /** * The first domain name mapped to this API, if defined through the `domainName` * configuration prop, or added via `addDomainName` */ get domainName() { return this._domainName; } /** * Returns the URL for an HTTP path. * * Fails if `deploymentStage` is not set either by `deploy` or explicitly. */ urlForPath(path = '/') { if (!this.deploymentStage) { throw new Error('Cannot determine deployment stage for API from "deploymentStage". Use "deploy" or explicitly set "deploymentStage"'); } return this.deploymentStage.urlForPath(path); } /** * Defines an API Gateway domain name and maps it to this API. * @param id The construct id * @param options custom domain options */ addDomainName(id, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_DomainNameOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addDomainName); } throw error; } const domainName = new domain_name_1.DomainName(this, id, { ...options, mapping: this, }); if (!this._domainName) { this._domainName = domainName; } return domainName; } /** * Adds a usage plan. */ addUsagePlan(id, props = {}) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_UsagePlanProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addUsagePlan); } throw error; } return new usage_plan_1.UsagePlan(this, id, props); } arnForExecuteApi(method = '*', path = '/*', stage = '*') { if (!core_1.Token.isUnresolved(path) && !path.startsWith('/')) { throw new Error(`"path" must begin with a "/": '${path}'`); } if (method.toUpperCase() === 'ANY') { method = '*'; } return core_1.Stack.of(this).formatArn({ service: 'execute-api', resource: this.restApiId, arnFormat: core_1.ArnFormat.SLASH_RESOURCE_NAME, resourceName: `${stage}/${method}${path}`, }); } /** * Adds a new gateway response. */ addGatewayResponse(id, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_GatewayResponseOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addGatewayResponse); } throw error; } return new gateway_response_1.GatewayResponse(this, id, { restApi: this, ...options, }); } /** * Add an ApiKey */ addApiKey(id, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ApiKeyOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addApiKey); } throw error; } return new api_key_1.ApiKey(this, id, { resources: [this], ...options, }); } /** * Returns the given named metric for this API */ metric(metricName, props) { return new cloudwatch.Metric({ namespace: 'AWS/ApiGateway', metricName, dimensionsMap: { ApiName: this.restApiName }, ...props, }).attachTo(this); } /** * Metric for the number of client-side errors captured in a given period. * * Default: sum over 5 minutes */ metricClientError(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics._4XxErrorSum, props); } /** * Metric for the number of server-side errors captured in a given period. * * Default: sum over 5 minutes */ metricServerError(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics._5XxErrorSum, props); } /** * Metric for the number of requests served from the API cache in a given period. * * Default: sum over 5 minutes */ metricCacheHitCount(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.cacheHitCountSum, props); } /** * Metric for the number of requests served from the backend in a given period, * when API caching is enabled. * * Default: sum over 5 minutes */ metricCacheMissCount(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.cacheMissCountSum, props); } /** * Metric for the total number API requests in a given period. * * Default: sample count over 5 minutes */ metricCount(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.countSum, { statistic: 'SampleCount', ...props, }); } /** * Metric for the time between when API Gateway relays a request to the backend * and when it receives a response from the backend. * * Default: average over 5 minutes. */ metricIntegrationLatency(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.integrationLatencyAverage, props); } /** * The time between when API Gateway receives a request from a client * and when it returns a response to the client. * The latency includes the integration latency and other API Gateway overhead. * * Default: average over 5 minutes. */ metricLatency(props) { return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.latencyAverage, props); } /** * Internal API used by `Method` to keep an inventory of methods at the API * level for validation purposes. * * @internal */ _attachMethod(method) { ignore(method); } /** * Associates a Deployment resource with this REST API. * * @internal */ _attachDeployment(deployment) { ignore(deployment); } /** * Associates a Stage with this REST API * * @internal */ _attachStage(stage) { if (this.cloudWatchAccount) { stage.node.addDependency(this.cloudWatchAccount); } } /** * @internal */ _configureCloudWatchRole(apiResource) { const role = new iam.Role(this, 'CloudWatchRole', { assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'), managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonAPIGatewayPushToCloudWatchLogs')], }); this.cloudWatchAccount = new apigateway_generated_1.CfnAccount(this, 'Account', { cloudWatchRoleArn: role.roleArn, }); this.cloudWatchAccount.node.addDependency(apiResource); } /** * @deprecated This method will be made internal. No replacement */ configureCloudWatchRole(apiResource) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.RestApiBase#configureCloudWatchRole", "This method will be made internal. No replacement"); jsiiDeprecationWarnings._aws_cdk_aws_apigateway_CfnRestApi(apiResource); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.configureCloudWatchRole); } throw error; } this._configureCloudWatchRole(apiResource); } /** * @deprecated This method will be made internal. No replacement */ configureDeployment(props) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.RestApiBase#configureDeployment", "This method will be made internal. No replacement"); jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiBaseProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.configureDeployment); } throw error; } this._configureDeployment(props); } /** * @internal */ _configureDeployment(props) { const deploy = props.deploy ?? true; if (deploy) { this._latestDeployment = new deployment_1.Deployment(this, 'Deployment', { description: 'Automatically created by the RestApi construct', api: this, retainDeployments: props.retainDeployments, }); // encode the stage name into the construct id, so if we change the stage name, it will recreate a new stage. // stage name is part of the endpoint, so that makes sense. const stageName = (props.deployOptions && props.deployOptions.stageName) || 'prod'; this.deploymentStage = new stage_1.Stage(this, `DeploymentStage.${stageName}`, { deployment: this._latestDeployment, ...props.deployOptions, }); new core_1.CfnOutput(this, 'Endpoint', { exportName: props.endpointExportName, value: this.urlForPath() }); } else { if (props.deployOptions) { throw new Error('Cannot set \'deployOptions\' if \'deploy\' is disabled'); } } } /** * @internal */ _configureEndpoints(props) { if (props.endpointTypes && props.endpointConfiguration) { throw new Error('Only one of the RestApi props, endpointTypes or endpointConfiguration, is allowed'); } if (props.endpointConfiguration) { return { types: props.endpointConfiguration.types, vpcEndpointIds: props.endpointConfiguration?.vpcEndpoints?.map(vpcEndpoint => vpcEndpoint.vpcEndpointId), }; } if (props.endpointTypes) { return { types: props.endpointTypes }; } return undefined; } cannedMetric(fn, props) { return new cloudwatch.Metric({ ...fn({ ApiName: this.restApiName }), ...props, }).attachTo(this); } } exports.RestApiBase = RestApiBase; _a = JSII_RTTI_SYMBOL_1; RestApiBase[_a] = { fqn: "@aws-cdk/aws-apigateway.RestApiBase", version: "1.204.0" }; /** * Represents a REST API in Amazon API Gateway, created with an OpenAPI specification. * * Some properties normally accessible on @see {@link RestApi} - such as the description - * must be declared in the specification. All Resources and Methods need to be defined as * part of the OpenAPI specification file, and cannot be added via the CDK. * * By default, the API will automatically be deployed and accessible from a * public endpoint. * * * @resource AWS::ApiGateway::RestApi */ class SpecRestApi extends RestApiBase { constructor(scope, id, props) { super(scope, id, props); try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_SpecRestApiProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, SpecRestApi); } throw error; } const apiDefConfig = props.apiDefinition.bind(this); const resource = new apigateway_generated_1.CfnRestApi(this, 'Resource', { name: this.restApiName, policy: props.policy, failOnWarnings: props.failOnWarnings, body: apiDefConfig.inlineDefinition ?? undefined, bodyS3Location: apiDefConfig.inlineDefinition ? undefined : apiDefConfig.s3Location, endpointConfiguration: this._configureEndpoints(props), parameters: props.parameters, }); props.apiDefinition.bindAfterCreate(this, this); this.node.defaultChild = resource; this.restApiId = resource.ref; this.restApiRootResourceId = resource.attrRootResourceId; this.root = new RootResource(this, {}, this.restApiRootResourceId); this._configureDeployment(props); if (props.domainName) { this.addDomainName('CustomDomain', props.domainName); } const cloudWatchRole = props.cloudWatchRole ?? true; if (cloudWatchRole) { this._configureCloudWatchRole(resource); } } } exports.SpecRestApi = SpecRestApi; _b = JSII_RTTI_SYMBOL_1; SpecRestApi[_b] = { fqn: "@aws-cdk/aws-apigateway.SpecRestApi", version: "1.204.0" }; /** * Represents a REST API in Amazon API Gateway. * * Use `addResource` and `addMethod` to configure the API model. * * By default, the API will automatically be deployed and accessible from a * public endpoint. */ class RestApi extends RestApiBase { constructor(scope, id, props = {}) { super(scope, id, props); /** * The list of methods bound to this RestApi */ this.methods = new Array(); /** * This list of deployments bound to this RestApi */ this.deployments = new Array(); try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, RestApi); } throw error; } const resource = new apigateway_generated_1.CfnRestApi(this, 'Resource', { name: this.physicalName, description: props.description, policy: props.policy, failOnWarnings: props.failOnWarnings, minimumCompressionSize: props.minimumCompressionSize, binaryMediaTypes: props.binaryMediaTypes, endpointConfiguration: this._configureEndpoints(props), apiKeySourceType: props.apiKeySourceType, cloneFrom: props.cloneFrom?.restApiId, parameters: props.parameters, disableExecuteApiEndpoint: props.disableExecuteApiEndpoint, }); this.node.defaultChild = resource; this.restApiId = resource.ref; const cloudWatchRole = props.cloudWatchRole ?? true; if (cloudWatchRole) { this._configureCloudWatchRole(resource); } this._configureDeployment(props); if (props.domainName) { this.addDomainName('CustomDomain', props.domainName); } this.root = new RootResource(this, props, resource.attrRootResourceId); this.restApiRootResourceId = resource.attrRootResourceId; } /** * Import an existing RestApi. */ static fromRestApiId(scope, id, restApiId) { class Import extends RestApiBase { constructor() { super(...arguments); this.restApiId = restApiId; } get root() { throw new Error('root is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.'); } get restApiRootResourceId() { throw new Error('restApiRootResourceId is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.'); } } return new Import(scope, id); } /** * Import an existing RestApi that can be configured with additional Methods and Resources. */ static fromRestApiAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromRestApiAttributes); } throw error; } class Import extends RestApiBase { constructor() { super(...arguments); this.restApiId = attrs.restApiId; this.restApiRootResourceId = attrs.rootResourceId; this.root = new RootResource(this, {}, this.restApiRootResourceId); } } return new Import(scope, id); } /** * The deployed root URL of this REST API. */ get url() { return this.urlForPath(); } /** * Adds a new model. */ addModel(id, props) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ModelOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addModel); } throw error; } return new model_1.Model(this, id, { ...props, restApi: this, }); } /** * Adds a new request validator. */ addRequestValidator(id, props) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RequestValidatorOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addRequestValidator); } throw error; } return new requestvalidator_1.RequestValidator(this, id, { ...props, restApi: this, }); } /** * Internal API used by `Method` to keep an inventory of methods at the API * level for validation purposes. * * @internal */ _attachMethod(method) { this.methods.push(method); // add this method as a dependency to all deployments defined for this api // when additional deployments are added, _attachDeployment is called and // this method will be added there. for (const dep of this.deployments) { dep._addMethodDependency(method); } } /** * Attaches a deployment to this REST API. * * @internal */ _attachDeployment(deployment) { this.deployments.push(deployment); // add all methods that were already defined as dependencies of this // deployment when additional methods are added, _attachMethod is called and // it will be added as a dependency to this deployment. for (const method of this.methods) { deployment._addMethodDependency(method); } } /** * Performs validation of the REST API. */ validate() { if (this.methods.length === 0) { return ["The REST API doesn't contain any methods"]; } return []; } } exports.RestApi = RestApi; _c = JSII_RTTI_SYMBOL_1; RestApi[_c] = { fqn: "@aws-cdk/aws-apigateway.RestApi", version: "1.204.0" }; var ApiKeySourceType; (function (ApiKeySourceType) { /** * To read the API key from the `X-API-Key` header of a request. */ ApiKeySourceType["HEADER"] = "HEADER"; /** * To read the API key from the `UsageIdentifierKey` from a custom authorizer. */ ApiKeySourceType["AUTHORIZER"] = "AUTHORIZER"; })(ApiKeySourceType = exports.ApiKeySourceType || (exports.ApiKeySourceType = {})); var EndpointType; (function (EndpointType) { /** * For an edge-optimized API and its custom domain name. */ EndpointType["EDGE"] = "EDGE"; /** * For a regional API and its custom domain name. */ EndpointType["REGIONAL"] = "REGIONAL"; /** * For a private API and its custom domain name. */ EndpointType["PRIVATE"] = "PRIVATE"; })(EndpointType = exports.EndpointType || (exports.EndpointType = {})); class RootResource extends resource_1.ResourceBase { constructor(api, props, resourceId) { super(api, 'Default'); this.parentResource = undefined; this.defaultIntegration = props.defaultIntegration; this.defaultMethodOptions = props.defaultMethodOptions; this.defaultCorsPreflightOptions = props.defaultCorsPreflightOptions; this.api = api; this.resourceId = resourceId; this.path = '/'; if (api instanceof RestApi) { this._restApi = api; } if (this.defaultCorsPreflightOptions) { this.addCorsPreflight(this.defaultCorsPreflightOptions); } } /** * Get the RestApi associated with this Resource. * @deprecated - Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead. */ get restApi() { if (!this._restApi) { throw new Error('RestApi is not available on Resource not connected to an instance of RestApi. Use `api` instead'); } return this._restApi; } } function ignore(_x) { return; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdGFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc3RhcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0RBQXNEO0FBRXRELHdDQUF3QztBQUN4Qyx3Q0FBeUc7QUFHekcsdUNBQTJEO0FBQzNELCtGQUEwRTtBQUMxRSxpRUFBZ0U7QUFFaEUsNkNBQTBDO0FBQzFDLCtDQUE4RDtBQUM5RCx5REFBNkU7QUFHN0UsbUNBQThDO0FBQzlDLHlEQUErRTtBQUMvRSx5Q0FBc0U7QUFDdEUsbUNBQThDO0FBQzlDLDZDQUF5RDtBQUV6RCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7QUE0T3pFOztHQUVHO0FBQ0gsTUFBc0IsV0FBWSxTQUFRLGVBQVE7SUErRGhELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsUUFBMEIsRUFBRzs7Ozs7OytDQS9EbkQsV0FBVzs7OztRQWdFN0IsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7UUFDNUMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixZQUFZLEVBQUUsV0FBVztTQUMxQixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUUvQixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztLQUM5RDtJQXRFRDs7O09BR0c7SUFDSSxNQUFNLENBQUMsY0FBYyxDQUFDLENBQU07UUFDakMsT0FBTyxDQUFDLEtBQUssSUFBSSxJQUFJLE9BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUksY0FBYyxJQUFJLENBQUMsQ0FBQztLQUNwRTtJQUVEOzs7O09BSUc7SUFDSCxJQUFXLGdCQUFnQjtRQUN6QixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztLQUMvQjtJQUVE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Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBJVnBjRW5kcG9pbnQgfSBmcm9tICdAYXdzLWNkay9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCB7IEFybkZvcm1hdCwgQ2ZuT3V0cHV0LCBJUmVzb3VyY2UgYXMgSVJlc291cmNlQmFzZSwgUmVzb3VyY2UsIFN0YWNrLCBUb2tlbiB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBcGlEZWZpbml0aW9uIH0gZnJvbSAnLi9hcGktZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBBcGlLZXksIEFwaUtleU9wdGlvbnMsIElBcGlLZXkgfSBmcm9tICcuL2FwaS1rZXknO1xuaW1wb3J0IHsgQXBpR2F0ZXdheU1ldHJpY3MgfSBmcm9tICcuL2FwaWdhdGV3YXktY2FubmVkLW1ldHJpY3MuZ2VuZXJhdGVkJztcbmltcG9ydCB7IENmbkFjY291bnQsIENmblJlc3RBcGkgfSBmcm9tICcuL2FwaWdhdGV3YXkuZ2VuZXJhdGVkJztcbmltcG9ydCB7IENvcnNPcHRpb25zIH0gZnJvbSAnLi9jb3JzJztcbmltcG9ydCB7IERlcGxveW1lbnQgfSBmcm9tICcuL2RlcGxveW1lbnQnO1xuaW1wb3J0IHsgRG9tYWluTmFtZSwgRG9tYWluTmFtZU9wdGlvbnMgfSBmcm9tICcuL2RvbWFpbi1uYW1lJztcbmltcG9ydCB7IEdhdGV3YXlSZXNwb25zZSwgR2F0ZXdheVJlc3BvbnNlT3B0aW9ucyB9IGZyb20gJy4vZ2F0ZXdheS1yZXNwb25zZSc7XG5pbXBvcnQgeyBJbnRlZ3JhdGlvbiB9IGZyb20gJy4vaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgTWV0aG9kLCBNZXRob2RPcHRpb25zIH0gZnJvbSAnLi9tZXRob2QnO1xuaW1wb3J0IHsgTW9kZWwsIE1vZGVsT3B0aW9ucyB9IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHsgUmVxdWVzdFZhbGlkYXRvciwgUmVxdWVzdFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tICcuL3JlcXVlc3R2YWxpZGF0b3InO1xuaW1wb3J0IHsgSVJlc291cmNlLCBSZXNvdXJjZUJhc2UsIFJlc291cmNlT3B0aW9ucyB9IGZyb20gJy4vcmVzb3VyY2UnO1xuaW1wb3J0IHsgU3RhZ2UsIFN0YWdlT3B0aW9ucyB9IGZyb20gJy4vc3RhZ2UnO1xuaW1wb3J0IHsgVXNhZ2VQbGFuLCBVc2FnZVBsYW5Qcm9wcyB9IGZyb20gJy4vdXNhZ2UtcGxhbic7XG5cbmNvbnN0IFJFU1RBUElfU1lNQk9MID0gU3ltYm9sLmZvcignQGF3cy1jZGsvYXdzLWFwaWdhdGV3YXkuUmVzdEFwaUJhc2UnKTtcblxuZXhwb3J0IGludGVyZmFjZSBJUmVzdEFwaSBleHRlbmRzIElSZXNvdXJjZUJhc2Uge1xuICAvKipcbiAgICogVGhlIElEIG9mIHRoaXMgQVBJIEdhdGV3YXkgUmVzdEFwaS5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdEFwaUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByZXNvdXJjZSBJRCBvZiB0aGUgcm9vdCByZXNvdXJjZS5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdEFwaVJvb3RSZXNvdXJjZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFQSSBHYXRld2F5IGRlcGxveW1lbnQgdGhhdCByZXByZXNlbnRzIHRoZSBsYXRlc3QgY2hhbmdlcyBvZiB0aGUgQVBJLlxuICAgKiBUaGlzIHJlc291cmNlIHdpbGwgYmUgYXV0b21hdGljYWxseSB1cGRhdGVkIGV2ZXJ5IHRpbWUgdGhlIFJFU1QgQVBJIG1vZGVsIGNoYW5nZXMuXG4gICAqIGB1bmRlZmluZWRgIHdoZW4gbm8gZGVwbG95bWVudCBpcyBjb25maWd1cmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbGF0ZXN0RGVwbG95bWVudD86IERlcGxveW1lbnQ7XG5cbiAgLyoqXG4gICAqIEFQSSBHYXRld2F5IHN0YWdlIHRoYXQgcG9pbnRzIHRvIHRoZSBsYXRlc3QgZGVwbG95bWVudCAoaWYgZGVmaW5lZCkuXG4gICAqL1xuICBkZXBsb3ltZW50U3RhZ2U6IFN0YWdlO1xuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSByb290IHJlc291cmNlIChcIi9cIikgb2YgdGhpcyBBUEkuIFVzZSBpdCB0byBkZWZpbmUgdGhlIEFQSSBtb2RlbDpcbiAgICpcbiAgICogICAgYXBpLnJvb3QuYWRkTWV0aG9kKCdBTlknLCByZWRpcmVjdFRvSG9tZVBhZ2UpOyAvLyBcIkFOWSAvXCJcbiAgICogICAgYXBpLnJvb3QuYWRkUmVzb3VyY2UoJ2ZyaWVuZHMnKS5hZGRNZXRob2QoJ0dFVCcsIGdldEZyaWVuZHNIYW5kbGVyKTsgLy8gXCJHRVQgL2ZyaWVuZHNcIlxuICAgKlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdDogSVJlc291cmNlO1xuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBcImV4ZWN1dGUtYXBpXCIgQVJOXG4gICAqIEByZXR1cm5zIFRoZSBcImV4ZWN1dGUtYXBpXCIgQVJOLlxuICAgKiBAZGVmYXVsdCBcIipcIiByZXR1cm5zIHRoZSBleGVjdXRlIEFQSSBBUk4gZm9yIGFsbCBtZXRob2RzL3Jlc291cmNlcyBpblxuICAgKiB0aGlzIEFQSS5cbiAgICogQHBhcmFtIG1ldGhvZCBUaGUgbWV0aG9kIChkZWZhdWx0IGAqYClcbiAgICogQHBhcmFtIHBhdGggVGhlIHJlc291cmNlIHBhdGguIE11c3Qgc3RhcnQgd2l0aCAnLycgKGRlZmF1bHQgYCpgKVxuICAgKiBAcGFyYW0gc3RhZ2UgVGhlIHN0YWdlIChkZWZhdWx0IGAqYClcbiAgICovXG4gIGFybkZvckV4ZWN1dGVBcGkobWV0aG9kPzogc3RyaW5nLCBwYXRoPzogc3RyaW5nLCBzdGFnZT86IHN0cmluZyk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBwcm9wcyB0aGF0IGFsbCBSZXN0IEFQSXMgc2hhcmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXN0QXBpQmFzZVByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIERlcGxveW1lbnQgc2hvdWxkIGJlIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmb3IgdGhpcyBBUEksXG4gICAqIGFuZCByZWNyZWF0ZWQgd2hlbiB0aGUgQVBJIG1vZGVsIChyZXNvdXJjZXMsIG1ldGhvZHMpIGNoYW5nZXMuXG4gICAqXG4gICAqIFNpbmNlIEFQSSBHYXRld2F5IGRlcGxveW1lbnRzIGFyZSBpbW11dGFibGUsIFdoZW4gdGhpcyBvcHRpb24gaXMgZW5hYmxlZFxuICAgKiAoYnkgZGVmYXVsdCksIGFuIEFXUzo6QXBpR2F0ZXdheTo6RGVwbG95bWVudCByZXNvdXJjZSB3aWxsIGF1dG9tYXRpY2FsbHlcbiAgICogY3JlYXRlZCB3aXRoIGEgbG9naWNhbCBJRCB0aGF0IGhhc2hlcyB0aGUgQVBJIG1vZGVsIChtZXRob2RzLCByZXNvdXJjZXNcbiAgICogYW5kIG9wdGlvbnMpLiBUaGlzIG1lYW5zIHRoYXQgd2hlbiB0aGUgbW9kZWwgY2hhbmdlcywgdGhlIGxvZ2ljYWwgSUQgb2ZcbiAgICogdGhpcyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB3aWxsIGNoYW5nZSwgYW5kIGEgbmV3IGRlcGxveW1lbnQgd2lsbCBiZVxuICAgKiBjcmVhdGVkLlxuICAgKlxuICAgKiBJZiB0aGlzIGlzIHNldCwgYGxhdGVzdERlcGxveW1lbnRgIHdpbGwgcmVmZXIgdG8gdGhlIGBEZXBsb3ltZW50YCBvYmplY3RcbiAgICogYW5kIGBkZXBsb3ltZW50U3RhZ2VgIHdpbGwgcmVmZXIgdG8gYSBgU3RhZ2VgIHRoYXQgcG9pbnRzIHRvIHRoaXNcbiAgICogZGVwbG95bWVudC4gVG8gY3VzdG9taXplIHRoZSBzdGFnZSBvcHRpb25zLCB1c2UgdGhlIGBkZXBsb3lPcHRpb25zYFxuICAgKiBwcm9wZXJ0eS5cbiAgICpcbiAgICogQSBDbG91ZEZvcm1hdGlvbiBPdXRwdXQgd2lsbCBhbHNvIGJlIGRlZmluZWQgd2l0aCB0aGUgcm9vdCBVUkwgZW5kcG9pbnRcbiAgICogb2YgdGhpcyBSRVNUIEFQSS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVwbG95PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdGhlIEFQSSBHYXRld2F5IHN0YWdlIHRoYXQgd2lsbCBhbHdheXMgcG9pbnQgdG8gdGhlIGxhdGVzdFxuICAgKiBkZXBsb3ltZW50IHdoZW4gYGRlcGxveWAgaXMgZW5hYmxlZC4gSWYgYGRlcGxveWAgaXMgZGlzYWJsZWQsXG4gICAqIHRoaXMgdmFsdWUgY2Fubm90IGJlIHNldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBCYXNlZCBvbiBkZWZhdWx0cyBvZiBgU3RhZ2VPcHRpb25zYC5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveU9wdGlvbnM/OiBTdGFnZU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFJldGFpbnMgb2xkIGRlcGxveW1lbnQgcmVzb3VyY2VzIHdoZW4gdGhlIEFQSSBjaGFuZ2VzLiBUaGlzIGFsbG93c1xuICAgKiBtYW51YWxseSByZXZlcnRpbmcgc3RhZ2VzIHRvIHBvaW50IHRvIG9sZCBkZXBsb3ltZW50cyB2aWEgdGhlIEFXU1xuICAgKiBDb25zb2xlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcmV0YWluRGVwbG95bWVudHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBIG5hbWUgZm9yIHRoZSBBUEkgR2F0ZXdheSBSZXN0QXBpIHJlc291cmNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIElEIG9mIHRoZSBSZXN0QXBpIGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IHJlc3RBcGlOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gaGVhZGVyIHBhcmFtZXRlcnMgZm9yIHRoZSByZXF1ZXN0LlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jbGkvbGF0ZXN0L3JlZmVyZW5jZS9hcGlnYXRld2F5L2ltcG9ydC1yZXN0LWFwaS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcGFyYW1ldGVycy5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBBIHBvbGljeSBkb2N1bWVudCB0aGF0IGNvbnRhaW5zIHRoZSBwZXJtaXNzaW9ucyBmb3IgdGhpcyBSZXN0QXBpXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcG9saWN5LlxuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0byByb2xsIGJhY2sgdGhlIHJlc291cmNlIGlmIGEgd2FybmluZyBvY2N1cnMgd2hpbGUgQVBJXG4gICAqIEdhdGV3YXkgaXMgY3JlYXRpbmcgdGhlIFJlc3RBcGkgcmVzb3VyY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBmYWlsT25XYXJuaW5ncz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBhIGN1c3RvbSBkb21haW4gbmFtZSBhbmQgbWFwIGl0IHRvIHRoaXMgQVBJLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGRvbWFpbiBuYW1lIGlzIGRlZmluZWQsIHVzZSBgYWRkRG9tYWluTmFtZWAgb3IgZGlyZWN0bHkgZGVmaW5lIGEgYERvbWFpbk5hbWVgLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluTmFtZT86IERvbWFpbk5hbWVPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBdXRvbWF0aWNhbGx5IGNvbmZpZ3VyZSBhbiBBV1MgQ2xvdWRXYXRjaCByb2xlIGZvciBBUEkgR2F0ZXdheS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2xvdWRXYXRjaFJvbGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFeHBvcnQgbmFtZSBmb3IgdGhlIENmbk91dHB1dCBjb250YWluaW5nIHRoZSBBUEkgZW5kcG9pbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB3aGVuIG5vIGV4cG9ydCBuYW1lIGlzIGdpdmVuLCBvdXRwdXQgd2lsbCBiZSBjcmVhdGVkIHdpdGhvdXQgZXhwb3J0XG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludEV4cG9ydE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiB0aGUgZW5kcG9pbnQgdHlwZXMgb2YgdGhlIEFQSS4gVXNlIHRoaXMgcHJvcGVydHkgd2hlbiBjcmVhdGluZ1xuICAgKiBhbiBBUEkuXG4gICAqXG4gICAqIEBkZWZhdWx0IEVuZHBvaW50VHlwZS5FREdFXG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludFR5cGVzPzogRW5kcG9pbnRUeXBlW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB3aGV0aGVyIGNsaWVudHMgY2FuIGludm9rZSB0aGUgQVBJIHVzaW5nIHRoZSBkZWZhdWx0IGV4ZWN1dGUtYXBpXG4gICAqIGVuZHBvaW50LiBUbyByZXF1aXJlIHRoYXQgY2xpZW50cyB1c2UgYSBjdXN0b20gZG9tYWluIG5hbWUgdG8gaW52b2tlIHRoZVxuICAgKiBBUEksIGRpc2FibGUgdGhlIGRlZmF1bHQgZW5kcG9pbnQuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWFwaWdhdGV3YXktcmVzdGFwaS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkaXNhYmxlRXhlY3V0ZUFwaUVuZHBvaW50PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBwcm9wcyB0aGF0IGFsbCBSZXN0IEFQSXMgc2hhcmUuXG4gKiBAZGVwcmVjYXRlZCAtIHN1cGVyc2VkZWQgYnkgYFJlc3RBcGlCYXNlUHJvcHNgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdEFwaU9wdGlvbnMgZXh0ZW5kcyBSZXN0QXBpQmFzZVByb3BzLCBSZXNvdXJjZU9wdGlvbnMge1xufVxuXG4vKipcbiAqIFByb3BzIHRvIGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiBSZXN0QXBpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdEFwaVByb3BzIGV4dGVuZHMgUmVzdEFwaU9wdGlvbnMge1xuICAvKipcbiAgICogQSBkZXNjcmlwdGlvbiBvZiB0aGUgcHVycG9zZSBvZiB0aGlzIEFQSSBHYXRld2F5IFJlc3RBcGkgcmVzb3VyY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVzY3JpcHRpb24uXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgYmluYXJ5IG1lZGlhIG1pbWUtdHlwZXMgdGhhdCBhcmUgc3VwcG9ydGVkIGJ5IHRoZSBSZXN0QXBpXG4gICAqIHJlc291cmNlLCBzdWNoIGFzIFwiaW1hZ2UvcG5nXCIgb3IgXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFJlc3RBcGkgc3VwcG9ydHMgb25seSBVVEYtOC1lbmNvZGVkIHRleHQgcGF5bG9hZHMuXG4gICAqL1xuICByZWFkb25seSBiaW5hcnlNZWRpYVR5cGVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEEgbnVsbGFibGUgaW50ZWdlciB0aGF0IGlzIHVzZWQgdG8gZW5hYmxlIGNvbXByZXNzaW9uICh3aXRoIG5vbi1uZWdhdGl2ZVxuICAgKiBiZXR3ZWVuIDAgYW5kIDEwNDg1NzYwICgxME0pIGJ5dGVzLCBpbmNsdXNpdmUpIG9yIGRpc2FibGUgY29tcHJlc3Npb25cbiAgICogKHdoZW4gdW5kZWZpbmVkKSBvbiBhbiBBUEkuIFdoZW4gY29tcHJlc3Npb24gaXMgZW5hYmxlZCwgY29tcHJlc3Npb24gb3JcbiAgICogZGVjb21wcmVzc2lvbiBpcyBub3QgYXBwbGllZCBvbiB0aGUgcGF5bG9hZCBpZiB0aGUgcGF5bG9hZCBzaXplIGlzXG4gICAqIHNtYWxsZXIgdGhhbiB0aGlzIHZhbHVlLiBTZXR0aW5nIGl0IHRvIHplcm8gYWxsb3dzIGNvbXByZXNzaW9uIGZvciBhbnlcbiAgICogcGF5bG9hZCBzaXplLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENvbXByZXNzaW9uIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbWluaW11bUNvbXByZXNzaW9uU2l6ZT86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIElEIG9mIHRoZSBBUEkgR2F0ZXdheSBSZXN0QXBpIHJlc291cmNlIHRoYXQgeW91IHdhbnQgdG8gY2xvbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZS5cbiAgICovXG4gIHJlYWRvbmx5IGNsb25lRnJvbT86IElSZXN0QXBpO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIG9mIHRoZSBBUEkga2V5IGZvciBtZXRlcmluZyByZXF1ZXN0cyBhY2NvcmRpbmcgdG8gYSB1c2FnZVxuICAgKiBwbGFuLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE1ldGVyaW5nIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBpS2V5U291cmNlVHlwZT86IEFwaUtleVNvdXJjZVR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBFbmRwb2ludENvbmZpZ3VyYXRpb24gcHJvcGVydHkgdHlwZSBzcGVjaWZpZXMgdGhlIGVuZHBvaW50IHR5cGVzIG9mIGEgUkVTVCBBUElcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1hcGlnYXRld2F5LXJlc3RhcGktZW5kcG9pbnRjb25maWd1cmF0aW9uLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgRW5kcG9pbnRUeXBlLkVER0VcbiAgICovXG4gIHJlYWRvbmx5IGVuZHBvaW50Q29uZmlndXJhdGlvbj86IEVuZHBvaW50Q29uZmlndXJhdGlvbjtcbn1cblxuLyoqXG4gKiBQcm9wcyB0byBpbnN0YW50aWF0ZSBhIG5ldyBTcGVjUmVzdEFwaVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwZWNSZXN0QXBpUHJvcHMgZXh0ZW5kcyBSZXN0QXBpQmFzZVByb3BzIHtcbiAgLyoqXG4gICAqIEFuIE9wZW5BUEkgZGVmaW5pdGlvbiBjb21wYXRpYmxlIHdpdGggQVBJIEdhdGV3YXkuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaS1nYXRld2F5LWltcG9ydC1hcGkuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgYXBpRGVmaW5pdGlvbjogQXBpRGVmaW5pdGlvbjtcbn1cblxuLyoqXG4gKiBCYXNlIGltcGxlbWVudGF0aW9uIHRoYXQgYXJlIGNvbW1vbiB0byB2YXJpb3VzIGltcGxlbWVudGF0aW9ucyBvZiBJUmVzdEFwaVxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUmVzdEFwaUJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElSZXN0QXBpIHtcbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGFuIGluc3RhbmNlIG9mIFJlc3RBcGlCYXNlLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1Ym