@fgv/ts-res 5.0.0-22 → 5.0.0-23

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 (189) hide show
  1. package/README.md +665 -44
  2. package/dist/ts-res.d.ts +421 -19
  3. package/lib/packlets/common/convert.d.ts +10 -0
  4. package/lib/packlets/common/convert.js +11 -1
  5. package/lib/packlets/common/resources.d.ts +14 -0
  6. package/lib/packlets/common/validate/regularExpressions.d.ts +4 -0
  7. package/lib/packlets/common/validate/regularExpressions.js +5 -1
  8. package/lib/packlets/common/validate/resources.d.ts +35 -1
  9. package/lib/packlets/common/validate/resources.js +54 -0
  10. package/lib/packlets/config/convert.js +1 -1
  11. package/lib/packlets/config/json.d.ts +1 -1
  12. package/lib/packlets/qualifier-types/config/convert.d.ts +22 -1
  13. package/lib/packlets/qualifier-types/config/convert.js +67 -2
  14. package/lib/packlets/qualifier-types/config/json.d.ts +11 -2
  15. package/lib/packlets/qualifier-types/helpers.d.ts +1 -2
  16. package/lib/packlets/qualifier-types/languageQualifierType.d.ts +27 -1
  17. package/lib/packlets/qualifier-types/languageQualifierType.js +75 -0
  18. package/lib/packlets/qualifier-types/literalQualifierType.d.ts +30 -4
  19. package/lib/packlets/qualifier-types/literalQualifierType.js +77 -0
  20. package/lib/packlets/qualifier-types/literalValueHierarchy.d.ts +6 -10
  21. package/lib/packlets/qualifier-types/literalValueHierarchy.js +10 -0
  22. package/lib/packlets/qualifier-types/qualifierType.d.ts +28 -0
  23. package/lib/packlets/qualifier-types/territoryQualifierType.d.ts +28 -4
  24. package/lib/packlets/qualifier-types/territoryQualifierType.js +77 -0
  25. package/lib/packlets/resource-json/compiled/convert.js +2 -1
  26. package/lib/packlets/resource-json/compiled/json.d.ts +6 -2
  27. package/lib/packlets/resource-types/jsonResourceType.d.ts +4 -0
  28. package/lib/packlets/resource-types/jsonResourceType.js +4 -0
  29. package/lib/packlets/resource-types/resourceType.d.ts +4 -0
  30. package/lib/packlets/resources/candidateValue.d.ts +92 -0
  31. package/lib/packlets/resources/candidateValue.js +128 -0
  32. package/lib/packlets/resources/candidateValueCollector.d.ts +55 -0
  33. package/lib/packlets/resources/candidateValueCollector.js +96 -0
  34. package/lib/packlets/resources/index.d.ts +2 -0
  35. package/lib/packlets/resources/index.js +2 -0
  36. package/lib/packlets/resources/resource.js +2 -2
  37. package/lib/packlets/resources/resourceBuilder.d.ts +6 -0
  38. package/lib/packlets/resources/resourceBuilder.js +3 -1
  39. package/lib/packlets/resources/resourceCandidate.d.ts +10 -1
  40. package/lib/packlets/resources/resourceCandidate.js +11 -5
  41. package/lib/packlets/resources/resourceManagerBuilder.d.ts +7 -0
  42. package/lib/packlets/resources/resourceManagerBuilder.js +13 -6
  43. package/lib/packlets/runtime/compiledResourceCollection.d.ts +20 -8
  44. package/lib/packlets/runtime/compiledResourceCollection.js +25 -4
  45. package/lib/packlets/runtime/resource-tree/common.d.ts +1 -1
  46. package/lib/test/unit/qualifier-types/testQualifierType.d.ts +4 -0
  47. package/lib/test/unit/qualifier-types/testQualifierType.js +24 -0
  48. package/lib/test/unit/resource-types/testDerivedResourceType.d.ts +1 -0
  49. package/lib/test/unit/resource-types/testDerivedResourceType.js +3 -0
  50. package/lib/test/unit/resources/candidateValue.test.d.ts +2 -0
  51. package/lib/test/unit/resources/candidateValueCollector.test.d.ts +2 -0
  52. package/package.json +7 -7
  53. package/src/index.ts +0 -75
  54. package/src/packlets/bundle/bundleBuilder.ts +0 -159
  55. package/src/packlets/bundle/bundleLoader.ts +0 -157
  56. package/src/packlets/bundle/bundleNormalizer.ts +0 -173
  57. package/src/packlets/bundle/bundleUtils.ts +0 -142
  58. package/src/packlets/bundle/convert.ts +0 -87
  59. package/src/packlets/bundle/index.ts +0 -52
  60. package/src/packlets/bundle/model.ts +0 -138
  61. package/src/packlets/common/conditions.ts +0 -226
  62. package/src/packlets/common/convert.ts +0 -184
  63. package/src/packlets/common/helpers/conditions.ts +0 -84
  64. package/src/packlets/common/helpers/context.ts +0 -88
  65. package/src/packlets/common/helpers/index.ts +0 -26
  66. package/src/packlets/common/helpers/qualifierDefaultValues.ts +0 -91
  67. package/src/packlets/common/helpers/resources.ts +0 -96
  68. package/src/packlets/common/index.ts +0 -30
  69. package/src/packlets/common/resources.ts +0 -105
  70. package/src/packlets/common/validate/conditions.ts +0 -595
  71. package/src/packlets/common/validate/index.ts +0 -27
  72. package/src/packlets/common/validate/regularExpressions.ts +0 -92
  73. package/src/packlets/common/validate/resources.ts +0 -170
  74. package/src/packlets/conditions/condition.ts +0 -351
  75. package/src/packlets/conditions/conditionCollector.ts +0 -103
  76. package/src/packlets/conditions/conditionDecls.ts +0 -50
  77. package/src/packlets/conditions/conditionSet.ts +0 -318
  78. package/src/packlets/conditions/conditionSetCollector.ts +0 -127
  79. package/src/packlets/conditions/conditionSetDecls.ts +0 -41
  80. package/src/packlets/conditions/conditionToken.ts +0 -180
  81. package/src/packlets/conditions/convert/conditionSetDecls.ts +0 -72
  82. package/src/packlets/conditions/convert/decls.ts +0 -95
  83. package/src/packlets/conditions/convert/index.ts +0 -24
  84. package/src/packlets/conditions/index.ts +0 -33
  85. package/src/packlets/config/common.ts +0 -107
  86. package/src/packlets/config/configInitFactory.ts +0 -142
  87. package/src/packlets/config/convert.ts +0 -61
  88. package/src/packlets/config/index.ts +0 -30
  89. package/src/packlets/config/json.ts +0 -43
  90. package/src/packlets/config/predefined/default.ts +0 -150
  91. package/src/packlets/config/predefined/extended.ts +0 -198
  92. package/src/packlets/config/predefined/index.ts +0 -26
  93. package/src/packlets/config/systemConfiguration.ts +0 -217
  94. package/src/packlets/context/contextDecls.ts +0 -76
  95. package/src/packlets/context/contextToken.ts +0 -252
  96. package/src/packlets/context/convert/decls.ts +0 -126
  97. package/src/packlets/context/convert/index.ts +0 -23
  98. package/src/packlets/context/index.ts +0 -27
  99. package/src/packlets/decisions/abstractDecision.ts +0 -87
  100. package/src/packlets/decisions/abstractDecisionCollector.ts +0 -122
  101. package/src/packlets/decisions/candidate.ts +0 -101
  102. package/src/packlets/decisions/common.ts +0 -37
  103. package/src/packlets/decisions/concreteDecision.ts +0 -157
  104. package/src/packlets/decisions/decision.ts +0 -172
  105. package/src/packlets/decisions/index.ts +0 -28
  106. package/src/packlets/import/fsItem.ts +0 -212
  107. package/src/packlets/import/importContext.ts +0 -183
  108. package/src/packlets/import/importManager.ts +0 -187
  109. package/src/packlets/import/importable.ts +0 -107
  110. package/src/packlets/import/importers/collectionImporter.ts +0 -153
  111. package/src/packlets/import/importers/fsItemImporter.ts +0 -154
  112. package/src/packlets/import/importers/importer.ts +0 -58
  113. package/src/packlets/import/importers/index.ts +0 -27
  114. package/src/packlets/import/importers/jsonImporter.ts +0 -133
  115. package/src/packlets/import/importers/pathImporter.ts +0 -134
  116. package/src/packlets/import/index.ts +0 -29
  117. package/src/packlets/qualifier-types/config/convert.ts +0 -108
  118. package/src/packlets/qualifier-types/config/index.ts +0 -27
  119. package/src/packlets/qualifier-types/config/json.ts +0 -126
  120. package/src/packlets/qualifier-types/convert.ts +0 -77
  121. package/src/packlets/qualifier-types/helpers.ts +0 -94
  122. package/src/packlets/qualifier-types/index.ts +0 -34
  123. package/src/packlets/qualifier-types/languageQualifierType.ts +0 -143
  124. package/src/packlets/qualifier-types/literalQualifierType.ts +0 -244
  125. package/src/packlets/qualifier-types/literalValueHierarchy.ts +0 -332
  126. package/src/packlets/qualifier-types/qualifierType.ts +0 -360
  127. package/src/packlets/qualifier-types/qualifierTypeCollector.ts +0 -102
  128. package/src/packlets/qualifier-types/territoryQualifierType.ts +0 -255
  129. package/src/packlets/qualifiers/convert/decls.ts +0 -90
  130. package/src/packlets/qualifiers/convert/index.ts +0 -24
  131. package/src/packlets/qualifiers/convert/qualifier.ts +0 -55
  132. package/src/packlets/qualifiers/index.ts +0 -31
  133. package/src/packlets/qualifiers/qualifier.ts +0 -169
  134. package/src/packlets/qualifiers/qualifierCollector.ts +0 -194
  135. package/src/packlets/qualifiers/qualifierDecl.ts +0 -80
  136. package/src/packlets/qualifiers/qualifierDefaultValueDecls.ts +0 -57
  137. package/src/packlets/qualifiers/qualifierDefaultValueToken.ts +0 -230
  138. package/src/packlets/resource-json/compiled/common.ts +0 -35
  139. package/src/packlets/resource-json/compiled/convert.ts +0 -143
  140. package/src/packlets/resource-json/compiled/index.ts +0 -27
  141. package/src/packlets/resource-json/compiled/json.ts +0 -239
  142. package/src/packlets/resource-json/convert.ts +0 -236
  143. package/src/packlets/resource-json/helpers.ts +0 -284
  144. package/src/packlets/resource-json/index.ts +0 -33
  145. package/src/packlets/resource-json/json.ts +0 -295
  146. package/src/packlets/resource-json/normalized.ts +0 -211
  147. package/src/packlets/resource-json/resourceDeclCollection.ts +0 -117
  148. package/src/packlets/resource-json/resourceDeclContainer.ts +0 -48
  149. package/src/packlets/resource-json/resourceDeclTree.ts +0 -116
  150. package/src/packlets/resource-types/config/convert.ts +0 -38
  151. package/src/packlets/resource-types/config/index.ts +0 -27
  152. package/src/packlets/resource-types/config/json.ts +0 -33
  153. package/src/packlets/resource-types/helpers.ts +0 -44
  154. package/src/packlets/resource-types/index.ts +0 -30
  155. package/src/packlets/resource-types/jsonResourceType.ts +0 -102
  156. package/src/packlets/resource-types/resourceType.ts +0 -292
  157. package/src/packlets/resource-types/resourceTypeCollector.ts +0 -79
  158. package/src/packlets/resources/candidateReducer.ts +0 -331
  159. package/src/packlets/resources/common.ts +0 -114
  160. package/src/packlets/resources/index.ts +0 -28
  161. package/src/packlets/resources/resource.ts +0 -307
  162. package/src/packlets/resources/resourceBuilder.ts +0 -269
  163. package/src/packlets/resources/resourceCandidate.ts +0 -333
  164. package/src/packlets/resources/resourceManagerBuilder.ts +0 -1169
  165. package/src/packlets/runtime/cacheListener.ts +0 -113
  166. package/src/packlets/runtime/cacheMetrics.ts +0 -206
  167. package/src/packlets/runtime/compiledResourceCollection.ts +0 -607
  168. package/src/packlets/runtime/conditionSetResolutionResult.ts +0 -160
  169. package/src/packlets/runtime/context/contextQualifierProvider.ts +0 -117
  170. package/src/packlets/runtime/context/contextQualifierProviderValidator.ts +0 -281
  171. package/src/packlets/runtime/context/index.ts +0 -26
  172. package/src/packlets/runtime/context/simpleContextQualifierProvider.ts +0 -225
  173. package/src/packlets/runtime/context/validatingSimpleContextQualifierProvider.ts +0 -96
  174. package/src/packlets/runtime/iResourceManager.ts +0 -130
  175. package/src/packlets/runtime/index.ts +0 -35
  176. package/src/packlets/runtime/resource-tree/common.ts +0 -126
  177. package/src/packlets/runtime/resource-tree/index.ts +0 -26
  178. package/src/packlets/runtime/resource-tree/readOnlyResourceTree.ts +0 -342
  179. package/src/packlets/runtime/resource-tree/resourceTreeChildren.ts +0 -125
  180. package/src/packlets/runtime/resource-tree/resourceTreeChildrenValidator.ts +0 -187
  181. package/src/packlets/runtime/resourceResolver.ts +0 -712
  182. package/src/packlets/runtime/validate.ts +0 -63
  183. package/src/packlets/zip-archive/convert.ts +0 -121
  184. package/src/packlets/zip-archive/index.ts +0 -76
  185. package/src/packlets/zip-archive/json.ts +0 -91
  186. package/src/packlets/zip-archive/types.ts +0 -140
  187. package/src/packlets/zip-archive/zipArchiveCreator.ts +0 -229
  188. package/src/packlets/zip-archive/zipArchiveFormat.ts +0 -158
  189. package/src/packlets/zip-archive/zipArchiveLoader.ts +0 -370
