@fgv/ts-res-ui-components 5.0.0-10
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/.rush/temp/03c8b056281d9db0a97d8a6e25eea798a160d393.tar.log +271 -0
- package/.rush/temp/chunked-rush-logs/ts-res-ui-components.build.chunks.jsonl +9 -0
- package/.rush/temp/operation/build/all.log +9 -0
- package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +1111 -0
- package/README.md +18 -0
- package/REFACTORING_PLAN.md +171 -0
- package/config/jest.config.json +16 -0
- package/config/jest.setup.js +64 -0
- package/config/rig.json +16 -0
- package/lib/components/common/QualifierContextControl.d.ts +14 -0
- package/lib/components/common/QualifierContextControl.d.ts.map +1 -0
- package/lib/components/common/QualifierContextControl.js +78 -0
- package/lib/components/common/QualifierContextControl.js.map +1 -0
- package/lib/components/common/ResourceListView.d.ts +11 -0
- package/lib/components/common/ResourceListView.d.ts.map +1 -0
- package/lib/components/common/ResourceListView.js +20 -0
- package/lib/components/common/ResourceListView.js.map +1 -0
- package/lib/components/common/ResourceTreeView.d.ts +12 -0
- package/lib/components/common/ResourceTreeView.d.ts.map +1 -0
- package/lib/components/common/ResourceTreeView.js +162 -0
- package/lib/components/common/ResourceTreeView.js.map +1 -0
- package/lib/components/forms/HierarchyEditor.d.ts +10 -0
- package/lib/components/forms/HierarchyEditor.d.ts.map +1 -0
- package/lib/components/forms/HierarchyEditor.js +106 -0
- package/lib/components/forms/HierarchyEditor.js.map +1 -0
- package/lib/components/forms/QualifierEditForm.d.ts +11 -0
- package/lib/components/forms/QualifierEditForm.d.ts.map +1 -0
- package/lib/components/forms/QualifierEditForm.js +181 -0
- package/lib/components/forms/QualifierEditForm.js.map +1 -0
- package/lib/components/forms/QualifierTypeEditForm.d.ts +10 -0
- package/lib/components/forms/QualifierTypeEditForm.d.ts.map +1 -0
- package/lib/components/forms/QualifierTypeEditForm.js +172 -0
- package/lib/components/forms/QualifierTypeEditForm.js.map +1 -0
- package/lib/components/forms/ResourceTypeEditForm.d.ts +10 -0
- package/lib/components/forms/ResourceTypeEditForm.d.ts.map +1 -0
- package/lib/components/forms/ResourceTypeEditForm.js +188 -0
- package/lib/components/forms/ResourceTypeEditForm.js.map +1 -0
- package/lib/components/forms/index.d.ts +9 -0
- package/lib/components/forms/index.d.ts.map +1 -0
- package/lib/components/forms/index.js +5 -0
- package/lib/components/forms/index.js.map +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts +14 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts.map +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js +278 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js.map +1 -0
- package/lib/components/views/CompiledView/index.d.ts +5 -0
- package/lib/components/views/CompiledView/index.d.ts.map +1 -0
- package/lib/components/views/CompiledView/index.js +595 -0
- package/lib/components/views/CompiledView/index.js.map +1 -0
- package/lib/components/views/ConfigurationView/index.d.ts +5 -0
- package/lib/components/views/ConfigurationView/index.d.ts.map +1 -0
- package/lib/components/views/ConfigurationView/index.js +363 -0
- package/lib/components/views/ConfigurationView/index.js.map +1 -0
- package/lib/components/views/FilterView/index.d.ts +5 -0
- package/lib/components/views/FilterView/index.d.ts.map +1 -0
- package/lib/components/views/FilterView/index.js +463 -0
- package/lib/components/views/FilterView/index.js.map +1 -0
- package/lib/components/views/ImportView/index.d.ts +5 -0
- package/lib/components/views/ImportView/index.d.ts.map +1 -0
- package/lib/components/views/ImportView/index.js +514 -0
- package/lib/components/views/ImportView/index.js.map +1 -0
- package/lib/components/views/ResolutionView/EditableJsonView.d.ts +21 -0
- package/lib/components/views/ResolutionView/EditableJsonView.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/EditableJsonView.js +109 -0
- package/lib/components/views/ResolutionView/EditableJsonView.js.map +1 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts +19 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.js +82 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.js.map +1 -0
- package/lib/components/views/ResolutionView/index.d.ts +5 -0
- package/lib/components/views/ResolutionView/index.d.ts.map +1 -0
- package/lib/components/views/ResolutionView/index.js +255 -0
- package/lib/components/views/ResolutionView/index.js.map +1 -0
- package/lib/components/views/SourceView/index.d.ts +5 -0
- package/lib/components/views/SourceView/index.d.ts.map +1 -0
- package/lib/components/views/SourceView/index.js +316 -0
- package/lib/components/views/SourceView/index.js.map +1 -0
- package/lib/components/views/ZipLoaderView/index.d.ts +5 -0
- package/lib/components/views/ZipLoaderView/index.d.ts.map +1 -0
- package/lib/components/views/ZipLoaderView/index.js +313 -0
- package/lib/components/views/ZipLoaderView/index.js.map +1 -0
- package/lib/hooks/useConfigurationState.d.ts +46 -0
- package/lib/hooks/useConfigurationState.d.ts.map +1 -0
- package/lib/hooks/useConfigurationState.js +239 -0
- package/lib/hooks/useConfigurationState.js.map +1 -0
- package/lib/hooks/useFilterState.d.ts +7 -0
- package/lib/hooks/useFilterState.d.ts.map +1 -0
- package/lib/hooks/useFilterState.js +80 -0
- package/lib/hooks/useFilterState.js.map +1 -0
- package/lib/hooks/useResolutionState.d.ts +8 -0
- package/lib/hooks/useResolutionState.d.ts.map +1 -0
- package/lib/hooks/useResolutionState.js +253 -0
- package/lib/hooks/useResolutionState.js.map +1 -0
- package/lib/hooks/useResourceData.d.ts +19 -0
- package/lib/hooks/useResourceData.d.ts.map +1 -0
- package/lib/hooks/useResourceData.js +368 -0
- package/lib/hooks/useResourceData.js.map +1 -0
- package/lib/hooks/useViewState.d.ts +10 -0
- package/lib/hooks/useViewState.d.ts.map +1 -0
- package/lib/hooks/useViewState.js +29 -0
- package/lib/hooks/useViewState.js.map +1 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +34 -0
- package/lib/index.js.map +1 -0
- package/lib/test/helpers/testDataLoader.d.ts +37 -0
- package/lib/test/helpers/testDataLoader.d.ts.map +1 -0
- package/lib/test/helpers/testDataLoader.js +171 -0
- package/lib/test/helpers/testDataLoader.js.map +1 -0
- package/lib/test/unit/utils/configurationUtils.test.d.ts +2 -0
- package/lib/test/unit/utils/configurationUtils.test.d.ts.map +1 -0
- package/lib/test/unit/utils/configurationUtils.test.js +497 -0
- package/lib/test/unit/utils/configurationUtils.test.js.map +1 -0
- package/lib/test/unit/utils/fileProcessing.test.d.ts +2 -0
- package/lib/test/unit/utils/fileProcessing.test.d.ts.map +1 -0
- package/lib/test/unit/utils/fileProcessing.test.js +321 -0
- package/lib/test/unit/utils/fileProcessing.test.js.map +1 -0
- package/lib/test/unit/utils/filterResources.test.d.ts +2 -0
- package/lib/test/unit/utils/filterResources.test.d.ts.map +1 -0
- package/lib/test/unit/utils/filterResources.test.js +403 -0
- package/lib/test/unit/utils/filterResources.test.js.map +1 -0
- package/lib/test/unit/utils/resolutionEditing.test.d.ts +2 -0
- package/lib/test/unit/utils/resolutionEditing.test.d.ts.map +1 -0
- package/lib/test/unit/utils/resolutionEditing.test.js +439 -0
- package/lib/test/unit/utils/resolutionEditing.test.js.map +1 -0
- package/lib/test/unit/utils/resolutionUtils.test.d.ts +2 -0
- package/lib/test/unit/utils/resolutionUtils.test.d.ts.map +1 -0
- package/lib/test/unit/utils/resolutionUtils.test.js +397 -0
- package/lib/test/unit/utils/resolutionUtils.test.js.map +1 -0
- package/lib/test/unit/utils/tsResIntegration.test.d.ts +2 -0
- package/lib/test/unit/utils/tsResIntegration.test.d.ts.map +1 -0
- package/lib/test/unit/utils/tsResIntegration.test.js +376 -0
- package/lib/test/unit/utils/tsResIntegration.test.js.map +1 -0
- package/lib/types/index.d.ts +251 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -0
- package/lib/utils/configurationUtils.d.ts +74 -0
- package/lib/utils/configurationUtils.d.ts.map +1 -0
- package/lib/utils/configurationUtils.js +359 -0
- package/lib/utils/configurationUtils.js.map +1 -0
- package/lib/utils/fileProcessing.d.ts +18 -0
- package/lib/utils/fileProcessing.d.ts.map +1 -0
- package/lib/utils/fileProcessing.js +142 -0
- package/lib/utils/fileProcessing.js.map +1 -0
- package/lib/utils/filterResources.d.ts +38 -0
- package/lib/utils/filterResources.d.ts.map +1 -0
- package/lib/utils/filterResources.js +153 -0
- package/lib/utils/filterResources.js.map +1 -0
- package/lib/utils/resolutionEditing.d.ts +58 -0
- package/lib/utils/resolutionEditing.d.ts.map +1 -0
- package/lib/utils/resolutionEditing.js +246 -0
- package/lib/utils/resolutionEditing.js.map +1 -0
- package/lib/utils/resolutionUtils.d.ts +28 -0
- package/lib/utils/resolutionUtils.d.ts.map +1 -0
- package/lib/utils/resolutionUtils.js +216 -0
- package/lib/utils/resolutionUtils.js.map +1 -0
- package/lib/utils/tsResIntegration.d.ts +71 -0
- package/lib/utils/tsResIntegration.d.ts.map +1 -0
- package/lib/utils/tsResIntegration.js +294 -0
- package/lib/utils/tsResIntegration.js.map +1 -0
- package/lib/utils/zipLoader/browserZipLoader.d.ts +48 -0
- package/lib/utils/zipLoader/browserZipLoader.d.ts.map +1 -0
- package/lib/utils/zipLoader/browserZipLoader.js +247 -0
- package/lib/utils/zipLoader/browserZipLoader.js.map +1 -0
- package/lib/utils/zipLoader/index.d.ts +8 -0
- package/lib/utils/zipLoader/index.d.ts.map +1 -0
- package/lib/utils/zipLoader/index.js +13 -0
- package/lib/utils/zipLoader/index.js.map +1 -0
- package/lib/utils/zipLoader/nodeZipBuilder.d.ts +55 -0
- package/lib/utils/zipLoader/nodeZipBuilder.d.ts.map +1 -0
- package/lib/utils/zipLoader/nodeZipBuilder.js +98 -0
- package/lib/utils/zipLoader/nodeZipBuilder.js.map +1 -0
- package/lib/utils/zipLoader/types.d.ts +139 -0
- package/lib/utils/zipLoader/types.d.ts.map +1 -0
- package/lib/utils/zipLoader/types.js +2 -0
- package/lib/utils/zipLoader/types.js.map +1 -0
- package/lib/utils/zipLoader/zipUtils.d.ts +53 -0
- package/lib/utils/zipLoader/zipUtils.d.ts.map +1 -0
- package/lib/utils/zipLoader/zipUtils.js +229 -0
- package/lib/utils/zipLoader/zipUtils.js.map +1 -0
- package/package.json +69 -0
- package/rush-logs/ts-res-ui-components.build.cache.log +3 -0
- package/rush-logs/ts-res-ui-components.build.log +9 -0
- package/src/components/common/QualifierContextControl.tsx +151 -0
- package/src/components/common/ResourceListView.tsx +63 -0
- package/src/components/common/ResourceTreeView.tsx +271 -0
- package/src/components/forms/HierarchyEditor.tsx +204 -0
- package/src/components/forms/QualifierEditForm.tsx +355 -0
- package/src/components/forms/QualifierTypeEditForm.tsx +347 -0
- package/src/components/forms/ResourceTypeEditForm.tsx +331 -0
- package/src/components/forms/index.ts +11 -0
- package/src/components/orchestrator/ResourceOrchestrator.tsx +372 -0
- package/src/components/views/CompiledView/index.tsx +922 -0
- package/src/components/views/ConfigurationView/index.tsx +800 -0
- package/src/components/views/FilterView/index.tsx +825 -0
- package/src/components/views/ImportView/index.tsx +717 -0
- package/src/components/views/ResolutionView/EditableJsonView.tsx +214 -0
- package/src/components/views/ResolutionView/ResolutionEditControls.tsx +170 -0
- package/src/components/views/ResolutionView/index.tsx +591 -0
- package/src/components/views/SourceView/index.tsx +536 -0
- package/src/components/views/ZipLoaderView/index.tsx +485 -0
- package/src/hooks/useConfigurationState.ts +374 -0
- package/src/hooks/useFilterState.ts +97 -0
- package/src/hooks/useResolutionState.ts +355 -0
- package/src/hooks/useResourceData.ts +467 -0
- package/src/hooks/useViewState.ts +44 -0
- package/src/index.ts +45 -0
- package/src/test/helpers/testDataLoader.ts +195 -0
- package/src/test/unit/utils/configurationUtils.test.ts +630 -0
- package/src/test/unit/utils/fileProcessing.test.ts +391 -0
- package/src/test/unit/utils/filterResources.test.ts +574 -0
- package/src/test/unit/utils/resolutionEditing.test.ts +556 -0
- package/src/test/unit/utils/resolutionUtils.test.ts +521 -0
- package/src/test/unit/utils/tsResIntegration.test.ts +433 -0
- package/src/types/index.ts +322 -0
- package/src/utils/configurationUtils.ts +424 -0
- package/src/utils/fileProcessing.ts +160 -0
- package/src/utils/filterResources.ts +206 -0
- package/src/utils/resolutionEditing.ts +319 -0
- package/src/utils/resolutionUtils.ts +289 -0
- package/src/utils/tsResIntegration.ts +440 -0
- package/src/utils/zipLoader/browserZipLoader.ts +319 -0
- package/src/utils/zipLoader/index.ts +26 -0
- package/src/utils/zipLoader/nodeZipBuilder.ts +153 -0
- package/src/utils/zipLoader/types.ts +175 -0
- package/src/utils/zipLoader/zipUtils.ts +266 -0
- package/temp/build/typescript/ts_gZid87Hu.json +1 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { succeed, fail, MessageAggregator } from '@fgv/ts-utils';
|
|
2
|
+
import { Runtime } from '@fgv/ts-res';
|
|
3
|
+
// Helper function for conditional debug logging
|
|
4
|
+
const debugLog = (enableDebug, ...args) => {
|
|
5
|
+
if (enableDebug) {
|
|
6
|
+
console.log(...args);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Create a resolver with context for resource resolution
|
|
11
|
+
*/
|
|
12
|
+
export function createResolverWithContext(processedResources, contextValues, options = {}) {
|
|
13
|
+
const enableDebug = options.enableDebugLogging === true;
|
|
14
|
+
debugLog(enableDebug, '=== CREATING RESOLVER WITH CONTEXT ===');
|
|
15
|
+
debugLog(enableDebug, 'Context values:', contextValues);
|
|
16
|
+
// Create context provider with filtered values (remove undefined)
|
|
17
|
+
const filteredContext = Object.fromEntries(Object.entries(contextValues).filter(([, value]) => value !== undefined));
|
|
18
|
+
return Runtime.ValidatingSimpleContextQualifierProvider.create({
|
|
19
|
+
qualifiers: processedResources.system.qualifiers
|
|
20
|
+
})
|
|
21
|
+
.withErrorFormat((e) => `Failed to create context provider: ${e}`)
|
|
22
|
+
.onSuccess((contextProvider) => {
|
|
23
|
+
const errors = new MessageAggregator();
|
|
24
|
+
// Set context values
|
|
25
|
+
for (const [qualifierName, value] of Object.entries(filteredContext)) {
|
|
26
|
+
contextProvider.validating
|
|
27
|
+
.set(qualifierName, value)
|
|
28
|
+
.withErrorFormat((e) => `Failed to set context value ${qualifierName}=${value}: ${e}`)
|
|
29
|
+
.aggregateError(errors);
|
|
30
|
+
}
|
|
31
|
+
if (errors.hasMessages) {
|
|
32
|
+
return fail(`Errors setting context values: ${errors.toString()}`);
|
|
33
|
+
}
|
|
34
|
+
// Create resolver
|
|
35
|
+
const resolverParams = {
|
|
36
|
+
resourceManager: processedResources.system.resourceManager,
|
|
37
|
+
qualifierTypes: processedResources.system.qualifierTypes,
|
|
38
|
+
contextQualifierProvider: contextProvider
|
|
39
|
+
};
|
|
40
|
+
// Add cache metrics listener if caching is enabled
|
|
41
|
+
if (options.enableCaching) {
|
|
42
|
+
const metricsListener = new Runtime.ResourceResolverCacheMetricsListener(() => new Runtime.AggregateCacheMetrics());
|
|
43
|
+
resolverParams.listener = metricsListener;
|
|
44
|
+
}
|
|
45
|
+
return Runtime.ResourceResolver.create(resolverParams)
|
|
46
|
+
.withErrorFormat((e) => `Failed to create resolver: ${e}`)
|
|
47
|
+
.onSuccess((resolver) => {
|
|
48
|
+
debugLog(enableDebug, 'Resolver created successfully');
|
|
49
|
+
return succeed(resolver);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Evaluate conditions for a specific candidate
|
|
55
|
+
*/
|
|
56
|
+
export function evaluateConditionsForCandidate(resolver, candidateIndex, compiledResource, compiledCollection) {
|
|
57
|
+
try {
|
|
58
|
+
const decision = compiledCollection.decisions[compiledResource.decision];
|
|
59
|
+
if (!decision || !decision.conditionSets || candidateIndex >= decision.conditionSets.length) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
const conditionSetIndex = decision.conditionSets[candidateIndex];
|
|
63
|
+
const conditionSet = compiledCollection.conditionSets[conditionSetIndex];
|
|
64
|
+
if (!conditionSet || !conditionSet.conditions) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const evaluations = [];
|
|
68
|
+
for (const conditionIndex of conditionSet.conditions) {
|
|
69
|
+
const condition = compiledCollection.conditions[conditionIndex];
|
|
70
|
+
if (!condition)
|
|
71
|
+
continue;
|
|
72
|
+
const qualifier = compiledCollection.qualifiers[condition.qualifierIndex];
|
|
73
|
+
if (!qualifier)
|
|
74
|
+
continue;
|
|
75
|
+
// Get the qualifier value from context
|
|
76
|
+
const qualifierValueResult = resolver.contextQualifierProvider.get(qualifier);
|
|
77
|
+
const qualifierValue = qualifierValueResult.orDefault();
|
|
78
|
+
// Get the cached condition result from resolver (if available)
|
|
79
|
+
const cachedResult = resolver.conditionCache?.[conditionIndex];
|
|
80
|
+
const score = cachedResult?.score || 0;
|
|
81
|
+
const matchType = cachedResult?.matchType || 'noMatch';
|
|
82
|
+
const matched = matchType !== 'noMatch';
|
|
83
|
+
evaluations.push({
|
|
84
|
+
qualifierName: qualifier.name,
|
|
85
|
+
qualifierValue,
|
|
86
|
+
conditionValue: condition.value,
|
|
87
|
+
operator: condition.operator || 'matches',
|
|
88
|
+
score,
|
|
89
|
+
matched,
|
|
90
|
+
matchType,
|
|
91
|
+
scoreAsDefault: condition.scoreAsDefault,
|
|
92
|
+
conditionIndex
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return evaluations;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.warn('Error evaluating conditions for candidate:', error);
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve a resource and create detailed resolution result
|
|
104
|
+
*/
|
|
105
|
+
export function resolveResourceDetailed(resolver, resourceId, processedResources, options = {}) {
|
|
106
|
+
const enableDebug = options.enableDebugLogging === true;
|
|
107
|
+
debugLog(enableDebug, '=== RESOLVING RESOURCE ===');
|
|
108
|
+
debugLog(enableDebug, 'Resource ID:', resourceId);
|
|
109
|
+
const resourceResult = processedResources.system.resourceManager.getBuiltResource(resourceId);
|
|
110
|
+
if (resourceResult.isFailure()) {
|
|
111
|
+
return succeed({
|
|
112
|
+
success: false,
|
|
113
|
+
resourceId,
|
|
114
|
+
error: `Failed to get resource: ${resourceResult.message}`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const resource = resourceResult.value;
|
|
118
|
+
const compiledCollection = processedResources.compiledCollection;
|
|
119
|
+
// Find the compiled resource for condition analysis
|
|
120
|
+
const compiledResource = compiledCollection.resources.find((r) => r.id === resourceId);
|
|
121
|
+
if (!compiledResource) {
|
|
122
|
+
return succeed({
|
|
123
|
+
success: false,
|
|
124
|
+
resourceId,
|
|
125
|
+
error: 'Failed to find compiled resource'
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// Resolve best candidate
|
|
129
|
+
const bestResult = resolver.resolveResource(resource);
|
|
130
|
+
// Resolve all candidates
|
|
131
|
+
const allResult = resolver.resolveAllResourceCandidates(resource);
|
|
132
|
+
// Resolve composed value
|
|
133
|
+
const composedResult = resolver.resolveComposedResourceValue(resource);
|
|
134
|
+
// Get decision resolution result
|
|
135
|
+
const decisionResult = resolver.resolveDecision(resource.decision.baseDecision);
|
|
136
|
+
if (decisionResult.isFailure()) {
|
|
137
|
+
return succeed({
|
|
138
|
+
success: false,
|
|
139
|
+
resourceId,
|
|
140
|
+
error: `Failed to resolve decision: ${decisionResult.message}`
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const decision = decisionResult.value;
|
|
144
|
+
// Build detailed candidate information
|
|
145
|
+
const candidateDetails = [];
|
|
146
|
+
const matchedCandidates = allResult.isSuccess() ? allResult.value : [];
|
|
147
|
+
// Create lookup sets for regular and default matches
|
|
148
|
+
const regularMatchIndices = new Set(decision?.success ? decision.instanceIndices : []);
|
|
149
|
+
const defaultMatchIndices = new Set(decision?.success ? decision.defaultInstanceIndices : []);
|
|
150
|
+
// Add matched candidates first
|
|
151
|
+
matchedCandidates.forEach((matchedCandidate) => {
|
|
152
|
+
const index = resource.candidates.findIndex((candidate) => candidate === matchedCandidate);
|
|
153
|
+
if (index !== -1) {
|
|
154
|
+
const conditionSetKey = `cs-${index}`;
|
|
155
|
+
const conditionEvaluations = evaluateConditionsForCandidate(resolver, index, compiledResource, compiledCollection);
|
|
156
|
+
const isDefaultMatch = defaultMatchIndices.has(index);
|
|
157
|
+
const isRegularMatch = regularMatchIndices.has(index);
|
|
158
|
+
const candidateMatchType = isRegularMatch ? 'match' : isDefaultMatch ? 'matchAsDefault' : 'noMatch';
|
|
159
|
+
candidateDetails.push({
|
|
160
|
+
candidate: resource.candidates[index],
|
|
161
|
+
conditionSetKey,
|
|
162
|
+
candidateIndex: index,
|
|
163
|
+
matched: true,
|
|
164
|
+
matchType: candidateMatchType,
|
|
165
|
+
isDefaultMatch,
|
|
166
|
+
conditionEvaluations
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
// Add non-matching candidates
|
|
171
|
+
resource.candidates.forEach((candidate, index) => {
|
|
172
|
+
const isMatched = matchedCandidates.some((mc) => mc === candidate);
|
|
173
|
+
if (!isMatched) {
|
|
174
|
+
// Handle different candidate formats - IResourceCandidate doesn't have conditions
|
|
175
|
+
const conditionSetKey = candidate.conditions?.toHash ? candidate.conditions.toHash() : `cs-${index}`;
|
|
176
|
+
const conditionEvaluations = evaluateConditionsForCandidate(resolver, index, compiledResource, compiledCollection);
|
|
177
|
+
candidateDetails.push({
|
|
178
|
+
candidate,
|
|
179
|
+
conditionSetKey,
|
|
180
|
+
candidateIndex: index,
|
|
181
|
+
matched: false,
|
|
182
|
+
matchType: 'noMatch',
|
|
183
|
+
isDefaultMatch: false,
|
|
184
|
+
conditionEvaluations
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
const result = {
|
|
189
|
+
success: true,
|
|
190
|
+
resourceId,
|
|
191
|
+
resource,
|
|
192
|
+
bestCandidate: bestResult.isSuccess() ? bestResult.value : undefined,
|
|
193
|
+
allCandidates: allResult.isSuccess() ? allResult.value : undefined,
|
|
194
|
+
candidateDetails,
|
|
195
|
+
composedValue: composedResult.isSuccess() ? composedResult.value : undefined,
|
|
196
|
+
error: bestResult.isFailure() ? bestResult.message : undefined
|
|
197
|
+
};
|
|
198
|
+
debugLog(enableDebug, 'Resolution completed successfully');
|
|
199
|
+
return succeed(result);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get available qualifiers from processed resources
|
|
203
|
+
*/
|
|
204
|
+
export function getAvailableQualifiers(processedResources) {
|
|
205
|
+
if (processedResources.compiledCollection.qualifiers) {
|
|
206
|
+
return processedResources.compiledCollection.qualifiers.map((q) => q.name);
|
|
207
|
+
}
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if context has any pending changes
|
|
212
|
+
*/
|
|
213
|
+
export function hasPendingContextChanges(contextValues, pendingContextValues) {
|
|
214
|
+
return JSON.stringify(contextValues) !== JSON.stringify(pendingContextValues);
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=resolutionUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolutionUtils.js","sourceRoot":"","sources":["../../src/utils/resolutionUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import { Result, succeed, fail, MessageAggregator } from '@fgv/ts-utils';\nimport { Runtime } from '@fgv/ts-res';\nimport { ProcessedResources, ResolutionResult, CandidateInfo, ConditionEvaluationResult } from '../types';\n\nexport interface ResolutionOptions {\n enableCaching?: boolean;\n enableDebugLogging?: boolean;\n}\n\n// Helper function for conditional debug logging\nconst debugLog = (enableDebug: boolean, ...args: any[]) => {\n if (enableDebug) {\n console.log(...args);\n }\n};\n\n/**\n * Create a resolver with context for resource resolution\n */\nexport function createResolverWithContext(\n processedResources: ProcessedResources,\n contextValues: Record<string, string | undefined>,\n options: ResolutionOptions = {}\n): Result<Runtime.ResourceResolver> {\n const enableDebug = options.enableDebugLogging === true;\n\n debugLog(enableDebug, '=== CREATING RESOLVER WITH CONTEXT ===');\n debugLog(enableDebug, 'Context values:', contextValues);\n\n // Create context provider with filtered values (remove undefined)\n const filteredContext = Object.fromEntries(\n Object.entries(contextValues).filter(([, value]) => value !== undefined)\n ) as Record<string, string>;\n\n return Runtime.ValidatingSimpleContextQualifierProvider.create({\n qualifiers: processedResources.system.qualifiers\n })\n .withErrorFormat((e) => `Failed to create context provider: ${e}`)\n .onSuccess((contextProvider) => {\n const errors = new MessageAggregator();\n // Set context values\n for (const [qualifierName, value] of Object.entries(filteredContext)) {\n contextProvider.validating\n .set(qualifierName, value)\n .withErrorFormat((e) => `Failed to set context value ${qualifierName}=${value}: ${e}`)\n .aggregateError(errors);\n }\n\n if (errors.hasMessages) {\n return fail(`Errors setting context values: ${errors.toString()}`);\n }\n\n // Create resolver\n const resolverParams: any = {\n resourceManager: processedResources.system.resourceManager,\n qualifierTypes: processedResources.system.qualifierTypes,\n contextQualifierProvider: contextProvider\n };\n\n // Add cache metrics listener if caching is enabled\n if (options.enableCaching) {\n const metricsListener = new Runtime.ResourceResolverCacheMetricsListener(\n () => new Runtime.AggregateCacheMetrics()\n );\n resolverParams.listener = metricsListener;\n }\n\n return Runtime.ResourceResolver.create(resolverParams)\n .withErrorFormat((e) => `Failed to create resolver: ${e}`)\n .onSuccess((resolver) => {\n debugLog(enableDebug, 'Resolver created successfully');\n return succeed(resolver);\n });\n });\n}\n\n/**\n * Evaluate conditions for a specific candidate\n */\nexport function evaluateConditionsForCandidate(\n resolver: Runtime.ResourceResolver,\n candidateIndex: number,\n compiledResource: any,\n compiledCollection: any\n): ConditionEvaluationResult[] {\n try {\n const decision = compiledCollection.decisions[compiledResource.decision];\n if (!decision || !decision.conditionSets || candidateIndex >= decision.conditionSets.length) {\n return [];\n }\n\n const conditionSetIndex = decision.conditionSets[candidateIndex];\n const conditionSet = compiledCollection.conditionSets[conditionSetIndex];\n if (!conditionSet || !conditionSet.conditions) {\n return [];\n }\n\n const evaluations: ConditionEvaluationResult[] = [];\n\n for (const conditionIndex of conditionSet.conditions) {\n const condition = compiledCollection.conditions[conditionIndex];\n if (!condition) continue;\n\n const qualifier = compiledCollection.qualifiers[condition.qualifierIndex];\n if (!qualifier) continue;\n\n // Get the qualifier value from context\n const qualifierValueResult = resolver.contextQualifierProvider.get(qualifier);\n const qualifierValue = qualifierValueResult.orDefault();\n\n // Get the cached condition result from resolver (if available)\n const cachedResult = resolver.conditionCache?.[conditionIndex];\n const score = cachedResult?.score || 0;\n const matchType = cachedResult?.matchType || 'noMatch';\n const matched = matchType !== 'noMatch';\n\n evaluations.push({\n qualifierName: qualifier.name,\n qualifierValue,\n conditionValue: condition.value,\n operator: condition.operator || 'matches',\n score,\n matched,\n matchType,\n scoreAsDefault: condition.scoreAsDefault,\n conditionIndex\n });\n }\n\n return evaluations;\n } catch (error) {\n console.warn('Error evaluating conditions for candidate:', error);\n return [];\n }\n}\n\n/**\n * Resolve a resource and create detailed resolution result\n */\nexport function resolveResourceDetailed(\n resolver: Runtime.ResourceResolver,\n resourceId: string,\n processedResources: ProcessedResources,\n options: ResolutionOptions = {}\n): Result<ResolutionResult> {\n const enableDebug = options.enableDebugLogging === true;\n\n debugLog(enableDebug, '=== RESOLVING RESOURCE ===');\n debugLog(enableDebug, 'Resource ID:', resourceId);\n\n const resourceResult = processedResources.system.resourceManager.getBuiltResource(resourceId);\n if (resourceResult.isFailure()) {\n return succeed({\n success: false,\n resourceId,\n error: `Failed to get resource: ${resourceResult.message}`\n });\n }\n\n const resource = resourceResult.value;\n const compiledCollection = processedResources.compiledCollection;\n\n // Find the compiled resource for condition analysis\n const compiledResource = compiledCollection.resources.find((r) => r.id === resourceId);\n if (!compiledResource) {\n return succeed({\n success: false,\n resourceId,\n error: 'Failed to find compiled resource'\n });\n }\n\n // Resolve best candidate\n const bestResult = resolver.resolveResource(resource);\n\n // Resolve all candidates\n const allResult = resolver.resolveAllResourceCandidates(resource);\n\n // Resolve composed value\n const composedResult = resolver.resolveComposedResourceValue(resource);\n\n // Get decision resolution result\n const decisionResult = resolver.resolveDecision(resource.decision.baseDecision);\n if (decisionResult.isFailure()) {\n return succeed({\n success: false,\n resourceId,\n error: `Failed to resolve decision: ${decisionResult.message}`\n });\n }\n\n const decision = decisionResult.value;\n\n // Build detailed candidate information\n const candidateDetails: CandidateInfo[] = [];\n const matchedCandidates = allResult.isSuccess() ? allResult.value : [];\n\n // Create lookup sets for regular and default matches\n const regularMatchIndices = new Set(decision?.success ? decision.instanceIndices : []);\n const defaultMatchIndices = new Set(decision?.success ? decision.defaultInstanceIndices : []);\n\n // Add matched candidates first\n matchedCandidates.forEach((matchedCandidate) => {\n const index = resource.candidates.findIndex((candidate: any) => candidate === matchedCandidate);\n if (index !== -1) {\n const conditionSetKey = `cs-${index}`;\n const conditionEvaluations = evaluateConditionsForCandidate(\n resolver,\n index,\n compiledResource,\n compiledCollection\n );\n\n const isDefaultMatch = defaultMatchIndices.has(index);\n const isRegularMatch = regularMatchIndices.has(index);\n\n const candidateMatchType = isRegularMatch ? 'match' : isDefaultMatch ? 'matchAsDefault' : 'noMatch';\n\n candidateDetails.push({\n candidate: resource.candidates[index],\n conditionSetKey,\n candidateIndex: index,\n matched: true,\n matchType: candidateMatchType,\n isDefaultMatch,\n conditionEvaluations\n });\n }\n });\n\n // Add non-matching candidates\n resource.candidates.forEach((candidate: any, index: number) => {\n const isMatched = matchedCandidates.some((mc) => mc === candidate);\n if (!isMatched) {\n // Handle different candidate formats - IResourceCandidate doesn't have conditions\n const conditionSetKey = candidate.conditions?.toHash ? candidate.conditions.toHash() : `cs-${index}`;\n const conditionEvaluations = evaluateConditionsForCandidate(\n resolver,\n index,\n compiledResource,\n compiledCollection\n );\n\n candidateDetails.push({\n candidate,\n conditionSetKey,\n candidateIndex: index,\n matched: false,\n matchType: 'noMatch',\n isDefaultMatch: false,\n conditionEvaluations\n });\n }\n });\n\n const result: ResolutionResult = {\n success: true,\n resourceId,\n resource,\n bestCandidate: bestResult.isSuccess() ? bestResult.value : undefined,\n allCandidates: allResult.isSuccess() ? allResult.value : undefined,\n candidateDetails,\n composedValue: composedResult.isSuccess() ? composedResult.value : undefined,\n error: bestResult.isFailure() ? bestResult.message : undefined\n };\n\n debugLog(enableDebug, 'Resolution completed successfully');\n return succeed(result);\n}\n\n/**\n * Get available qualifiers from processed resources\n */\nexport function getAvailableQualifiers(processedResources: ProcessedResources): string[] {\n if (processedResources.compiledCollection.qualifiers) {\n return processedResources.compiledCollection.qualifiers.map((q) => q.name);\n }\n return [];\n}\n\n/**\n * Check if context has any pending changes\n */\nexport function hasPendingContextChanges(\n contextValues: Record<string, string | undefined>,\n pendingContextValues: Record<string, string | undefined>\n): boolean {\n return JSON.stringify(contextValues) !== JSON.stringify(pendingContextValues);\n}\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Result, FileTree } from '@fgv/ts-utils';
|
|
2
|
+
import { QualifierTypes, Qualifiers, ResourceTypes, Resources, Import, Runtime, ResourceJson, Config } from '@fgv/ts-res';
|
|
3
|
+
import { ImportedDirectory, ImportedFile } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Get the default system configuration from ts-res library
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDefaultSystemConfiguration(): Config.Model.ISystemConfiguration;
|
|
8
|
+
/**
|
|
9
|
+
* Create a simple context provider from qualifier values
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSimpleContext(qualifiers: Qualifiers.IReadOnlyQualifierCollector, values: Record<string, string | undefined>): Result<Runtime.ValidatingSimpleContextQualifierProvider>;
|
|
12
|
+
/**
|
|
13
|
+
* Convert ImportedDirectory to FileTree format
|
|
14
|
+
*/
|
|
15
|
+
export declare function convertImportedDirectoryToFileTree(directory: ImportedDirectory): FileTree.FileTree;
|
|
16
|
+
/**
|
|
17
|
+
* Create ts-res system from configuration
|
|
18
|
+
*/
|
|
19
|
+
export declare function createTsResSystemFromConfig(systemConfig?: Config.Model.ISystemConfiguration): Result<{
|
|
20
|
+
qualifierTypes: QualifierTypes.ReadOnlyQualifierTypeCollector;
|
|
21
|
+
qualifiers: Qualifiers.IReadOnlyQualifierCollector;
|
|
22
|
+
resourceTypes: ResourceTypes.ReadOnlyResourceTypeCollector;
|
|
23
|
+
resourceManager: Resources.ResourceManagerBuilder;
|
|
24
|
+
importManager: Import.ImportManager;
|
|
25
|
+
contextQualifierProvider: Runtime.ValidatingSimpleContextQualifierProvider;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Process imported files using the ts-res system
|
|
29
|
+
*/
|
|
30
|
+
export declare function processImportedFiles(files: ImportedFile[], systemConfig?: Config.Model.ISystemConfiguration): Result<{
|
|
31
|
+
system: {
|
|
32
|
+
qualifierTypes: QualifierTypes.ReadOnlyQualifierTypeCollector;
|
|
33
|
+
qualifiers: Qualifiers.IReadOnlyQualifierCollector;
|
|
34
|
+
resourceTypes: ResourceTypes.ReadOnlyResourceTypeCollector;
|
|
35
|
+
resourceManager: Resources.ResourceManagerBuilder;
|
|
36
|
+
importManager: Import.ImportManager;
|
|
37
|
+
contextQualifierProvider: Runtime.ValidatingSimpleContextQualifierProvider;
|
|
38
|
+
};
|
|
39
|
+
compiledCollection: ResourceJson.Compiled.ICompiledResourceCollection;
|
|
40
|
+
resolver: Runtime.ResourceResolver;
|
|
41
|
+
resourceCount: number;
|
|
42
|
+
summary: {
|
|
43
|
+
totalResources: number;
|
|
44
|
+
resourceIds: string[];
|
|
45
|
+
errorCount: number;
|
|
46
|
+
warnings: string[];
|
|
47
|
+
};
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Process imported directory using the ts-res system
|
|
51
|
+
*/
|
|
52
|
+
export declare function processImportedDirectory(directory: ImportedDirectory, systemConfig?: Config.Model.ISystemConfiguration): Result<{
|
|
53
|
+
system: {
|
|
54
|
+
qualifierTypes: QualifierTypes.ReadOnlyQualifierTypeCollector;
|
|
55
|
+
qualifiers: Qualifiers.IReadOnlyQualifierCollector;
|
|
56
|
+
resourceTypes: ResourceTypes.ReadOnlyResourceTypeCollector;
|
|
57
|
+
resourceManager: Resources.ResourceManagerBuilder;
|
|
58
|
+
importManager: Import.ImportManager;
|
|
59
|
+
contextQualifierProvider: Runtime.ValidatingSimpleContextQualifierProvider;
|
|
60
|
+
};
|
|
61
|
+
compiledCollection: ResourceJson.Compiled.ICompiledResourceCollection;
|
|
62
|
+
resolver: Runtime.ResourceResolver;
|
|
63
|
+
resourceCount: number;
|
|
64
|
+
summary: {
|
|
65
|
+
totalResources: number;
|
|
66
|
+
resourceIds: string[];
|
|
67
|
+
errorCount: number;
|
|
68
|
+
warnings: string[];
|
|
69
|
+
};
|
|
70
|
+
}>;
|
|
71
|
+
//# sourceMappingURL=tsResIntegration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsResIntegration.d.ts","sourceRoot":"","sources":["../../src/utils/tsResIntegration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { succeed, fail, FileTree } from '@fgv/ts-utils';
|
|
2
|
+
import { Resources, Import, Runtime, Config } from '@fgv/ts-res';
|
|
3
|
+
/**
|
|
4
|
+
* Get the default system configuration from ts-res library
|
|
5
|
+
*/
|
|
6
|
+
export function getDefaultSystemConfiguration() {
|
|
7
|
+
return Config.getPredefinedDeclaration('default').orDefault({
|
|
8
|
+
// Fallback configuration if predefined default is not available
|
|
9
|
+
name: 'Browser Default Configuration',
|
|
10
|
+
description: 'Fallback default configuration for ts-res browser tool',
|
|
11
|
+
qualifierTypes: [
|
|
12
|
+
{
|
|
13
|
+
name: 'language',
|
|
14
|
+
systemType: 'language',
|
|
15
|
+
configuration: {
|
|
16
|
+
allowContextList: true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'territory',
|
|
21
|
+
systemType: 'territory',
|
|
22
|
+
configuration: {
|
|
23
|
+
allowContextList: false
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
qualifiers: [
|
|
28
|
+
{
|
|
29
|
+
name: 'currentTerritory',
|
|
30
|
+
token: 'geo',
|
|
31
|
+
typeName: 'territory',
|
|
32
|
+
defaultPriority: 850
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'language',
|
|
36
|
+
token: 'lang',
|
|
37
|
+
typeName: 'language',
|
|
38
|
+
defaultPriority: 800
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
resourceTypes: [
|
|
42
|
+
{
|
|
43
|
+
name: 'json',
|
|
44
|
+
typeName: 'json'
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a simple context provider from qualifier values
|
|
51
|
+
*/
|
|
52
|
+
export function createSimpleContext(qualifiers, values) {
|
|
53
|
+
return Runtime.ValidatingSimpleContextQualifierProvider.create({
|
|
54
|
+
qualifiers
|
|
55
|
+
}).withErrorFormat((e) => `Failed to create context: ${e}`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Convert ImportedDirectory to FileTree format
|
|
59
|
+
*/
|
|
60
|
+
export function convertImportedDirectoryToFileTree(directory) {
|
|
61
|
+
// Convert files to IInMemoryFile format and flatten the directory structure
|
|
62
|
+
const flattenFiles = (dir, parentPath = '') => {
|
|
63
|
+
const files = [];
|
|
64
|
+
// Add files from current directory
|
|
65
|
+
if (dir.files) {
|
|
66
|
+
dir.files.forEach((file) => {
|
|
67
|
+
const filePath = parentPath ? `${parentPath}/${file.name}` : file.name;
|
|
68
|
+
files.push({
|
|
69
|
+
path: filePath,
|
|
70
|
+
contents: file.content
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Recursively process subdirectories
|
|
75
|
+
if (dir.subdirectories) {
|
|
76
|
+
dir.subdirectories.forEach((subdir) => {
|
|
77
|
+
const subdirPath = parentPath ? `${parentPath}/${subdir.name}` : subdir.name;
|
|
78
|
+
files.push(...flattenFiles(subdir, subdirPath));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return files;
|
|
82
|
+
};
|
|
83
|
+
const inMemoryFiles = flattenFiles(directory);
|
|
84
|
+
console.log('[convertImportedDirectoryToFileTree] Converting directory to FileTree:', {
|
|
85
|
+
directoryName: directory.name,
|
|
86
|
+
directoryPath: directory.path,
|
|
87
|
+
numFiles: directory.files?.length || 0,
|
|
88
|
+
numSubdirs: directory.subdirectories?.length || 0,
|
|
89
|
+
totalFlattenedFiles: inMemoryFiles.length,
|
|
90
|
+
sampleFiles: inMemoryFiles.slice(0, 3).map((f) => f.path)
|
|
91
|
+
});
|
|
92
|
+
// Use ts-res's inMemory FileTree utility
|
|
93
|
+
return FileTree.inMemory(inMemoryFiles).orThrow((msg) => `Failed to create file tree: ${msg}`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create ts-res system from configuration
|
|
97
|
+
*/
|
|
98
|
+
export function createTsResSystemFromConfig(systemConfig) {
|
|
99
|
+
const configToUse = systemConfig ?? getDefaultSystemConfiguration();
|
|
100
|
+
return Config.SystemConfiguration.create(configToUse)
|
|
101
|
+
.onSuccess((systemConfiguration) => {
|
|
102
|
+
return Resources.ResourceManagerBuilder.create({
|
|
103
|
+
qualifiers: systemConfiguration.qualifiers,
|
|
104
|
+
resourceTypes: systemConfiguration.resourceTypes
|
|
105
|
+
})
|
|
106
|
+
.withErrorFormat((e) => `Failed to create resource manager: ${e}`)
|
|
107
|
+
.onSuccess((resourceManager) => {
|
|
108
|
+
return Import.ImportManager.create({
|
|
109
|
+
resources: resourceManager
|
|
110
|
+
})
|
|
111
|
+
.withErrorFormat((e) => `Failed to create import manager: ${e}`)
|
|
112
|
+
.onSuccess((importManager) => {
|
|
113
|
+
return Runtime.ValidatingSimpleContextQualifierProvider.create({
|
|
114
|
+
qualifiers: systemConfiguration.qualifiers
|
|
115
|
+
})
|
|
116
|
+
.withErrorFormat((e) => `Failed to create context qualifier provider: ${e}`)
|
|
117
|
+
.onSuccess((contextQualifierProvider) => {
|
|
118
|
+
return succeed({
|
|
119
|
+
qualifierTypes: systemConfiguration.qualifierTypes,
|
|
120
|
+
qualifiers: systemConfiguration.qualifiers,
|
|
121
|
+
resourceTypes: systemConfiguration.resourceTypes,
|
|
122
|
+
resourceManager,
|
|
123
|
+
importManager,
|
|
124
|
+
contextQualifierProvider
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
})
|
|
130
|
+
.withErrorFormat((e) => `Failed to create ts-res system: ${e}`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Process imported files using the ts-res system
|
|
134
|
+
*/
|
|
135
|
+
export function processImportedFiles(files, systemConfig) {
|
|
136
|
+
if (files.length === 0) {
|
|
137
|
+
return fail('No files provided for processing');
|
|
138
|
+
}
|
|
139
|
+
return createTsResSystemFromConfig(systemConfig)
|
|
140
|
+
.onSuccess((tsResSystem) => {
|
|
141
|
+
// Convert ImportedFile[] to IInMemoryFile[] format
|
|
142
|
+
const inMemoryFiles = files.map((file) => ({
|
|
143
|
+
path: file.path || file.name,
|
|
144
|
+
contents: file.content
|
|
145
|
+
}));
|
|
146
|
+
return FileTree.inMemory(inMemoryFiles)
|
|
147
|
+
.onSuccess((fileTree) => {
|
|
148
|
+
return Import.ImportManager.create({
|
|
149
|
+
fileTree,
|
|
150
|
+
resources: tsResSystem.resourceManager
|
|
151
|
+
});
|
|
152
|
+
})
|
|
153
|
+
.onSuccess((importManager) => {
|
|
154
|
+
// Import each file using its filesystem path
|
|
155
|
+
for (const file of files) {
|
|
156
|
+
const importResult = importManager.importFromFileSystem(file.path || file.name);
|
|
157
|
+
if (importResult.isFailure()) {
|
|
158
|
+
return fail(`Failed to import file ${file.path || file.name}: ${importResult.message}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Finalize processing
|
|
162
|
+
const updatedSystem = {
|
|
163
|
+
...tsResSystem,
|
|
164
|
+
importManager
|
|
165
|
+
};
|
|
166
|
+
return finalizeProcessing(updatedSystem);
|
|
167
|
+
});
|
|
168
|
+
})
|
|
169
|
+
.withErrorFormat((message) => `processImportedFiles failed: ${message}`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Process imported directory using the ts-res system
|
|
173
|
+
*/
|
|
174
|
+
export function processImportedDirectory(directory, systemConfig) {
|
|
175
|
+
return createTsResSystemFromConfig(systemConfig)
|
|
176
|
+
.onSuccess((tsResSystem) => {
|
|
177
|
+
// Convert directory to file tree
|
|
178
|
+
const fileTree = convertImportedDirectoryToFileTree(directory);
|
|
179
|
+
return Import.ImportManager.create({
|
|
180
|
+
fileTree,
|
|
181
|
+
resources: tsResSystem.resourceManager
|
|
182
|
+
}).onSuccess((importManager) => {
|
|
183
|
+
// Simply try to import from the filesystem root
|
|
184
|
+
// The ImportManager will handle finding and importing all resources
|
|
185
|
+
console.log('[tsResIntegration] Starting resource import from FileTree');
|
|
186
|
+
const importResult = importManager.importFromFileSystem('/');
|
|
187
|
+
if (importResult.isFailure()) {
|
|
188
|
+
console.warn(`[tsResIntegration] Failed to import from root, trying individual files`);
|
|
189
|
+
// If root import fails, try to import files individually
|
|
190
|
+
// We'll recursively traverse the tree using the FileTree API
|
|
191
|
+
let importedCount = 0;
|
|
192
|
+
const failedImports = [];
|
|
193
|
+
const importDirectory = (dirPath) => {
|
|
194
|
+
const dirResult = fileTree.getDirectory(dirPath);
|
|
195
|
+
if (dirResult.isSuccess()) {
|
|
196
|
+
const dir = dirResult.value;
|
|
197
|
+
const childrenResult = dir.getChildren();
|
|
198
|
+
if (childrenResult.isSuccess()) {
|
|
199
|
+
for (const child of childrenResult.value) {
|
|
200
|
+
if (child.type === 'file' && child.name.endsWith('.json')) {
|
|
201
|
+
console.log(`[tsResIntegration] Importing file: ${child.absolutePath}`);
|
|
202
|
+
const fileImportResult = importManager.importFromFileSystem(child.absolutePath);
|
|
203
|
+
if (fileImportResult.isSuccess()) {
|
|
204
|
+
importedCount++;
|
|
205
|
+
console.log(`[tsResIntegration] Successfully imported ${child.absolutePath}`);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
console.warn(`[tsResIntegration] Failed to import ${child.absolutePath}: ${fileImportResult.message}`);
|
|
209
|
+
failedImports.push({ file: child.absolutePath, error: fileImportResult.message });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else if (child.type === 'directory') {
|
|
213
|
+
importDirectory(child.absolutePath);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
// Start from root
|
|
220
|
+
importDirectory('/');
|
|
221
|
+
// Also try without leading slash
|
|
222
|
+
if (importedCount === 0) {
|
|
223
|
+
importDirectory('');
|
|
224
|
+
}
|
|
225
|
+
console.log(`[tsResIntegration] Import complete. Imported ${importedCount} files`);
|
|
226
|
+
if (importedCount === 0 && failedImports.length > 0) {
|
|
227
|
+
// Create a summary of unique errors
|
|
228
|
+
const errorSummary = new Map();
|
|
229
|
+
failedImports.forEach(({ file, error }) => {
|
|
230
|
+
// Extract the main error (e.g., "invalid item: role: not found")
|
|
231
|
+
const mainError = error.split('\n')[0];
|
|
232
|
+
if (!errorSummary.has(mainError)) {
|
|
233
|
+
errorSummary.set(mainError, []);
|
|
234
|
+
}
|
|
235
|
+
errorSummary.get(mainError).push(file);
|
|
236
|
+
});
|
|
237
|
+
let errorMessage = `Failed to import resources. Missing qualifiers in configuration:\n`;
|
|
238
|
+
errorSummary.forEach((files, error) => {
|
|
239
|
+
errorMessage += `- ${error} (${files.length} file${files.length > 1 ? 's' : ''})\n`;
|
|
240
|
+
});
|
|
241
|
+
return fail(errorMessage);
|
|
242
|
+
}
|
|
243
|
+
else if (importedCount === 0) {
|
|
244
|
+
return fail(`No resource files found in ${directory.name}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
console.log('[tsResIntegration] Successfully imported resources from root');
|
|
249
|
+
}
|
|
250
|
+
// Finalize processing
|
|
251
|
+
const updatedSystem = {
|
|
252
|
+
...tsResSystem,
|
|
253
|
+
importManager
|
|
254
|
+
};
|
|
255
|
+
return finalizeProcessing(updatedSystem);
|
|
256
|
+
});
|
|
257
|
+
})
|
|
258
|
+
.withErrorFormat((message) => `processImportedDirectory failed: ${message}`);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Finalizes processing and creates compiled resources
|
|
262
|
+
*/
|
|
263
|
+
function finalizeProcessing(system) {
|
|
264
|
+
return system.resourceManager
|
|
265
|
+
.getCompiledResourceCollection({ includeMetadata: true })
|
|
266
|
+
.onSuccess((compiledCollection) => {
|
|
267
|
+
// Create resolver directly without CompiledResourceCollection manager
|
|
268
|
+
return Runtime.ResourceResolver.create({
|
|
269
|
+
resourceManager: system.resourceManager,
|
|
270
|
+
qualifierTypes: system.qualifierTypes,
|
|
271
|
+
contextQualifierProvider: system.contextQualifierProvider
|
|
272
|
+
}).onSuccess((resolver) => {
|
|
273
|
+
// Create summary
|
|
274
|
+
const resourceIds = Array.from(system.resourceManager.resources.keys());
|
|
275
|
+
const summary = {
|
|
276
|
+
totalResources: resourceIds.length,
|
|
277
|
+
resourceIds,
|
|
278
|
+
errorCount: 0,
|
|
279
|
+
warnings: []
|
|
280
|
+
};
|
|
281
|
+
return succeed({
|
|
282
|
+
system,
|
|
283
|
+
compiledCollection,
|
|
284
|
+
resolver,
|
|
285
|
+
resourceCount: resourceIds.length,
|
|
286
|
+
summary
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
})
|
|
290
|
+
.withErrorFormat((message) => `Failed to finalize processing: ${message}`);
|
|
291
|
+
}
|
|
292
|
+
// Note: createCompiledResourceCollectionManager was removed as part of the refactoring
|
|
293
|
+
// We now always use ResourceManagerBuilder as the primary data structure
|
|
294
|
+
//# sourceMappingURL=tsResIntegration.js.map
|