@fgv/ts-res 5.0.1-9 → 5.0.1
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.
- package/dist/index.browser.js +53 -0
- package/dist/index.js +45 -0
- package/dist/packlets/bundle/bundleBuilder.js +130 -0
- package/dist/packlets/bundle/bundleLoader.js +101 -0
- package/dist/packlets/bundle/bundleNormalizer.js +138 -0
- package/dist/packlets/bundle/bundleUtils.js +113 -0
- package/dist/packlets/bundle/convert.js +75 -0
- package/dist/packlets/bundle/index.js +42 -0
- package/dist/packlets/bundle/model.js +23 -0
- package/dist/packlets/common/conditions.js +47 -0
- package/dist/packlets/common/convert.js +172 -0
- package/dist/packlets/common/helpers/conditions.js +66 -0
- package/dist/packlets/common/helpers/context.js +70 -0
- package/dist/packlets/common/helpers/index.js +26 -0
- package/dist/packlets/common/helpers/qualifierDefaultValues.js +66 -0
- package/dist/packlets/common/helpers/resources.js +93 -0
- package/dist/packlets/common/index.js +28 -0
- package/dist/packlets/common/resources.js +27 -0
- package/dist/packlets/common/validate/conditions.js +544 -0
- package/dist/packlets/common/validate/index.js +26 -0
- package/dist/packlets/common/validate/regularExpressions.js +84 -0
- package/dist/packlets/common/validate/resources.js +209 -0
- package/dist/packlets/conditions/condition.js +252 -0
- package/dist/packlets/conditions/conditionCollector.js +69 -0
- package/dist/packlets/conditions/conditionDecls.js +23 -0
- package/dist/packlets/conditions/conditionSet.js +247 -0
- package/dist/packlets/conditions/conditionSetCollector.js +89 -0
- package/dist/packlets/conditions/conditionSetDecls.js +23 -0
- package/dist/packlets/conditions/conditionToken.js +147 -0
- package/dist/packlets/conditions/convert/conditionSetDecls.js +51 -0
- package/dist/packlets/conditions/convert/decls.js +75 -0
- package/dist/packlets/conditions/convert/index.js +24 -0
- package/dist/packlets/conditions/index.js +31 -0
- package/dist/packlets/config/common.js +78 -0
- package/dist/packlets/config/configInitFactory.js +258 -0
- package/dist/packlets/config/convert.js +56 -0
- package/dist/packlets/config/index.browser.js +34 -0
- package/dist/packlets/config/index.js +28 -0
- package/dist/packlets/config/json.js +23 -0
- package/dist/packlets/config/predefined/default.js +138 -0
- package/dist/packlets/config/predefined/extended.js +190 -0
- package/dist/packlets/config/predefined/index.js +25 -0
- package/dist/packlets/config/systemConfiguration.js +147 -0
- package/dist/packlets/context/contextDecls.js +23 -0
- package/dist/packlets/context/contextToken.js +202 -0
- package/dist/packlets/context/convert/decls.js +91 -0
- package/dist/packlets/context/convert/index.js +23 -0
- package/dist/packlets/context/index.js +26 -0
- package/dist/packlets/decisions/abstractDecision.js +68 -0
- package/dist/packlets/decisions/abstractDecisionCollector.js +90 -0
- package/dist/packlets/decisions/candidate.js +76 -0
- package/dist/packlets/decisions/common.js +23 -0
- package/dist/packlets/decisions/concreteDecision.js +111 -0
- package/dist/packlets/decisions/decision.js +126 -0
- package/dist/packlets/decisions/index.js +28 -0
- package/dist/packlets/import/fsItem.js +134 -0
- package/dist/packlets/import/importContext.js +129 -0
- package/dist/packlets/import/importManager.js +129 -0
- package/dist/packlets/import/importable.js +32 -0
- package/dist/packlets/import/importers/collectionImporter.js +118 -0
- package/dist/packlets/import/importers/fsItemImporter.js +116 -0
- package/dist/packlets/import/importers/importer.js +23 -0
- package/dist/packlets/import/importers/index.browser.js +29 -0
- package/dist/packlets/import/importers/index.js +27 -0
- package/dist/packlets/import/importers/jsonImporter.js +94 -0
- package/dist/packlets/import/importers/pathImporter.js +84 -0
- package/dist/packlets/import/index.browser.js +34 -0
- package/dist/packlets/import/index.js +28 -0
- package/dist/packlets/qualifier-types/config/convert.js +124 -0
- package/dist/packlets/qualifier-types/config/index.js +25 -0
- package/dist/packlets/qualifier-types/config/json.js +32 -0
- package/dist/packlets/qualifier-types/convert.js +56 -0
- package/dist/packlets/qualifier-types/helpers.js +82 -0
- package/dist/packlets/qualifier-types/index.js +32 -0
- package/dist/packlets/qualifier-types/languageQualifierType.js +142 -0
- package/dist/packlets/qualifier-types/literalQualifierType.js +200 -0
- package/dist/packlets/qualifier-types/literalValueHierarchy.js +236 -0
- package/dist/packlets/qualifier-types/qualifierType.js +184 -0
- package/dist/packlets/qualifier-types/qualifierTypeCollector.js +66 -0
- package/dist/packlets/qualifier-types/territoryQualifierType.js +200 -0
- package/dist/packlets/qualifiers/convert/decls.js +70 -0
- package/dist/packlets/qualifiers/convert/index.js +24 -0
- package/dist/packlets/qualifiers/convert/qualifier.js +40 -0
- package/dist/packlets/qualifiers/index.js +29 -0
- package/dist/packlets/qualifiers/qualifier.js +108 -0
- package/dist/packlets/qualifiers/qualifierCollector.js +123 -0
- package/dist/packlets/qualifiers/qualifierDecl.js +23 -0
- package/dist/packlets/qualifiers/qualifierDefaultValueDecls.js +23 -0
- package/dist/packlets/qualifiers/qualifierDefaultValueToken.js +175 -0
- package/dist/packlets/resource-json/compiled/common.js +23 -0
- package/dist/packlets/resource-json/compiled/convert.js +132 -0
- package/dist/packlets/resource-json/compiled/index.js +26 -0
- package/dist/packlets/resource-json/compiled/json.js +2 -0
- package/dist/packlets/resource-json/convert.js +171 -0
- package/dist/packlets/resource-json/helpers.js +241 -0
- package/dist/packlets/resource-json/index.js +31 -0
- package/dist/packlets/resource-json/json.js +36 -0
- package/dist/packlets/resource-json/normalized.js +23 -0
- package/dist/packlets/resource-json/resourceDeclCollection.js +88 -0
- package/dist/packlets/resource-json/resourceDeclContainer.js +23 -0
- package/dist/packlets/resource-json/resourceDeclTree.js +94 -0
- package/dist/packlets/resource-types/config/convert.js +35 -0
- package/dist/packlets/resource-types/config/index.js +25 -0
- package/dist/packlets/resource-types/config/json.js +23 -0
- package/dist/packlets/resource-types/helpers.js +42 -0
- package/dist/packlets/resource-types/index.js +28 -0
- package/dist/packlets/resource-types/jsonResourceType.js +66 -0
- package/dist/packlets/resource-types/resourceType.js +95 -0
- package/dist/packlets/resource-types/resourceTypeCollector.js +61 -0
- package/dist/packlets/resources/candidateReducer.js +246 -0
- package/dist/packlets/resources/candidateValue.js +92 -0
- package/dist/packlets/resources/candidateValueCollector.js +94 -0
- package/dist/packlets/resources/common.js +23 -0
- package/dist/packlets/resources/deltaGenerator.js +338 -0
- package/dist/packlets/resources/index.js +31 -0
- package/dist/packlets/resources/resource.js +207 -0
- package/dist/packlets/resources/resourceBuilder.js +183 -0
- package/dist/packlets/resources/resourceCandidate.js +216 -0
- package/dist/packlets/resources/resourceManagerBuilder.js +890 -0
- package/dist/packlets/runtime/cacheListener.js +58 -0
- package/dist/packlets/runtime/cacheMetrics.js +149 -0
- package/dist/packlets/runtime/compiledResourceCollection.js +473 -0
- package/dist/packlets/runtime/conditionSetResolutionResult.js +134 -0
- package/dist/packlets/runtime/context/contextQualifierProvider.js +29 -0
- package/dist/packlets/runtime/context/contextQualifierProviderValidator.js +146 -0
- package/dist/packlets/runtime/context/index.js +26 -0
- package/dist/packlets/runtime/context/simpleContextQualifierProvider.js +196 -0
- package/dist/packlets/runtime/context/validatingSimpleContextQualifierProvider.js +60 -0
- package/dist/packlets/runtime/iResourceManager.js +23 -0
- package/dist/packlets/runtime/index.js +34 -0
- package/dist/packlets/runtime/resource-tree/common.js +23 -0
- package/dist/packlets/runtime/resource-tree/index.js +26 -0
- package/dist/packlets/runtime/resource-tree/readOnlyResourceTree.js +216 -0
- package/dist/packlets/runtime/resource-tree/resourceTreeChildren.js +97 -0
- package/dist/packlets/runtime/resource-tree/resourceTreeChildrenValidator.js +161 -0
- package/dist/packlets/runtime/resourceResolver.js +481 -0
- package/dist/packlets/runtime/resourceTreeResolver.js +220 -0
- package/dist/packlets/runtime/validate.js +47 -0
- package/dist/packlets/zip-archive/convert.js +100 -0
- package/dist/packlets/zip-archive/index.browser.js +54 -0
- package/dist/packlets/zip-archive/index.js +47 -0
- package/dist/packlets/zip-archive/json.js +23 -0
- package/dist/packlets/zip-archive/types.js +36 -0
- package/dist/packlets/zip-archive/zipArchiveCreator.js +191 -0
- package/dist/packlets/zip-archive/zipArchiveFormat.js +140 -0
- package/dist/packlets/zip-archive/zipArchiveLoader.js +282 -0
- package/dist/test/data/sample.json +32 -0
- package/dist/test/unit/qualifier-types/testQualifierType.js +76 -0
- package/dist/test/unit/resource-types/testDerivedResourceType.js +109 -0
- package/dist/test/unit/resources/deltaGenerator.helpers.js +282 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/index.browser.d.ts +24 -0
- package/lib/index.browser.js +116 -0
- package/lib/packlets/config/index.browser.d.ts +7 -0
- package/lib/packlets/config/index.browser.js +74 -0
- package/lib/packlets/import/importers/index.browser.d.ts +4 -0
- package/lib/packlets/import/importers/index.browser.js +45 -0
- package/lib/packlets/import/index.browser.d.ts +7 -0
- package/lib/packlets/import/index.browser.js +74 -0
- package/lib/packlets/zip-archive/index.browser.d.ts +27 -0
- package/lib/packlets/zip-archive/index.browser.js +102 -0
- package/package.json +21 -7
|
@@ -0,0 +1,32 @@
|
|
|
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 * as Config from './config';
|
|
23
|
+
import * as Convert from './convert';
|
|
24
|
+
export * from './qualifierType';
|
|
25
|
+
export * from './languageQualifierType';
|
|
26
|
+
export * from './literalQualifierType';
|
|
27
|
+
export * from './literalValueHierarchy';
|
|
28
|
+
export * from './territoryQualifierType';
|
|
29
|
+
export * from './qualifierTypeCollector';
|
|
30
|
+
export * from './helpers';
|
|
31
|
+
export { Config, Convert };
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,142 @@
|
|
|
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 { captureResult, succeed } from '@fgv/ts-utils';
|
|
23
|
+
import { Bcp47 } from '@fgv/ts-bcp47';
|
|
24
|
+
import { Convert, NoMatch, Validate } from '../common';
|
|
25
|
+
import { QualifierType } from './qualifierType';
|
|
26
|
+
import * as Config from './config';
|
|
27
|
+
import { sanitizeJsonObject } from '@fgv/ts-json-base';
|
|
28
|
+
/**
|
|
29
|
+
* {@link QualifierTypes.QualifierType | Qualifier type} which matches BCP-47 language tags
|
|
30
|
+
* applying {@link https://github.com/ErikFortune/fgv/tree/main/libraries/ts-bcp47#tag-matching | similarity matching}.
|
|
31
|
+
* Accepts a list of language tags in the context by default.
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export class LanguageQualifierType extends QualifierType {
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new instance of a {@link QualifierTypes.LanguageQualifierType | language qualifier type}.
|
|
37
|
+
* @param name - Optional name for the qualifier type. Defaults to 'language'.
|
|
38
|
+
* @param allowContextList - Optional flag indicating whether the context can be a
|
|
39
|
+
* list of values. Defaults to `true`.
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
constructor({ name, allowContextList, index }) {
|
|
43
|
+
allowContextList = allowContextList !== false;
|
|
44
|
+
/* c8 ignore next 2 - coverage intermittently drops these two lines even though they're tested */
|
|
45
|
+
name = name !== null && name !== void 0 ? name : 'language';
|
|
46
|
+
const validated = index ? { index: Convert.qualifierTypeIndex.convert(index).orThrow() } : {};
|
|
47
|
+
super(Object.assign({ name,
|
|
48
|
+
allowContextList }, validated));
|
|
49
|
+
/**
|
|
50
|
+
* {@inheritdoc QualifierTypes.IQualifierType.systemTypeName}
|
|
51
|
+
*/
|
|
52
|
+
this.systemTypeName = Convert.qualifierTypeName.convert('language').orThrow();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new instance of a {@link QualifierTypes.LanguageQualifierType | language qualifier type}.
|
|
56
|
+
* @param params - Optional {@link QualifierTypes.ILanguageQualifierTypeCreateParams | parameters}
|
|
57
|
+
* to use when creating the new instance.
|
|
58
|
+
* @returns `Success` with the new {@link QualifierTypes.LanguageQualifierType | language qualifier type}
|
|
59
|
+
* if successful, `Failure` otherwise.
|
|
60
|
+
*/
|
|
61
|
+
static create(params) {
|
|
62
|
+
/* c8 ignore next 1 - coverage seems to intermittently miss the branch even though it's tested */
|
|
63
|
+
params = params !== null && params !== void 0 ? params : {};
|
|
64
|
+
return captureResult(() => new LanguageQualifierType(params));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Creates a new {@link QualifierTypes.LanguageQualifierType | LanguageQualifierType} from a configuration object.
|
|
68
|
+
* @param config - The {@link QualifierTypes.Config.IQualifierTypeConfig | configuration object} containing
|
|
69
|
+
* the name, systemType, and optional language-specific configuration.
|
|
70
|
+
* @returns `Success` with the new {@link QualifierTypes.LanguageQualifierType | LanguageQualifierType}
|
|
71
|
+
* if successful, `Failure` with an error message otherwise.
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
static createFromConfig(config) {
|
|
75
|
+
var _a;
|
|
76
|
+
return sanitizeJsonObject({
|
|
77
|
+
name: config.name,
|
|
78
|
+
allowContextList: ((_a = config.configuration) === null || _a === void 0 ? void 0 : _a.allowContextList) === true
|
|
79
|
+
}).onSuccess(LanguageQualifierType.create);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* {@inheritdoc QualifierTypes.IQualifierType.isValidConditionValue}
|
|
83
|
+
*/
|
|
84
|
+
isValidConditionValue(value) {
|
|
85
|
+
return Bcp47.tag(value)
|
|
86
|
+
.onSuccess((tag) => succeed(tag.isValid))
|
|
87
|
+
.orDefault(false);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Gets a {@link QualifierTypes.Config.ISystemLanguageQualifierTypeConfig | strongly typed configuration object}
|
|
91
|
+
* for this qualifier type.
|
|
92
|
+
* @returns `Success` with the configuration if successful, `Failure` with an error message otherwise.
|
|
93
|
+
*/
|
|
94
|
+
getConfiguration() {
|
|
95
|
+
return this.getConfigurationJson().onSuccess((json) => Config.Convert.systemLanguageQualifierTypeConfig.convert(json));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* {@inheritdoc QualifierTypes.IQualifierType.getConfigurationJson}
|
|
99
|
+
*/
|
|
100
|
+
getConfigurationJson() {
|
|
101
|
+
return succeed({
|
|
102
|
+
name: this.name,
|
|
103
|
+
systemType: 'language',
|
|
104
|
+
configuration: {
|
|
105
|
+
allowContextList: this.allowContextList
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* {@inheritdoc QualifierTypes.IQualifierType.validateConfigurationJson}
|
|
111
|
+
*/
|
|
112
|
+
validateConfigurationJson(from) {
|
|
113
|
+
return Config.Convert.systemLanguageQualifierTypeConfig.convert(from);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Validates a {@link QualifierTypes.Config.ISystemLanguageQualifierTypeConfig | strongly typed configuration object}
|
|
117
|
+
* for this qualifier type.
|
|
118
|
+
* @param from - The unknown data to validate as a configuration object.
|
|
119
|
+
* @returns `Success` with the validated configuration if successful, `Failure` with an error message otherwise.
|
|
120
|
+
*/
|
|
121
|
+
validateConfiguration(from) {
|
|
122
|
+
return Config.Convert.systemLanguageQualifierTypeConfig.convert(from);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Matches a single language condition against a single language context value using
|
|
126
|
+
* {@link https://github.com/ErikFortune/fgv/tree/main/libraries/ts-bcp47#tag-matching | similarity matching}.
|
|
127
|
+
* @param condition - The language condition value to match.
|
|
128
|
+
* @param context - The language context value to match against.
|
|
129
|
+
* @param operator - The operator to use for the match. Must be 'matches'.
|
|
130
|
+
* @returns The match score, or `noMatch` if the match fails.
|
|
131
|
+
*/
|
|
132
|
+
_matchOne(condition, context, operator) {
|
|
133
|
+
if (operator === 'matches') {
|
|
134
|
+
const similarity = Bcp47.similarity(condition, context).orDefault(Bcp47.tagSimilarity.none);
|
|
135
|
+
if (similarity > 0.0 && Validate.isValidQualifierMatchScore(similarity)) {
|
|
136
|
+
return similarity;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return NoMatch;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=languageQualifierType.js.map
|
|
@@ -0,0 +1,200 @@
|
|
|
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 { captureResult, mapResults, fail, succeed } from '@fgv/ts-utils';
|
|
23
|
+
import { Convert, NoMatch, PerfectMatch, Validate } from '../common';
|
|
24
|
+
import { QualifierType } from './qualifierType';
|
|
25
|
+
import { LiteralValueHierarchy } from './literalValueHierarchy';
|
|
26
|
+
import * as Config from './config';
|
|
27
|
+
import { sanitizeJsonObject } from '@fgv/ts-json-base';
|
|
28
|
+
/**
|
|
29
|
+
* A {@link QualifierTypes.QualifierType | qualifier} that matches a literal value,
|
|
30
|
+
* optionally case-sensitive or matching against an ordered list of values at runtime.
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export class LiteralQualifierType extends QualifierType {
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a new {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType}.
|
|
36
|
+
* @param name - Optional name for the qualifier type. Defaults to 'literal'.
|
|
37
|
+
* @param caseSensitive - Optional flag indicating whether the match should be
|
|
38
|
+
* case-sensitive. Defaults to `false`.
|
|
39
|
+
* @param allowContextList - Optional flag indicating whether the context can be a
|
|
40
|
+
* list of values. Defaults to `false`.
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
constructor({ name, caseSensitive, allowContextList, enumeratedValues, hierarchy, index }) {
|
|
44
|
+
allowContextList = allowContextList !== false;
|
|
45
|
+
super({
|
|
46
|
+
name: name !== null && name !== void 0 ? name : 'literal',
|
|
47
|
+
allowContextList,
|
|
48
|
+
index: index !== undefined ? Convert.qualifierTypeIndex.convert(index).orThrow() : undefined
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* {@inheritdoc QualifierTypes.IQualifierType.systemTypeName}
|
|
52
|
+
*/
|
|
53
|
+
this.systemTypeName = Convert.qualifierTypeName.convert('literal').orThrow();
|
|
54
|
+
this.caseSensitive = caseSensitive === true;
|
|
55
|
+
this.enumeratedValues = enumeratedValues
|
|
56
|
+
? mapResults(Array.from(enumeratedValues).map(LiteralQualifierType.toLiteralConditionValue)).orThrow()
|
|
57
|
+
: undefined;
|
|
58
|
+
if (hierarchy) {
|
|
59
|
+
/* c8 ignore next 5 - defensive coding: enumeratedValues ?? [] fallback enables open values mode */
|
|
60
|
+
this.hierarchy = LiteralValueHierarchy.create({
|
|
61
|
+
values: enumeratedValues !== null && enumeratedValues !== void 0 ? enumeratedValues : [],
|
|
62
|
+
hierarchy: hierarchy
|
|
63
|
+
}).orThrow();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Determines whether a value is a valid condition value for a literal qualifier.
|
|
68
|
+
* The {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType} accepts
|
|
69
|
+
* any identifier as a valid condition value.
|
|
70
|
+
* @param value - The value to validate.
|
|
71
|
+
* @returns `true` if the value is a valid condition value, `false` otherwise.
|
|
72
|
+
*/
|
|
73
|
+
isValidConditionValue(value) {
|
|
74
|
+
if (this.enumeratedValues) {
|
|
75
|
+
if (this.caseSensitive) {
|
|
76
|
+
return this.enumeratedValues.includes(value);
|
|
77
|
+
}
|
|
78
|
+
return this.enumeratedValues.some((v) => v.toLowerCase() === value.toLowerCase());
|
|
79
|
+
}
|
|
80
|
+
return LiteralQualifierType.isValidLiteralConditionValue(value);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* {@inheritdoc QualifierTypes.IQualifierType.isPotentialMatch}
|
|
84
|
+
*/
|
|
85
|
+
isPotentialMatch(conditionValue, contextValue) {
|
|
86
|
+
if (this.isValidConditionValue(conditionValue) && this.isValidContextValue(contextValue)) {
|
|
87
|
+
if (this._matchOne(conditionValue, contextValue, 'matches') !== NoMatch) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (this.hierarchy) {
|
|
91
|
+
return this.hierarchy.isAncestor(conditionValue, contextValue);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Gets a {@link QualifierTypes.Config.ISystemLiteralQualifierTypeConfig | strongly typed configuration object}
|
|
98
|
+
* for this qualifier type.
|
|
99
|
+
* @returns `Success` with the configuration if successful, `Failure` with an error message otherwise.
|
|
100
|
+
*/
|
|
101
|
+
getConfiguration() {
|
|
102
|
+
return this.getConfigurationJson().onSuccess((json) => Config.Convert.systemLiteralQualifierTypeConfig.convert(json));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* {@inheritdoc QualifierTypes.IQualifierType.getConfigurationJson}
|
|
106
|
+
*/
|
|
107
|
+
getConfigurationJson() {
|
|
108
|
+
const hierarchy = this.hierarchy ? { hierarchy: this.hierarchy.asRecord() } : {};
|
|
109
|
+
const enumeratedValues = this.enumeratedValues
|
|
110
|
+
? { enumeratedValues: [...this.enumeratedValues] }
|
|
111
|
+
: {};
|
|
112
|
+
return succeed({
|
|
113
|
+
name: this.name,
|
|
114
|
+
systemType: 'literal',
|
|
115
|
+
configuration: Object.assign(Object.assign({ allowContextList: this.allowContextList, caseSensitive: this.caseSensitive }, enumeratedValues), hierarchy)
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* {@inheritdoc QualifierTypes.IQualifierType.validateConfigurationJson}
|
|
120
|
+
*/
|
|
121
|
+
validateConfigurationJson(from) {
|
|
122
|
+
return Config.Convert.systemLiteralQualifierTypeConfig.convert(from);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validates a {@link QualifierTypes.Config.ISystemLiteralQualifierTypeConfig | strongly typed configuration object}
|
|
126
|
+
* for this qualifier type.
|
|
127
|
+
* @param from - The unknown data to validate as a configuration object.
|
|
128
|
+
* @returns `Success` with the validated configuration if successful, `Failure` with an error message otherwise.
|
|
129
|
+
*/
|
|
130
|
+
validateConfiguration(from) {
|
|
131
|
+
return Config.Convert.systemLiteralQualifierTypeConfig.convert(from);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* {@inheritdoc QualifierTypes.QualifierType._matchOne}
|
|
135
|
+
*/
|
|
136
|
+
_matchOne(condition, context, __operator) {
|
|
137
|
+
if (this.hierarchy) {
|
|
138
|
+
return this.hierarchy.match(condition, context, __operator);
|
|
139
|
+
}
|
|
140
|
+
if (this.caseSensitive) {
|
|
141
|
+
return condition === context ? PerfectMatch : NoMatch;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
return condition.toLowerCase() === context.toLowerCase() ? PerfectMatch : NoMatch;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates a new {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType}.
|
|
149
|
+
* @param params - Optional {@link QualifierTypes.ILiteralQualifierTypeCreateParams | parameters}
|
|
150
|
+
* to use when creating the new instance.
|
|
151
|
+
* @returns `Success` with the new {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType}
|
|
152
|
+
* if successful, `Failure` with an error message otherwise.
|
|
153
|
+
* @public
|
|
154
|
+
*/
|
|
155
|
+
static create(params) {
|
|
156
|
+
return captureResult(() => new LiteralQualifierType(params !== null && params !== void 0 ? params : {}));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Creates a new {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType} from a configuration object.
|
|
160
|
+
* @param config - The {@link QualifierTypes.Config.IQualifierTypeConfig | configuration object} containing
|
|
161
|
+
* the name, systemType, and optional literal-specific configuration including case sensitivity,
|
|
162
|
+
* enumerated values, and hierarchy information.
|
|
163
|
+
* @returns `Success` with the new {@link QualifierTypes.LiteralQualifierType | LiteralQualifierType}
|
|
164
|
+
* if successful, `Failure` with an error message otherwise.
|
|
165
|
+
* @public
|
|
166
|
+
*/
|
|
167
|
+
static createFromConfig(config) {
|
|
168
|
+
var _a;
|
|
169
|
+
const literalConfig = (_a = config.configuration) !== null && _a !== void 0 ? _a : {};
|
|
170
|
+
return sanitizeJsonObject({
|
|
171
|
+
name: config.name,
|
|
172
|
+
allowContextList: literalConfig.allowContextList === true,
|
|
173
|
+
caseSensitive: literalConfig.caseSensitive,
|
|
174
|
+
enumeratedValues: literalConfig.enumeratedValues,
|
|
175
|
+
hierarchy: literalConfig.hierarchy
|
|
176
|
+
}).onSuccess(LiteralQualifierType.create);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Checks if the given value is a valid literal condition value.
|
|
180
|
+
* @param from - The value to validate.
|
|
181
|
+
* @returns `true` if the value is a valid literal condition value, otherwise `false`.
|
|
182
|
+
* @public
|
|
183
|
+
*/
|
|
184
|
+
static isValidLiteralConditionValue(from) {
|
|
185
|
+
return Validate.RegularExpressions.identifier.test(from);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Converts a string to a {@link QualifierConditionValue | literal condition value}.
|
|
189
|
+
* @param from - The string to convert.
|
|
190
|
+
* @returns `Success` with the converted value if valid, or `Failure` with an error
|
|
191
|
+
* message if not.
|
|
192
|
+
* @public
|
|
193
|
+
*/
|
|
194
|
+
static toLiteralConditionValue(from) {
|
|
195
|
+
return LiteralQualifierType.isValidLiteralConditionValue(from)
|
|
196
|
+
? succeed(from)
|
|
197
|
+
: fail(`${from}: invalid literal condition value.`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=literalQualifierType.js.map
|
|
@@ -0,0 +1,236 @@
|
|
|
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 { captureResult, MessageAggregator, succeed, fail } from '@fgv/ts-utils';
|
|
23
|
+
import { NoMatch, PerfectMatch, Convert as CommonConverters } from '../common';
|
|
24
|
+
/**
|
|
25
|
+
* A class that implements a hierarchy of literal values. The hierarchy is defined as a
|
|
26
|
+
* tree, where each value can have multiple children but only one parent. The root of the
|
|
27
|
+
* tree has no parent. The hierarchy is used to determine the relationship between values
|
|
28
|
+
* when matching conditions and contexts.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* The hierarchy can be created in two modes:
|
|
32
|
+
* - **Constrained mode**: When enumerated values are provided, only those values are allowed
|
|
33
|
+
* in the hierarchy and matching operations.
|
|
34
|
+
* - **Open values mode**: When no enumerated values are provided, all values referenced in
|
|
35
|
+
* the hierarchy are automatically collected and used. This allows for flexible hierarchies
|
|
36
|
+
* where any value can be used in matching operations.
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export class LiteralValueHierarchy {
|
|
40
|
+
constructor(params) {
|
|
41
|
+
const result = LiteralValueHierarchy._buildValuesFromHierarchy(params);
|
|
42
|
+
this.values = result.orThrow();
|
|
43
|
+
this.isOpenValues = !params.values || params.values.length === 0;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new {@link QualifierTypes.LiteralValueHierarchy | LiteralValueHierarchy} instance.
|
|
47
|
+
* @param params - The {@link QualifierTypes.ILiteralValueHierarchyCreateParams | parameters}
|
|
48
|
+
* used to create the hierarchy.
|
|
49
|
+
* @returns `Success` with the new hierarchy or `Failure` with an error message.
|
|
50
|
+
*/
|
|
51
|
+
static create(params) {
|
|
52
|
+
return captureResult(() => new LiteralValueHierarchy(params));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Checks if a value exists in the hierarchy.
|
|
56
|
+
* @param value - The value to check.
|
|
57
|
+
* @returns `true` if the value exists in the hierarchy, `false` otherwise.
|
|
58
|
+
*/
|
|
59
|
+
hasValue(value) {
|
|
60
|
+
return this.values.has(value);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gets all root values (values with no parent) in the hierarchy.
|
|
64
|
+
* @returns `Success` with an array of root values.
|
|
65
|
+
*/
|
|
66
|
+
getRoots() {
|
|
67
|
+
return succeed(Array.from(this.values.values())
|
|
68
|
+
.filter((v) => !v.parent)
|
|
69
|
+
.map((v) => v.name));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Gets all ancestors of a value in the hierarchy.
|
|
73
|
+
* @param value - The value to get ancestors for.
|
|
74
|
+
* @returns `Success` with an array of ancestor values, ordered from immediate parent
|
|
75
|
+
* to root, or `Failure` if the value is not in the hierarchy.
|
|
76
|
+
*/
|
|
77
|
+
getAncestors(value) {
|
|
78
|
+
const current = this.values.get(value);
|
|
79
|
+
/* c8 ignore next 3 - functional error case tested but coverage intermittently missed */
|
|
80
|
+
if (!current) {
|
|
81
|
+
return fail(`${value}: not found in hierarchy`);
|
|
82
|
+
}
|
|
83
|
+
const ancestors = [];
|
|
84
|
+
let ancestor = current.parent;
|
|
85
|
+
while (ancestor) {
|
|
86
|
+
ancestors.push(ancestor.name);
|
|
87
|
+
ancestor = ancestor.parent;
|
|
88
|
+
}
|
|
89
|
+
return succeed(ancestors);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Determines if a value is an ancestor of a possible ancestor value.
|
|
93
|
+
* @param value - The value to check.
|
|
94
|
+
* @param possibleAncestor - The possible ancestor value.
|
|
95
|
+
* @returns `true` if the value is an ancestor of the possible ancestor, `false` otherwise.
|
|
96
|
+
*/
|
|
97
|
+
isAncestor(value, possibleAncestor) {
|
|
98
|
+
const ancestors = this.getAncestors(value);
|
|
99
|
+
if (ancestors.isSuccess()) {
|
|
100
|
+
return ancestors.value.includes(possibleAncestor);
|
|
101
|
+
}
|
|
102
|
+
/* c8 ignore next 2 - edge case: ancestor validation fallback */
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Gets all descendants of a value in the hierarchy.
|
|
107
|
+
* @param value - The value to get descendants for.
|
|
108
|
+
* @returns `Success` with an array of descendant values, or `Failure` if the value
|
|
109
|
+
* is not in the hierarchy.
|
|
110
|
+
*/
|
|
111
|
+
getDescendants(value) {
|
|
112
|
+
const current = this.values.get(value);
|
|
113
|
+
if (!current) {
|
|
114
|
+
return fail(`${value}: not found in hierarchy`);
|
|
115
|
+
}
|
|
116
|
+
const descendants = [];
|
|
117
|
+
if (current.children) {
|
|
118
|
+
for (const childName of current.children) {
|
|
119
|
+
descendants.push(childName);
|
|
120
|
+
const childDescendants = this.getDescendants(childName);
|
|
121
|
+
if (childDescendants.isSuccess()) {
|
|
122
|
+
descendants.push(...childDescendants.value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return succeed(descendants);
|
|
127
|
+
}
|
|
128
|
+
match(condition, context, __operator) {
|
|
129
|
+
var _a;
|
|
130
|
+
// For open hierarchies, skip validation and allow any values
|
|
131
|
+
if (!this.isOpenValues) {
|
|
132
|
+
// Validate that both condition and context exist in the hierarchy
|
|
133
|
+
/* c8 ignore next 3 - functional error case tested but coverage intermittently missed */
|
|
134
|
+
if (!this.values.has(condition)) {
|
|
135
|
+
return NoMatch;
|
|
136
|
+
}
|
|
137
|
+
/* c8 ignore next 3 - functional error case tested but coverage intermittently missed */
|
|
138
|
+
if (!this.values.has(context)) {
|
|
139
|
+
return NoMatch;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (condition === context) {
|
|
143
|
+
return PerfectMatch;
|
|
144
|
+
}
|
|
145
|
+
// For open hierarchies, if values aren't in the hierarchy, treat as no match
|
|
146
|
+
// but don't fail validation
|
|
147
|
+
const values = this.values;
|
|
148
|
+
/* c8 ignore next 1 - ? is defense in depth */
|
|
149
|
+
let value = (_a = values.get(context)) === null || _a === void 0 ? void 0 : _a.parent;
|
|
150
|
+
/* c8 ignore next 2 - functional error case tested but coverage intermittently missed */
|
|
151
|
+
if (!value) {
|
|
152
|
+
return NoMatch;
|
|
153
|
+
}
|
|
154
|
+
let score = PerfectMatch;
|
|
155
|
+
while (value) {
|
|
156
|
+
score *= 0.9;
|
|
157
|
+
if (value.name === condition) {
|
|
158
|
+
return CommonConverters.qualifierMatchScore.convert(score).orDefault(NoMatch);
|
|
159
|
+
}
|
|
160
|
+
value = value.parent;
|
|
161
|
+
}
|
|
162
|
+
return NoMatch;
|
|
163
|
+
}
|
|
164
|
+
static _buildValuesFromHierarchy(params) {
|
|
165
|
+
var _a;
|
|
166
|
+
const errors = new MessageAggregator();
|
|
167
|
+
const values = params.values;
|
|
168
|
+
/* c8 ignore next 1 - defense in depth */
|
|
169
|
+
const hierarchy = (_a = params.hierarchy) !== null && _a !== void 0 ? _a : {};
|
|
170
|
+
// If no values are provided, collect all values from the hierarchy
|
|
171
|
+
let allValues;
|
|
172
|
+
if (!values || values.length === 0) {
|
|
173
|
+
const hierarchyValues = new Set();
|
|
174
|
+
// Add all keys and values from the hierarchy
|
|
175
|
+
Object.keys(hierarchy).forEach((key) => hierarchyValues.add(key));
|
|
176
|
+
Object.values(hierarchy).forEach((value) => hierarchyValues.add(value));
|
|
177
|
+
allValues = Array.from(hierarchyValues);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
allValues = [...values];
|
|
181
|
+
}
|
|
182
|
+
const valueMap = new Map(allValues.map((name) => [name, { name }]));
|
|
183
|
+
if (hierarchy) {
|
|
184
|
+
for (const [valueName, parentName] of Object.entries(hierarchy)) {
|
|
185
|
+
const value = valueMap.get(valueName);
|
|
186
|
+
if (!value) {
|
|
187
|
+
errors.addMessage(`${valueName}: invalid literal value.`);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const parent = valueMap.get(parentName);
|
|
191
|
+
if (!parent) {
|
|
192
|
+
errors.addMessage(`${valueName}: parent ${parentName} is invalid literal value.`);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
let ancestor = parent.parent;
|
|
196
|
+
let circular = false;
|
|
197
|
+
const ancestors = [];
|
|
198
|
+
while (ancestor) {
|
|
199
|
+
/* c8 ignore next 1 - defensive coding: complex circular reference detection intermittently missed */
|
|
200
|
+
ancestors.push(ancestor.name);
|
|
201
|
+
/* c8 ignore next 1 - defensive coding: ancestor.parent === value is very difficult to reach */
|
|
202
|
+
if (ancestor.parent === parent || ancestor.parent === value) {
|
|
203
|
+
/* c8 ignore next 4 - defensive coding: circular reference error reporting intermittently missed */
|
|
204
|
+
errors.addMessage(`${valueName}: Circular reference detected: ${ancestors.join('->')}`);
|
|
205
|
+
circular = true;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
ancestor = ancestor.parent;
|
|
209
|
+
}
|
|
210
|
+
/* c8 ignore next 3 - defensive coding: circular reference handling intermittently missed */
|
|
211
|
+
if (circular) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
value.parent = parent;
|
|
215
|
+
if (parent.children) {
|
|
216
|
+
parent.children.push(value.name);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
parent.children = [value.name];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return errors.returnOrReport(succeed(valueMap));
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Converts the hierarchy to a record of parent-child relationships.
|
|
227
|
+
* @returns A record of parent-child relationships.
|
|
228
|
+
*/
|
|
229
|
+
asRecord() {
|
|
230
|
+
const entries = Array.from(this.values.values())
|
|
231
|
+
.filter((v) => v.parent !== undefined)
|
|
232
|
+
.map((v) => [v.name, v.parent.name]);
|
|
233
|
+
return Object.fromEntries(entries);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=literalValueHierarchy.js.map
|