@@ -0,0 +1,55 @@
1
+ import { JsonValue } from '@fgv/ts-json-base';
2
+ import { Hash, Result, ValidatingCollector } from '@fgv/ts-utils';
3
+ import { CandidateValue } from './candidateValue';
4
+ /**
5
+ * Parameters for creating a {@link Resources.CandidateValueCollector}.
6
+ * @public
7
+ */
8
+ export interface ICandidateValueCollectorCreateParams {
9
+ /**
10
+ * Optional normalizer to use for normalizing JSON values.
11
+ * If not provided, a default Crc32Normalizer will be used.
12
+ */
13
+ normalizer?: Hash.HashingNormalizer;
14
+ /**
15
+ * Optional initial candidate values to add to the collection.
16
+ */
17
+ candidateValues?: (CandidateValue | JsonValue)[];
18
+ }
19
+ /**
20
+ * A `ValidatingCollector` for {@link Resources.CandidateValue | CandidateValues},
21
+ * which collects candidate values supplied as either {@link Resources.CandidateValue | CandidateValue} or
22
+ * `JsonValue`.
23
+ * @public
24
+ */
25
+ export declare class CandidateValueCollector extends ValidatingCollector<CandidateValue> {
26
+ readonly normalizer: Hash.HashingNormalizer;
27
+ /**
28
+ * Constructor for a {@link Resources.CandidateValueCollector} object.
29
+ * @param params - Parameters to create the collector.
30
+ * @internal
31
+ */
32
+ protected constructor(params?: ICandidateValueCollectorCreateParams);
33
+ /**
34
+ * Creates a new {@link Resources.CandidateValueCollector} object.
35
+ * @param params - Parameters to create the collector.
36
+ * @returns `Success` with the new collector if successful,
37
+ * or `Failure` with an error message if not.
38
+ * @public
39
+ */
40
+ static create(params?: ICandidateValueCollectorCreateParams): Result<CandidateValueCollector>;
41
+ /**
42
+ * Returns an array of JSON values ordered by their indices.
43
+ * @returns Array of JsonValue objects in index order.
44
+ * @public
45
+ */
46
+ getValuesByIndex(): JsonValue[];
47
+ /**
48
+ * Converter method to handle CandidateValue | JsonValue.
49
+ * @param from - The value to convert.
50
+ * @returns `Success` with the CandidateValue if successful, or `Failure` with an error message if not.
51
+ * @internal
52
+ */
53
+ private _toCandidateValue;
54
+ }
55
+ //# sourceMappingURL=candidateValueCollector.d.ts.map
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2025 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.CandidateValueCollector = void 0;
25
+ const ts_json_base_1 = require("@fgv/ts-json-base");
26
+ const ts_utils_1 = require("@fgv/ts-utils");
27
+ const common_1 = require("../common");
28
+ const candidateValue_1 = require("./candidateValue");
29
+ /**
30
+ * A `ValidatingCollector` for {@link Resources.CandidateValue | CandidateValues},
31
+ * which collects candidate values supplied as either {@link Resources.CandidateValue | CandidateValue} or
32
+ * `JsonValue`.
33
+ * @public
34
+ */
35
+ class CandidateValueCollector extends ts_utils_1.ValidatingCollector {
36
+ /**
37
+ * Constructor for a {@link Resources.CandidateValueCollector} object.
38
+ * @param params - Parameters to create the collector.
39
+ * @internal
40
+ */
41
+ constructor(params = {}) {
42
+ var _a, _b;
43
+ super({
44
+ converters: new ts_utils_1.Collections.KeyValueConverters({
45
+ key: common_1.Convert.candidateValueKey,
46
+ value: (from) => this._toCandidateValue(from)
47
+ })
48
+ });
49
+ this.normalizer = (_a = params === null || params === void 0 ? void 0 : params.normalizer) !== null && _a !== void 0 ? _a : new ts_utils_1.Hash.Crc32Normalizer();
50
+ (_b = params.candidateValues) === null || _b === void 0 ? void 0 : _b.forEach((candidateValue) => this.validating.add(candidateValue));
51
+ }
52
+ /**
53
+ * Creates a new {@link Resources.CandidateValueCollector} object.
54
+ * @param params - Parameters to create the collector.
55
+ * @returns `Success` with the new collector if successful,
56
+ * or `Failure` with an error message if not.
57
+ * @public
58
+ */
59
+ static create(params) {
60
+ return (0, ts_utils_1.captureResult)(() => new CandidateValueCollector(params));
61
+ }
62
+ /**
63
+ * Returns an array of JSON values ordered by their indices.
64
+ * @returns Array of JsonValue objects in index order.
65
+ * @public
66
+ */
67
+ getValuesByIndex() {
68
+ // Use the base class valuesByIndex() method to get CandidateValues in index order,
69
+ // then extract their JSON values
70
+ return this.valuesByIndex().map((candidateValue) => candidateValue.json);
71
+ }
72
+ /**
73
+ * Converter method to handle CandidateValue | JsonValue.
74
+ * @param from - The value to convert.
75
+ * @returns `Success` with the CandidateValue if successful, or `Failure` with an error message if not.
76
+ * @internal
77
+ */
78
+ _toCandidateValue(from) {
79
+ /* c8 ignore next 3 - functional code tested but coverage intermittently missed */
80
+ if (from instanceof candidateValue_1.CandidateValue) {
81
+ return (0, ts_utils_1.succeed)(from);
82
+ }
83
+ // Validate as JsonValue and create new CandidateValue
84
+ return ts_json_base_1.Validators.jsonValue
85
+ .validate(from)
86
+ .withErrorFormat((msg) => `Invalid JSON value: ${msg}`)
87
+ .onSuccess((jsonValue) => {
88
+ return candidateValue_1.CandidateValue.create({
89
+ json: jsonValue,
90
+ normalizer: this.normalizer
91
+ });
92
+ });
93
+ }
94
+ }
95
+ exports.CandidateValueCollector = CandidateValueCollector;
96
+ //# sourceMappingURL=candidateValueCollector.js.map
@@ -1,4 +1,6 @@
1
1
  export * from './candidateReducer';
