@fgv/ts-res 5.0.0-23 → 5.0.0-24
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/CHANGELOG.md +14 -0
- package/lib/packlets/runtime/index.d.ts +1 -0
- package/lib/packlets/runtime/index.js +1 -0
- package/lib/packlets/runtime/resourceTreeResolver.d.ts +152 -0
- package/lib/packlets/runtime/resourceTreeResolver.js +222 -0
- package/package.json +12 -12
- package/.vscode/4.json +0 -3
- package/.vscode/launch.json +0 -16
- package/.vscode/settings.json +0 -3
- package/dist/ts-res.d.ts +0 -10115
- package/dist/tsdoc-metadata.json +0 -11
- package/lib/test/data/sample.json +0 -32
- package/lib/test/unit/bundle/bundleBuilder.test.d.ts +0 -2
- package/lib/test/unit/bundle/bundleLoader.test.d.ts +0 -2
- package/lib/test/unit/bundle/bundleUtils.test.d.ts +0 -2
- package/lib/test/unit/bundle/convert.test.d.ts +0 -2
- package/lib/test/unit/bundle/integration.test.d.ts +0 -2
- package/lib/test/unit/bundle/model.test.d.ts +0 -2
- package/lib/test/unit/bundle/normalization.test.d.ts +0 -2
- package/lib/test/unit/common/conditions.test.d.ts +0 -2
- package/lib/test/unit/common/helpers/conditions.test.d.ts +0 -2
- package/lib/test/unit/common/helpers/contexts.test.d.ts +0 -2
- package/lib/test/unit/common/helpers/qualifierDefaultValues.test.d.ts +0 -2
- package/lib/test/unit/common/resources.test.d.ts +0 -2
- package/lib/test/unit/conditions/condition.test.d.ts +0 -2
- package/lib/test/unit/conditions/conditionCollector.test.d.ts +0 -2
- package/lib/test/unit/conditions/conditionScoreAsDefault.test.d.ts +0 -2
- package/lib/test/unit/conditions/conditionSet.test.d.ts +0 -2
- package/lib/test/unit/conditions/conditionSetCollector.test.d.ts +0 -2
- package/lib/test/unit/conditions/conditionToken.test.d.ts +0 -2
- package/lib/test/unit/conditions/convert.test.d.ts +0 -2
- package/lib/test/unit/config/common.test.d.ts +0 -2
- package/lib/test/unit/config/convert.test.d.ts +0 -2
- package/lib/test/unit/config/predefined/default.test.d.ts +0 -2
- package/lib/test/unit/config/predefined/extended.test.d.ts +0 -2
- package/lib/test/unit/config/systemConfiguration.test.d.ts +0 -2
- package/lib/test/unit/config/systemConfigurationInitParams.test.d.ts +0 -2
- package/lib/test/unit/context/contextToken.test.d.ts +0 -2
- package/lib/test/unit/context/convert.test.d.ts +0 -2
- package/lib/test/unit/decisions/abstractDecision.test.d.ts +0 -2
- package/lib/test/unit/decisions/abstractDecisionCollector.test.d.ts +0 -2
- package/lib/test/unit/decisions/candidate.test.d.ts +0 -2
- package/lib/test/unit/decisions/concreteDecision.test.d.ts +0 -2
- package/lib/test/unit/decisions/decision.test.d.ts +0 -2
- package/lib/test/unit/import/collectionImporter.test.d.ts +0 -2
- package/lib/test/unit/import/fsItem.test.d.ts +0 -2
- package/lib/test/unit/import/fsItemImporter.test.d.ts +0 -2
- package/lib/test/unit/import/importContext.test.d.ts +0 -2
- package/lib/test/unit/import/importManager.test.d.ts +0 -2
- package/lib/test/unit/import/jsonImporter.test.d.ts +0 -2
- package/lib/test/unit/import/pathImporter.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/convert.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/helpers.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/languageQualifierType.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/literalQualifierType.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/literalValueHierarchy.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/qualifierType.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/qualifierTypeCollector.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/territoryQualifierType.test.d.ts +0 -2
- package/lib/test/unit/qualifier-types/testQualifierType.d.ts +0 -19
- package/lib/test/unit/qualifier-types/testQualifierType.js +0 -113
- package/lib/test/unit/qualifiers/convert.test.d.ts +0 -2
- package/lib/test/unit/qualifiers/qualifierCollector.test.d.ts +0 -2
- package/lib/test/unit/qualifiers/qualifierDefaultValue.test.d.ts +0 -2
- package/lib/test/unit/qualifiers/qualifierDefaultValueToken.test.d.ts +0 -2
- package/lib/test/unit/resource-json/convert.test.d.ts +0 -2
- package/lib/test/unit/resource-json/nameInheritance.test.d.ts +0 -2
- package/lib/test/unit/resource-json/resourceDeclCollection.test.d.ts +0 -2
- package/lib/test/unit/resource-json/resourceDeclTree.test.d.ts +0 -2
- package/lib/test/unit/resource-types/derivedResourceType.test.d.ts +0 -2
- package/lib/test/unit/resource-types/jsonResourceType.test.d.ts +0 -2
- package/lib/test/unit/resource-types/resourceTypeCollector.test.d.ts +0 -2
- package/lib/test/unit/resource-types/testDerivedResourceType.d.ts +0 -79
- package/lib/test/unit/resource-types/testDerivedResourceType.js +0 -113
- package/lib/test/unit/resources/candidateReducer.integration.test.d.ts +0 -2
- package/lib/test/unit/resources/candidateReducer.test.d.ts +0 -2
- package/lib/test/unit/resources/candidateValue.test.d.ts +0 -2
- package/lib/test/unit/resources/candidateValueCollector.test.d.ts +0 -2
- package/lib/test/unit/resources/reduceCandidates.test.d.ts +0 -2
- package/lib/test/unit/resources/reduceQualifiers.comprehensive.test.d.ts +0 -2
- package/lib/test/unit/resources/reduceQualifiers.test.d.ts +0 -2
- package/lib/test/unit/resources/resource.test.d.ts +0 -2
- package/lib/test/unit/resources/resourceBuilder.test.d.ts +0 -2
- package/lib/test/unit/resources/resourceCandidate.test.d.ts +0 -2
- package/lib/test/unit/resources/resourceManagerBuilder.clone.test.d.ts +0 -2
- package/lib/test/unit/resources/resourceManagerBuilder.getBuiltResourceTree.test.d.ts +0 -2
- package/lib/test/unit/resources/resourceManagerBuilder.test.d.ts +0 -2
- package/lib/test/unit/runtime/cacheListener.test.d.ts +0 -2
- package/lib/test/unit/runtime/cacheMetrics.test.d.ts +0 -2
- package/lib/test/unit/runtime/compiledResourceCollection.test.d.ts +0 -2
- package/lib/test/unit/runtime/conditionSetResolutionResult.comprehensive.test.d.ts +0 -2
- package/lib/test/unit/runtime/conditionSetResolutionResult.test.d.ts +0 -2
- package/lib/test/unit/runtime/context/contextQualifierProvider.test.d.ts +0 -2
- package/lib/test/unit/runtime/context/contextQualifierProviderValidator.test.d.ts +0 -2
- package/lib/test/unit/runtime/context/simpleContextQualifierProvider.test.d.ts +0 -2
- package/lib/test/unit/runtime/context/validatingSimpleContextQualifierProvider.test.d.ts +0 -2
- package/lib/test/unit/runtime/resource-tree/readOnlyResourceTree.test.d.ts +0 -2
- package/lib/test/unit/runtime/resource-tree/resourceTreeChildren.test.d.ts +0 -2
- package/lib/test/unit/runtime/resource-tree/resourceTreeChildrenValidator.test.d.ts +0 -2
- package/lib/test/unit/runtime/resourceResolver.coverage.test.d.ts +0 -2
- package/lib/test/unit/runtime/resourceResolver.defaultResolution.test.d.ts +0 -2
- package/lib/test/unit/runtime/resourceResolver.newFeatures.test.d.ts +0 -2
- package/lib/test/unit/runtime/resourceResolver.test.d.ts +0 -2
- package/lib/test/unit/runtime/validate.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/convert.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/json.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/zipArchiveCreator.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/zipArchiveFormat.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/zipArchiveIdempotency.test.d.ts +0 -2
- package/lib/test/unit/zip-archive/zipArchiveLoader.test.d.ts +0 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Change Log - @fgv/ts-res
|
|
2
|
+
|
|
3
|
+
This log was last generated on Thu, 17 Jul 2025 00:13:24 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 5.0.0
|
|
6
|
+
Thu, 17 Jul 2025 00:13:24 GMT
|
|
7
|
+
|
|
8
|
+
### Updates
|
|
9
|
+
|
|
10
|
+
- add decl generators
|
|
11
|
+
- fix merge errors
|
|
12
|
+
- flesh out tests
|
|
13
|
+
- initial checkin
|
|
14
|
+
|
|
@@ -3,6 +3,7 @@ export * from './iResourceManager';
|
|
|
3
3
|
export * from './context/simpleContextQualifierProvider';
|
|
4
4
|
export * from './context/validatingSimpleContextQualifierProvider';
|
|
5
5
|
export * from './resourceResolver';
|
|
6
|
+
export * from './resourceTreeResolver';
|
|
6
7
|
export * from './conditionSetResolutionResult';
|
|
7
8
|
export * from './cacheListener';
|
|
8
9
|
export * from './cacheMetrics';
|
|
@@ -63,6 +63,7 @@ __exportStar(require("./iResourceManager"), exports);
|
|
|
63
63
|
__exportStar(require("./context/simpleContextQualifierProvider"), exports);
|
|
64
64
|
__exportStar(require("./context/validatingSimpleContextQualifierProvider"), exports);
|
|
65
65
|
__exportStar(require("./resourceResolver"), exports);
|
|
66
|
+
__exportStar(require("./resourceTreeResolver"), exports);
|
|
66
67
|
__exportStar(require("./conditionSetResolutionResult"), exports);
|
|
67
68
|
__exportStar(require("./cacheListener"), exports);
|
|
68
69
|
__exportStar(require("./cacheMetrics"), exports);
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Result } from '@fgv/ts-utils';
|
|
2
|
+
import { JsonValue, JsonObject } from '@fgv/ts-json-base';
|
|
3
|
+
import { IResource } from './iResourceManager';
|
|
4
|
+
import { IReadOnlyResourceTreeNode, IReadOnlyResourceTreeRoot } from './resource-tree/common';
|
|
5
|
+
import { ResourceResolver } from './resourceResolver';
|
|
6
|
+
/**
|
|
7
|
+
* Type for handling resource resolution errors during tree traversal.
|
|
8
|
+
* The handler receives the resource that failed to resolve, the error message, and the resolver for recovery attempts.
|
|
9
|
+
* It can return:
|
|
10
|
+
* - Success(undefined) to omit the property from the result
|
|
11
|
+
* - Success(value) to use an alternate value
|
|
12
|
+
* - Failure to propagate the error
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export type ResourceErrorHandler = (resource: IResource, message: string, resolver: ResourceResolver) => Result<JsonValue | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* Type for handling empty branch nodes during tree composition.
|
|
18
|
+
* The handler receives the branch node, names of failed children, and the resolver for recovery attempts.
|
|
19
|
+
* It can return:
|
|
20
|
+
* - Success(undefined) to omit the branch from the result
|
|
21
|
+
* - Success(value) to use an alternate value for the branch
|
|
22
|
+
* - Failure to propagate the error
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export type EmptyBranchHandler = (branchNode: IReadOnlyResourceTreeNode<IResource>, failedChildNames: string[], resolver: ResourceResolver) => Result<JsonValue | undefined>;
|
|
26
|
+
/**
|
|
27
|
+
* Options for configuring resource tree resolution.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export interface IResolveResourceTreeOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Controls how errors are handled when resolving individual resources in the tree.
|
|
33
|
+
* - 'fail': Aggregate all errors and fail if any resource fails to resolve
|
|
34
|
+
* - 'ignore': Skip failed resources and omit them from the result
|
|
35
|
+
* - callback: Custom error handler that can provide alternate values or propagate errors
|
|
36
|
+
* @defaultValue 'fail'
|
|
37
|
+
*/
|
|
38
|
+
onResourceError?: 'fail' | 'ignore' | ResourceErrorHandler;
|
|
39
|
+
/**
|
|
40
|
+
* Controls how empty branch nodes are handled during tree composition.
|
|
41
|
+
* - 'allow': Include empty branches as empty objects in the result
|
|
42
|
+
* - 'omit': Exclude empty branches from the parent object
|
|
43
|
+
* - callback: Custom handler that can provide alternate values or recovery logic
|
|
44
|
+
* @defaultValue 'allow'
|
|
45
|
+
*/
|
|
46
|
+
onEmptyBranch?: 'allow' | 'omit' | EmptyBranchHandler;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Specialized resolver for resource tree operations, providing enhanced APIs for
|
|
50
|
+
* resolving entire resource trees from either resource IDs or pre-built tree nodes.
|
|
51
|
+
*
|
|
52
|
+
* This class provides a clean separation between individual resource resolution
|
|
53
|
+
* (handled by ResourceResolver) and tree-based operations, with support for
|
|
54
|
+
* lazy tree construction and enhanced error handling.
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export declare class ResourceTreeResolver {
|
|
59
|
+
/**
|
|
60
|
+
* The {@link Runtime.ResourceResolver | ResourceResolver} to use for individual resource resolution
|
|
61
|
+
*/
|
|
62
|
+
readonly resolver: ResourceResolver;
|
|
63
|
+
/**
|
|
64
|
+
* The {@link Runtime.IResourceManager | IResourceManager} to use for lazy tree construction.
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
private readonly _resourceManager;
|
|
68
|
+
/**
|
|
69
|
+
* The built resource tree, lazily built on first access.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
private _tree?;
|
|
73
|
+
/**
|
|
74
|
+
* Creates a {@link Runtime.ResourceTreeResolver | ResourceTreeResolver} instance.
|
|
75
|
+
* @param resolver - The ResourceResolver to use for individual resource resolution
|
|
76
|
+
*/
|
|
77
|
+
constructor(resolver: ResourceResolver);
|
|
78
|
+
/**
|
|
79
|
+
* Creates a {@link Runtime.ResourceTreeResolver | ResourceTreeResolver} instance.
|
|
80
|
+
* @param resolver - The ResourceResolver to use for individual resource resolution
|
|
81
|
+
*/
|
|
82
|
+
static create(resolver: ResourceResolver): Result<ResourceTreeResolver>;
|
|
83
|
+
/**
|
|
84
|
+
* Gets the built resource tree, building it lazily on first access.
|
|
85
|
+
* @returns The resource tree root
|
|
86
|
+
* @throws Error if no resource manager was provided or tree building fails
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
get tree(): IReadOnlyResourceTreeRoot<IResource>;
|
|
90
|
+
/**
|
|
91
|
+
* Resolves a resource tree from a resource ID, building the tree lazily from the resource manager.
|
|
92
|
+
* @param resourceId - The ID of the root resource to resolve
|
|
93
|
+
* @param options - Optional configuration for error handling during resolution
|
|
94
|
+
* @returns Success with the composed JsonObject or undefined, or Failure with error message
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
resolveComposedResourceTree(resourceId: string, options?: IResolveResourceTreeOptions): Result<JsonObject | undefined>;
|
|
98
|
+
/**
|
|
99
|
+
* Resolves a pre-built resource tree node.
|
|
100
|
+
* @param node - The resource tree node to resolve
|
|
101
|
+
* @param options - Optional configuration for error handling during resolution
|
|
102
|
+
* @returns Success with the composed JsonObject or undefined, or Failure with error message
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
resolveComposedResourceTree(node: IReadOnlyResourceTreeNode<IResource>, options?: IResolveResourceTreeOptions): Result<JsonObject | undefined>;
|
|
106
|
+
private _getTree;
|
|
107
|
+
/**
|
|
108
|
+
* Resolves a tree from a resource ID by first building the tree from the resource manager.
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
private _resolveFromResourceId;
|
|
112
|
+
/**
|
|
113
|
+
* Resolves a pre-built tree node using the extracted tree resolution logic.
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
private _resolveFromTreeNode;
|
|
117
|
+
/**
|
|
118
|
+
* Handles resource resolution errors according to the specified mode.
|
|
119
|
+
* @param resource - The resource that failed to resolve
|
|
120
|
+
* @param message - The error message from the failed resolution
|
|
121
|
+
* @param mode - The error handling mode
|
|
122
|
+
* @param path - The path to the resource in the tree (for error context)
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
private _handleResourceError;
|
|
126
|
+
/**
|
|
127
|
+
* Handles empty branch nodes according to the specified mode.
|
|
128
|
+
* @param node - The empty branch node
|
|
129
|
+
* @param failedChildren - Names of children that failed to resolve
|
|
130
|
+
* @param mode - The empty branch handling mode
|
|
131
|
+
* @param path - The path to the branch in the tree (for error context)
|
|
132
|
+
* @internal
|
|
133
|
+
*/
|
|
134
|
+
private _handleEmptyBranch;
|
|
135
|
+
/**
|
|
136
|
+
* Processes a leaf node by resolving its resource value.
|
|
137
|
+
* @param node - The leaf node to process (must be a leaf node)
|
|
138
|
+
* @param path - The path to the node in the tree
|
|
139
|
+
* @param resourceErrorMode - How to handle resource resolution errors
|
|
140
|
+
* @internal
|
|
141
|
+
*/
|
|
142
|
+
private _processLeafNode;
|
|
143
|
+
/**
|
|
144
|
+
* Processes a branch node by recursively resolving all its children.
|
|
145
|
+
* @param node - The branch node to process (must be a branch node)
|
|
146
|
+
* @param path - The path to the node in the tree
|
|
147
|
+
* @param options - Resolution options
|
|
148
|
+
* @internal
|
|
149
|
+
*/
|
|
150
|
+
private _processBranchNode;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=resourceTreeResolver.d.ts.map
|
|
@@ -0,0 +1,222 @@
|
|
|
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.ResourceTreeResolver = void 0;
|
|
25
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
26
|
+
const ts_json_base_1 = require("@fgv/ts-json-base");
|
|
27
|
+
/**
|
|
28
|
+
* Specialized resolver for resource tree operations, providing enhanced APIs for
|
|
29
|
+
* resolving entire resource trees from either resource IDs or pre-built tree nodes.
|
|
30
|
+
*
|
|
31
|
+
* This class provides a clean separation between individual resource resolution
|
|
32
|
+
* (handled by ResourceResolver) and tree-based operations, with support for
|
|
33
|
+
* lazy tree construction and enhanced error handling.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
class ResourceTreeResolver {
|
|
38
|
+
/**
|
|
39
|
+
* Creates a {@link Runtime.ResourceTreeResolver | ResourceTreeResolver} instance.
|
|
40
|
+
* @param resolver - The ResourceResolver to use for individual resource resolution
|
|
41
|
+
*/
|
|
42
|
+
constructor(resolver) {
|
|
43
|
+
this.resolver = resolver;
|
|
44
|
+
this._resourceManager = resolver.resourceManager;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a {@link Runtime.ResourceTreeResolver | ResourceTreeResolver} instance.
|
|
48
|
+
* @param resolver - The ResourceResolver to use for individual resource resolution
|
|
49
|
+
*/
|
|
50
|
+
static create(resolver) {
|
|
51
|
+
return (0, ts_utils_1.captureResult)(() => new ResourceTreeResolver(resolver));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Gets the built resource tree, building it lazily on first access.
|
|
55
|
+
* @returns The resource tree root
|
|
56
|
+
* @throws Error if no resource manager was provided or tree building fails
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
get tree() {
|
|
60
|
+
return this._getTree().orThrow();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Implementation for both overloads.
|
|
64
|
+
*/
|
|
65
|
+
resolveComposedResourceTree(idOrNode, options) {
|
|
66
|
+
if (typeof idOrNode === 'string') {
|
|
67
|
+
return this._resolveFromResourceId(idOrNode, options);
|
|
68
|
+
}
|
|
69
|
+
return this._resolveFromTreeNode(idOrNode, options);
|
|
70
|
+
}
|
|
71
|
+
_getTree() {
|
|
72
|
+
if (!this._tree) {
|
|
73
|
+
this._tree = this._resourceManager.getBuiltResourceTree();
|
|
74
|
+
}
|
|
75
|
+
return this._tree;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolves a tree from a resource ID by first building the tree from the resource manager.
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
_resolveFromResourceId(resourceId, options) {
|
|
82
|
+
return this._getTree().onSuccess((tree) => {
|
|
83
|
+
return tree.children.validating
|
|
84
|
+
.getById(resourceId)
|
|
85
|
+
.onFailure((message) => (0, ts_utils_1.fail)(`${resourceId}: Resource not found in resource tree: ${message}`))
|
|
86
|
+
.onSuccess((rootNode) => this._resolveFromTreeNode(rootNode, options));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Resolves a pre-built tree node using the extracted tree resolution logic.
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
_resolveFromTreeNode(node, options) {
|
|
94
|
+
var _a, _b;
|
|
95
|
+
const resourceErrorMode = (_a = options === null || options === void 0 ? void 0 : options.onResourceError) !== null && _a !== void 0 ? _a : 'fail';
|
|
96
|
+
const emptyBranchMode = (_b = options === null || options === void 0 ? void 0 : options.onEmptyBranch) !== null && _b !== void 0 ? _b : 'allow';
|
|
97
|
+
// Handle root node with proper Result chaining
|
|
98
|
+
return node.isLeaf
|
|
99
|
+
? this._processLeafNode(node, '', resourceErrorMode).onSuccess((value) => value !== undefined ? ts_json_base_1.Converters.jsonObject.convert(value) : (0, ts_utils_1.succeed)(undefined))
|
|
100
|
+
: this._processBranchNode(node, '', {
|
|
101
|
+
onResourceError: resourceErrorMode,
|
|
102
|
+
onEmptyBranch: emptyBranchMode
|
|
103
|
+
}).onSuccess((value) => {
|
|
104
|
+
// Only convert undefined to {} if emptyBranchMode is 'allow'
|
|
105
|
+
// For 'omit' mode or custom handlers returning undefined, preserve undefined
|
|
106
|
+
return (0, ts_utils_1.succeed)(value === undefined && emptyBranchMode === 'allow' ? {} : value);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Handles resource resolution errors according to the specified mode.
|
|
111
|
+
* @param resource - The resource that failed to resolve
|
|
112
|
+
* @param message - The error message from the failed resolution
|
|
113
|
+
* @param mode - The error handling mode
|
|
114
|
+
* @param path - The path to the resource in the tree (for error context)
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
117
|
+
_handleResourceError(resource, message, mode, path) {
|
|
118
|
+
if (mode === 'ignore') {
|
|
119
|
+
return (0, ts_utils_1.succeed)(undefined);
|
|
120
|
+
}
|
|
121
|
+
if (mode === 'fail') {
|
|
122
|
+
const errorMessage = path ? `${path}: ${message}` : message;
|
|
123
|
+
return (0, ts_utils_1.fail)(errorMessage);
|
|
124
|
+
}
|
|
125
|
+
// Custom handler - pass the resolver for recovery attempts
|
|
126
|
+
return mode(resource, message, this.resolver);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Handles empty branch nodes according to the specified mode.
|
|
130
|
+
* @param node - The empty branch node
|
|
131
|
+
* @param failedChildren - Names of children that failed to resolve
|
|
132
|
+
* @param mode - The empty branch handling mode
|
|
133
|
+
* @param path - The path to the branch in the tree (for error context)
|
|
134
|
+
* @internal
|
|
135
|
+
*/
|
|
136
|
+
_handleEmptyBranch(node, failedChildren, mode, path) {
|
|
137
|
+
if (mode === 'omit') {
|
|
138
|
+
return (0, ts_utils_1.succeed)(undefined);
|
|
139
|
+
}
|
|
140
|
+
if (mode === 'allow') {
|
|
141
|
+
return (0, ts_utils_1.succeed)({});
|
|
142
|
+
}
|
|
143
|
+
// Custom handler - pass the resolver for recovery attempts
|
|
144
|
+
return mode(node, failedChildren, this.resolver);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Processes a leaf node by resolving its resource value.
|
|
148
|
+
* @param node - The leaf node to process (must be a leaf node)
|
|
149
|
+
* @param path - The path to the node in the tree
|
|
150
|
+
* @param resourceErrorMode - How to handle resource resolution errors
|
|
151
|
+
* @internal
|
|
152
|
+
*/
|
|
153
|
+
_processLeafNode(node, path, resourceErrorMode) {
|
|
154
|
+
/* c8 ignore next 3 - defense in depth */
|
|
155
|
+
if (!node.isLeaf) {
|
|
156
|
+
return (0, ts_utils_1.fail)(`Internal error: processLeafNode called on non-leaf node at ${path}`);
|
|
157
|
+
}
|
|
158
|
+
return this.resolver
|
|
159
|
+
.resolveComposedResourceValue(node.resource)
|
|
160
|
+
.onSuccess((value) => (0, ts_utils_1.succeed)(value))
|
|
161
|
+
.onFailure((message) => this._handleResourceError(node.resource, message, resourceErrorMode, path));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Processes a branch node by recursively resolving all its children.
|
|
165
|
+
* @param node - The branch node to process (must be a branch node)
|
|
166
|
+
* @param path - The path to the node in the tree
|
|
167
|
+
* @param options - Resolution options
|
|
168
|
+
* @internal
|
|
169
|
+
*/
|
|
170
|
+
_processBranchNode(node, path, options) {
|
|
171
|
+
var _a, _b;
|
|
172
|
+
/* c8 ignore next 3 - defense in depth */
|
|
173
|
+
if (node.isLeaf) {
|
|
174
|
+
return (0, ts_utils_1.fail)(`Internal error: processBranchNode called on leaf node at ${path}`);
|
|
175
|
+
}
|
|
176
|
+
const resourceErrorMode = (_a = options.onResourceError) !== null && _a !== void 0 ? _a : 'fail';
|
|
177
|
+
const emptyBranchMode = (_b = options.onEmptyBranch) !== null && _b !== void 0 ? _b : 'allow';
|
|
178
|
+
const aggregator = new ts_utils_1.MessageAggregator();
|
|
179
|
+
// Process all children
|
|
180
|
+
const childResults = {};
|
|
181
|
+
const failedChildren = [];
|
|
182
|
+
for (const [childName, childNode] of node.children) {
|
|
183
|
+
const childPath = path ? `${path}.${childName}` : childName;
|
|
184
|
+
const childResult = childNode.isLeaf
|
|
185
|
+
? this._processLeafNode(childNode, childPath, resourceErrorMode)
|
|
186
|
+
: this._processBranchNode(childNode, childPath, options);
|
|
187
|
+
// Process the child result and update our state
|
|
188
|
+
if (childResult.isSuccess()) {
|
|
189
|
+
const value = childResult.value;
|
|
190
|
+
if (value !== undefined) {
|
|
191
|
+
childResults[childName] = value;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
failedChildren.push(childName);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
if (resourceErrorMode === 'fail') {
|
|
199
|
+
aggregator.addMessage(childResult.message);
|
|
200
|
+
}
|
|
201
|
+
failedChildren.push(childName);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Check for accumulated errors in 'fail' mode
|
|
205
|
+
if (resourceErrorMode === 'fail' && aggregator.hasMessages) {
|
|
206
|
+
return (0, ts_utils_1.fail)(aggregator.toString('; '));
|
|
207
|
+
}
|
|
208
|
+
// Handle empty branch
|
|
209
|
+
if (Object.keys(childResults).length === 0) {
|
|
210
|
+
return this._handleEmptyBranch(node, failedChildren, emptyBranchMode, path).onSuccess((value) => {
|
|
211
|
+
if (value === undefined) {
|
|
212
|
+
return (0, ts_utils_1.succeed)(undefined);
|
|
213
|
+
}
|
|
214
|
+
// Ensure we return JsonObject or undefined
|
|
215
|
+
return ts_json_base_1.Converters.jsonObject.convert(value);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return (0, ts_utils_1.succeed)(childResults);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.ResourceTreeResolver = ResourceTreeResolver;
|
|
222
|
+
//# sourceMappingURL=resourceTreeResolver.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-res",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-24",
|
|
4
4
|
"description": "Multi-dimensional Resource Runtime",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "dist/ts-res.d.ts",
|
|
@@ -36,24 +36,24 @@
|
|
|
36
36
|
"rimraf": "^5.0.7",
|
|
37
37
|
"ts-jest": "^29.4.1",
|
|
38
38
|
"ts-node": "^10.9.2",
|
|
39
|
-
"typescript": "
|
|
39
|
+
"typescript": "5.8.3",
|
|
40
40
|
"eslint-plugin-n": "^16.6.2",
|
|
41
|
-
"@rushstack/eslint-config": "
|
|
42
|
-
"@rushstack/heft": "
|
|
43
|
-
"@rushstack/heft-jest-plugin": "
|
|
44
|
-
"@rushstack/heft-node-rig": "
|
|
41
|
+
"@rushstack/eslint-config": "4.4.0",
|
|
42
|
+
"@rushstack/heft": "0.74.3",
|
|
43
|
+
"@rushstack/heft-jest-plugin": "0.16.12",
|
|
44
|
+
"@rushstack/heft-node-rig": "2.9.4",
|
|
45
45
|
"@types/heft-jest": "1.0.6",
|
|
46
46
|
"eslint-plugin-tsdoc": "~0.4.0",
|
|
47
|
-
"@fgv/ts-utils-jest": "5.0.0-
|
|
48
|
-
"@fgv/ts-extras": "5.0.0-
|
|
47
|
+
"@fgv/ts-utils-jest": "5.0.0-24",
|
|
48
|
+
"@fgv/ts-extras": "5.0.0-24"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"luxon": "^3.7.1",
|
|
52
52
|
"fflate": "~0.8.2",
|
|
53
|
-
"@fgv/ts-utils": "5.0.0-
|
|
54
|
-
"@fgv/ts-json-base": "5.0.0-
|
|
55
|
-
"@fgv/ts-json": "5.0.0-
|
|
56
|
-
"@fgv/ts-bcp47": "5.0.0-
|
|
53
|
+
"@fgv/ts-utils": "5.0.0-24",
|
|
54
|
+
"@fgv/ts-json-base": "5.0.0-24",
|
|
55
|
+
"@fgv/ts-json": "5.0.0-24",
|
|
56
|
+
"@fgv/ts-bcp47": "5.0.0-24"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"build": "heft build --clean",
|
package/.vscode/4.json
DELETED
package/.vscode/launch.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
{
|
|
8
|
-
"type": "node",
|
|
9
|
-
"request": "launch",
|
|
10
|
-
"name": "Launch Program",
|
|
11
|
-
"skipFiles": ["<node_internals>/**"],
|
|
12
|
-
"program": "${workspaceFolder}/lib/index.js",
|
|
13
|
-
"outFiles": ["${workspaceFolder}/**/*.js"]
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
}
|
package/.vscode/settings.json
DELETED