@fgv/ts-res 5.0.1-9 → 5.0.2-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.
Files changed (162) hide show
  1. package/dist/index.browser.js +53 -0
  2. package/dist/index.js +45 -0
  3. package/dist/packlets/bundle/bundleBuilder.js +130 -0
  4. package/dist/packlets/bundle/bundleLoader.js +101 -0
  5. package/dist/packlets/bundle/bundleNormalizer.js +138 -0
  6. package/dist/packlets/bundle/bundleUtils.js +113 -0
  7. package/dist/packlets/bundle/convert.js +75 -0
  8. package/dist/packlets/bundle/index.js +42 -0
  9. package/dist/packlets/bundle/model.js +23 -0
  10. package/dist/packlets/common/conditions.js +47 -0
  11. package/dist/packlets/common/convert.js +172 -0
  12. package/dist/packlets/common/helpers/conditions.js +66 -0
  13. package/dist/packlets/common/helpers/context.js +70 -0
  14. package/dist/packlets/common/helpers/index.js +26 -0
  15. package/dist/packlets/common/helpers/qualifierDefaultValues.js +66 -0
  16. package/dist/packlets/common/helpers/resources.js +93 -0
  17. package/dist/packlets/common/index.js +28 -0
  18. package/dist/packlets/common/resources.js +27 -0
  19. package/dist/packlets/common/validate/conditions.js +544 -0
  20. package/dist/packlets/common/validate/index.js +26 -0
  21. package/dist/packlets/common/validate/regularExpressions.js +84 -0
  22. package/dist/packlets/common/validate/resources.js +209 -0
  23. package/dist/packlets/conditions/condition.js +252 -0
  24. package/dist/packlets/conditions/conditionCollector.js +69 -0
  25. package/dist/packlets/conditions/conditionDecls.js +23 -0
  26. package/dist/packlets/conditions/conditionSet.js +247 -0
  27. package/dist/packlets/conditions/conditionSetCollector.js +89 -0
  28. package/dist/packlets/conditions/conditionSetDecls.js +23 -0
  29. package/dist/packlets/conditions/conditionToken.js +147 -0
  30. package/dist/packlets/conditions/convert/conditionSetDecls.js +51 -0
  31. package/dist/packlets/conditions/convert/decls.js +75 -0
  32. package/dist/packlets/conditions/convert/index.js +24 -0
  33. package/dist/packlets/conditions/index.js +31 -0
  34. package/dist/packlets/config/common.js +78 -0
  35. package/dist/packlets/config/configInitFactory.js +258 -0
  36. package/dist/packlets/config/convert.js +56 -0
  37. package/dist/packlets/config/index.browser.js +34 -0
  38. package/dist/packlets/config/index.js +28 -0
  39. package/dist/packlets/config/json.js +23 -0
  40. package/dist/packlets/config/predefined/default.js +138 -0
  41. package/dist/packlets/config/predefined/extended.js +190 -0
  42. package/dist/packlets/config/predefined/index.js +25 -0
  43. package/dist/packlets/config/systemConfiguration.js +147 -0
  44. package/dist/packlets/context/contextDecls.js +23 -0
  45. package/dist/packlets/context/contextToken.js +202 -0
  46. package/dist/packlets/context/convert/decls.js +91 -0
  47. package/dist/packlets/context/convert/index.js +23 -0
  48. package/dist/packlets/context/index.js +26 -0
  49. package/dist/packlets/decisions/abstractDecision.js +68 -0
  50. package/dist/packlets/decisions/abstractDecisionCollector.js +90 -0
  51. package/dist/packlets/decisions/candidate.js +76 -0
  52. package/dist/packlets/decisions/common.js +23 -0
  53. package/dist/packlets/decisions/concreteDecision.js +111 -0
  54. package/dist/packlets/decisions/decision.js +126 -0
  55. package/dist/packlets/decisions/index.js +28 -0
  56. package/dist/packlets/import/fsItem.js +134 -0
  57. package/dist/packlets/import/importContext.js +129 -0
  58. package/dist/packlets/import/importManager.js +129 -0
  59. package/dist/packlets/import/importable.js +32 -0
  60. package/dist/packlets/import/importers/collectionImporter.js +118 -0
  61. package/dist/packlets/import/importers/fsItemImporter.js +116 -0
  62. package/dist/packlets/import/importers/importer.js +23 -0
  63. package/dist/packlets/import/importers/index.browser.js +29 -0
  64. package/dist/packlets/import/importers/index.js +27 -0
  65. package/dist/packlets/import/importers/jsonImporter.js +94 -0
  66. package/dist/packlets/import/importers/pathImporter.js +84 -0
  67. package/dist/packlets/import/index.browser.js +34 -0
  68. package/dist/packlets/import/index.js +28 -0
  69. package/dist/packlets/qualifier-types/config/convert.js +124 -0
  70. package/dist/packlets/qualifier-types/config/index.js +25 -0
  71. package/dist/packlets/qualifier-types/config/json.js +32 -0
  72. package/dist/packlets/qualifier-types/convert.js +56 -0
  73. package/dist/packlets/qualifier-types/helpers.js +82 -0
  74. package/dist/packlets/qualifier-types/index.js +32 -0
  75. package/dist/packlets/qualifier-types/languageQualifierType.js +142 -0
  76. package/dist/packlets/qualifier-types/literalQualifierType.js +200 -0
  77. package/dist/packlets/qualifier-types/literalValueHierarchy.js +236 -0
  78. package/dist/packlets/qualifier-types/qualifierType.js +184 -0
  79. package/dist/packlets/qualifier-types/qualifierTypeCollector.js +66 -0
  80. package/dist/packlets/qualifier-types/territoryQualifierType.js +200 -0
  81. package/dist/packlets/qualifiers/convert/decls.js +70 -0
  82. package/dist/packlets/qualifiers/convert/index.js +24 -0
  83. package/dist/packlets/qualifiers/convert/qualifier.js +40 -0
  84. package/dist/packlets/qualifiers/index.js +29 -0
  85. package/dist/packlets/qualifiers/qualifier.js +108 -0
  86. package/dist/packlets/qualifiers/qualifierCollector.js +123 -0
  87. package/dist/packlets/qualifiers/qualifierDecl.js +23 -0
  88. package/dist/packlets/qualifiers/qualifierDefaultValueDecls.js +23 -0
  89. package/dist/packlets/qualifiers/qualifierDefaultValueToken.js +175 -0
  90. package/dist/packlets/resource-json/compiled/common.js +23 -0
  91. package/dist/packlets/resource-json/compiled/convert.js +132 -0
  92. package/dist/packlets/resource-json/compiled/index.js +26 -0
  93. package/dist/packlets/resource-json/compiled/json.js +2 -0
  94. package/dist/packlets/resource-json/convert.js +171 -0
  95. package/dist/packlets/resource-json/helpers.js +241 -0
  96. package/dist/packlets/resource-json/index.js +31 -0
  97. package/dist/packlets/resource-json/json.js +36 -0
  98. package/dist/packlets/resource-json/normalized.js +23 -0
  99. package/dist/packlets/resource-json/resourceDeclCollection.js +88 -0
  100. package/dist/packlets/resource-json/resourceDeclContainer.js +23 -0
  101. package/dist/packlets/resource-json/resourceDeclTree.js +94 -0
  102. package/dist/packlets/resource-types/config/convert.js +35 -0
  103. package/dist/packlets/resource-types/config/index.js +25 -0
  104. package/dist/packlets/resource-types/config/json.js +23 -0
  105. package/dist/packlets/resource-types/helpers.js +42 -0
  106. package/dist/packlets/resource-types/index.js +28 -0
  107. package/dist/packlets/resource-types/jsonResourceType.js +66 -0
  108. package/dist/packlets/resource-types/resourceType.js +95 -0
  109. package/dist/packlets/resource-types/resourceTypeCollector.js +61 -0
  110. package/dist/packlets/resources/candidateReducer.js +246 -0
  111. package/dist/packlets/resources/candidateValue.js +92 -0
  112. package/dist/packlets/resources/candidateValueCollector.js +94 -0
  113. package/dist/packlets/resources/common.js +23 -0
  114. package/dist/packlets/resources/deltaGenerator.js +338 -0
  115. package/dist/packlets/resources/index.js +31 -0
  116. package/dist/packlets/resources/resource.js +207 -0
  117. package/dist/packlets/resources/resourceBuilder.js +183 -0
  118. package/dist/packlets/resources/resourceCandidate.js +216 -0
  119. package/dist/packlets/resources/resourceManagerBuilder.js +890 -0
  120. package/dist/packlets/runtime/cacheListener.js +58 -0
  121. package/dist/packlets/runtime/cacheMetrics.js +149 -0
  122. package/dist/packlets/runtime/compiledResourceCollection.js +473 -0
  123. package/dist/packlets/runtime/conditionSetResolutionResult.js +134 -0
  124. package/dist/packlets/runtime/context/contextQualifierProvider.js +29 -0
  125. package/dist/packlets/runtime/context/contextQualifierProviderValidator.js +146 -0
  126. package/dist/packlets/runtime/context/index.js +26 -0
  127. package/dist/packlets/runtime/context/simpleContextQualifierProvider.js +196 -0
  128. package/dist/packlets/runtime/context/validatingSimpleContextQualifierProvider.js +60 -0
  129. package/dist/packlets/runtime/iResourceManager.js +23 -0
  130. package/dist/packlets/runtime/index.js +34 -0
  131. package/dist/packlets/runtime/resource-tree/common.js +23 -0
  132. package/dist/packlets/runtime/resource-tree/index.js +26 -0
  133. package/dist/packlets/runtime/resource-tree/readOnlyResourceTree.js +216 -0
  134. package/dist/packlets/runtime/resource-tree/resourceTreeChildren.js +97 -0
  135. package/dist/packlets/runtime/resource-tree/resourceTreeChildrenValidator.js +161 -0
  136. package/dist/packlets/runtime/resourceResolver.js +481 -0
  137. package/dist/packlets/runtime/resourceTreeResolver.js +220 -0
  138. package/dist/packlets/runtime/validate.js +47 -0
  139. package/dist/packlets/zip-archive/convert.js +100 -0
  140. package/dist/packlets/zip-archive/index.browser.js +54 -0
  141. package/dist/packlets/zip-archive/index.js +47 -0
  142. package/dist/packlets/zip-archive/json.js +23 -0
  143. package/dist/packlets/zip-archive/types.js +36 -0
  144. package/dist/packlets/zip-archive/zipArchiveCreator.js +191 -0
  145. package/dist/packlets/zip-archive/zipArchiveFormat.js +140 -0
  146. package/dist/packlets/zip-archive/zipArchiveLoader.js +282 -0
  147. package/dist/test/data/sample.json +32 -0
  148. package/dist/test/unit/qualifier-types/testQualifierType.js +76 -0
  149. package/dist/test/unit/resource-types/testDerivedResourceType.js +109 -0
  150. package/dist/test/unit/resources/deltaGenerator.helpers.js +282 -0
  151. package/dist/tsdoc-metadata.json +1 -1
  152. package/lib/index.browser.d.ts +24 -0
  153. package/lib/index.browser.js +116 -0
  154. package/lib/packlets/config/index.browser.d.ts +7 -0
  155. package/lib/packlets/config/index.browser.js +74 -0
  156. package/lib/packlets/import/importers/index.browser.d.ts +4 -0
  157. package/lib/packlets/import/importers/index.browser.js +45 -0
  158. package/lib/packlets/import/index.browser.d.ts +7 -0
  159. package/lib/packlets/import/index.browser.js +74 -0
  160. package/lib/packlets/zip-archive/index.browser.d.ts +27 -0
  161. package/lib/packlets/zip-archive/index.browser.js +102 -0
  162. package/package.json +25 -7