2
+ export * from './candidateValue';
3
+ export * from './candidateValueCollector';
2
4
  export * from './resourceCandidate';
3
5
  export * from './resource';
4
6
  export * from './resourceBuilder';
@@ -36,6 +36,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  __exportStar(require("./candidateReducer"), exports);
39
+ __exportStar(require("./candidateValue"), exports);
40
+ __exportStar(require("./candidateValueCollector"), exports);
39
41
  __exportStar(require("./resourceCandidate"), exports);
40
42
  __exportStar(require("./resource"), exports);
41
43
  __exportStar(require("./resourceBuilder"), exports);
@@ -115,9 +115,9 @@ class Resource {
115
115
  */
116
116
  toCompiled(options) {
117
117
  const candidates = this._getMatchingCandidates(options).map((c) => ({
118
- json: c.json,
119
118
  isPartial: c.isPartial,
120
- mergeMethod: c.mergeMethod
119
+ mergeMethod: c.mergeMethod,
120
+ valueIndex: c.candidateValue.index
121
121
  }));
122
122
  return {
123
123
  id: this.id,
@@ -5,6 +5,7 @@ import { ReadOnlyResourceTypeCollector, ResourceType } from '../resource-types';
5
5
  import { Resource } from './resource';
6
6
  import { ConditionSetCollector } from '../conditions';
7
7
  import { AbstractDecisionCollector } from '../decisions';
8
+ import { CandidateValueCollector } from './candidateValueCollector';
8
9
  import * as ResourceJson from '../resource-json';
9
10
  import * as Context from '../context';
10
11
  /**
@@ -17,6 +18,7 @@ export interface IResourceBuilderCreateParams {
17
18
  conditionSets: ConditionSetCollector;
18
19
  resourceTypes: ReadOnlyResourceTypeCollector;
19
20
  decisions: AbstractDecisionCollector;
21
+ candidateValues: CandidateValueCollector;
20
22
  }
21
23
  /**
22
24
  * Possible result details returned by the resource builder
@@ -66,6 +68,10 @@ export declare class ResourceBuilder {
66
68
  * Collector for {@link Decisions.AbstractDecision | abstract decisions}.
67
69
  */
68
70
  protected _decisions: AbstractDecisionCollector;
71
+ /**
72
+ * Collector for candidate values.
73
+ */
74
+ protected _candidateValues: CandidateValueCollector;
69
75
  /**
70
76
  * Constructor for a {@link Resources.ResourceBuilder | ResourceBuilder} object.
71
77
  * @param params - Parameters to construct the new {@link Resources.ResourceBuilder | ResourceBuilder}.
@@ -56,6 +56,7 @@ class ResourceBuilder {
56
56
  this._resourceTypes = params.resourceTypes;
57
57
  this._conditionSets = params.conditionSets;
58
58
  this._decisions = params.decisions;
59
+ this._candidateValues = params.candidateValues;
59
60
  this._candidates = new ts_utils_1.ResultMap();
60
61
  if (params.typeName) {
61
62
  this._resourceType = this._resourceTypes.validating.get(params.typeName).orThrow();
@@ -93,7 +94,8 @@ class ResourceBuilder {
93
94
  id: this.id,
94
95
  resourceType: this._resourceType,
95
96
  decl: childDecl,
96
- conditionSets: this._conditionSets
97
+ conditionSets: this._conditionSets,
98
+ candidateValues: this._candidateValues
97
99
  })
98
100
  .withDetail('failure', 'success')
99
101
  .onSuccess((candidate) => {
@@ -3,6 +3,8 @@ import { CandidateCompleteness, QualifierName, ResourceId, ResourceValueMergeMet
3
3
  import { Condition, ConditionSet, ConditionSetCollector } from '../conditions';
4
4
  import * as ResourceJson from '../resource-json';
5
5
  import { ResourceType } from '../resource-types';
6
+ import { CandidateValue } from './candidateValue';
7
+ import { CandidateValueCollector } from './candidateValueCollector';
6
8
  import { Result } from '@fgv/ts-utils';
7
9
  import * as Context from '../context';
8
10
  import { IResourceCandidate } from '../runtime';
@@ -16,6 +18,7 @@ export interface IResourceCandidateCreateParams {
16
18
  resourceType?: ResourceType;
17
19
  parentConditions?: ReadonlyArray<Condition>;
18
20
  conditionSets: ConditionSetCollector;
21
+ candidateValues: CandidateValueCollector;
19
22
  }
20
23
  /**
21
24
  * Options for creating a {@link Resources.ResourceCandidate | ResourceCandidate} declaration.
@@ -43,10 +46,16 @@ export declare class ResourceCandidate implements IResourceCandidate {
43
46
  * is a possible instance.
44
47
  */
45
48
  readonly id: ResourceId;
49
+ /**
50
+ * The candidate value that contains the JSON representation of the instance data.
51
+ */
52
+ readonly candidateValue: CandidateValue;
46
53
  /**
47
54
  * The JSON representation of the instance data to be applied.
55
+ * @remarks
56
+ * This property provides access to the JSON data from the underlying candidate value.
48
57
  */
49
- readonly json: JsonObject;
58
+ get json(): JsonObject;
50
59
  /**
51
60
  * The conditions under which this candidate applies.
52
61
  */
@@ -66,6 +66,14 @@ const ts_utils_1 = require("@fgv/ts-utils");
66
66
  * @public
67
67
  */
68
68
  class ResourceCandidate {
69
+ /**
70
+ * The JSON representation of the instance data to be applied.
71
+ * @remarks
72
+ * This property provides access to the JSON data from the underlying candidate value.
73
+ */
74
+ get json() {
75
+ return this.candidateValue.json;
76
+ }
69
77
  /**
70
78
  * The completeness of the candidate value.
71
79
  */
@@ -80,7 +88,7 @@ class ResourceCandidate {
80
88
  constructor(params) {
81
89
  var _a, _b;
82
90
  this.id = common_1.Validate.toResourceId(params.id).orThrow();
83
- this.json = params.decl.json;
91
+ this.candidateValue = params.candidateValues.validating.getOrAdd(params.decl.json).orThrow();
84
92
  this.conditions = ResourceCandidate._mergeConditions(params.conditionSets, params.decl.conditions, params.parentConditions).orThrow();
85
93
  this.isPartial = (_a = params.decl.isPartial) !== null && _a !== void 0 ? _a : false;
86
94
  this.mergeMethod = (_b = params.decl.mergeMethod) !== null && _b !== void 0 ? _b : 'augment';
@@ -181,10 +189,8 @@ class ResourceCandidate {
181
189
  rc1.mergeMethod === rc2.mergeMethod &&
182
190
  conditions_1.ConditionSet.compare(rc1.conditions, rc2.conditions) === 0;
183
191
  if (equal) {
184
- const normalizer = new ts_utils_1.Hash.Crc32Normalizer();
185
- const n1 = normalizer.computeHash(rc1.json).orDefault('(n1 normalization failed)');
186
- const n2 = normalizer.computeHash(rc2.json).orDefault('(n2 normalization failed)');
187
- equal = n1 === n2;
192
+ // Compare candidate values by their keys for efficient JSON comparison
193
+ equal = rc1.candidateValue.key === rc2.candidateValue.key;
188
194
  }
189
195
  return equal;
190
196
  }
@@ -8,6 +8,7 @@ import { IResourceManager, ResourceTree } from '../runtime';
8
8
  import { ResourceBuilder, ResourceBuilderResultDetail } from './resourceBuilder';
9
9
  import { Resource } from './resource';
10
10
  import { ResourceCandidate } from './resourceCandidate';
11
+ import { CandidateValueCollector } from './candidateValueCollector';
11
12
  import { IResourceDeclarationOptions, IResourceManagerCloneOptions } from './common';
12
13
  import * as ResourceJson from '../resource-json';
13
14
  import * as Context from '../context';
@@ -57,6 +58,11 @@ export declare class ResourceManagerBuilder implements IResourceManager<Resource
57
58
  * @internal
58
59
  */
59
60
  protected readonly _decisions: AbstractDecisionCollector;
61
+ /**
62
+ * The candidate value collector used by this resource manager.
63
+ * @internal
64
+ */
65
+ protected readonly _candidateValues: CandidateValueCollector;
60
66
  /**
61
67
  * The {@link Resources.ResourceBuilder | resource builders} used by this resource manager.
62
68
  * @internal
@@ -383,6 +389,7 @@ export declare class ResourceManagerBuilder implements IResourceManager<Resource
383
389
  * @param decision - The decision containing condition sets.
384
390
  * @param resourceType - The resource type for the candidates.
385
391
  * @param builder - The builder to add candidates to.
392
+ * @param candidateValues - Array of candidate values indexed by valueIndex.
386
393
  * @returns `Success` if all candidates were added successfully, `Failure` otherwise.
387
394
  * @internal
388
395
  */
@@ -63,6 +63,7 @@ const common_1 = require("../common");
63
63
  const runtime_1 = require("../runtime");
64
64
  const resourceBuilder_1 = require("./resourceBuilder");
65
65
  const resource_1 = require("./resource");
66
+ const candidateValueCollector_1 = require("./candidateValueCollector");
66
67
  const ResourceJson = __importStar(require("../resource-json"));
67
68
  const Context = __importStar(require("../context"));
68
69
  const Config = __importStar(require("../config"));
@@ -79,6 +80,7 @@ class ResourceManagerBuilder {
79
80
  * The {@link QualifierTypes.ReadOnlyQualifierTypeCollector | qualifier types} used by this resource manager.
80
81
  */
81
82
  get qualifierTypes() {
83
+ /* c8 ignore next 1 - functional code tested but coverage intermittently missed */
82
84
  return this.qualifiers.qualifierTypes;
83
85
  }
84
86
  /**
@@ -149,6 +151,7 @@ class ResourceManagerBuilder {
149
151
  this._conditions = conditions_1.ConditionCollector.create({ qualifiers: params.qualifiers }).orThrow();
150
152
  this._conditionSets = conditions_1.ConditionSetCollector.create({ conditions: this._conditions }).orThrow();
151
153
  this._decisions = decisions_1.AbstractDecisionCollector.create({ conditionSets: this._conditionSets }).orThrow();
154
+ this._candidateValues = candidateValueCollector_1.CandidateValueCollector.create().orThrow();
152
155
  this._resources = new ts_utils_1.ValidatingResultMap({
153
156
  converters: new ts_utils_1.Collections.KeyValueConverters({
154
157
  key: common_1.Convert.resourceId,
@@ -234,7 +237,8 @@ class ResourceManagerBuilder {
234
237
  id,
235
238
  resourceTypes: this.resourceTypes,
236
239
  conditionSets: this._conditionSets,
237
- decisions: this._decisions
240
+ decisions: this._decisions,
241
+ candidateValues: this._candidateValues
238
242
  }));
239
243
  /* c8 ignore next 6 - defense in depth against internal error */
240
244
  if (builderResult.isFailure()) {
@@ -259,7 +263,8 @@ class ResourceManagerBuilder {
259
263
  typeName: decl.resourceTypeName,
260
264
  resourceTypes: this.resourceTypes,
261
265
  conditionSets: this._conditionSets,
262
- decisions: this._decisions
266
+ decisions: this._decisions,
267
+ candidateValues: this._candidateValues
263
268
  }));
264
269
  /* c8 ignore next 3 - defense in depth against internal error */
265
270
  if (getOrAddMessage !== undefined) {
@@ -494,6 +499,7 @@ class ResourceManagerBuilder {
494
499
  conditions: Array.from(this._conditions.values()).map((c) => c.toCompiled(options)),
495
500
  conditionSets: Array.from(this._conditionSets.values()).map((cs) => cs.toCompiled(options)),
496
501
  decisions: Array.from(this._decisions.values()).map((d) => d.toCompiled(options)),
502
+ candidateValues: this._candidateValues.getValuesByIndex(),
497
503
  resources: Array.from(this._builtResources.values()).map((r) => r.toCompiled(options))
498
504
  };
499
505
  // Apply validation through the converter
@@ -848,7 +854,7 @@ class ResourceManagerBuilder {
848
854
  const decision = decisionResult.value;
849
855
  const resourceType = resourceTypeResult.value;
850
856
  // Create candidates from the decision's condition sets
851
- ResourceManagerBuilder._createCandidatesFromDecision(compiledResource, decision, resourceType, builder).aggregateError(errors);
857
+ ResourceManagerBuilder._createCandidatesFromDecision(compiledResource, decision, resourceType, builder, compiledCollection.candidateValues).aggregateError(errors);
852
858
  }
853
859
  return errors.returnOrReport((0, ts_utils_1.succeed)(true));
854
860
  }
@@ -858,10 +864,11 @@ class ResourceManagerBuilder {
858
864
  * @param decision - The decision containing condition sets.
859
865
  * @param resourceType - The resource type for the candidates.
860
866
  * @param builder - The builder to add candidates to.
867
+ * @param candidateValues - Array of candidate values indexed by valueIndex.
861
868
  * @returns `Success` if all candidates were added successfully, `Failure` otherwise.
862
869
  * @internal
863
870
  */
864
- static _createCandidatesFromDecision(compiledResource, decision, resourceType, builder) {
871
+ static _createCandidatesFromDecision(compiledResource, decision, resourceType, builder, candidateValues) {
865
872
  var _a;
866
873
  const errors = new ts_utils_1.MessageAggregator();
867
874
  // Match each candidate to its corresponding condition set
@@ -880,9 +887,9 @@ class ResourceManagerBuilder {
880
887
  conditions = undefined;
881
888
  }
882
889
  }
883
- // Convert json value to JsonObject, handling undefined case
890
+ // Get json value from candidateValues array using valueIndex
884
891
  /* c8 ignore next 1 - defense in depth */
885
- const rawJson = (_a = candidate.json) !== null && _a !== void 0 ? _a : {};
892
+ const rawJson = (_a = candidateValues[candidate.valueIndex]) !== null && _a !== void 0 ? _a : {};
886
893
  ts_json_base_1.Converters.jsonObject
887
894
  .convert(rawJson)
888
895
  .onSuccess((json) => {
@@ -1,10 +1,11 @@
1
1
  import { Collections, Result } from '@fgv/ts-utils';
2
2
  import { ReadOnlyConditionCollector, ReadOnlyConditionSetCollector } from '../conditions';
3
3
  import { ReadOnlyAbstractDecisionCollector } from '../decisions';
4
- import { QualifierCollector } from '../qualifiers';
5
- import { ResourceType, ResourceTypeCollector } from '../resource-types';
6
- import { QualifierType, QualifierTypeCollector } from '../qualifier-types';
4
+ import { IReadOnlyQualifierCollector } from '../qualifiers';
5
+ import { ResourceType, ReadOnlyResourceTypeCollector } from '../resource-types';
6
+ import { QualifierType, ReadOnlyQualifierTypeCollector } from '../qualifier-types';
7
7
  import { ResourceId } from '../common';
8
+ import { JsonValue } from '@fgv/ts-json-base';
8
9
  import { IResourceManager, IResource } from './iResourceManager';
9
10
  import * as ResourceJson from '../resource-json';
10
11
  import { ReadOnlyResourceTreeRoot } from './resource-tree';
@@ -40,23 +41,28 @@ export declare class CompiledResourceCollection implements IResourceManager<IRes
40
41
  private readonly _qualifierTypes;
41
42
  private readonly _qualifiers;
42
43
  private readonly _resourceTypes;
44
+ private readonly _candidateValues;
43
45
  private readonly _builtResources;
44
46
  private _cachedResourceTree?;
45
47
  /**
46
- * A {@link QualifierTypes.QualifierTypeCollector | QualifierTypeCollector} which
48
+ * A {@link QualifierTypes.ReadOnlyQualifierTypeCollector | ReadOnlyQualifierTypeCollector} which
47
49
  * contains the {@link QualifierTypes.QualifierType | qualifier types} used in this collection.
48
50
  */
49
- get qualifierTypes(): QualifierTypeCollector;
51
+ get qualifierTypes(): ReadOnlyQualifierTypeCollector;
50
52
  /**
51
- * A {@link Qualifiers.QualifierCollector | QualifierCollector} which
53
+ * A {@link Qualifiers.IReadOnlyQualifierCollector | ReadOnlyQualifierCollector} which
52
54
  * contains the {@link Qualifiers.Qualifier | qualifiers} used in this collection.
53
55
  */
54
- get qualifiers(): QualifierCollector;
56
+ get qualifiers(): IReadOnlyQualifierCollector;
55
57
  /**
56
58
  * A {@link ResourceTypes.ResourceTypeCollector | ResourceTypeCollector} which
57
59
  * contains the {@link ResourceTypes.ResourceType | resource types} used in this collection.
58
60
  */
59
- get resourceTypes(): ResourceTypeCollector;
61
+ get resourceTypes(): ReadOnlyResourceTypeCollector;
62
+ /**
63
+ * The candidate values in the collection.
64
+ */
65
+ get candidateValues(): ReadonlyArray<JsonValue>;
60
66
  /**
61
67
  * {@inheritdoc Runtime.IResourceManager.builtResources}
62
68
  */
@@ -154,6 +160,12 @@ export declare class CompiledResourceCollection implements IResourceManager<IRes
154
160
  * @internal
155
161
  */
156
162
  private _buildDecisions;
163
+ /**
164
+ * Gets a candidate value from the collection.
165
+ * @param valueIndex - The index of the candidate value to get.
166
+ * @returns
167
+ */
168
+ private _getCandidateValue;
157
169
  /**
158
170
  * Reconstructs a ValidatingResultMap of resources from compiled data.
159
171
  * @param compiled - The compiled resource collection
@@ -75,14 +75,14 @@ const Context = __importStar(require("../context"));
75
75
  */
76
76
  class CompiledResourceCollection {
77
77
  /**
78
- * A {@link QualifierTypes.QualifierTypeCollector | QualifierTypeCollector} which
78
+ * A {@link QualifierTypes.ReadOnlyQualifierTypeCollector | ReadOnlyQualifierTypeCollector} which
79
79
  * contains the {@link QualifierTypes.QualifierType | qualifier types} used in this collection.
80
80
  */
81
81
  get qualifierTypes() {
82
82
  return this._qualifierTypes;
83
83
  }
84
84
  /**
85
- * A {@link Qualifiers.QualifierCollector | QualifierCollector} which
85
+ * A {@link Qualifiers.IReadOnlyQualifierCollector | ReadOnlyQualifierCollector} which
86
86
  * contains the {@link Qualifiers.Qualifier | qualifiers} used in this collection.
87
87
  */
88
88
  get qualifiers() {
@@ -95,6 +95,12 @@ class CompiledResourceCollection {
95
95
  get resourceTypes() {
96
96
  return this._resourceTypes;
97
97
  }
98
+ /**
99
+ * The candidate values in the collection.
100
+ */
101
+ get candidateValues() {
102
+ return this._candidateValues;
103
+ }
98
104
  /**
99
105
  * {@inheritdoc Runtime.IResourceManager.builtResources}
100
106
  */
@@ -133,6 +139,7 @@ class CompiledResourceCollection {
133
139
  this.conditions = conditionCollector;
134
140
  this.conditionSets = conditionSetCollector;
135
141
  this.decisions = decisionCollector;
142
+ this._candidateValues = [...params.compiledCollection.candidateValues];
136
143
  // Build resources from compiled data
137
144
  this._builtResources = this._buildResources(params.compiledCollection, this._resourceTypes, decisionCollector).orThrow();
138
145
  }
@@ -381,6 +388,21 @@ class CompiledResourceCollection {
381
388
  }
382
389
  return errors.hasMessages ? (0, ts_utils_1.fail)(errors.toString()) : (0, ts_utils_1.succeed)(decisionCollector);
383
390
  }
391
+ /**
392
+ * Gets a candidate value from the collection.
393
+ * @param valueIndex - The index of the candidate value to get.
394
+ * @returns
395
+ */
396
+ _getCandidateValue(valueIndex) {
397
+ if (valueIndex < 0 || valueIndex >= this._candidateValues.length) {
398
+ return (0, ts_utils_1.fail)(`Invalid candidate value index ${valueIndex}`);
399
+ }
400
+ /* c8 ignore next 3 - defensive coding for invalid candidate value conversion */
401
+ if (!(0, ts_json_base_1.isJsonObject)(this._candidateValues[valueIndex])) {
402
+ return (0, ts_utils_1.fail)(`${valueIndex}: candidate value not a JSON object.`);
403
+ }
404
+ return (0, ts_utils_1.succeed)(this._candidateValues[valueIndex]);
405
+ }
384
406
  /**
385
407
  * Reconstructs a ValidatingResultMap of resources from compiled data.
386
408
  * @param compiled - The compiled resource collection
@@ -413,7 +435,7 @@ class CompiledResourceCollection {
413
435
  }
414
436
  const decision = decisionResult.value;
415
437
  // Build candidates from compiled data
416
- const candidateDeclsResult = (0, ts_utils_1.mapResults)(compiledResource.candidates.map((compiledCandidate) => ts_json_base_1.Converters.jsonObject.convert(compiledCandidate.json).onSuccess((json) => {
438
+ const candidateDeclsResult = (0, ts_utils_1.mapResults)(compiledResource.candidates.map((compiledCandidate) => this._getCandidateValue(compiledCandidate.valueIndex).onSuccess((json) => {
417
439
  return (0, ts_utils_1.succeed)({
418
440
  json,
419
441
  isPartial: compiledCandidate.isPartial,
@@ -431,7 +453,6 @@ class CompiledResourceCollection {
431
453
  isPartial: candidateDecl.isPartial,
432
454
  mergeMethod: candidateDecl.mergeMethod
433
455
  }));
434
- // Create a ConcreteDecision from the abstract decision and candidate values
435
456
  const candidatesWithConditionSets = decision.candidates.map((baseCandidate, idx) => ({
436
457
  conditionSet: baseCandidate.conditionSet,
437
458
  value: candidates[idx].json
@@ -49,7 +49,7 @@ export type IReadOnlyResourceTreeNode<T> = IReadOnlyResourceTreeLeaf<T> | IReadO
49
49
  * Interface for a read-only result-based resource tree with navigation methods.
50
50
  * @public
51
51
  */
52
- export interface IReadOnlyResourceTreeChildren<T, TID extends string = ResourceId, TNAME extends string = ResourceName> extends IReadOnlyResultMap<ResourceName, IReadOnlyResourceTreeNode<T>> {
52
+ export interface IReadOnlyResourceTreeChildren<T, TID extends string = ResourceId, TNAME extends string = ResourceName> extends IReadOnlyResultMap<TNAME, IReadOnlyResourceTreeNode<T>> {
53
53
  /**
54
54
  * Gets a tree node by its full ResourceId path.
55
55
  * @param id - The ResourceId path to look up
@@ -1,15 +1,19 @@
1
1
  import { Result } from '@fgv/ts-utils';
2
2
  import * as TsRes from '../../../index';
3
+ import { JsonObject } from '@fgv/ts-json-base';
3
4
  export interface ITestQualifierTypeConstructorParams {
4
5
  name?: string;
5
6
  allowContextList?: string;
6
7
  index?: number;
7
8
  }
8
9
  export declare class TestQualifierType extends TsRes.QualifierTypes.QualifierType {
10
+ readonly systemTypeName: TsRes.QualifierTypeName;
9
11
  constructor(params?: ITestQualifierTypeConstructorParams);
10
12
  static create(params?: ITestQualifierTypeConstructorParams): Result<TestQualifierType>;
11
13
  isValidConditionValue(value: string): value is TsRes.QualifierConditionValue;
12
14
  validateCondition(value: string, operator?: TsRes.ConditionOperator): Result<TsRes.QualifierConditionValue>;
15
+ getConfigurationJson(): Result<JsonObject>;
16
+ validateConfigurationJson(from: unknown): Result<JsonObject>;
13
17
  protected _matchOne(condition: TsRes.QualifierConditionValue, context: TsRes.QualifierContextValue, operator: TsRes.ConditionOperator): TsRes.QualifierMatchScore;
14
18
  }
15
19
  //# sourceMappingURL=testQualifierType.d.ts.map
@@ -65,6 +65,9 @@ class TestQualifierType extends TsRes.QualifierTypes.QualifierType {
65
65
  allowContextList: (params === null || params === void 0 ? void 0 : params.allowContextList) === 'true',
66
66
  index: params === null || params === void 0 ? void 0 : params.index
67
67
  });
68
+ this.systemTypeName = TsRes.Convert.qualifierTypeName
69
+ .convert('test')
70
+ .orThrow();
68
71
  }
69
72
  static create(params) {
70
73
  return (0, ts_utils_1.captureResult)(() => new TestQualifierType(params));
@@ -75,6 +78,27 @@ class TestQualifierType extends TsRes.QualifierTypes.QualifierType {
75
78
  validateCondition(value, operator) {
76
79
  return this.isValidConditionValue(value) ? (0, ts_utils_1.succeed)(value) : (0, ts_utils_1.fail)(`Invalid condition value: ${value}`);
77
80
  }
81
+ getConfigurationJson() {
82
+ return (0, ts_utils_1.succeed)({
83
+ name: this.name,
84
+ systemType: 'test',
85
+ configuration: {}
86
+ });
87
+ }
88
+ validateConfigurationJson(from) {
89
+ // Simple validation for test class
90
+ if (typeof from !== 'object' || from === null) {
91
+ return (0, ts_utils_1.fail)('Expected object');
92
+ }
93
+ const obj = from;
94
+ if (typeof obj.name !== 'string') {
95
+ return (0, ts_utils_1.fail)('name must be string');
96
+ }
97
+ if (obj.systemType !== 'test') {
98
+ return (0, ts_utils_1.fail)('systemType must be test');
99
+ }
100
+ return (0, ts_utils_1.succeed)(from);
101
+ }
78
102
  _matchOne(condition, context, operator) {
79
103
  if (condition === context) {
80
104
  return TsRes.PerfectMatch;
@@ -50,6 +50,7 @@ export interface IPartialTestData {
50
50
  * 3. Type-specific defaults and error handling
51
51
  */
52
52
  export declare class TestDerivedResourceType extends ResourceType<ITestData> {
53
+ readonly systemTypeName: ResourceTypeName;
53
54
  private _templateResourceId?;
54
55
  protected constructor(key: ResourceTypeName, index?: number, template?: JsonObject, templateResourceId?: string);
55
56
  /**
@@ -35,6 +35,9 @@ const resourceType_1 = require("../../../packlets/resource-types/resourceType");
35
35
  class TestDerivedResourceType extends resourceType_1.ResourceType {
36
36
  constructor(key, index, template, templateResourceId) {
37
37
  super(key, index, template);
38
+ this.systemTypeName = common_1.Convert.resourceTypeName
39
+ .convert('test-derived')
40
+ .orThrow();
38
41
  this._templateResourceId = templateResourceId;
39
42
  }
40
43
  /**
@@ -0,0 +1,2 @@
1
+ import '@fgv/ts-utils-jest';
2
+ //# sourceMappingURL=candidateValue.test.d.ts.map
@@ -0,0 +1,2 @@
1
+ import '@fgv/ts-utils-jest';
2
+ //# sourceMappingURL=candidateValueCollector.test.d.ts.map