532 lines
56 KiB
JavaScript
532 lines
56 KiB
JavaScript
"use strict";
|
|||
|
|
var _a, _b, _c;
|
||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
|
exports.RootConstruct = exports.ConstructOrder = exports.Construct = exports.Node = void 0;
|
||
|
|
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
||
|
|
const dependency_1 = require("./dependency");
|
||
|
|
const stack_trace_1 = require("./private/stack-trace");
|
||
|
|
const uniqueid_1 = require("./private/uniqueid");
|
||
|
|
const CONSTRUCT_SYM = Symbol.for('constructs.Construct');
|
||
|
|
/**
|
||
|
|
* Represents the construct node in the scope tree.
|
||
|
|
*/
|
||
|
|
class Node {
|
||
|
|
/**
|
||
|
|
* Returns the node associated with a construct.
|
||
|
|
* @param construct the construct
|
||
|
|
*
|
||
|
|
* @deprecated use `construct.node` instead
|
||
|
|
*/
|
||
|
|
static of(construct) {
|
||
|
|
return construct.node;
|
||
|
|
}
|
||
|
|
constructor(host, scope, id) {
|
||
|
|
this.host = host;
|
||
|
|
this._locked = false; // if this is "true", addChild will fail
|
||
|
|
id = id ?? ''; // if undefined, convert to empty string
|
||
|
|
this.id = sanitizeId(id);
|
||
|
|
this.scope = scope;
|
||
|
|
if (scope && !this.id) {
|
||
|
|
throw new Error('Only root constructs may have an empty ID');
|
||
|
|
}
|
||
|
|
// add to parent scope
|
||
|
|
scope?.node.addChild(host, this.id);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* The full, absolute path of this construct in the tree.
|
||
|
|
*
|
||
|
|
* Components are separated by '/'.
|
||
|
|
*/
|
||
|
|
get path() {
|
||
|
|
const components = [];
|
||
|
|
for (const scope of this.scopes) {
|
||
|
|
if (scope.node.id) {
|
||
|
|
components.push(scope.node.id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return components.join(Node.PATH_SEP);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Returns an opaque tree-unique address for this construct.
|
||
|
|
*
|
||
|
|
* Addresses are 42 characters hexadecimal strings. They begin with "c8"
|
||
|
|
* followed by 40 lowercase hexadecimal characters (0-9a-f).
|
||
|
|
*
|
||
|
|
* Addresses are calculated using a SHA-1 of the components of the construct
|
||
|
|
* path.
|
||
|
|
*
|
||
|
|
* To enable refactoring of construct trees, constructs with the ID `Default`
|
||
|
|
* will be excluded from the calculation. In those cases constructs in the
|
||
|
|
* same tree may have the same address.
|
||
|
|
*
|
||
|
|
* @example c83a2846e506bcc5f10682b564084bca2d275709ee
|
||
|
|
*/
|
||
|
|
get addr() {
|
||
|
|
if (!this._addr) {
|
||
|
|
this._addr = (0, uniqueid_1.addressOf)(this.scopes.map(c => c.node.id));
|
||
|
|
}
|
||
|
|
return this._addr;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Return a direct child by id, or undefined
|
||
|
|
*
|
||
|
|
* @param id Identifier of direct child
|
||
|
|
* @returns the child if found, or undefined
|
||
|
|
*/
|
||
|
|
tryFindChild(id) {
|
||
|
|
return this._children?.[sanitizeId(id)];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Return a direct child by id
|
||
|
|
*
|
||
|
|
* Throws an error if the child is not found.
|
||
|
|
*
|
||
|
|
* @param id Identifier of direct child
|
||
|
|
* @returns Child with the given id.
|
||
|
|
*/
|
||
|
|
findChild(id) {
|
||
|
|
const ret = this.tryFindChild(id);
|
||
|
|
if (!ret) {
|
||
|
|
throw new Error(`No child with id: '${id}'`);
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Returns the child construct that has the id `Default` or `Resource`.
|
||
|
|
* This is usually the construct that provides the bulk of the underlying functionality.
|
||
|
|
* Useful for modifications of the underlying construct that are not available at the higher levels.
|
||
|
|
*
|
||
|
|
* @throws if there is more than one child
|
||
|
|
* @returns a construct or undefined if there is no default child
|
||
|
|
*/
|
||
|
|
get defaultChild() {
|
||
|
|
if (this._defaultChild !== undefined) {
|
||
|
|
return this._defaultChild;
|
||
|
|
}
|
||
|
|
const resourceChild = this.tryFindChild('Resource');
|
||
|
|
const defaultChild = this.tryFindChild('Default');
|
||
|
|
if (resourceChild && defaultChild) {
|
||
|
|
throw new Error(`Cannot determine default child for ${this.path}. There is both a child with id "Resource" and id "Default"`);
|
||
|
|
}
|
||
|
|
return defaultChild || resourceChild;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Override the defaultChild property.
|
||
|
|
*
|
||
|
|
* This should only be used in the cases where the correct
|
||
|
|
* default child is not named 'Resource' or 'Default' as it
|
||
|
|
* should be.
|
||
|
|
*
|
||
|
|
* If you set this to undefined, the default behavior of finding
|
||
|
|
* the child named 'Resource' or 'Default' will be used.
|
||
|
|
*/
|
||
|
|
set defaultChild(value) {
|
||
|
|
this._defaultChild = value;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* All direct children of this construct.
|
||
|
|
*/
|
||
|
|
get children() {
|
||
|
|
return Object.values(this._children ?? {});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Return this construct and all of its children in the given order
|
||
|
|
*/
|
||
|
|
findAll(order = ConstructOrder.PREORDER) {
|
||
|
|
const ret = new Array();
|
||
|
|
visit(this.host);
|
||
|
|
return ret;
|
||
|
|
function visit(c) {
|
||
|
|
if (order === ConstructOrder.PREORDER) {
|
||
|
|
ret.push(c);
|
||
|
|
}
|
||
|
|
for (const child of c.node.children) {
|
||
|
|
visit(child);
|
||
|
|
}
|
||
|
|
if (order === ConstructOrder.POSTORDER) {
|
||
|
|
ret.push(c);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* This can be used to set contextual values.
|
||
|
|
* Context must be set before any children are added, since children may consult context info during construction.
|
||
|
|
* If the key already exists, it will be overridden.
|
||
|
|
* @param key The context key
|
||
|
|
* @param value The context value
|
||
|
|
*/
|
||
|
|
setContext(key, value) {
|
||
|
|
if (this.children.length > 0) {
|
||
|
|
const names = this.children.map(c => c.node.id);
|
||
|
|
throw new Error('Cannot set context after children have been added: ' + names.join(','));
|
||
|
|
}
|
||
|
|
if (!this._context) {
|
||
|
|
this._context = {};
|
||
|
|
}
|
||
|
|
this._context[key] = value;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Retrieves a value from tree context if present. Otherwise, would throw an error.
|
||
|
|
*
|
||
|
|
* Context is usually initialized at the root, but can be overridden at any point in the tree.
|
||
|
|
*
|
||
|
|
* @param key The context key
|
||
|
|
* @returns The context value or throws error if there is no context value for this key
|
||
|
|
*/
|
||
|
|
getContext(key) {
|
||
|
|
const value = this._context?.[key];
|
||
|
|
if (value !== undefined) {
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
if (value === undefined && !this.scope?.node) {
|
||
|
|
throw new Error(`No context value present for ${key} key`);
|
||
|
|
}
|
||
|
|
return this.scope && this.scope.node.getContext(key);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Retrieves the all context of a node from tree context.
|
||
|
|
*
|
||
|
|
* Context is usually initialized at the root, but can be overridden at any point in the tree.
|
||
|
|
*
|
||
|
|
* @param defaults Any keys to override the retrieved context
|
||
|
|
* @returns The context object or an empty object if there is discovered context
|
||
|
|
*/
|
||
|
|
getAllContext(defaults) {
|
||
|
|
return this.scopes.reverse()
|
||
|
|
.reduce((a, s) => ({ ...(s.node._context), ...a }), { ...defaults });
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Retrieves a value from tree context.
|
||
|
|
*
|
||
|
|
* Context is usually initialized at the root, but can be overridden at any point in the tree.
|
||
|
|
*
|
||
|
|
* @param key The context key
|
||
|
|
* @returns The context value or `undefined` if there is no context value for this key.
|
||
|
|
*/
|
||
|
|
tryGetContext(key) {
|
||
|
|
const value = this._context?.[key];
|
||
|
|
if (value !== undefined) {
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
return this.scope && this.scope.node.tryGetContext(key);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* An immutable array of metadata objects associated with this construct.
|
||
|
|
* This can be used, for example, to implement support for deprecation notices, source mapping, etc.
|
||
|
|
*/
|
||
|
|
get metadata() {
|
||
|
|
return [...this._metadata ?? []];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Adds a metadata entry to this construct.
|
||
|
|
* Entries are arbitrary values and will also include a stack trace to allow tracing back to
|
||
|
|
* the code location for when the entry was added. It can be used, for example, to include source
|
||
|
|
* mapping in CloudFormation templates to improve diagnostics.
|
||
|
|
* Note that construct metadata is not the same as CloudFormation resource metadata and is never written to the CloudFormation template.
|
||
|
|
* The metadata entries are written to the Cloud Assembly Manifest if the `treeMetadata` property is specified in the props of the App that contains this Construct.
|
||
|
|
*
|
||
|
|
* @param type a string denoting the type of metadata
|
||
|
|
* @param data the value of the metadata (can be a Token). If null/undefined, metadata will not be added.
|
||
|
|
* @param options options
|
||
|
|
*/
|
||
|
|
addMetadata(type, data, options = {}) {
|
||
|
|
if (data == null) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const node = this;
|
||
|
|
function getTrace() {
|
||
|
|
if (options.stackTraceOverride && options.stackTraceOverride.length > 0) {
|
||
|
|
return options.stackTraceOverride;
|
||
|
|
}
|
||
|
|
const shouldTrace = options.stackTrace ?? false;
|
||
|
|
return shouldTrace ? (0, stack_trace_1.captureStackTrace)(options.traceFromFunction ?? node.addMetadata) : undefined;
|
||
|
|
}
|
||
|
|
if (!this._metadata) {
|
||
|
|
this._metadata = [];
|
||
|
|
}
|
||
|
|
this._metadata.push({ type, data, trace: getTrace() });
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* All parent scopes of this construct.
|
||
|
|
*
|
||
|
|
* @returns a list of parent scopes. The last element in the list will always
|
||
|
|
* be the current construct and the first element will be the root of the
|
||
|
|
* tree.
|
||
|
|
*/
|
||
|
|
get scopes() {
|
||
|
|
const ret = new Array();
|
||
|
|
let curr = this.host;
|
||
|
|
while (curr) {
|
||
|
|
ret.unshift(curr);
|
||
|
|
curr = curr.node.scope;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Returns the root of the construct tree.
|
||
|
|
* @returns The root of the construct tree.
|
||
|
|
*/
|
||
|
|
get root() {
|
||
|
|
return this.scopes[0];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Returns true if this construct or the scopes in which it is defined are
|
||
|
|
* locked.
|
||
|
|
*/
|
||
|
|
get locked() {
|
||
|
|
if (this._locked) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (this.scope && this.scope.node.locked) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Add an ordering dependency on another construct.
|
||
|
|
*
|
||
|
|
* An `IDependable`
|
||
|
|
*/
|
||
|
|
addDependency(...deps) {
|
||
|
|
if (!this._dependencies) {
|
||
|
|
this._dependencies = new Set();
|
||
|
|
}
|
||
|
|
for (const d of deps) {
|
||
|
|
this._dependencies.add(d);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Return all dependencies registered on this node (non-recursive).
|
||
|
|
*/
|
||
|
|
get dependencies() {
|
||
|
|
const result = new Array();
|
||
|
|
if (this._dependencies) {
|
||
|
|
for (const dep of this._dependencies) {
|
||
|
|
for (const root of dependency_1.Dependable.of(dep).dependencyRoots) {
|
||
|
|
result.push(root);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Remove the child with the given name, if present.
|
||
|
|
*
|
||
|
|
* @returns Whether a child with the given name was deleted.
|
||
|
|
*/
|
||
|
|
tryRemoveChild(childName) {
|
||
|
|
if (!this._children || !(childName in this._children)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
delete this._children[childName];
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Adds a validation to this construct.
|
||
|
|
*
|
||
|
|
* When `node.validate()` is called, the `validate()` method will be called on
|
||
|
|
* all validations and all errors will be returned.
|
||
|
|
*
|
||
|
|
* @param validation The validation object
|
||
|
|
*/
|
||
|
|
addValidation(validation) {
|
||
|
|
if (!this._validations) {
|
||
|
|
this._validations = [];
|
||
|
|
}
|
||
|
|
this._validations.push(validation);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Validates this construct.
|
||
|
|
*
|
||
|
|
* Invokes the `validate()` method on all validations added through
|
||
|
|
* `addValidation()`.
|
||
|
|
*
|
||
|
|
* @returns an array of validation error messages associated with this
|
||
|
|
* construct.
|
||
|
|
*/
|
||
|
|
validate() {
|
||
|
|
return (this._validations ?? []).flatMap(v => v.validate());
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Locks this construct from allowing more children to be added. After this
|
||
|
|
* call, no more children can be added to this construct or to any children.
|
||
|
|
*/
|
||
|
|
lock() {
|
||
|
|
this._locked = true;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Applies one or more mixins to this construct.
|
||
|
|
*
|
||
|
|
* Mixins are applied in order. The list of constructs is captured at the
|
||
|
|
* start of the call, so constructs added by a mixin will not be visited.
|
||
|
|
* Use multiple `with()` calls if subsequent mixins should apply to added
|
||
|
|
* constructs.
|
||
|
|
*
|
||
|
|
* @param mixins The mixins to apply
|
||
|
|
* @returns This construct for chaining
|
||
|
|
*/
|
||
|
|
with(...mixins) {
|
||
|
|
const allConstructs = this.findAll();
|
||
|
|
for (const mixin of mixins) {
|
||
|
|
for (const construct of allConstructs) {
|
||
|
|
if (mixin.supports(construct)) {
|
||
|
|
mixin.applyTo(construct);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return this.host;
|
||
|
|
}
|
||
|
|
;
|
||
|
|
/**
|
||
|
|
* Adds a child construct to this node.
|
||
|
|
*
|
||
|
|
* @param child The child construct
|
||
|
|
* @param childName The type name of the child construct.
|
||
|
|
* @returns The resolved path part name of the child
|
||
|
|
*/
|
||
|
|
addChild(child, childName) {
|
||
|
|
if (this.locked) {
|
||
|
|
// special error if root is locked
|
||
|
|
if (!this.path) {
|
||
|
|
throw new Error('Cannot add children during synthesis');
|
||
|
|
}
|
||
|
|
throw new Error(`Cannot add children to "${this.path}" during synthesis`);
|
||
|
|
}
|
||
|
|
if (!this._children) {
|
||
|
|
this._children = {};
|
||
|
|
}
|
||
|
|
if (this._children[childName]) {
|
||
|
|
const name = this.id ?? '';
|
||
|
|
const typeName = this.host.constructor.name;
|
||
|
|
throw new Error(`There is already a Construct with name '${childName}' in ${typeName}${name.length > 0 ? ' [' + name + ']' : ''}`);
|
||
|
|
}
|
||
|
|
this._children[childName] = child;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
exports.Node = Node;
|
||
|
|
_a = JSII_RTTI_SYMBOL_1;
|
||
|
|
Node[_a] = { fqn: "constructs.Node", version: "10.6.0" };
|
||
|
|
/**
|
||
|
|
* Separator used to delimit construct path components.
|
||
|
|
*/
|
||
|
|
Node.PATH_SEP = '/';
|
||
|
|
/**
|
||
|
|
* Represents the building block of the construct graph.
|
||
|
|
*
|
||
|
|
* All constructs besides the root construct must be created within the scope of
|
||
|
|
* another construct.
|
||
|
|
*/
|
||
|
|
class Construct {
|
||
|
|
/**
|
||
|
|
* Checks if `x` is a construct.
|
||
|
|
*
|
||
|
|
* Use this method instead of `instanceof` to properly detect `Construct`
|
||
|
|
* instances, even when the construct library is symlinked.
|
||
|
|
*
|
||
|
|
* Explanation: in JavaScript, multiple copies of the `constructs` library on
|
||
|
|
* disk are seen as independent, completely different libraries. As a
|
||
|
|
* consequence, the class `Construct` in each copy of the `constructs` library
|
||
|
|
* is seen as a different class, and an instance of one class will not test as
|
||
|
|
* `instanceof` the other class. `npm install` will not create installations
|
||
|
|
* like this, but users may manually symlink construct libraries together or
|
||
|
|
* use a monorepo tool: in those cases, multiple copies of the `constructs`
|
||
|
|
* library can be accidentally installed, and `instanceof` will behave
|
||
|
|
* unpredictably. It is safest to avoid using `instanceof`, and using
|
||
|
|
* this type-testing method instead.
|
||
|
|
*
|
||
|
|
* @returns true if `x` is an object created from a class which extends `Construct`.
|
||
|
|
* @param x Any object
|
||
|
|
*/
|
||
|
|
static isConstruct(x) {
|
||
|
|
return x && typeof x === 'object' && x[CONSTRUCT_SYM];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Creates a new construct node.
|
||
|
|
*
|
||
|
|
* @param scope The scope in which to define this construct
|
||
|
|
* @param id The scoped construct ID. Must be unique amongst siblings. If
|
||
|
|
* the ID includes a path separator (`/`), then it will be replaced by double
|
||
|
|
* dash `--`.
|
||
|
|
*/
|
||
|
|
constructor(scope, id) {
|
||
|
|
this.node = new Node(this, scope, id);
|
||
|
|
// implement IDependable privately
|
||
|
|
dependency_1.Dependable.implement(this, {
|
||
|
|
dependencyRoots: [this],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Applies one or more mixins to this construct.
|
||
|
|
*
|
||
|
|
* Mixins are applied in order. The list of constructs is captured at the
|
||
|
|
* start of the call, so constructs added by a mixin will not be visited.
|
||
|
|
* Use multiple `with()` calls if subsequent mixins should apply to added
|
||
|
|
* constructs.
|
||
|
|
*
|
||
|
|
* @param mixins The mixins to apply
|
||
|
|
* @returns This construct for chaining
|
||
|
|
*/
|
||
|
|
with(...mixins) {
|
||
|
|
return this.node.with(...mixins);
|
||
|
|
}
|
||
|
|
;
|
||
|
|
/**
|
||
|
|
* Returns a string representation of this construct.
|
||
|
|
*/
|
||
|
|
toString() {
|
||
|
|
return this.node.path || '<root>';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
exports.Construct = Construct;
|
||
|
|
_b = JSII_RTTI_SYMBOL_1;
|
||
|
|
Construct[_b] = { fqn: "constructs.Construct", version: "10.6.0" };
|
||
|
|
/**
|
||
|
|
* In what order to return constructs
|
||
|
|
*/
|
||
|
|
var ConstructOrder;
|
||
|
|
(function (ConstructOrder) {
|
||
|
|
/**
|
||
|
|
* Depth-first, pre-order
|
||
|
|
*/
|
||
|
|
ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER";
|
||
|
|
/**
|
||
|
|
* Depth-first, post-order (leaf nodes first)
|
||
|
|
*/
|
||
|
|
ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER";
|
||
|
|
})(ConstructOrder || (exports.ConstructOrder = ConstructOrder = {}));
|
||
|
|
const PATH_SEP_REGEX = new RegExp(`${Node.PATH_SEP}`, 'g');
|
||
|
|
/**
|
||
|
|
* Return a sanitized version of an arbitrary string, so it can be used as an ID
|
||
|
|
*/
|
||
|
|
function sanitizeId(id) {
|
||
|
|
// Escape path seps as double dashes
|
||
|
|
return id.replace(PATH_SEP_REGEX, '--');
|
||
|
|
}
|
||
|
|
// Mark all instances of 'Construct'
|
||
|
|
Object.defineProperty(Construct.prototype, CONSTRUCT_SYM, {
|
||
|
|
value: true,
|
||
|
|
enumerable: false,
|
||
|
|
writable: false,
|
||
|
|
});
|
||
|
|
/**
|
||
|
|
* Creates a new root construct node.
|
||
|
|
*
|
||
|
|
* The root construct represents the top of the construct tree and is not contained within a parent scope itself.
|
||
|
|
* For root constructs, the id is optional.
|
||
|
|
*/
|
||
|
|
class RootConstruct extends Construct {
|
||
|
|
/**
|
||
|
|
* Creates a new root construct node.
|
||
|
|
*
|
||
|
|
* @param id The scoped construct ID. Must be unique amongst siblings. If
|
||
|
|
* the ID includes a path separator (`/`), then it will be replaced by double
|
||
|
|
* dash `--`.
|
||
|
|
*/
|
||
|
|
constructor(id) {
|
||
|
|
super(undefined, id ?? '');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
exports.RootConstruct = RootConstruct;
|
||
|
|
_c = JSII_RTTI_SYMBOL_1;
|
||
|
|
RootConstruct[_c] = { fqn: "constructs.RootConstruct", version: "10.6.0" };
|
||
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0cnVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLDZDQUEwQztBQUcxQyx1REFBMEQ7QUFDMUQsaURBQStDO0FBRS9DLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztBQXVCekQ7O0dBRUc7QUFDSCxNQUFhLElBQUk7SUFNZjs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBcUI7UUFDcEMsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDO0lBQ3hCLENBQUM7SUF5QkQsWUFBb0MsSUFBZSxFQUFFLEtBQWlCLEVBQUUsRUFBVTtRQUE5QyxTQUFJLEdBQUosSUFBSSxDQUFXO1FBVDNDLFlBQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyx3Q0FBd0M7UUFVL0QsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyx3Q0FBd0M7UUFFdkQsSUFBSSxDQUFDLEVBQUUsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFFbkIsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQVcsSUFBSTtRQUNiLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUN0QixLQUFLLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMs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
|