@@ -0,0 +1,183 @@
1
+ /*
2
+ * Copyright (c) 2025 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ResultMap, captureResult, fail, failWithDetail, succeed, succeedWithDetail } from '@fgv/ts-utils';
23
+ import { Validate } from '../common';
24
+ import { ResourceCandidate } from './resourceCandidate';
25
+ import { Resource } from './resource';
26
+ /**
27
+ * Represents a builder for a single logical {@link Resources.Resource | resource}. Collects candidates
28
+ * with a common resource ID, validates them against each other and builds a {@link Resources.Resource | resource}
29
+ * object once all candidates are collected.
30
+ * @public
31
+ */
32
+ export class ResourceBuilder {
33
+ /**
34
+ * Supplied or inferred {@link ResourceTypes.ResourceType | type} of the resource being built.
35
+ * If no type is supplied, the type will be inferred from the candidates - at least one candidate must
36
+ * define resource type and all candidates must be of the same type.
37
+ */
38
+ get resourceType() {
39
+ return this._resourceType;
40
+ }
41
+ /**
42
+ * Array of {@link Resources.ResourceCandidate | candidates} for the resource being built.
43
+ */
44
+ get candidates() {
45
+ return Array.from(this._candidates.values()).sort(ResourceCandidate.compare).reverse();
46
+ }
47
+ /**
48
+ * Constructor for a {@link Resources.ResourceBuilder | ResourceBuilder} object.
49
+ * @param params - Parameters to construct the new {@link Resources.ResourceBuilder | ResourceBuilder}.
50
+ */
51
+ constructor(params) {
52
+ this.id = Validate.toResourceId(params.id).orThrow();
53
+ this._resourceTypes = params.resourceTypes;
54
+ this._conditionSets = params.conditionSets;
55
+ this._decisions = params.decisions;
56
+ this._candidateValues = params.candidateValues;
57
+ this._candidates = new ResultMap();
58
+ if (params.typeName) {
59
+ this._resourceType = this._resourceTypes.validating.get(params.typeName).orThrow();
60
+ }
61
+ }
62
+ /**
63
+ * Creates a new {@link Resources.ResourceBuilder | ResourceBuilder} object.
64
+ * @param params - Parameters to create a new {@link Resources.ResourceBuilder | ResourceBuilder}.
65
+ * @returns `Success` with the new {@link Resources.ResourceBuilder | ResourceBuilder} object if successful,
66
+ * or `Failure` with an error message if not.
67
+ * @public
68
+ */
69
+ static create(params) {
70
+ return captureResult(() => new ResourceBuilder(params));
71
+ }
72
+ /**
73
+ * Gets the {@link Resources.ResourceCandidate | candidates} that match a given {@link Context.IValidatedContextDecl | context}.
74
+ * @param context - The {@link Context.IValidatedContextDecl | context} to get candidates for.
75
+ * @param options - Optional {@link Context.IContextMatchOptions | context match options} to use when matching candidates.
76
+ * @returns An array of {@link Resources.ResourceCandidate | candidates} that match the given context.
77
+ */
78
+ getCandidatesForContext(context, options) {
79
+ return Array.from(this._candidates.values()).filter((candidate) => candidate.canMatchPartialContext(context, options));
80
+ }
81
+ /**
82
+ * Given a {@link ResourceJson.Json.IChildResourceCandidateDecl | child resource candidate declaration}, creates and adds a
83
+ * {@link Resources.ResourceCandidate | candidate} to the resource being built.
84
+ * @param candidate - The {@link ResourceJson.Json.IChildResourceCandidateDecl | IChildResourceCandidateDecl} to add to the
85
+ * resource being built.
86
+ * @returns `Success` with the added {@link Resources.ResourceCandidate | candidate} if successful,
87
+ * or `Failure` with an error message if not.
88
+ */
89
+ addChildCandidate(childDecl) {
90
+ return ResourceCandidate.create({
91
+ id: this.id,
92
+ resourceType: this._resourceType,
93
+ decl: childDecl,
94
+ conditionSets: this._conditionSets,
95
+ candidateValues: this._candidateValues
96
+ })
97
+ .withDetail('failure', 'success')
98
+ .onSuccess((candidate) => {
99
+ return this._candidates
100
+ .getOrAdd(candidate.conditions.toString(), candidate)
101
+ .onSuccess((added, detail) => {
102
+ if (detail === 'exists') {
103
+ /* c8 ignore next 5 - defensive coding: conflicting candidates with same conditions should not occur */
104
+ /* c8 ignore next 6 - functional code tested but coverage intermittently missed */
105
+ if (!ResourceCandidate.equal(added, candidate)) {
106
+ return failWithDetail(`${this.id}: conflicting candidates.`, 'exists');
107
+ }
108
+ }
109
+ return succeedWithDetail(added, detail);
110
+ });
111
+ });
112
+ }
113
+ /**
114
+ * Given a {@link ResourceJson.Json.ILooseResourceCandidateDecl | resource candidate declaration}, creates and adds a
115
+ * {@link Resources.ResourceCandidate | candidate} to the resource being built.
116
+ * @param candidate - The {@link ResourceJson.Json.ILooseResourceCandidateDecl | IResourceCandidateDecl} to add to the
117
+ * resource being built.
118
+ * @returns `Success` with the added {@link Resources.ResourceCandidate | candidate} if successful,
119
+ * or `Failure` with an error message if not. Fails with error detail 'type-mismatch' if the candidate
120
+ * specifies a different resource type than previously added candidates, or with 'exists' if a candidate
121
+ * already exists with the same conditions but different values. Succeeds with 'exists' and returns the
122
+ * existing candidate if the candidate to be added is identical to an existing candidate.
123
+ */
124
+ addLooseCandidate(decl) {
125
+ /* c8 ignore next 6 - functional code path tested but coverage intermittently missed */
126
+ if (decl.id !== this.id) {
127
+ return failWithDetail(`${this.id}: mismatched candidate id ${decl.id}.`, 'id-mismatch');
128
+ }
129
+ if (decl.resourceTypeName !== undefined) {
130
+ const rt = this.setResourceType(decl.resourceTypeName);
131
+ /* c8 ignore next 3 - functional code tested but coverage intermittently missed */
132
+ if (rt.isFailure()) {
133
+ return failWithDetail(rt.message, 'type-mismatch');
134
+ }
135
+ }
136
+ return this.addChildCandidate(decl);
137
+ }
138
+ /**
139
+ * Sets the resource type for the resource being built. Fails if a resource type has already been set
140
+ * and it does not match the new resource type.
141
+ * @param resourceTypeName - The name of the resource type to set.
142
+ * @returns `Success` with the updated {@link Resources.ResourceBuilder | ResourceBuilder} object if successful,
143
+ * or `Failure` with an error message if not.
144
+ */
145
+ setResourceType(resourceTypeName) {
146
+ var _a;
147
+ /* c8 ignore next 2 - functional code tested but coverage intermittently missed */
148
+ if (((_a = this._resourceType) === null || _a === void 0 ? void 0 : _a.key) === resourceTypeName) {
149
+ return succeed(this);
150
+ }
151
+ else if (this._resourceType !== undefined) {
152
+ /* c8 ignore next 4 - functional code tested but coverage intermittently missed */
153
+ return fail(`${this.id}: conflicting resource types ${this._resourceType.key} !== ${resourceTypeName}.`);
154
+ }
155
+ return this._resourceTypes.validating.get(resourceTypeName).onSuccess((resourceType) => {
156
+ this._resourceType = resourceType;
157
+ return succeedWithDetail(this, 'success');
158
+ });
159
+ }
160
+ /**
161
+ * Builds the {@link Resources.Resource | resource} object from this builder.
162
+ * @returns `Success` with the new {@link Resources.Resource | Resource} object if successful,
163
+ * or `Failure` with an error message if not. Fails if no candidates have been added
164
+ * or if the resource type is not defined.
165
+ */
166
+ build() {
167
+ /* c8 ignore next 3 - functional code path tested but coverage intermittently missed */
168
+ if (this._candidates.size === 0) {
169
+ return fail(`${this.id}: no candidates supplied.`);
170
+ }
171
+ /* c8 ignore next 3 - functional code path tested but coverage intermittently missed */
172
+ if (this._resourceType === undefined) {
173
+ return fail(`${this.id}: no resource type supplied or inferred.`);
174
+ }
175
+ return Resource.create({
176
+ id: this.id,
177
+ resourceType: this._resourceType,
178
+ candidates: this.candidates,
179
+ decisions: this._decisions
180
+ });
181
+ }
182
+ }
183
+ //# sourceMappingURL=resourceBuilder.js.map
@@ -0,0 +1,216 @@
1
+ /*
2
+ * Copyright (c) 2025 Erik Fortune
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { PerfectMatch, Validate } from '../common';
23
+ import { ConditionSet } from '../conditions';
24
+ import * as ResourceJson from '../resource-json';
25
+ import { captureResult, mapResults, MessageAggregator, fail, succeed } from '@fgv/ts-utils';
26
+ /**
27
+ * A {@link Resources.ResourceCandidate | resource candidate} represents a single possible
28
+ * instance value for some resource, with the conditions under which it applies
29
+ * and instructions on how to merge it with other instances.
30
+ * @public
31
+ */
32
+ export class ResourceCandidate {
33
+ /**
34
+ * The JSON representation of the instance data to be applied.
35
+ * @remarks
36
+ * This property provides access to the JSON data from the underlying candidate value.
37
+ */
38
+ get json() {
39
+ return this.candidateValue.json;
40
+ }
41
+ /**
42
+ * The completeness of the candidate value.
43
+ */
44
+ get completeness() {
45
+ return this.isPartial ? 'partial' : 'full';
46
+ }
47
+ /**
48
+ * Constructor for a {@link Resources.ResourceCandidate | ResourceCandidate} object.
49
+ * @param params - Parameters to create a new {@link Resources.ResourceCandidate | ResourceCandidate}.
50
+ * @public
51
+ */
52
+ constructor(params) {
53
+ var _a, _b;
54
+ this.id = Validate.toResourceId(params.id).orThrow();
55
+ this.candidateValue = params.candidateValues.validating.getOrAdd(params.decl.json).orThrow();
56
+ this.conditions = ResourceCandidate._mergeConditions(params.conditionSets, params.decl.conditions, params.parentConditions).orThrow();
57
+ this.isPartial = (_a = params.decl.isPartial) !== null && _a !== void 0 ? _a : false;
58
+ this.mergeMethod = (_b = params.decl.mergeMethod) !== null && _b !== void 0 ? _b : 'augment';
59
+ this.resourceType = params.resourceType;
60
+ if (this.resourceType) {
61
+ this.resourceType.validateDeclaration(this).orThrow();
62
+ }
63
+ }
64
+ /**
65
+ * Creates a new {@link Resources.ResourceCandidate | ResourceCandidate} object.
66
+ * @param params - Parameters to create a new {@link Resources.ResourceCandidate | ResourceCandidate}.
67
+ * @returns `Success` with the new {@link Resources.ResourceCandidate | ResourceCandidate} object if successful,
68
+ * or `Failure` with an error message if not.
69
+ * @public
70
+ */
71
+ static create(params) {
72
+ return captureResult(() => new ResourceCandidate(params));
73
+ }
74
+ /**
75
+ * Determines if this candidate can match the supplied context (possibly partial).
76
+ * @param context - The context to match.
77
+ * @param options - Options to use when matching.
78
+ * @returns `true` if the candidate can match the context, `false` otherwise.
79
+ */
80
+ canMatchPartialContext(context, options) {
81
+ return this.conditions.canMatchPartialContext(context, options);
82
+ }
83
+ /**
84
+ * Gets the {@link ResourceJson.Json.IChildResourceCandidateDecl | child resource candidate declaration}
85
+ * for this candidate.
86
+ * @param options - {@link ResourceJson.Helpers.IDeclarationOptions | options} to use when creating the declaration.
87
+ * @returns The {@link ResourceJson.Json.IChildResourceCandidateDecl | child resource candidate declaration}.
88
+ */
89
+ toChildResourceCandidateDecl(options) {
90
+ const showDefaults = (options === null || options === void 0 ? void 0 : options.showDefaults) === true;
91
+ return Object.assign(Object.assign({ json: this.json, conditions: this.conditions.toConditionSetRecordDecl(options) }, (showDefaults || this.isPartial ? { isPartial: this.isPartial } : {})), (showDefaults || this.mergeMethod !== 'augment' ? { mergeMethod: this.mergeMethod } : {}));
92
+ }
93
+ /**
94
+ * Gets the {@link ResourceJson.Json.ILooseResourceCandidateDecl | loose resource candidate declaration}
95
+ * for this candidate.
96
+ * @param options - {@link ResourceJson.Helpers.IDeclarationOptions | options} to use when creating the declaration.
97
+ * @returns The {@link ResourceJson.Json.ILooseResourceCandidateDecl | loose resource candidate declaration}.
98
+ */
99
+ toLooseResourceCandidateDecl(options) {
100
+ var _a;
101
+ const showDefaults = (options === null || options === void 0 ? void 0 : options.showDefaults) === true;
102
+ const resourceTypeName = (_a = this.resourceType) === null || _a === void 0 ? void 0 : _a.key;
103
+ return Object.assign(Object.assign(Object.assign({ id: this.id.toString(), json: this.json, conditions: this.conditions.toConditionSetRecordDecl(options) }, (showDefaults || this.isPartial ? { isPartial: this.isPartial } : {})), (showDefaults || this.mergeMethod !== 'augment' ? { mergeMethod: this.mergeMethod } : {})), (resourceTypeName ? { resourceTypeName } : {}));
104
+ }
105
+ /**
106
+ * Extracts the {@link ResourceTypes.ResourceType | resource type} from a list of {@link Resources.ResourceCandidate | resource candidates},
107
+ * if present.
108
+ * @param candidates - The list of candidates from which to extract the resource type.
109
+ * @returns `Success` with the resource type if successful, `Success` with `undefined` if none of the candidates
110
+ * specify a resource tap, and `Failure` with an error message if clients specify conflicting resource types.
111
+ * @public
112
+ */
113
+ static validateResourceTypes(candidates, expectedType) {
114
+ const errors = new MessageAggregator();
115
+ let selectedType = expectedType;
116
+ for (const candidate of candidates) {
117
+ if (selectedType === undefined) {
118
+ /* c8 ignore next 1 - functional code path tested but coverage intermittently missed */
119
+ selectedType = candidate.resourceType;
120
+ }
121
+ else if (candidate.resourceType && selectedType !== candidate.resourceType) {
122
+ /* c8 ignore next 4 - functional code path tested but coverage intermittently missed */
123
+ errors.addMessage(`${candidate.id}: resource type mismatch (${selectedType.key} != ${candidate.resourceType.key})`);
124
+ }
125
+ }
126
+ return errors.returnOrReport(succeed(selectedType));
127
+ }
128
+ /**
129
+ * Compares two {@link Resources.ResourceCandidate | ResourceCandidates} for sorting purposes.
130
+ * @param rc1 - The first candidate to compare.
131
+ * @param rc2 - The second candidate to compare.
132
+ * @returns A negative number if `rc1` should come before `rc2`, a positive number if `rc2` should come before `rc1`,
133
+ * or zero if they are equivalent.
134
+ * @public
135
+ */
136
+ static compare(rc1, rc2) {
137
+ return ConditionSet.compare(rc1.conditions, rc2.conditions);
138
+ }
139
+ /**
140
+ * Compares two {@link Resources.ResourceCandidate | ResourceCandidates} for equality.
141
+ * @param rc1 - The first candidate to compare.
142
+ * @param rc2 - The second candidate to compare.
143
+ * @returns `true` if the candidates are equal, `false` otherwise.
144
+ * @public
145
+ */
146
+ static equal(rc1, rc2) {
147
+ /* c8 ignore next 3 - functional code path tested but coverage intermittently missed */
148
+ if (rc1 === rc2) {
149
+ return true;
150
+ }
151
+ let equal = rc1.id === rc2.id &&
152
+ rc1.isPartial === rc2.isPartial &&
153
+ rc1.mergeMethod === rc2.mergeMethod &&
154
+ ConditionSet.compare(rc1.conditions, rc2.conditions) === 0;
155
+ if (equal) {
156
+ // Compare candidate values by their keys for efficient JSON comparison
157
+ equal = rc1.candidateValue.key === rc2.candidateValue.key;
158
+ }
159
+ return equal;
160
+ }
161
+ /**
162
+ * Validates declared conditions and merges them with parent conditions.
163
+ * @param conditionSets - The {@link Conditions.ConditionSetCollector | condition set collector}
164
+ * to use for this candidate.
165
+ * @param declared - The declared conditions for the candidate.
166
+ * @param parent - The parent conditions to merge with the declared conditions.
167
+ * @returns `Success` with the merged conditions if successful, `Failure` otherwise.
168
+ * @internal
169
+ */
170
+ static _mergeConditions(conditionSets, declared, parent) {
171
+ /* c8 ignore next 2 - code coverage is flaky */
172
+ declared = declared !== null && declared !== void 0 ? declared : {};
173
+ parent = parent !== null && parent !== void 0 ? parent : [];
174
+ const { value: conditionDecls, message } = ResourceJson.Convert.conditionSetDecl.convert(declared);
175
+ /* c8 ignore next 3 - functional code path tested but coverage intermittently missed */
176
+ if (message !== undefined) {
177
+ return fail(message);
178
+ }
179
+ return mapResults(
180
+ // get or add all declared conditions from our condition collector
181
+ conditionDecls.map((decl) => conditionSets.conditions.validating.getOrAdd(decl))).onSuccess((declaredConditions) => {
182
+ // make sure our parent conditions all come from our condition collector too
183
+ return mapResults(parent.map((c) => conditionSets.conditions.getOrAdd(c))).onSuccess((parentConditions) => {
184
+ const conditions = [...parentConditions, ...declaredConditions];
185
+ return conditionSets.validating.getOrAdd(conditions);
186
+ });
187
+ });
188
+ }
189
+ /**
190
+ * Finds the qualifiers that are made irrelevant by the supplied filterForContext.
191
+ * @param candidates - The candidates to find the reducible qualifiers for.
192
+ * @param filterForContext - The filter for context to use.
193
+ * @returns The qualifiers that are made irrelevant by the filterForContext.
194
+ * @remarks
195
+ * For any given set of candidates, qualifiers that match every candidate perfectly
196
+ * are irrelevant to the filtered content and can be removed. Qualifiers that do not
197
+ * match, that are not in the filterForContext, or which partially match at least one
198
+ * candidate remain relevant and must not be removed.
199
+ * @public
200
+ */
201
+ static findReducibleQualifiers(candidates, filterForContext) {
202
+ const qualifiersToReduce = new Set(Object.keys(filterForContext));
203
+ for (const candidate of candidates) {
204
+ for (const condition of candidate.conditions.conditions) {
205
+ if (qualifiersToReduce.has(condition.qualifier.name)) {
206
+ const match = condition.qualifier.type.matches(condition.value, filterForContext[condition.qualifier.name], 'matches');
207
+ if (match !== PerfectMatch) {
208
+ qualifiersToReduce.delete(condition.qualifier.name);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ return qualifiersToReduce.size > 0 ? qualifiersToReduce : undefined;
214
+ }
215
+ }
216
+ //# sourceMappingURL=resourceCandidate.js.map