@aws-cdk/service-spec-types 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,316 @@
1
+ import { Entity, Reference, Relationship } from '@cdklabs/tskb';
2
+ import { SpecDatabase } from './database';
3
+ export interface Partition extends Entity {
4
+ readonly partition: string;
5
+ }
6
+ export type HasRegion = Relationship<Partition, Region, {
7
+ isPrimary?: boolean;
8
+ }>;
9
+ export interface Service extends Entity {
10
+ /**
11
+ * The full name of the service including the group prefix, lowercased and hyphenated.
12
+ *
13
+ * E.g. `AWS::DynamoDB` -> `aws-dynamodb`
14
+ *
15
+ * @example aws-dynamodb
16
+ */
17
+ readonly name: string;
18
+ /**
19
+ * Only the service part of the name, lowercased.
20
+ *
21
+ * E.g. `AWS::DynamoDB` -> `dynamodb`
22
+ *
23
+ * @example dynamodb
24
+ */
25
+ readonly shortName: string;
26
+ /**
27
+ * The shortname of the service in capitalized form
28
+ *
29
+ * E.g. `AWS::DynamoDB` -> `DynamoDB`
30
+ *
31
+ * @example dynamodb
32
+ */
33
+ readonly capitalized: string;
34
+ /**
35
+ * The complete cloudformation style namespace of the service
36
+ *
37
+ * E.g. `AWS::DynamoDB`
38
+ *
39
+ * @example dynamodb
40
+ */
41
+ readonly cloudFormationNamespace: string;
42
+ }
43
+ export interface Region extends Entity {
44
+ readonly name: string;
45
+ readonly description?: string;
46
+ }
47
+ export interface Documentation extends Entity {
48
+ readonly markdown: string;
49
+ }
50
+ export interface Resource extends Entity {
51
+ readonly name: string;
52
+ readonly cloudFormationType: string;
53
+ /**
54
+ * If set, this CloudFormation Transform is required by the resource
55
+ */
56
+ cloudFormationTransform?: string;
57
+ documentation?: string;
58
+ readonly properties: ResourceProperties;
59
+ readonly attributes: Record<string, Attribute>;
60
+ readonly validations?: unknown;
61
+ identifier?: ResourceIdentifier;
62
+ isStateful?: boolean;
63
+ /**
64
+ * Information about the taggability of this resource
65
+ *
66
+ * Undefined if the resource is not taggable.
67
+ */
68
+ tagInformation?: TagInformation;
69
+ /**
70
+ * Whether changes to this resource need to be scrutinized
71
+ *
72
+ * @default ResourceScrutinyType.NONE
73
+ */
74
+ scrutinizable?: ResourceScrutinyType;
75
+ }
76
+ export type ResourceProperties = Record<string, Property>;
77
+ export interface TypeDefinition extends Entity {
78
+ readonly name: string;
79
+ documentation?: string;
80
+ readonly properties: ResourceProperties;
81
+ /**
82
+ * If true, render this type even if it is unused.
83
+ */
84
+ mustRenderForBwCompat?: boolean;
85
+ }
86
+ export interface Property {
87
+ /**
88
+ * Description of the property
89
+ */
90
+ documentation?: string;
91
+ /**
92
+ * Is this property required
93
+ *
94
+ * @default false
95
+ */
96
+ required?: boolean;
97
+ /**
98
+ * The current type of this property
99
+ */
100
+ type: PropertyType;
101
+ /**
102
+ * An ordered list of previous types of this property in ascending order
103
+ *
104
+ * Does not include the current type, use `type` for this.
105
+ */
106
+ previousTypes?: PropertyType[];
107
+ /**
108
+ * A string representation the default value of this property
109
+ *
110
+ * This value is not directly functional; it describes how the underlying resource
111
+ * will behave if the value is not specified.
112
+ *
113
+ * @default - Default unknown
114
+ */
115
+ defaultValue?: string;
116
+ /**
117
+ * Whether this property is deprecated
118
+ *
119
+ * @default - Not deprecated
120
+ */
121
+ deprecated?: Deprecation;
122
+ /**
123
+ * Whether changes to this property needs to be scrutinized specially
124
+ *
125
+ * @default PropertyScrutinyType.NONE
126
+ */
127
+ scrutinizable?: PropertyScrutinyType;
128
+ }
129
+ export declare class RichTypedField {
130
+ private readonly field;
131
+ constructor(field: Pick<Property, 'type' | 'previousTypes'>);
132
+ types(): PropertyType[];
133
+ addPreviousType(type: PropertyType): boolean;
134
+ }
135
+ export declare class RichProperty extends RichTypedField {
136
+ constructor(property: Property);
137
+ }
138
+ export declare class RichAttribute extends RichTypedField {
139
+ constructor(attr: Attribute);
140
+ }
141
+ export interface Attribute {
142
+ documentation?: string;
143
+ type: PropertyType;
144
+ /**
145
+ * An ordered list of previous types of this property in ascending order
146
+ *
147
+ * Does not include the current type, use `type` for this.
148
+ */
149
+ previousTypes?: PropertyType[];
150
+ }
151
+ export declare enum Deprecation {
152
+ /**
153
+ * Not deprecated
154
+ */
155
+ NONE = "NONE",
156
+ /**
157
+ * Warn about use
158
+ */
159
+ WARN = "WARN",
160
+ /**
161
+ * Do not emit the value at all
162
+ *
163
+ * (Handle properties that were incorrectly added to the spec)
164
+ */
165
+ IGNORE = "IGNORE"
166
+ }
167
+ export type PropertyType = PrimitiveType | DefinitionReference | BuiltinTagType | ArrayType<PropertyType> | MapType<PropertyType> | TypeUnion<PropertyType>;
168
+ export type PrimitiveType = StringType | NumberType | IntegerType | BooleanType | JsonType | DateTimeType | NullType | BuiltinTagType;
169
+ export declare function isCollectionType(x: PropertyType): x is ArrayType<any> | MapType<any>;
170
+ export interface TagInformation {
171
+ /**
172
+ * Name of the property that holds the tags
173
+ */
174
+ readonly tagPropertyName: string;
175
+ /**
176
+ * Used to instruct cdk.TagManager how to handle tags
177
+ */
178
+ readonly variant: TagVariant;
179
+ }
180
+ export type TagVariant = 'standard' | 'asg' | 'map';
181
+ export interface StringType {
182
+ readonly type: 'string';
183
+ }
184
+ export interface BuiltinTagType {
185
+ readonly type: 'tag';
186
+ }
187
+ export interface NumberType {
188
+ readonly type: 'number';
189
+ }
190
+ export interface IntegerType {
191
+ readonly type: 'integer';
192
+ }
193
+ export interface BooleanType {
194
+ readonly type: 'boolean';
195
+ }
196
+ export interface JsonType {
197
+ readonly type: 'json';
198
+ }
199
+ export interface NullType {
200
+ readonly type: 'null';
201
+ }
202
+ export interface DateTimeType {
203
+ readonly type: 'date-time';
204
+ }
205
+ /**
206
+ * The "legacy" tag type (used in the old resource spec)
207
+ */
208
+ export interface BuiltinTagType {
209
+ readonly type: 'tag';
210
+ }
211
+ export interface DefinitionReference {
212
+ readonly type: 'ref';
213
+ readonly reference: Reference<TypeDefinition>;
214
+ }
215
+ export interface ArrayType<E> {
216
+ readonly type: 'array';
217
+ readonly element: E;
218
+ }
219
+ export interface MapType<E> {
220
+ readonly type: 'map';
221
+ readonly element: E;
222
+ }
223
+ export interface TypeUnion<E> {
224
+ readonly type: 'union';
225
+ readonly types: E[];
226
+ }
227
+ export type HasResource = Relationship<Service, Resource>;
228
+ export type RegionHasResource = Relationship<Region, Resource>;
229
+ export type RegionHasService = Relationship<Region, Service>;
230
+ export type ResourceDoc = Relationship<Resource, Documentation>;
231
+ export type ServiceInRegion = Relationship<Region, Service>;
232
+ export type ResourceInRegion = Relationship<Region, Resource>;
233
+ export type UsesType = Relationship<Resource, TypeDefinition>;
234
+ export interface ResourceIdentifier extends Entity {
235
+ readonly arnTemplate?: string;
236
+ readonly primaryIdentifier?: string[];
237
+ }
238
+ /**
239
+ * Mark a resource as a resource that needs additional scrutiy when added, removed or changed
240
+ *
241
+ * Used to mark resources that represent security policies.
242
+ */
243
+ export declare enum ResourceScrutinyType {
244
+ /**
245
+ * No additional scrutiny
246
+ */
247
+ None = "None",
248
+ /**
249
+ * An externally attached policy document to a resource
250
+ *
251
+ * (Common for SQS, SNS, S3, ...)
252
+ */
253
+ ResourcePolicyResource = "ResourcePolicyResource",
254
+ /**
255
+ * This is an IAM policy on an identity resource
256
+ *
257
+ * (Basically saying: this is AWS::IAM::Policy)
258
+ */
259
+ IdentityPolicyResource = "IdentityPolicyResource",
260
+ /**
261
+ * This is a Lambda Permission policy
262
+ */
263
+ LambdaPermission = "LambdaPermission",
264
+ /**
265
+ * An ingress rule object
266
+ */
267
+ IngressRuleResource = "IngressRuleResource",
268
+ /**
269
+ * A set of egress rules
270
+ */
271
+ EgressRuleResource = "EgressRuleResource"
272
+ }
273
+ /**
274
+ * Mark a property as a property that needs additional scrutiny when it changes
275
+ *
276
+ * Used to mark sensitive properties that have security-related implications.
277
+ */
278
+ export declare enum PropertyScrutinyType {
279
+ /**
280
+ * No additional scrutiny
281
+ */
282
+ None = "None",
283
+ /**
284
+ * This is an IAM policy directly on a resource
285
+ */
286
+ InlineResourcePolicy = "InlineResourcePolicy",
287
+ /**
288
+ * Either an AssumeRolePolicyDocument or a dictionary of policy documents
289
+ */
290
+ InlineIdentityPolicies = "InlineIdentityPolicies",
291
+ /**
292
+ * A list of managed policies (on an identity resource)
293
+ */
294
+ ManagedPolicies = "ManagedPolicies",
295
+ /**
296
+ * A set of ingress rules (on a security group)
297
+ */
298
+ IngressRules = "IngressRules",
299
+ /**
300
+ * A set of egress rules (on a security group)
301
+ */
302
+ EgressRules = "EgressRules"
303
+ }
304
+ export declare class RichPropertyType {
305
+ private readonly type;
306
+ constructor(type: PropertyType);
307
+ equals(rhs: PropertyType): boolean;
308
+ /**
309
+ * Whether the current type is JavaScript-equal to the RHS type
310
+ *
311
+ * Same as normal equality, but consider `integer` and `number` the same types.
312
+ */
313
+ javascriptEquals(rhs: PropertyType): boolean;
314
+ stringify(db: SpecDatabase): string;
315
+ sortKey(): string[];
316
+ }
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RichPropertyType = exports.PropertyScrutinyType = exports.ResourceScrutinyType = exports.isCollectionType = exports.Deprecation = exports.RichAttribute = exports.RichProperty = exports.RichTypedField = void 0;
4
+ const sorting_1 = require("../util/sorting");
5
+ class RichTypedField {
6
+ constructor(field) {
7
+ this.field = field;
8
+ if (field === undefined) {
9
+ throw new Error('Field is undefined');
10
+ }
11
+ }
12
+ types() {
13
+ var _a;
14
+ return [...((_a = this.field.previousTypes) !== null && _a !== void 0 ? _a : []), this.field.type];
15
+ }
16
+ addPreviousType(type) {
17
+ const richType = new RichPropertyType(type);
18
+ // Only add this type if we don't already have it. We are only doing comparisons where 'integer' and 'number'
19
+ // are treated the same, for all other types we need strict equality. We used to use 'assignableTo' as a
20
+ // condition, but these types will be rendered in both co- and contravariant positions, and so we really can't
21
+ // do much better than full equality.
22
+ if (this.types().some((t) => richType.javascriptEquals(t))) {
23
+ // Nothing to do, type is already in there.
24
+ return false;
25
+ }
26
+ if (!this.field.previousTypes) {
27
+ this.field.previousTypes = [];
28
+ }
29
+ this.field.previousTypes.unshift(type);
30
+ return true;
31
+ }
32
+ }
33
+ exports.RichTypedField = RichTypedField;
34
+ class RichProperty extends RichTypedField {
35
+ constructor(property) {
36
+ super(property);
37
+ }
38
+ }
39
+ exports.RichProperty = RichProperty;
40
+ class RichAttribute extends RichTypedField {
41
+ constructor(attr) {
42
+ super(attr);
43
+ }
44
+ }
45
+ exports.RichAttribute = RichAttribute;
46
+ var Deprecation;
47
+ (function (Deprecation) {
48
+ /**
49
+ * Not deprecated
50
+ */
51
+ Deprecation["NONE"] = "NONE";
52
+ /**
53
+ * Warn about use
54
+ */
55
+ Deprecation["WARN"] = "WARN";
56
+ /**
57
+ * Do not emit the value at all
58
+ *
59
+ * (Handle properties that were incorrectly added to the spec)
60
+ */
61
+ Deprecation["IGNORE"] = "IGNORE";
62
+ })(Deprecation = exports.Deprecation || (exports.Deprecation = {}));
63
+ function isCollectionType(x) {
64
+ return x.type === 'array' || x.type === 'map';
65
+ }
66
+ exports.isCollectionType = isCollectionType;
67
+ /**
68
+ * Mark a resource as a resource that needs additional scrutiy when added, removed or changed
69
+ *
70
+ * Used to mark resources that represent security policies.
71
+ */
72
+ var ResourceScrutinyType;
73
+ (function (ResourceScrutinyType) {
74
+ /**
75
+ * No additional scrutiny
76
+ */
77
+ ResourceScrutinyType["None"] = "None";
78
+ /**
79
+ * An externally attached policy document to a resource
80
+ *
81
+ * (Common for SQS, SNS, S3, ...)
82
+ */
83
+ ResourceScrutinyType["ResourcePolicyResource"] = "ResourcePolicyResource";
84
+ /**
85
+ * This is an IAM policy on an identity resource
86
+ *
87
+ * (Basically saying: this is AWS::IAM::Policy)
88
+ */
89
+ ResourceScrutinyType["IdentityPolicyResource"] = "IdentityPolicyResource";
90
+ /**
91
+ * This is a Lambda Permission policy
92
+ */
93
+ ResourceScrutinyType["LambdaPermission"] = "LambdaPermission";
94
+ /**
95
+ * An ingress rule object
96
+ */
97
+ ResourceScrutinyType["IngressRuleResource"] = "IngressRuleResource";
98
+ /**
99
+ * A set of egress rules
100
+ */
101
+ ResourceScrutinyType["EgressRuleResource"] = "EgressRuleResource";
102
+ })(ResourceScrutinyType = exports.ResourceScrutinyType || (exports.ResourceScrutinyType = {}));
103
+ /**
104
+ * Mark a property as a property that needs additional scrutiny when it changes
105
+ *
106
+ * Used to mark sensitive properties that have security-related implications.
107
+ */
108
+ var PropertyScrutinyType;
109
+ (function (PropertyScrutinyType) {
110
+ /**
111
+ * No additional scrutiny
112
+ */
113
+ PropertyScrutinyType["None"] = "None";
114
+ /**
115
+ * This is an IAM policy directly on a resource
116
+ */
117
+ PropertyScrutinyType["InlineResourcePolicy"] = "InlineResourcePolicy";
118
+ /**
119
+ * Either an AssumeRolePolicyDocument or a dictionary of policy documents
120
+ */
121
+ PropertyScrutinyType["InlineIdentityPolicies"] = "InlineIdentityPolicies";
122
+ /**
123
+ * A list of managed policies (on an identity resource)
124
+ */
125
+ PropertyScrutinyType["ManagedPolicies"] = "ManagedPolicies";
126
+ /**
127
+ * A set of ingress rules (on a security group)
128
+ */
129
+ PropertyScrutinyType["IngressRules"] = "IngressRules";
130
+ /**
131
+ * A set of egress rules (on a security group)
132
+ */
133
+ PropertyScrutinyType["EgressRules"] = "EgressRules";
134
+ })(PropertyScrutinyType = exports.PropertyScrutinyType || (exports.PropertyScrutinyType = {}));
135
+ class RichPropertyType {
136
+ constructor(type) {
137
+ this.type = type;
138
+ }
139
+ equals(rhs) {
140
+ switch (this.type.type) {
141
+ case 'integer':
142
+ case 'boolean':
143
+ case 'date-time':
144
+ case 'json':
145
+ case 'null':
146
+ case 'number':
147
+ case 'string':
148
+ case 'tag':
149
+ return rhs.type === this.type.type;
150
+ case 'array':
151
+ case 'map':
152
+ return rhs.type === this.type.type && new RichPropertyType(this.type.element).equals(rhs.element);
153
+ case 'ref':
154
+ return rhs.type === 'ref' && this.type.reference.$ref === rhs.reference.$ref;
155
+ case 'union':
156
+ const lhsKey = this.sortKey();
157
+ const rhsKey = new RichPropertyType(rhs).sortKey();
158
+ return lhsKey.length === rhsKey.length && lhsKey.every((l, i) => l === rhsKey[i]);
159
+ }
160
+ }
161
+ /**
162
+ * Whether the current type is JavaScript-equal to the RHS type
163
+ *
164
+ * Same as normal equality, but consider `integer` and `number` the same types.
165
+ */
166
+ javascriptEquals(rhs) {
167
+ switch (this.type.type) {
168
+ case 'number':
169
+ case 'integer':
170
+ // Widening
171
+ return rhs.type === 'integer' || rhs.type === 'number';
172
+ case 'array':
173
+ case 'map':
174
+ return rhs.type === this.type.type && new RichPropertyType(this.type.element).javascriptEquals(rhs.element);
175
+ case 'union':
176
+ if (rhs.type !== 'union') {
177
+ return false;
178
+ }
179
+ // Every type in this union needs to be equal one type in RHS
180
+ return this.type.types.every((t1) => rhs.types.some((t2) => new RichPropertyType(t1).javascriptEquals(t2)));
181
+ default:
182
+ // For anything else, need strict equality
183
+ return this.equals(rhs);
184
+ }
185
+ }
186
+ stringify(db) {
187
+ switch (this.type.type) {
188
+ case 'integer':
189
+ case 'boolean':
190
+ case 'date-time':
191
+ case 'json':
192
+ case 'null':
193
+ case 'number':
194
+ case 'string':
195
+ case 'tag':
196
+ return this.type.type;
197
+ case 'array':
198
+ return `Array<${new RichPropertyType(this.type.element).stringify(db)}>`;
199
+ case 'map':
200
+ return `Map<string, ${new RichPropertyType(this.type.element).stringify(db)}>`;
201
+ case 'ref':
202
+ const type = db.get('typeDefinition', this.type.reference);
203
+ return `${type.name}(${this.type.reference.$ref})`;
204
+ case 'union':
205
+ return this.type.types.map((t) => new RichPropertyType(t).stringify(db)).join(' | ');
206
+ }
207
+ }
208
+ sortKey() {
209
+ switch (this.type.type) {
210
+ case 'integer':
211
+ case 'boolean':
212
+ case 'date-time':
213
+ case 'json':
214
+ case 'null':
215
+ case 'number':
216
+ case 'string':
217
+ case 'tag':
218
+ return [this.type.type];
219
+ case 'array':
220
+ case 'map':
221
+ return [this.type.type, ...new RichPropertyType(this.type.element).sortKey()];
222
+ case 'ref':
223
+ return [this.type.type, this.type.reference.$ref];
224
+ case 'union':
225
+ const typeKeys = this.type.types.map((t) => new RichPropertyType(t).sortKey());
226
+ typeKeys.sort((0, sorting_1.sortKeyComparator)((x) => x));
227
+ return [this.type.type, ...typeKeys.flatMap((x) => x)];
228
+ }
229
+ }
230
+ }
231
+ exports.RichPropertyType = RichPropertyType;
232
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvcmVzb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsNkNBQW9EO0FBZ0pwRCxNQUFhLGNBQWM7SUFDekIsWUFBNkIsS0FBK0M7UUFBL0MsVUFBSyxHQUFMLEtBQUssQ0FBMEM7UUFDMUUsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO1lBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztTQUN2QztJQUNILENBQUM7SUFFTSxLQUFLOztRQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBQSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsbUNBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRU0sZUFBZSxDQUFDLElBQWtCO1FBQ3ZDLE1BQU0sUUFBUSxHQUFHLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFNUMsNkdBQTZHO1FBQzdHLHdHQUF3RztRQUN4Ryw4R0FBOEc7UUFDOUcscUNBQXFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDMUQsMkNBQTJDO1lBQzNDLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUU7WUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1NBQy9CO1FBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztDQUNGO0FBNUJELHdDQTRCQztB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QUMsQ0FBQyxDQUFDLENBQUM7U0FDMUQ7SUFDSCxDQUFDO0NBQ0Y7QUFwR0QsNENBb0dDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW50aXR5LCBSZWZlcmVuY2UsIFJlbGF0aW9uc2hpcCB9IGZyb20gJ0BjZGtsYWJzL3Rza2InO1xuaW1wb3J0IHsgU3BlY0RhdGFiYXNlIH0gZnJvbSAnLi9kYXRhYmFzZSc7XG5pbXBvcnQgeyBzb3J0S2V5Q29tcGFyYXRvciB9IGZyb20gJy4uL3V0aWwvc29ydGluZyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFydGl0aW9uIGV4dGVuZHMgRW50aXR5IHtcbiAgcmVhZG9ubHkgcGFydGl0aW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIEhhc1JlZ2lvbiA9IFJlbGF0aW9uc2hpcDxQYXJ0aXRpb24sIFJlZ2lvbiwgeyBpc1ByaW1hcnk/OiBib29sZWFuIH0+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2UgZXh0ZW5kcyBFbnRpdHkge1xuICAvKipcbiAgICogVGhlIGZ1bGwgbmFtZSBvZiB0aGUgc2VydmljZSBpbmNsdWRpbmcgdGhlIGdyb3VwIHByZWZpeCwgbG93ZXJjYXNlZCBhbmQgaHlwaGVuYXRlZC5cbiAgICpcbiAgICogRS5nLiBgQVdTOjpEeW5hbW9EQmAgLT4gYGF3cy1keW5hbW9kYmBcbiAgICpcbiAgICogQGV4YW1wbGUgYXdzLWR5bmFtb2RiXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPbmx5IHRoZSBzZXJ2aWNlIHBhcnQgb2YgdGhlIG5hbWUsIGxvd2VyY2FzZWQuXG4gICAqXG4gICAqIEUuZy4gYEFXUzo6RHluYW1vREJgIC0+IGBkeW5hbW9kYmBcbiAgICpcbiAgICogQGV4YW1wbGUgZHluYW1vZGJcbiAgICovXG4gIHJlYWRvbmx5IHNob3J0TmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHNob3J0bmFtZSBvZiB0aGUgc2VydmljZSBpbiBjYXBpdGFsaXplZCBmb3JtXG4gICAqXG4gICAqIEUuZy4gYEFXUzo6RHluYW1vREJgIC0+IGBEeW5hbW9EQmBcbiAgICpcbiAgICogQGV4YW1wbGUgZHluYW1vZGJcbiAgICovXG4gIHJlYWRvbmx5IGNhcGl0YWxpemVkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgY29tcGxldGUgY2xvdWRmb3JtYXRpb24gc3R5bGUgbmFtZXNwYWNlIG9mIHRoZSBzZXJ2aWNlXG4gICAqXG4gICAqIEUuZy4gYEFXUzo6RHluYW1vREJgXG4gICAqXG4gICAqIEBleGFtcGxlIGR5bmFtb2RiXG4gICAqL1xuICByZWFkb25seSBjbG91ZEZvcm1hdGlvbk5hbWVzcGFjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvbiBleHRlbmRzIEVudGl0eSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRG9jdW1lbnRhdGlvbiBleHRlbmRzIEVudGl0eSB7XG4gIHJlYWRvbmx5IG1hcmtkb3duOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2UgZXh0ZW5kcyBFbnRpdHkge1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsb3VkRm9ybWF0aW9uVHlwZTogc3RyaW5nO1xuICAvKipcbiAgICogSWYgc2V0LCB0aGlzIENsb3VkRm9ybWF0aW9uIFRyYW5zZm9ybSBpcyByZXF1aXJlZCBieSB0aGUgcmVzb3VyY2VcbiAgICovXG4gIGNsb3VkRm9ybWF0aW9uVHJhbnNmb3JtPzogc3RyaW5nO1xuICBkb2N1bWVudGF0aW9uPzogc3RyaW5nO1xuICByZWFkb25seSBwcm9wZXJ0aWVzOiBSZXNvdXJjZVByb3BlcnRpZXM7XG4gIHJlYWRvbmx5IGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIEF0dHJpYnV0ZT47XG4gIHJlYWRvbmx5IHZhbGlkYXRpb25zPzogdW5rbm93bjtcbiAgaWRlbnRpZmllcj86IFJlc291cmNlSWRlbnRpZmllcjtcbiAgaXNTdGF0ZWZ1bD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluZm9ybWF0aW9uIGFib3V0IHRoZSB0YWdnYWJpbGl0eSBvZiB0aGlzIHJlc291cmNlXG4gICAqXG4gICAqIFVuZGVmaW5lZCBpZiB0aGUgcmVzb3VyY2UgaXMgbm90IHRhZ2dhYmxlLlxuICAgKi9cbiAgdGFnSW5mb3JtYXRpb24/OiBUYWdJbmZvcm1hdGlvbjtcblxuICAvKipcbiAgICogV2hldGhlciBjaGFuZ2VzIHRvIHRoaXMgcmVzb3VyY2UgbmVlZCB0byBiZSBzY3J1dGluaXplZFxuICAgKlxuICAgKiBAZGVmYXVsdCBSZXNvdXJjZVNjcnV0aW55VHlwZS5OT05FXG4gICAqL1xuICBzY3J1dGluaXphYmxlPzogUmVzb3VyY2VTY3J1dGlueVR5cGU7XG59XG5cbmV4cG9ydCB0eXBlIFJlc291cmNlUHJvcGVydGllcyA9IFJlY29yZDxzdHJpbmcsIFByb3BlcnR5PjtcblxuZXhwb3J0IGludGVyZmFjZSBUeXBlRGVmaW5pdGlvbiBleHRlbmRzIEVudGl0eSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgZG9jdW1lbnRhdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvcGVydGllczogUmVzb3VyY2VQcm9wZXJ0aWVzO1xuXG4gIC8qKlxuICAgKiBJZiB0cnVlLCByZW5kZXIgdGhpcyB0eXBlIGV2ZW4gaWYgaXQgaXMgdW51c2VkLlxuICAgKi9cbiAgbXVzdFJlbmRlckZvckJ3Q29tcGF0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9wZXJ0eSB7XG4gIC8qKlxuICAgKiBEZXNjcmlwdGlvbiBvZiB0aGUgcHJvcGVydHlcbiAgICovXG4gIGRvY3VtZW50YXRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIElzIHRoaXMgcHJvcGVydHkgcmVxdWlyZWRcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlcXVpcmVkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGN1cnJlbnQgdHlwZSBvZiB0aGlzIHByb3BlcnR5XG4gICAqL1xuICB0eXBlOiBQcm9wZXJ0eVR5cGU7XG5cbiAgLyoqXG4gICAqIEFuIG9yZGVyZWQgbGlzdCBvZiBwcmV2aW91cyB0eXBlcyBvZiB0aGlzIHByb3BlcnR5IGluIGFzY2VuZGluZyBvcmRlclxuICAgKlxuICAgKiBEb2VzIG5vdCBpbmNsdWRlIHRoZSBjdXJyZW50IHR5cGUsIHVzZSBgdHlwZWAgZm9yIHRoaXMuXG4gICAqL1xuICBwcmV2aW91c1R5cGVzPzogUHJvcGVydHlUeXBlW107XG5cbiAgLyoqXG4gICAqIEEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIHRoZSBkZWZhdWx0IHZhbHVlIG9mIHRoaXMgcHJvcGVydHlcbiAgICpcbiAgICogVGhpcyB2YWx1ZSBpcyBub3QgZGlyZWN0bHkgZnVuY3Rpb25hbDsgaXQgZGVzY3JpYmVzIGhvdyB0aGUgdW5kZXJseWluZyByZXNvdXJjZVxuICAgKiB3aWxsIGJlaGF2ZSBpZiB0aGUgdmFsdWUgaXMgbm90IHNwZWNpZmllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEZWZhdWx0IHVua25vd25cbiAgICovXG4gIGRlZmF1bHRWYWx1ZT86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3BlcnR5IGlzIGRlcHJlY2F0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb3QgZGVwcmVjYXRlZFxuICAgKi9cbiAgZGVwcmVjYXRlZD86IERlcHJlY2F0aW9uO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGNoYW5nZXMgdG8gdGhpcyBwcm9wZXJ0eSBuZWVkcyB0byBiZSBzY3J1dGluaXplZCBzcGVjaWFsbHlcbiAgICpcbiAgICogQGRlZmF1bHQgUHJvcGVydHlTY3J1dGlueVR5cGUuTk9ORVxuICAgKi9cbiAgc2NydXRpbml6YWJsZT86IFByb3BlcnR5U2NydXRpbnlUeXBlO1xufVxuXG5leHBvcnQgY2xhc3MgUmljaFR5cGVkRmllbGQge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGZpZWxkOiBQaWNrPFByb3BlcnR5LCAndHlwZScgfCAncHJldmlvdXNUeXBlcyc+KSB7XG4gICAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmllbGQgaXMgdW5kZWZpbmVkJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHR5cGVzKCk6IFByb3BlcnR5VHlwZVtdIHtcbiAgICByZXR1cm4gWy4uLih0aGlzLmZpZWxkLnByZXZpb3VzVHlwZXMgPz8gW10pLCB0aGlzLmZpZWxkLnR5cGVdO1xuICB9XG5cbiAgcHVibGljIGFkZFByZXZpb3VzVHlwZSh0eXBlOiBQcm9wZXJ0eVR5cGUpOiBib29sZWFuIHtcbiAgICBjb25zdCByaWNoVHlwZSA9IG5ldyBSaWNoUHJvcGVydHlUeXBlKHR5cGUpO1xuXG4gICAgLy8gT25seSBhZGQgdGhpcyB0eXBlIGlmIHdlIGRvbid0IGFscmVhZHkgaGF2ZSBpdC4gV2UgYXJlIG9ubHkgZG9pbmcgY29tcGFyaXNvbnMgd2hlcmUgJ2ludGVnZXInIGFuZCAnbnVtYmVyJ1xuICAgIC8vIGFyZSB0cmVhdGVkIHRoZSBzYW1lLCBmb3IgYWxsIG90aGVyIHR5cGVzIHdlIG5lZWQgc3RyaWN0IGVxdWFsaXR5LiBXZSB1c2VkIHRvIHVzZSAnYXNzaWduYWJsZVRvJyBhcyBhXG4gICAgLy8gY29uZGl0aW9uLCBidXQgdGhlc2UgdHlwZXMgd2lsbCBiZSByZW5kZXJlZCBpbiBib3RoIGNvLSBhbmQgY29udHJhdmFyaWFudCBwb3NpdGlvbnMsIGFuZCBzbyB3ZSByZWFsbHkgY2FuJ3RcbiAgICAvLyBkbyBtdWNoIGJldHRlciB0aGFuIGZ1bGwgZXF1YWxpdHkuXG4gICAgaWYgKHRoaXMudHlwZXMoKS5zb21lKCh0KSA9PiByaWNoVHlwZS5qYXZhc2NyaXB0RXF1YWxzKHQpKSkge1xuICAgICAgLy8gTm90aGluZyB0byBkbywgdHlwZSBpcyBhbHJlYWR5IGluIHRoZXJlLlxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuZmllbGQucHJldmlvdXNUeXBlcykge1xuICAgICAgdGhpcy5maWVsZC5wcmV2aW91c1R5cGVzID0gW107XG4gICAgfVxuICAgIHRoaXMuZmllbGQucHJldmlvdXNUeXBlcy51bnNoaWZ0KHR5cGUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBSaWNoUHJvcGVydHkgZXh0ZW5kcyBSaWNoVHlwZWRGaWVsZCB7XG4gIGNvbnN0cnVjdG9yKHByb3BlcnR5OiBQcm9wZXJ0eSkge1xuICAgIHN1cGVyKHByb3BlcnR5KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUmljaEF0dHJpYnV0ZSBleHRlbmRzIFJpY2hUeXBlZEZpZWxkIHtcbiAgY29uc3RydWN0b3IoYXR0cjogQXR0cmlidXRlKSB7XG4gICAgc3VwZXIoYXR0cik7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBBdHRyaWJ1dGUge1xuICBkb2N1bWVudGF0aW9uPzogc3RyaW5nO1xuICB0eXBlOiBQcm9wZXJ0eVR5cGU7XG4gIC8qKlxuICAgKiBBbiBvcmRlcmVkIGxpc3Qgb2YgcHJldmlvdXMgdHlwZXMgb2YgdGhpcyBwcm9wZXJ0eSBpbiBhc2NlbmRpbmcgb3JkZXJcbiAgICpcbiAgICogRG9lcyBub3QgaW5jbHVkZSB0aGUgY3VycmVudCB0eXBlLCB1c2UgYHR5cGVgIGZvciB0aGlzLlxuICAgKi9cbiAgcHJldmlvdXNUeXBlcz86IFByb3BlcnR5VHlwZVtdO1xufVxuXG5leHBvcnQgZW51bSBEZXByZWNhdGlvbiB7XG4gIC8qKlxuICAgKiBOb3QgZGVwcmVjYXRlZFxuICAgKi9cbiAgTk9ORSA9ICdOT05FJyxcblxuICAvKipcbiAgICogV2FybiBhYm91dCB1c2VcbiAgICovXG4gIFdBUk4gPSAnV0FSTicsXG5cbiAgLyoqXG4gICAqIERvIG5vdCBlbWl0IHRoZSB2YWx1ZSBhdCBhbGxcbiAgICpcbiAgICogKEhhbmRsZSBwcm9wZXJ0aWVzIHRoYXQgd2VyZSBpbmNvcnJlY3RseSBhZGRlZCB0byB0aGUgc3BlYylcbiAgICovXG4gIElHTk9SRSA9ICdJR05PUkUnLFxufVxuXG5leHBvcnQgdHlwZSBQcm9wZXJ0eVR5cGUgPVxuICB8IFByaW1pdGl2ZVR5cGVcbiAgfCBEZWZpbml0aW9uUmVmZXJlbmNlXG4gIHwgQnVpbHRpblRhZ1R5cGVcbiAgfCBBcnJheVR5cGU8UHJvcGVydHlUeXBlPlxuICB8IE1hcFR5cGU8UHJvcGVydHlUeXBlPlxuICB8IFR5cGVVbmlvbjxQcm9wZXJ0eVR5cGU+O1xuXG5leHBvcnQgdHlwZSBQcmltaXRpdmVUeXBlID1cbiAgfCBTdHJpbmdUeXBlXG4gIHwgTnVtYmVyVHlwZVxuICB8IEludGVnZXJUeXBlXG4gIHwgQm9vbGVhblR5cGVcbiAgfCBKc29uVHlwZVxuICB8IERhdGVUaW1lVHlwZVxuICB8IE51bGxUeXBlXG4gIHwgQnVpbHRpblRhZ1R5cGU7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbGxlY3Rpb25UeXBlKHg6IFByb3BlcnR5VHlwZSk6IHggaXMgQXJyYXlUeXBlPGFueT4gfCBNYXBUeXBlPGFueT4ge1xuICByZXR1cm4geC50eXBlID09PSAnYXJyYXknIHx8IHgudHlwZSA9PT0gJ21hcCc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFnSW5mb3JtYXRpb24ge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgcHJvcGVydHkgdGhhdCBob2xkcyB0aGUgdGFnc1xuICAgKi9cbiAgcmVhZG9ubHkgdGFnUHJvcGVydHlOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gaW5zdHJ1Y3QgY2RrLlRhZ01hbmFnZXIgaG93IHRvIGhhbmRsZSB0YWdzXG4gICAqL1xuICByZWFkb25seSB2YXJpYW50OiBUYWdWYXJpYW50O1xufVxuXG5leHBvcnQgdHlwZSBUYWdWYXJpYW50ID0gJ3N0YW5kYXJkJyB8ICdhc2cnIHwgJ21hcCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RyaW5nVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdzdHJpbmcnO1xufVxuZXhwb3J0IGludGVyZmFjZSBCdWlsdGluVGFnVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICd0YWcnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE51bWJlclR5cGUge1xuICByZWFkb25seSB0eXBlOiAnbnVtYmVyJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbnRlZ2VyVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdpbnRlZ2VyJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCb29sZWFuVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdib29sZWFuJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBKc29uVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdqc29uJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOdWxsVHlwZSB7XG4gIHJlYWRvbmx5IHR5cGU6ICdudWxsJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXRlVGltZVR5cGUge1xuICByZWFkb25seSB0eXBlOiAnZGF0ZS10aW1lJztcbn1cblxuLyoqXG4gKiBUaGUgXCJsZWdhY3lcIiB0YWcgdHlwZSAodXNlZCBpbiB0aGUgb2xkIHJlc291cmNlIHNwZWMpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbHRpblRhZ1R5cGUge1xuICByZWFkb25seSB0eXBlOiAndGFnJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZWZpbml0aW9uUmVmZXJlbmNlIHtcbiAgcmVhZG9ubHkgdHlwZTogJ3JlZic7XG4gIHJlYWRvbmx5IHJlZmVyZW5jZTogUmVmZXJlbmNlPFR5cGVEZWZpbml0aW9uPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcnJheVR5cGU8RT4ge1xuICByZWFkb25seSB0eXBlOiAnYXJyYXknO1xuICByZWFkb25seSBlbGVtZW50OiBFO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1hcFR5cGU8RT4ge1xuICByZWFkb25seSB0eXBlOiAnbWFwJztcbiAgcmVhZG9ubHkgZWxlbWVudDogRTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUeXBlVW5pb248RT4ge1xuICByZWFkb25seSB0eXBlOiAndW5pb24nO1xuICByZWFkb25seSB0eXBlczogRVtdO1xufVxuXG5leHBvcnQgdHlwZSBIYXNSZXNvdXJjZSA9IFJlbGF0aW9uc2hpcDxTZXJ2aWNlLCBSZXNvdXJjZT47XG5leHBvcnQgdHlwZSBSZWdpb25IYXNSZXNvdXJjZSA9IFJlbGF0aW9uc2hpcDxSZWdpb24sIFJlc291cmNlPjtcbmV4cG9ydCB0eXBlIFJlZ2lvbkhhc1NlcnZpY2UgPSBSZWxhdGlvbnNoaXA8UmVnaW9uLCBTZXJ2aWNlPjtcbmV4cG9ydCB0eXBlIFJlc291cmNlRG9jID0gUmVsYXRpb25zaGlwPFJlc291cmNlLCBEb2N1bWVudGF0aW9uPjtcblxuZXhwb3J0IHR5cGUgU2VydmljZUluUmVnaW9uID0gUmVsYXRpb25zaGlwPFJlZ2lvbiwgU2VydmljZT47XG5leHBvcnQgdHlwZSBSZXNvdXJjZUluUmVnaW9uID0gUmVsYXRpb25zaGlwPFJlZ2lvbiwgUmVzb3VyY2U+O1xuXG5leHBvcnQgdHlwZSBVc2VzVHlwZSA9IFJlbGF0aW9uc2hpcDxSZXNvdXJjZSwgVHlwZURlZmluaXRpb24+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlSWRlbnRpZmllciBleHRlbmRzIEVudGl0eSB7XG4gIHJlYWRvbmx5IGFyblRlbXBsYXRlPzogc3RyaW5nO1xuICByZWFkb25seSBwcmltYXJ5SWRlbnRpZmllcj86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIE1hcmsgYSByZXNvdXJjZSBhcyBhIHJlc291cmNlIHRoYXQgbmVlZHMgYWRkaXRpb25hbCBzY3J1dGl5IHdoZW4gYWRkZWQsIHJlbW92ZWQgb3IgY2hhbmdlZFxuICpcbiAqIFVzZWQgdG8gbWFyayByZXNvdXJjZXMgdGhhdCByZXByZXNlbnQgc2VjdXJpdHkgcG9saWNpZXMuXG4gKi9cbmV4cG9ydCBlbnVtIFJlc291cmNlU2NydXRpbnlUeXBlIHtcbiAgLyoqXG4gICAqIE5vIGFkZGl0aW9uYWwgc2NydXRpbnlcbiAgICovXG4gIE5vbmUgPSAnTm9uZScsXG5cbiAgLyoqXG4gICAqIEFuIGV4dGVybmFsbHkgYXR0YWNoZWQgcG9saWN5IGRvY3VtZW50IHRvIGEgcmVzb3VyY2VcbiAgICpcbiAgICogKENvbW1vbiBmb3IgU1FTLCBTTlMsIFMzLCAuLi4pXG4gICAqL1xuICBSZXNvdXJjZVBvbGljeVJlc291cmNlID0gJ1Jlc291cmNlUG9saWN5UmVzb3VyY2UnLFxuXG4gIC8qKlxuICAgKiBUaGlzIGlzIGFuIElBTSBwb2xpY3kgb24gYW4gaWRlbnRpdHkgcmVzb3VyY2VcbiAgICpcbiAgICogKEJhc2ljYWxseSBzYXlpbmc6IHRoaXMgaXMgQVdTOjpJQU06OlBvbGljeSlcbiAgICovXG4gIElkZW50aXR5UG9saWN5UmVzb3VyY2UgPSAnSWRlbnRpdHlQb2xpY3lSZXNvdXJjZScsXG5cbiAgLyoqXG4gICAqIFRoaXMgaXMgYSBMYW1iZGEgUGVybWlzc2lvbiBwb2xpY3lcbiAgICovXG4gIExhbWJkYVBlcm1pc3Npb24gPSAnTGFtYmRhUGVybWlzc2lvbicsXG5cbiAgLyoqXG4gICAqIEFuIGluZ3Jlc3MgcnVsZSBvYmplY3RcbiAgICovXG4gIEluZ3Jlc3NSdWxlUmVzb3VyY2UgPSAnSW5ncmVzc1J1bGVSZXNvdXJjZScsXG5cbiAgLyoqXG4gICAqIEEgc2V0IG9mIGVncmVzcyBydWxlc1xuICAgKi9cbiAgRWdyZXNzUnVsZVJlc291cmNlID0gJ0VncmVzc1J1bGVSZXNvdXJjZScsXG59XG5cbi8qKlxuICogTWFyayBhIHByb3BlcnR5IGFzIGEgcHJvcGVydHkgdGhhdCBuZWVkcyBhZGRpdGlvbmFsIHNjcnV0aW55IHdoZW4gaXQgY2hhbmdlc1xuICpcbiAqIFVzZWQgdG8gbWFyayBzZW5zaXRpdmUgcHJvcGVydGllcyB0aGF0IGhhdmUgc2VjdXJpdHktcmVsYXRlZCBpbXBsaWNhdGlvbnMuXG4gKi9cbmV4cG9ydCBlbnVtIFByb3BlcnR5U2NydXRpbnlUeXBlIHtcbiAgLyoqXG4gICAqIE5vIGFkZGl0aW9uYWwgc2NydXRpbnlcbiAgICovXG4gIE5vbmUgPSAnTm9uZScsXG5cbiAgLyoqXG4gICAqIFRoaXMgaXMgYW4gSUFNIHBvbGljeSBkaXJlY3RseSBvbiBhIHJlc291cmNlXG4gICAqL1xuICBJbmxpbmVSZXNvdXJjZVBvbGljeSA9ICdJbmxpbmVSZXNvdXJjZVBvbGljeScsXG5cbiAgLyoqXG4gICAqIEVpdGhlciBhbiBBc3N1bWVSb2xlUG9saWN5RG9jdW1lbnQgb3IgYSBkaWN0aW9uYXJ5IG9mIHBvbGljeSBkb2N1bWVudHNcbiAgICovXG4gIElubGluZUlkZW50aXR5UG9saWNpZXMgPSAnSW5saW5lSWRlbnRpdHlQb2xpY2llcycsXG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBtYW5hZ2VkIHBvbGljaWVzIChvbiBhbiBpZGVudGl0eSByZXNvdXJjZSlcbiAgICovXG4gIE1hbmFnZWRQb2xpY2llcyA9ICdNYW5hZ2VkUG9saWNpZXMnLFxuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBpbmdyZXNzIHJ1bGVzIChvbiBhIHNlY3VyaXR5IGdyb3VwKVxuICAgKi9cbiAgSW5ncmVzc1J1bGVzID0gJ0luZ3Jlc3NSdWxlcycsXG5cbiAgLyoqXG4gICAqIEEgc2V0IG9mIGVncmVzcyBydWxlcyAob24gYSBzZWN1cml0eSBncm91cClcbiAgICovXG4gIEVncmVzc1J1bGVzID0gJ0VncmVzc1J1bGVzJyxcbn1cblxuZXhwb3J0IGNsYXNzIFJpY2hQcm9wZXJ0eVR5cGUge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHR5cGU6IFByb3BlcnR5VHlwZSkge31cblxuICBwdWJsaWMgZXF1YWxzKHJoczogUHJvcGVydHlUeXBlKTogYm9vbGVhbiB7XG4gICAgc3dpdGNoICh0aGlzLnR5cGUudHlwZSkge1xuICAgICAgY2FzZSAnaW50ZWdlcic6XG4gICAgICBjYXNlICdib29sZWFuJzpcbiAgICAgIGNhc2UgJ2RhdGUtdGltZSc6XG4gICAgICBjYXNlICdqc29uJzpcbiAgICAgIGNhc2UgJ251bGwnOlxuICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICBjYXNlICd0YWcnOlxuICAgICAgICByZXR1cm4gcmhzLnR5cGUgPT09IHRoaXMudHlwZS50eXBlO1xuICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgY2FzZSAnbWFwJzpcbiAgICAgICAgcmV0dXJuIHJocy50eXBlID09PSB0aGlzLnR5cGUudHlwZSAmJiBuZXcgUmljaFByb3BlcnR5VHlwZSh0aGlzLnR5cGUuZWxlbWVudCkuZXF1YWxzKHJocy5lbGVtZW50KTtcbiAgICAgIGNhc2UgJ3JlZic6XG4gICAgICAgIHJldHVybiByaHMudHlwZSA9PT0gJ3JlZicgJiYgdGhpcy50eXBlLnJlZmVyZW5jZS4kcmVmID09PSByaHMucmVmZXJlbmNlLiRyZWY7XG4gICAgICBjYXNlICd1bmlvbic6XG4gICAgICAgIGNvbnN0IGxoc0tleSA9IHRoaXMuc29ydEtleSgpO1xuICAgICAgICBjb25zdCByaHNLZXkgPSBuZXcgUmljaFByb3BlcnR5VHlwZShyaHMpLnNvcnRLZXkoKTtcbiAgICAgICAgcmV0dXJuIGxoc0tleS5sZW5ndGggPT09IHJoc0tleS5sZW5ndGggJiYgbGhzS2V5LmV2ZXJ5KChsLCBpKSA9PiBsID09PSByaHNLZXlbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjdXJyZW50IHR5cGUgaXMgSmF2YVNjcmlwdC1lcXVhbCB0byB0aGUgUkhTIHR5cGVcbiAgICpcbiAgICogU2FtZSBhcyBub3JtYWwgZXF1YWxpdHksIGJ1dCBjb25zaWRlciBgaW50ZWdlcmAgYW5kIGBudW1iZXJgIHRoZSBzYW1lIHR5cGVzLlxuICAgKi9cbiAgcHVibGljIGphdmFzY3JpcHRFcXVhbHMocmhzOiBQcm9wZXJ0eVR5cGUpOiBib29sZWFuIHtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZS50eXBlKSB7XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgY2FzZSAnaW50ZWdlcic6XG4gICAgICAgIC8vIFdpZGVuaW5nXG4gICAgICAgIHJldHVybiByaHMudHlwZSA9PT0gJ2ludGVnZXInIHx8IHJocy50eXBlID09PSAnbnVtYmVyJztcblxuICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgY2FzZSAnbWFwJzpcbiAgICAgICAgcmV0dXJuIHJocy50eXBlID09PSB0aGlzLnR5cGUudHlwZSAmJiBuZXcgUmljaFByb3BlcnR5VHlwZSh0aGlzLnR5cGUuZWxlbWVudCkuamF2YXNjcmlwdEVxdWFscyhyaHMuZWxlbWVudCk7XG5cbiAgICAgIGNhc2UgJ3VuaW9uJzpcbiAgICAgICAgaWYgKHJocy50eXBlICE9PSAndW5pb24nKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEV2ZXJ5IHR5cGUgaW4gdGhpcyB1bmlvbiBuZWVkcyB0byBiZSBlcXVhbCBvbmUgdHlwZSBpbiBSSFNcbiAgICAgICAgcmV0dXJuIHRoaXMudHlwZS50eXBlcy5ldmVyeSgodDEpID0+IHJocy50eXBlcy5zb21lKCh0MikgPT4gbmV3IFJpY2hQcm9wZXJ0eVR5cGUodDEpLmphdmFzY3JpcHRFcXVhbHModDIpKSk7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIC8vIEZvciBhbnl0aGluZyBlbHNlLCBuZWVkIHN0cmljdCBlcXVhbGl0eVxuICAgICAgICByZXR1cm4gdGhpcy5lcXVhbHMocmhzKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc3RyaW5naWZ5KGRiOiBTcGVjRGF0YWJhc2UpOiBzdHJpbmcge1xuICAgIHN3aXRjaCAodGhpcy50eXBlLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2ludGVnZXInOlxuICAgICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICBjYXNlICdkYXRlLXRpbWUnOlxuICAgICAgY2FzZSAnanNvbic6XG4gICAgICBjYXNlICdudWxsJzpcbiAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgY2FzZSAndGFnJzpcbiAgICAgICAgcmV0dXJuIHRoaXMudHlwZS50eXBlO1xuICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgICByZXR1cm4gYEFycmF5PCR7bmV3IFJpY2hQcm9wZXJ0eVR5cGUodGhpcy50eXBlLmVsZW1lbnQpLnN0cmluZ2lmeShkYil9PmA7XG4gICAgICBjYXNlICdtYXAnOlxuICAgICAgICByZXR1cm4gYE1hcDxzdHJpbmcsICR7bmV3IFJpY2hQcm9wZXJ0eVR5cGUodGhpcy50eXBlLmVsZW1lbnQpLnN0cmluZ2lmeShkYil9PmA7XG4gICAgICBjYXNlICdyZWYnOlxuICAgICAgICBjb25zdCB0eXBlID0gZGIuZ2V0KCd0eXBlRGVmaW5pdGlvbicsIHRoaXMudHlwZS5yZWZlcmVuY2UpO1xuICAgICAgICByZXR1cm4gYCR7dHlwZS5uYW1lfSgke3RoaXMudHlwZS5yZWZlcmVuY2UuJHJlZn0pYDtcbiAgICAgIGNhc2UgJ3VuaW9uJzpcbiAgICAgICAgcmV0dXJuIHRoaXMudHlwZS50eXBlcy5tYXAoKHQpID0+IG5ldyBSaWNoUHJvcGVydHlUeXBlKHQpLnN0cmluZ2lmeShkYikpLmpvaW4oJyB8ICcpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzb3J0S2V5KCk6IHN0cmluZ1tdIHtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZS50eXBlKSB7XG4gICAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgY2FzZSAnZGF0ZS10aW1lJzpcbiAgICAgIGNhc2UgJ2pzb24nOlxuICAgICAgY2FzZSAnbnVsbCc6XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIGNhc2UgJ3RhZyc6XG4gICAgICAgIHJldHVybiBbdGhpcy50eXBlLnR5cGVdO1xuICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgY2FzZSAnbWFwJzpcbiAgICAgICAgcmV0dXJuIFt0aGlzLnR5cGUudHlwZSwgLi4ubmV3IFJpY2hQcm9wZXJ0eVR5cGUodGhpcy50eXBlLmVsZW1lbnQpLnNvcnRLZXkoKV07XG4gICAgICBjYXNlICdyZWYnOlxuICAgICAgICByZXR1cm4gW3RoaXMudHlwZS50eXBlLCB0aGlzLnR5cGUucmVmZXJlbmNlLiRyZWZdO1xuICAgICAgY2FzZSAndW5pb24nOlxuICAgICAgICBjb25zdCB0eXBlS2V5cyA9IHRoaXMudHlwZS50eXBlcy5tYXAoKHQpID0+IG5ldyBSaWNoUHJvcGVydHlUeXBlKHQpLnNvcnRLZXkoKSk7XG4gICAgICAgIHR5cGVLZXlzLnNvcnQoc29ydEtleUNvbXBhcmF0b3IoKHgpID0+IHgpKTtcbiAgICAgICAgcmV0dXJuIFt0aGlzLnR5cGUudHlwZSwgLi4udHlwZUtleXMuZmxhdE1hcCgoeCkgPT4geCldO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Make a sorting comparator that will sort by a given sort key
3
+ */
4
+ export declare function sortKeyComparator<A>(keyFn: (x: A) => Array<string | number>): (a: A, b: A) => number;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortKeyComparator = void 0;
4
+ /**
5
+ * Make a sorting comparator that will sort by a given sort key
6
+ */
7
+ function sortKeyComparator(keyFn) {
8
+ return (a, b) => {
9
+ const ak = keyFn(a);
10
+ const bk = keyFn(b);
11
+ for (let i = 0; i < ak.length && i < bk.length; i++) {
12
+ const av = ak[i];
13
+ const bv = bk[i];
14
+ let diff = 0;
15
+ if (typeof av === 'number' && typeof bv === 'number') {
16
+ diff = av - bv;
17
+ }
18
+ else if (typeof av === 'string' && typeof bv === 'string') {
19
+ diff = av.localeCompare(bv);
20
+ }
21
+ if (diff !== 0) {
22
+ return diff;
23
+ }
24
+ }
25
+ return bk.length - ak.length;
26
+ };
27
+ }
28
+ exports.sortKeyComparator = sortKeyComparator;
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ydGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL3NvcnRpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7O0dBRUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBSSxLQUF1QztJQUMxRSxPQUFPLENBQUMsQ0FBSSxFQUFFLENBQUksRUFBVSxFQUFFO1FBQzVCLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQixNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbkQsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pCLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVqQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7WUFDYixJQUFJLE9BQU8sRUFBRSxLQUFLLFFBQVEsSUFBSSxPQUFPLEVBQUUsS0FBSyxRQUFRLEVBQUU7Z0JBQ3BELElBQUksR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO2FBQ2hCO2lCQUFNLElBQUksT0FBTyxFQUFFLEtBQUssUUFBUSxJQUFJLE9BQU8sRUFBRSxLQUFLLFFBQVEsRUFBRTtnQkFDM0QsSUFBSSxHQUFHLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDN0I7WUFFRCxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUU7Z0JBQ2QsT0FBTyxJQUFJLENBQUM7YUFDYjtTQUNGO1FBRUQsT0FBTyxFQUFFLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDL0IsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQXZCRCw4Q0F1QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1ha2UgYSBzb3J0aW5nIGNvbXBhcmF0b3IgdGhhdCB3aWxsIHNvcnQgYnkgYSBnaXZlbiBzb3J0IGtleVxuICovXG5leHBvcnQgZnVuY3Rpb24gc29ydEtleUNvbXBhcmF0b3I8QT4oa2V5Rm46ICh4OiBBKSA9PiBBcnJheTxzdHJpbmcgfCBudW1iZXI+KSB7XG4gIHJldHVybiAoYTogQSwgYjogQSk6IG51bWJlciA9PiB7XG4gICAgY29uc3QgYWsgPSBrZXlGbihhKTtcbiAgICBjb25zdCBiayA9IGtleUZuKGIpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhay5sZW5ndGggJiYgaSA8IGJrLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBhdiA9IGFrW2ldO1xuICAgICAgY29uc3QgYnYgPSBia1tpXTtcblxuICAgICAgbGV0IGRpZmYgPSAwO1xuICAgICAgaWYgKHR5cGVvZiBhdiA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGJ2ID09PSAnbnVtYmVyJykge1xuICAgICAgICBkaWZmID0gYXYgLSBidjtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGF2ID09PSAnc3RyaW5nJyAmJiB0eXBlb2YgYnYgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGRpZmYgPSBhdi5sb2NhbGVDb21wYXJlKGJ2KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRpZmYgIT09IDApIHtcbiAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGJrLmxlbmd0aCAtIGFrLmxlbmd0aDtcbiAgfTtcbn1cbiJdfQ==