@fgv/ts-res-ui-components 5.0.0-21 → 5.0.0-23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/README.md +401 -155
  2. package/config/jest.setup.js +10 -0
  3. package/dist/ts-res-ui-components.d.ts +1657 -76
  4. package/lib/components/common/QualifierContextControl.js +4 -1
  5. package/lib/components/common/ResourceTreeView.js +4 -1
  6. package/lib/components/forms/GenericQualifierTypeEditForm.d.ts +26 -0
  7. package/lib/components/forms/GenericQualifierTypeEditForm.js +166 -0
  8. package/lib/components/forms/QualifierEditForm.d.ts +1 -1
  9. package/lib/components/forms/index.d.ts +2 -0
  10. package/lib/components/forms/index.js +1 -0
  11. package/lib/components/orchestrator/ResourceOrchestrator.d.ts +3 -0
  12. package/lib/components/orchestrator/ResourceOrchestrator.js +118 -51
  13. package/lib/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
  14. package/lib/components/pickers/ResourcePicker/index.js +4 -2
  15. package/lib/components/views/CompiledView/index.js +75 -16
  16. package/lib/components/views/ConfigurationView/index.js +94 -35
  17. package/lib/components/views/FilterView/index.js +7 -4
  18. package/lib/components/views/GridView/EditableGridCell.d.ts +76 -0
  19. package/lib/components/views/GridView/EditableGridCell.js +224 -0
  20. package/lib/components/views/GridView/GridSelector.d.ts +43 -0
  21. package/lib/components/views/GridView/GridSelector.js +89 -0
  22. package/lib/components/views/GridView/MultiGridView.d.ts +85 -0
  23. package/lib/components/views/GridView/MultiGridView.js +196 -0
  24. package/lib/components/views/GridView/ResourceGrid.d.ts +38 -0
  25. package/lib/components/views/GridView/ResourceGrid.js +232 -0
  26. package/lib/components/views/GridView/SharedContextControls.d.ts +47 -0
  27. package/lib/components/views/GridView/SharedContextControls.js +95 -0
  28. package/lib/components/views/GridView/cells/BooleanCell.d.ts +44 -0
  29. package/lib/components/views/GridView/cells/BooleanCell.js +49 -0
  30. package/lib/components/views/GridView/cells/DropdownCell.d.ts +58 -0
  31. package/lib/components/views/GridView/cells/DropdownCell.js +182 -0
  32. package/lib/components/views/GridView/cells/StringCell.d.ts +57 -0
  33. package/lib/components/views/GridView/cells/StringCell.js +106 -0
  34. package/lib/components/views/GridView/cells/TriStateCell.d.ts +54 -0
  35. package/lib/components/views/GridView/cells/TriStateCell.js +112 -0
  36. package/lib/components/views/GridView/cells/index.d.ts +15 -0
  37. package/lib/components/views/GridView/cells/index.js +11 -0
  38. package/lib/components/views/GridView/index.d.ts +53 -0
  39. package/lib/components/views/GridView/index.js +212 -0
  40. package/lib/components/views/ImportView/index.js +22 -19
  41. package/lib/components/views/MessagesWindow/index.js +4 -1
  42. package/lib/components/views/ResolutionView/index.js +8 -5
  43. package/lib/contexts/ObservabilityContext.d.ts +85 -0
  44. package/lib/contexts/ObservabilityContext.js +98 -0
  45. package/lib/contexts/index.d.ts +2 -0
  46. package/lib/contexts/index.js +24 -0
  47. package/lib/hooks/useConfigurationState.d.ts +3 -3
  48. package/lib/hooks/useResolutionState.js +850 -246
  49. package/lib/hooks/useResourceData.d.ts +7 -4
  50. package/lib/hooks/useResourceData.js +185 -184
  51. package/lib/index.d.ts +5 -1
  52. package/lib/index.js +8 -1
  53. package/lib/namespaces/GridTools.d.ts +136 -0
  54. package/lib/namespaces/GridTools.js +138 -0
  55. package/lib/namespaces/ObservabilityTools.d.ts +3 -0
  56. package/lib/namespaces/ObservabilityTools.js +23 -0
  57. package/lib/namespaces/ResolutionTools.d.ts +2 -1
  58. package/lib/namespaces/ResolutionTools.js +2 -0
  59. package/lib/namespaces/index.d.ts +2 -0
  60. package/lib/namespaces/index.js +2 -0
  61. package/lib/test/integration/observability.integration.test.d.ts +2 -0
  62. package/lib/test/unit/hooks/useResourceData.test.d.ts +2 -0
  63. package/lib/test/unit/utils/downloadHelper.test.d.ts +2 -0
  64. package/lib/test/unit/workflows/resolutionWorkflows.test.d.ts +2 -0
  65. package/lib/test/unit/workflows/resourceCreation.test.d.ts +2 -0
  66. package/lib/test/unit/workflows/resultPatternExtensions.test.d.ts +2 -0
  67. package/lib/test/unit/workflows/validation.test.d.ts +2 -0
  68. package/lib/types/index.d.ts +387 -20
  69. package/lib/types/index.js +2 -1
  70. package/lib/utils/cellValidation.d.ts +113 -0
  71. package/lib/utils/cellValidation.js +248 -0
  72. package/lib/utils/downloadHelper.d.ts +66 -0
  73. package/lib/utils/downloadHelper.js +195 -0
  74. package/lib/utils/observability/factories.d.ts +29 -0
  75. package/lib/utils/observability/factories.js +58 -0
  76. package/lib/utils/observability/implementations.d.ts +61 -0
  77. package/lib/utils/observability/implementations.js +103 -0
  78. package/lib/utils/observability/index.d.ts +4 -0
  79. package/lib/utils/observability/index.js +26 -0
  80. package/lib/utils/observability/interfaces.d.ts +30 -0
  81. package/lib/utils/observability/interfaces.js +23 -0
  82. package/lib/utils/resolutionEditing.js +2 -1
  83. package/lib/utils/resourceSelector.d.ts +97 -0
  84. package/lib/utils/resourceSelector.js +195 -0
  85. package/lib/utils/resourceSelectors.d.ts +146 -0
  86. package/lib/utils/resourceSelectors.js +233 -0
  87. package/lib/utils/tsResIntegration.d.ts +6 -41
  88. package/lib/utils/tsResIntegration.js +20 -16
  89. package/lib/utils/zipLoader/zipProcessingHelpers.d.ts +3 -2
  90. package/lib/utils/zipLoader/zipProcessingHelpers.js +6 -5
  91. package/lib-commonjs/components/common/QualifierContextControl.js +4 -1
  92. package/lib-commonjs/components/common/ResourceTreeView.js +4 -1
  93. package/lib-commonjs/components/forms/GenericQualifierTypeEditForm.js +171 -0
  94. package/lib-commonjs/components/forms/index.js +3 -1
  95. package/lib-commonjs/components/orchestrator/ResourceOrchestrator.js +118 -51
  96. package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
  97. package/lib-commonjs/components/pickers/ResourcePicker/index.js +4 -2
  98. package/lib-commonjs/components/views/CompiledView/index.js +75 -16
  99. package/lib-commonjs/components/views/ConfigurationView/index.js +93 -34
  100. package/lib-commonjs/components/views/FilterView/index.js +7 -4
  101. package/lib-commonjs/components/views/GridView/EditableGridCell.js +232 -0
  102. package/lib-commonjs/components/views/GridView/GridSelector.js +94 -0
  103. package/lib-commonjs/components/views/GridView/MultiGridView.js +201 -0
  104. package/lib-commonjs/components/views/GridView/ResourceGrid.js +237 -0
  105. package/lib-commonjs/components/views/GridView/SharedContextControls.js +100 -0
  106. package/lib-commonjs/components/views/GridView/cells/BooleanCell.js +54 -0
  107. package/lib-commonjs/components/views/GridView/cells/DropdownCell.js +187 -0
  108. package/lib-commonjs/components/views/GridView/cells/StringCell.js +111 -0
  109. package/lib-commonjs/components/views/GridView/cells/TriStateCell.js +117 -0
  110. package/lib-commonjs/components/views/GridView/cells/index.js +18 -0
  111. package/lib-commonjs/components/views/GridView/index.js +217 -0
  112. package/lib-commonjs/components/views/ImportView/index.js +22 -19
  113. package/lib-commonjs/components/views/MessagesWindow/index.js +4 -1
  114. package/lib-commonjs/components/views/ResolutionView/index.js +8 -5
  115. package/lib-commonjs/contexts/ObservabilityContext.js +104 -0
  116. package/lib-commonjs/contexts/index.js +30 -0
  117. package/lib-commonjs/hooks/useResolutionState.js +849 -245
  118. package/lib-commonjs/hooks/useResourceData.js +184 -215
  119. package/lib-commonjs/index.js +15 -1
  120. package/lib-commonjs/namespaces/GridTools.js +161 -0
  121. package/lib-commonjs/namespaces/ObservabilityTools.js +33 -0
  122. package/lib-commonjs/namespaces/ResolutionTools.js +10 -1
  123. package/lib-commonjs/namespaces/index.js +3 -1
  124. package/lib-commonjs/types/index.js +10 -0
  125. package/lib-commonjs/utils/cellValidation.js +253 -0
  126. package/lib-commonjs/utils/downloadHelper.js +198 -0
  127. package/lib-commonjs/utils/observability/factories.js +63 -0
  128. package/lib-commonjs/utils/observability/implementations.js +109 -0
  129. package/lib-commonjs/utils/observability/index.js +36 -0
  130. package/lib-commonjs/utils/observability/interfaces.js +24 -0
  131. package/lib-commonjs/utils/resolutionEditing.js +2 -1
  132. package/lib-commonjs/utils/resourceSelector.js +200 -0
  133. package/lib-commonjs/utils/resourceSelectors.js +242 -0
  134. package/lib-commonjs/utils/tsResIntegration.js +21 -16
  135. package/lib-commonjs/utils/zipLoader/zipProcessingHelpers.js +7 -5
  136. package/package.json +7 -7
  137. package/src/components/common/QualifierContextControl.tsx +0 -338
  138. package/src/components/common/ResolutionContextOptionsControl.tsx +0 -450
  139. package/src/components/common/ResolutionResults/index.tsx +0 -481
  140. package/src/components/common/ResourceListView.tsx +0 -167
  141. package/src/components/common/ResourcePickerOptionsControl.tsx +0 -351
  142. package/src/components/common/ResourceTreeView.tsx +0 -417
  143. package/src/components/common/SourceResourceDetail/index.tsx +0 -493
  144. package/src/components/forms/HierarchyEditor.tsx +0 -285
  145. package/src/components/forms/QualifierEditForm.tsx +0 -487
  146. package/src/components/forms/QualifierTypeEditForm.tsx +0 -458
  147. package/src/components/forms/ResourceTypeEditForm.tsx +0 -437
  148. package/src/components/forms/index.ts +0 -11
  149. package/src/components/orchestrator/ResourceOrchestrator.tsx +0 -444
  150. package/src/components/pickers/ResourcePicker/README.md +0 -570
  151. package/src/components/pickers/ResourcePicker/ResourceItem.tsx +0 -127
  152. package/src/components/pickers/ResourcePicker/ResourcePickerList.tsx +0 -114
  153. package/src/components/pickers/ResourcePicker/ResourcePickerTree.tsx +0 -461
  154. package/src/components/pickers/ResourcePicker/index.tsx +0 -234
  155. package/src/components/pickers/ResourcePicker/types.ts +0 -301
  156. package/src/components/pickers/ResourcePicker/utils/treeNavigation.ts +0 -210
  157. package/src/components/views/CompiledView/index.tsx +0 -1342
  158. package/src/components/views/ConfigurationView/index.tsx +0 -848
  159. package/src/components/views/FilterView/index.tsx +0 -681
  160. package/src/components/views/ImportView/index.tsx +0 -789
  161. package/src/components/views/MessagesWindow/index.tsx +0 -325
  162. package/src/components/views/ResolutionView/EditableJsonView.tsx +0 -386
  163. package/src/components/views/ResolutionView/NewResourceModal.tsx +0 -158
  164. package/src/components/views/ResolutionView/UnifiedChangeControls.tsx +0 -163
  165. package/src/components/views/ResolutionView/index.tsx +0 -751
  166. package/src/components/views/SourceView/index.tsx +0 -291
  167. package/src/hooks/useConfigurationState.ts +0 -436
  168. package/src/hooks/useFilterState.ts +0 -150
  169. package/src/hooks/useResolutionState.ts +0 -893
  170. package/src/hooks/useResourceData.ts +0 -596
  171. package/src/hooks/useViewState.ts +0 -97
  172. package/src/index.ts +0 -68
  173. package/src/namespaces/ConfigurationTools.ts +0 -59
  174. package/src/namespaces/FilterTools.ts +0 -47
  175. package/src/namespaces/ImportTools.ts +0 -42
  176. package/src/namespaces/PickerTools.ts +0 -104
  177. package/src/namespaces/ResolutionTools.ts +0 -68
  178. package/src/namespaces/ResourceTools.ts +0 -106
  179. package/src/namespaces/TsResTools.ts +0 -49
  180. package/src/namespaces/ViewStateTools.ts +0 -91
  181. package/src/namespaces/ZipTools.ts +0 -49
  182. package/src/namespaces/index.ts +0 -49
  183. package/src/types/index.ts +0 -1273
  184. package/src/utils/configurationUtils.ts +0 -339
  185. package/src/utils/fileProcessing.ts +0 -164
  186. package/src/utils/filterResources.ts +0 -356
  187. package/src/utils/resolutionEditing.ts +0 -346
  188. package/src/utils/resolutionUtils.ts +0 -740
  189. package/src/utils/tsResIntegration.ts +0 -475
  190. package/src/utils/zipLoader/index.ts +0 -5
  191. package/src/utils/zipLoader/zipProcessingHelpers.ts +0 -46
  192. package/src/utils/zipLoader/zipUtils.ts +0 -7
@@ -0,0 +1,103 @@
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 { Logging, succeed } from '@fgv/ts-utils';
23
+ /**
24
+ * Console-based user logger that extends diagnostic logging with success method.
25
+ * @public
26
+ */
27
+ export class ConsoleUserLogger extends Logging.LoggerBase {
28
+ /**
29
+ * Creates a new console user logger.
30
+ * @param logLevel - The level of logging to be used.
31
+ */
32
+ constructor(logLevel) {
33
+ super(logLevel);
34
+ }
35
+ /**
36
+ * {@inheritDoc ObservabilityTools.IUserLogger.success}
37
+ */
38
+ success(message, ...parameters) {
39
+ return this.log('info', message, ...parameters);
40
+ }
41
+ /**
42
+ * implements base class _log.
43
+ */
44
+ _log(message, level) {
45
+ switch (level) {
46
+ case 'error':
47
+ console.error(message);
48
+ break;
49
+ case 'warning':
50
+ console.warn(message);
51
+ break;
52
+ case 'info':
53
+ console.info(message);
54
+ break;
55
+ default:
56
+ console.log(message);
57
+ break;
58
+ }
59
+ return succeed(message);
60
+ }
61
+ }
62
+ /**
63
+ * No-op user logger that suppresses all output.
64
+ * @public
65
+ */
66
+ export class NoOpUserLogger extends Logging.LoggerBase {
67
+ /**
68
+ * Creates a new no-op user logger.
69
+ * @param logLevel - The level of logging to be used.
70
+ */
71
+ constructor(logLevel) {
72
+ super(logLevel);
73
+ }
74
+ /**
75
+ * {@inheritDoc ObservabilityTools.IUserLogger.success}
76
+ */
77
+ success(message, ...parameters) {
78
+ return succeed(undefined);
79
+ }
80
+ /**
81
+ * Implements base class _log method.
82
+ */
83
+ _log(message, __level) {
84
+ // no-op
85
+ return succeed(message);
86
+ }
87
+ }
88
+ /**
89
+ * Observability context that provides both diagnostic and user logging capabilities.
90
+ * @public
91
+ */
92
+ export class ObservabilityContext {
93
+ /**
94
+ * Creates a new observability context.
95
+ * @param diag - The diagnostic logger.
96
+ * @param user - The user logger.
97
+ */
98
+ constructor(diag, user) {
99
+ this.diag = diag;
100
+ this.user = user;
101
+ }
102
+ }
103
+ //# sourceMappingURL=implementations.js.map
@@ -0,0 +1,4 @@
1
+ export type { IUserLogger, IObservabilityContext } from './interfaces';
2
+ export { ConsoleUserLogger, NoOpUserLogger, ObservabilityContext } from './implementations';
3
+ export { createConsoleObservabilityContext, createNoOpObservabilityContext, DefaultObservabilityContext, TestObservabilityContext } from './factories';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,26 @@
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
+ // Export implementations
23
+ export { ConsoleUserLogger, NoOpUserLogger, ObservabilityContext } from './implementations';
24
+ // Export factories
25
+ export { createConsoleObservabilityContext, createNoOpObservabilityContext, DefaultObservabilityContext, TestObservabilityContext } from './factories';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,30 @@
1
+ import type { Logging, Success } from '@fgv/ts-utils';
2
+ /**
3
+ * User logger interface that extends ILogger with success method for UI feedback.
4
+ * @public
5
+ */
6
+ export interface IUserLogger extends Logging.ILogger {
7
+ /**
8
+ * Logs a success message for user feedback.
9
+ * @param message - The message to log.
10
+ * @param parameters - The parameters to log.
11
+ * @returns `Success` with the logged message if the level is enabled, or
12
+ * `Success` with `undefined` if the message is suppressed.
13
+ */
14
+ success(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
15
+ }
16
+ /**
17
+ * Observability context that provides both diagnostic and user logging capabilities.
18
+ * @public
19
+ */
20
+ export interface IObservabilityContext {
21
+ /**
22
+ * Diagnostic logger for internal system diagnostics.
23
+ */
24
+ readonly diag: Logging.ILogger;
25
+ /**
26
+ * User logger for user-facing messages and feedback.
27
+ */
28
+ readonly user: IUserLogger;
29
+ }
30
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1,23 @@
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
+ export {};
23
+ //# sourceMappingURL=interfaces.js.map
@@ -1,6 +1,7 @@
1
1
  import { succeed, fail } from '@fgv/ts-utils';
2
2
  import { Runtime } from '@fgv/ts-res';
3
3
  import { Diff } from '@fgv/ts-json';
4
+ import { isJsonObject } from '@fgv/ts-json-base';
4
5
  /**
5
6
  * Validates an edited resource JSON value
6
7
  */
@@ -67,7 +68,7 @@ export function computeResourceDelta(baseValue, resolvedValue, editedValue) {
67
68
  * Recursively adds null values to delta for all properties in the deleted object
68
69
  */
69
70
  function addDeletionsAsNull(deleted, delta) {
70
- if (typeof deleted === 'object' && deleted !== null && !Array.isArray(deleted)) {
71
+ if (isJsonObject(deleted)) {
71
72
  const deletedObj = deleted;
72
73
  for (const key in deletedObj) {
73
74
  if (deletedObj.hasOwnProperty(key)) {
@@ -0,0 +1,97 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { ProcessedResources, GridResourceSelector } from '../types';
3
+ /**
4
+ * Handler function type for resource selector implementations.
5
+ */
6
+ type SelectorHandler = (selector: any, resources: ProcessedResources) => Result<string[]>;
7
+ /**
8
+ * Resource selector utility for filtering resources based on various criteria.
9
+ * Supports built-in selector types and extensible custom selectors.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const selector = new ResourceSelector();
14
+ *
15
+ * // Use built-in selectors
16
+ * const prefixResult = selector.select(
17
+ * { type: 'prefix', prefix: 'user.' },
18
+ * processedResources
19
+ * );
20
+ *
21
+ * // Register and use custom selector
22
+ * selector.registerSelector('byMetadata', (config, resources) => {
23
+ * return succeed(resources.summary.resourceIds.filter(id =>
24
+ * hasMetadata(id, config.key, config.value)
25
+ * ));
26
+ * });
27
+ * ```
28
+ * @public
29
+ */
30
+ export declare class ResourceSelector {
31
+ private registry;
32
+ constructor();
33
+ /**
34
+ * Register a new selector type that can be used in grid configurations.
35
+ *
36
+ * @param type - Unique identifier for the selector type
37
+ * @param handler - Function that implements the selection logic
38
+ */
39
+ registerSelector(type: string, handler: SelectorHandler): void;
40
+ /**
41
+ * Get all registered selector types (useful for debugging/tooling).
42
+ */
43
+ getRegisteredTypes(): string[];
44
+ /**
45
+ * Select resources based on the provided selector configuration.
46
+ *
47
+ * @param selector - Resource selector configuration
48
+ * @param resources - Processed resources to select from
49
+ * @returns Result containing array of selected resource IDs
50
+ */
51
+ select(selector: GridResourceSelector, resources: ProcessedResources): Result<string[]>;
52
+ /**
53
+ * Select resources by explicit resource IDs.
54
+ */
55
+ private selectByIds;
56
+ /**
57
+ * Select resources with IDs starting with the specified prefix.
58
+ */
59
+ private selectByPrefix;
60
+ /**
61
+ * Select resources with IDs ending with the specified suffix.
62
+ */
63
+ private selectBySuffix;
64
+ /**
65
+ * Select resources by resource type names.
66
+ */
67
+ private selectByResourceTypes;
68
+ /**
69
+ * Select resources by simple glob pattern matching.
70
+ * Supports * as wildcard character.
71
+ */
72
+ private selectByPattern;
73
+ /**
74
+ * Select all available resources.
75
+ */
76
+ private selectAll;
77
+ /**
78
+ * Select resources using custom selector logic.
79
+ */
80
+ private selectCustom;
81
+ }
82
+ /**
83
+ * Default resource selector instance for use throughout the application.
84
+ * @public
85
+ */
86
+ export declare const defaultResourceSelector: ResourceSelector;
87
+ /**
88
+ * Utility function to select resources using the default selector.
89
+ *
90
+ * @param selector - Resource selector configuration
91
+ * @param resources - Processed resources to select from
92
+ * @returns Result containing array of selected resource IDs
93
+ * @public
94
+ */
95
+ export declare function selectResources(selector: GridResourceSelector, resources: ProcessedResources): Result<string[]>;
96
+ export {};
97
+ //# sourceMappingURL=resourceSelector.d.ts.map
@@ -0,0 +1,195 @@
1
+ import { succeed, fail } from '@fgv/ts-utils';
2
+ /**
3
+ * Resource selector utility for filtering resources based on various criteria.
4
+ * Supports built-in selector types and extensible custom selectors.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const selector = new ResourceSelector();
9
+ *
10
+ * // Use built-in selectors
11
+ * const prefixResult = selector.select(
12
+ * { type: 'prefix', prefix: 'user.' },
13
+ * processedResources
14
+ * );
15
+ *
16
+ * // Register and use custom selector
17
+ * selector.registerSelector('byMetadata', (config, resources) => {
18
+ * return succeed(resources.summary.resourceIds.filter(id =>
19
+ * hasMetadata(id, config.key, config.value)
20
+ * ));
21
+ * });
22
+ * ```
23
+ * @public
24
+ */
25
+ export class ResourceSelector {
26
+ constructor() {
27
+ this.registry = new Map();
28
+ /**
29
+ * Select resources by explicit resource IDs.
30
+ */
31
+ this.selectByIds = (selector, resources) => {
32
+ const availableIds = new Set(resources.summary.resourceIds);
33
+ const selectedIds = selector.resourceIds.filter((id) => availableIds.has(id));
34
+ if (selectedIds.length === 0 && selector.resourceIds.length > 0) {
35
+ return fail(`None of the specified resource IDs were found in the resource collection`);
36
+ }
37
+ return succeed(selectedIds);
38
+ };
39
+ /**
40
+ * Select resources with IDs starting with the specified prefix.
41
+ */
42
+ this.selectByPrefix = (selector, resources) => {
43
+ if (!selector.prefix) {
44
+ return fail('Prefix cannot be empty');
45
+ }
46
+ const matchingIds = resources.summary.resourceIds.filter((id) => id.startsWith(selector.prefix));
47
+ return succeed(matchingIds);
48
+ };
49
+ /**
50
+ * Select resources with IDs ending with the specified suffix.
51
+ */
52
+ this.selectBySuffix = (selector, resources) => {
53
+ if (!selector.suffix) {
54
+ return fail('Suffix cannot be empty');
55
+ }
56
+ const matchingIds = resources.summary.resourceIds.filter((id) => id.endsWith(selector.suffix));
57
+ return succeed(matchingIds);
58
+ };
59
+ /**
60
+ * Select resources by resource type names.
61
+ */
62
+ this.selectByResourceTypes = (selector, resources) => {
63
+ if (!selector.types || selector.types.length === 0) {
64
+ return fail('Resource types array cannot be empty');
65
+ }
66
+ const typeSet = new Set(selector.types);
67
+ const matchingIds = [];
68
+ // Iterate through all resources and check their types
69
+ resources.summary.resourceIds.forEach((resourceId) => {
70
+ try {
71
+ // Get the resource from the resolver to check its type
72
+ const resourceResult = resources.resolver.resourceManager.getBuiltResource(resourceId);
73
+ if (resourceResult.isSuccess()) {
74
+ const resource = resourceResult.value;
75
+ if (typeSet.has(resource.resourceType.key)) {
76
+ matchingIds.push(resourceId);
77
+ }
78
+ }
79
+ }
80
+ catch {
81
+ // Skip resources that can't be accessed
82
+ }
83
+ });
84
+ return succeed(matchingIds);
85
+ };
86
+ /**
87
+ * Select resources by simple glob pattern matching.
88
+ * Supports * as wildcard character.
89
+ */
90
+ this.selectByPattern = (selector, resources) => {
91
+ if (!selector.pattern) {
92
+ return fail('Pattern cannot be empty');
93
+ }
94
+ try {
95
+ // Convert glob pattern to regex
96
+ const regexPattern = selector.pattern
97
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape special regex chars
98
+ .replace(/\*/g, '.*'); // Convert * to .*
99
+ const regex = new RegExp(`^${regexPattern}$`);
100
+ const matchingIds = resources.summary.resourceIds.filter((id) => regex.test(id));
101
+ return succeed(matchingIds);
102
+ }
103
+ catch (error) {
104
+ return fail(`Invalid pattern: ${error instanceof Error ? error.message : String(error)}`);
105
+ }
106
+ };
107
+ /**
108
+ * Select all available resources.
109
+ */
110
+ this.selectAll = (_selector, resources) => {
111
+ return succeed([...resources.summary.resourceIds]);
112
+ };
113
+ /**
114
+ * Select resources using custom selector logic.
115
+ */
116
+ this.selectCustom = (selector, resources) => {
117
+ if (!selector.selector) {
118
+ return fail('Custom selector configuration is required');
119
+ }
120
+ try {
121
+ const selectedIds = selector.selector.select(resources);
122
+ // Validate that all returned IDs exist in the resource collection
123
+ const availableIds = new Set(resources.summary.resourceIds);
124
+ const validIds = selectedIds.filter((id) => availableIds.has(id));
125
+ if (validIds.length !== selectedIds.length) {
126
+ const invalidIds = selectedIds.filter((id) => !availableIds.has(id));
127
+ console.warn(`Custom selector returned invalid resource IDs: ${invalidIds.join(', ')}`);
128
+ }
129
+ return succeed(validIds);
130
+ }
131
+ catch (error) {
132
+ return fail(`Custom selector failed: ${error instanceof Error ? error.message : String(error)}`);
133
+ }
134
+ };
135
+ // Register built-in selectors
136
+ this.registry.set('ids', this.selectByIds);
137
+ this.registry.set('prefix', this.selectByPrefix);
138
+ this.registry.set('suffix', this.selectBySuffix);
139
+ this.registry.set('resourceTypes', this.selectByResourceTypes);
140
+ this.registry.set('pattern', this.selectByPattern);
141
+ this.registry.set('all', this.selectAll);
142
+ this.registry.set('custom', this.selectCustom);
143
+ }
144
+ /**
145
+ * Register a new selector type that can be used in grid configurations.
146
+ *
147
+ * @param type - Unique identifier for the selector type
148
+ * @param handler - Function that implements the selection logic
149
+ */
150
+ registerSelector(type, handler) {
151
+ this.registry.set(type, handler);
152
+ }
153
+ /**
154
+ * Get all registered selector types (useful for debugging/tooling).
155
+ */
156
+ getRegisteredTypes() {
157
+ return Array.from(this.registry.keys());
158
+ }
159
+ /**
160
+ * Select resources based on the provided selector configuration.
161
+ *
162
+ * @param selector - Resource selector configuration
163
+ * @param resources - Processed resources to select from
164
+ * @returns Result containing array of selected resource IDs
165
+ */
166
+ select(selector, resources) {
167
+ const handler = this.registry.get(selector.type);
168
+ if (!handler) {
169
+ return fail(`Unknown selector type: ${selector.type}`);
170
+ }
171
+ try {
172
+ return handler(selector, resources);
173
+ }
174
+ catch (error) {
175
+ return fail(`Selector error: ${error instanceof Error ? error.message : String(error)}`);
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Default resource selector instance for use throughout the application.
181
+ * @public
182
+ */
183
+ export const defaultResourceSelector = new ResourceSelector();
184
+ /**
185
+ * Utility function to select resources using the default selector.
186
+ *
187
+ * @param selector - Resource selector configuration
188
+ * @param resources - Processed resources to select from
189
+ * @returns Result containing array of selected resource IDs
190
+ * @public
191
+ */
192
+ export function selectResources(selector, resources) {
193
+ return defaultResourceSelector.select(selector, resources);
194
+ }
195
+ //# sourceMappingURL=resourceSelector.js.map
@@ -0,0 +1,146 @@
1
+ import { ResourceJson } from '@fgv/ts-res';
2
+ import { Result } from '@fgv/ts-utils';
3
+ /**
4
+ * Helper functions for working with pending resources and resource IDs.
5
+ * These utilities provide standardized ways to work with resource identification
6
+ * and selection patterns commonly needed by host applications.
7
+ *
8
+ * @public
9
+ */
10
+ /**
11
+ * Gets pending resources filtered by resource type.
12
+ *
13
+ * @param pendingResources - Map of pending resources (keys are guaranteed to be full resource IDs)
14
+ * @param resourceType - Resource type to filter by (e.g., 'json', 'string')
15
+ * @returns Array of pending resources of the specified type
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const jsonResources = getPendingAdditionsByType(pendingResources, 'json');
20
+ * const languageConfigs = getPendingAdditionsByType(pendingResources, 'languageConfig');
21
+ * ```
22
+ *
23
+ * @public
24
+ */
25
+ export declare function getPendingAdditionsByType(pendingResources: Map<string, ResourceJson.Json.ILooseResourceDecl>, resourceType: string): Array<{
26
+ id: string;
27
+ resource: ResourceJson.Json.ILooseResourceDecl;
28
+ }>;
29
+ /**
30
+ * Checks if a resource ID corresponds to a pending addition.
31
+ *
32
+ * @param resourceId - Resource ID to check (should be full resource ID)
33
+ * @param pendingResources - Map of pending resources
34
+ * @returns True if the resource ID exists in pending resources
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * if (isPendingAddition('platform.languages.az-AZ', pendingResources)) {
39
+ * console.log('This is a pending resource');
40
+ * }
41
+ * ```
42
+ *
43
+ * @public
44
+ */
45
+ export declare function isPendingAddition(resourceId: string, pendingResources: Map<string, ResourceJson.Json.ILooseResourceDecl>): boolean;
46
+ /**
47
+ * Derives a leaf ID from a full resource ID.
48
+ * Extracts the last segment after the final dot.
49
+ *
50
+ * @param fullResourceId - Full resource ID (e.g., 'platform.languages.az-AZ')
51
+ * @returns Result containing the leaf ID (e.g., 'az-AZ') or error if invalid format
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const leafResult = deriveLeafId('platform.languages.az-AZ');
56
+ * if (leafResult.isSuccess()) {
57
+ * console.log(leafResult.value); // 'az-AZ'
58
+ * }
59
+ *
60
+ * const invalidResult = deriveLeafId('invalid');
61
+ * if (invalidResult.isFailure()) {
62
+ * console.log(invalidResult.message); // 'Resource ID must contain at least one dot'
63
+ * }
64
+ * ```
65
+ *
66
+ * @public
67
+ */
68
+ export declare function deriveLeafId(fullResourceId: string): Result<string>;
69
+ /**
70
+ * Constructs a full resource ID from a root path and leaf ID.
71
+ *
72
+ * @param rootPath - Root path (e.g., 'platform.languages')
73
+ * @param leafId - Leaf identifier (e.g., 'az-AZ')
74
+ * @returns Result containing the full resource ID or error if invalid inputs
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const fullIdResult = deriveFullId('platform.languages', 'az-AZ');
79
+ * if (fullIdResult.isSuccess()) {
80
+ * console.log(fullIdResult.value); // 'platform.languages.az-AZ'
81
+ * }
82
+ *
83
+ * const invalidResult = deriveFullId('', 'az-AZ');
84
+ * if (invalidResult.isFailure()) {
85
+ * console.log(invalidResult.message); // 'Root path cannot be empty'
86
+ * }
87
+ * ```
88
+ *
89
+ * @public
90
+ */
91
+ export declare function deriveFullId(rootPath: string, leafId: string): Result<string>;
92
+ /**
93
+ * Gets all unique resource types from pending resources.
94
+ *
95
+ * @param pendingResources - Map of pending resources
96
+ * @returns Array of unique resource type names
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const types = getPendingResourceTypes(pendingResources);
101
+ * console.log(types); // ['json', 'string', 'languageConfig']
102
+ * ```
103
+ *
104
+ * @public
105
+ */
106
+ export declare function getPendingResourceTypes(pendingResources: Map<string, ResourceJson.Json.ILooseResourceDecl>): string[];
107
+ /**
108
+ * Gets statistics about pending resources.
109
+ * Provides summary information useful for UI displays.
110
+ *
111
+ * @param pendingResources - Map of pending resources
112
+ * @returns Statistics object with counts and breakdowns
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const stats = getPendingResourceStats(pendingResources);
117
+ * console.log(`${stats.totalCount} pending resources`);
118
+ * console.log(`Types: ${Object.keys(stats.byType).join(', ')}`);
119
+ * ```
120
+ *
121
+ * @public
122
+ */
123
+ export declare function getPendingResourceStats(pendingResources: Map<string, ResourceJson.Json.ILooseResourceDecl>): {
124
+ totalCount: number;
125
+ byType: Record<string, number>;
126
+ resourceIds: string[];
127
+ };
128
+ /**
129
+ * Validates that all keys in a pending resources map are properly formatted as full resource IDs.
130
+ * This is a diagnostic function to ensure the pending resource key invariant is maintained.
131
+ *
132
+ * @param pendingResources - Map of pending resources to validate
133
+ * @returns Result indicating whether all keys are valid full resource IDs, or details about any issues found
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const validation = validatePendingResourceKeys(pendingResources);
138
+ * if (validation.isFailure()) {
139
+ * console.error('Pending resource key validation failed:', validation.message);
140
+ * }
141
+ * ```
142
+ *
143
+ * @public
144
+ */
145
+ export declare function validatePendingResourceKeys(pendingResources: Map<string, ResourceJson.Json.ILooseResourceDecl>): Result<void>;
146
+ //# sourceMappingURL=resourceSelectors.d.ts.map