@cratis/scene.engine 4.2.1 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/editing/DescriptorCatalog.js +42 -0
- package/dist/cjs/editing/DescriptorCatalog.js.map +1 -0
- package/dist/cjs/editing/EditSession.js +44 -0
- package/dist/cjs/editing/EditSession.js.map +1 -0
- package/dist/cjs/editing/applyEdit.js +83 -0
- package/dist/cjs/editing/applyEdit.js.map +1 -0
- package/dist/cjs/editing/applyEffectiveConfiguration.js +62 -0
- package/dist/cjs/editing/applyEffectiveConfiguration.js.map +1 -0
- package/dist/cjs/editing/collectComponents.js +34 -0
- package/dist/cjs/editing/collectComponents.js.map +1 -0
- package/dist/cjs/editing/collectIconUsages.js +86 -0
- package/dist/cjs/editing/collectIconUsages.js.map +1 -0
- package/dist/cjs/editing/describeNode.js +63 -0
- package/dist/cjs/editing/describeNode.js.map +1 -0
- package/dist/cjs/editing/diagnoseIcons.js +67 -0
- package/dist/cjs/editing/diagnoseIcons.js.map +1 -0
- package/dist/cjs/editing/diagnostics.js +36 -0
- package/dist/cjs/editing/diagnostics.js.map +1 -0
- package/dist/cjs/editing/documentPaths.js +45 -0
- package/dist/cjs/editing/documentPaths.js.map +1 -0
- package/dist/cjs/editing/exposureEdits.js +106 -0
- package/dist/cjs/editing/exposureEdits.js.map +1 -0
- package/dist/cjs/editing/exposureGrants.js +115 -0
- package/dist/cjs/editing/exposureGrants.js.map +1 -0
- package/dist/cjs/editing/iconDiagnostics.js +103 -0
- package/dist/cjs/editing/iconDiagnostics.js.map +1 -0
- package/dist/cjs/editing/indexDocument.js +400 -0
- package/dist/cjs/editing/indexDocument.js.map +1 -0
- package/dist/cjs/editing/inspect.js +154 -0
- package/dist/cjs/editing/inspect.js.map +1 -0
- package/dist/cjs/editing/instanceEdits.js +267 -0
- package/dist/cjs/editing/instanceEdits.js.map +1 -0
- package/dist/cjs/editing/layoutTypeDescriptors.js +425 -0
- package/dist/cjs/editing/layoutTypeDescriptors.js.map +1 -0
- package/dist/cjs/editing/layoutTypeEdits.js +141 -0
- package/dist/cjs/editing/layoutTypeEdits.js.map +1 -0
- package/dist/cjs/editing/nodeIds.js +115 -0
- package/dist/cjs/editing/nodeIds.js.map +1 -0
- package/dist/cjs/editing/pathAccess.js +53 -0
- package/dist/cjs/editing/pathAccess.js.map +1 -0
- package/dist/cjs/editing/propertyEdits.js +125 -0
- package/dist/cjs/editing/propertyEdits.js.map +1 -0
- package/dist/cjs/editing/resolveEffectiveConfiguration.js +200 -0
- package/dist/cjs/editing/resolveEffectiveConfiguration.js.map +1 -0
- package/dist/cjs/editing/resolveTemplateChain.js +100 -0
- package/dist/cjs/editing/resolveTemplateChain.js.map +1 -0
- package/dist/cjs/editing/structureEdits.js +231 -0
- package/dist/cjs/editing/structureEdits.js.map +1 -0
- package/dist/cjs/editing/validateBinding.js +111 -0
- package/dist/cjs/editing/validateBinding.js.map +1 -0
- package/dist/cjs/editing/validateValue.js +114 -0
- package/dist/cjs/editing/validateValue.js.map +1 -0
- package/dist/cjs/icons/EffectiveIconCatalog.js +212 -0
- package/dist/cjs/icons/EffectiveIconCatalog.js.map +1 -0
- package/dist/cjs/icons/EffectiveIconEntry.js +22 -0
- package/dist/cjs/icons/EffectiveIconEntry.js.map +1 -0
- package/dist/cjs/icons/analyzeIconImpact.js +48 -0
- package/dist/cjs/icons/analyzeIconImpact.js.map +1 -0
- package/dist/cjs/icons/matchesIconQuery.js +22 -0
- package/dist/cjs/icons/matchesIconQuery.js.map +1 -0
- package/dist/cjs/icons/resolveIconLibraries.js +45 -0
- package/dist/cjs/icons/resolveIconLibraries.js.map +1 -0
- package/dist/cjs/index.js +67 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/editing/DescriptorCatalog.d.ts +9 -0
- package/dist/esm/editing/DescriptorCatalog.d.ts.map +1 -0
- package/dist/esm/editing/DescriptorCatalog.js +38 -0
- package/dist/esm/editing/DescriptorCatalog.js.map +1 -0
- package/dist/esm/editing/DocumentIndex.d.ts +31 -0
- package/dist/esm/editing/DocumentIndex.d.ts.map +1 -0
- package/dist/esm/editing/DocumentIndex.js +2 -0
- package/dist/esm/editing/DocumentIndex.js.map +1 -0
- package/dist/esm/editing/EditOutcome.d.ts +7 -0
- package/dist/esm/editing/EditOutcome.d.ts.map +1 -0
- package/dist/esm/editing/EditOutcome.js +2 -0
- package/dist/esm/editing/EditOutcome.js.map +1 -0
- package/dist/esm/editing/EditSession.d.ts +20 -0
- package/dist/esm/editing/EditSession.d.ts.map +1 -0
- package/dist/esm/editing/EditSession.js +42 -0
- package/dist/esm/editing/EditSession.js.map +1 -0
- package/dist/esm/editing/EditingContext.d.ts +10 -0
- package/dist/esm/editing/EditingContext.d.ts.map +1 -0
- package/dist/esm/editing/EditingContext.js +2 -0
- package/dist/esm/editing/EditingContext.js.map +1 -0
- package/dist/esm/editing/TemplateChain.d.ts +13 -0
- package/dist/esm/editing/TemplateChain.d.ts.map +1 -0
- package/dist/esm/editing/TemplateChain.js +2 -0
- package/dist/esm/editing/TemplateChain.js.map +1 -0
- package/dist/esm/editing/applyEdit.d.ts +5 -0
- package/dist/esm/editing/applyEdit.d.ts.map +1 -0
- package/dist/esm/editing/applyEdit.js +81 -0
- package/dist/esm/editing/applyEdit.js.map +1 -0
- package/dist/esm/editing/applyEffectiveConfiguration.d.ts +3 -0
- package/dist/esm/editing/applyEffectiveConfiguration.d.ts.map +1 -0
- package/dist/esm/editing/applyEffectiveConfiguration.js +60 -0
- package/dist/esm/editing/applyEffectiveConfiguration.js.map +1 -0
- package/dist/esm/editing/collectComponents.d.ts +3 -0
- package/dist/esm/editing/collectComponents.d.ts.map +1 -0
- package/dist/esm/editing/collectComponents.js +32 -0
- package/dist/esm/editing/collectComponents.js.map +1 -0
- package/dist/esm/editing/collectIconUsages.d.ts +5 -0
- package/dist/esm/editing/collectIconUsages.d.ts.map +1 -0
- package/dist/esm/editing/collectIconUsages.js +84 -0
- package/dist/esm/editing/collectIconUsages.js.map +1 -0
- package/dist/esm/editing/describeNode.d.ts +11 -0
- package/dist/esm/editing/describeNode.d.ts.map +1 -0
- package/dist/esm/editing/describeNode.js +60 -0
- package/dist/esm/editing/describeNode.js.map +1 -0
- package/dist/esm/editing/diagnoseIcons.d.ts +4 -0
- package/dist/esm/editing/diagnoseIcons.d.ts.map +1 -0
- package/dist/esm/editing/diagnoseIcons.js +65 -0
- package/dist/esm/editing/diagnoseIcons.js.map +1 -0
- package/dist/esm/editing/diagnostics.d.ts +6 -0
- package/dist/esm/editing/diagnostics.d.ts.map +1 -0
- package/dist/esm/editing/diagnostics.js +32 -0
- package/dist/esm/editing/diagnostics.js.map +1 -0
- package/dist/esm/editing/documentPaths.d.ts +8 -0
- package/dist/esm/editing/documentPaths.d.ts.map +1 -0
- package/dist/esm/editing/documentPaths.js +41 -0
- package/dist/esm/editing/documentPaths.js.map +1 -0
- package/dist/esm/editing/exposureEdits.d.ts +5 -0
- package/dist/esm/editing/exposureEdits.d.ts.map +1 -0
- package/dist/esm/editing/exposureEdits.js +103 -0
- package/dist/esm/editing/exposureEdits.js.map +1 -0
- package/dist/esm/editing/exposureGrants.d.ts +21 -0
- package/dist/esm/editing/exposureGrants.d.ts.map +1 -0
- package/dist/esm/editing/exposureGrants.js +112 -0
- package/dist/esm/editing/exposureGrants.js.map +1 -0
- package/dist/esm/editing/given/a_layout_document.d.ts +14 -0
- package/dist/esm/editing/given/a_layout_document.d.ts.map +1 -0
- package/dist/esm/editing/given/a_layout_document.js +67 -0
- package/dist/esm/editing/given/a_layout_document.js.map +1 -0
- package/dist/esm/editing/given/a_scene_document.d.ts +20 -0
- package/dist/esm/editing/given/a_scene_document.d.ts.map +1 -0
- package/dist/esm/editing/given/a_scene_document.js +110 -0
- package/dist/esm/editing/given/a_scene_document.js.map +1 -0
- package/dist/esm/editing/iconDiagnostics.d.ts +11 -0
- package/dist/esm/editing/iconDiagnostics.d.ts.map +1 -0
- package/dist/esm/editing/iconDiagnostics.js +99 -0
- package/dist/esm/editing/iconDiagnostics.js.map +1 -0
- package/dist/esm/editing/index.d.ts +22 -0
- package/dist/esm/editing/index.d.ts.map +1 -0
- package/dist/esm/editing/index.js +22 -0
- package/dist/esm/editing/index.js.map +1 -0
- package/dist/esm/editing/indexDocument.d.ts +6 -0
- package/dist/esm/editing/indexDocument.d.ts.map +1 -0
- package/dist/esm/editing/indexDocument.js +396 -0
- package/dist/esm/editing/indexDocument.js.map +1 -0
- package/dist/esm/editing/inspect.d.ts +8 -0
- package/dist/esm/editing/inspect.d.ts.map +1 -0
- package/dist/esm/editing/inspect.js +151 -0
- package/dist/esm/editing/inspect.js.map +1 -0
- package/dist/esm/editing/instanceEdits.d.ts +9 -0
- package/dist/esm/editing/instanceEdits.d.ts.map +1 -0
- package/dist/esm/editing/instanceEdits.js +260 -0
- package/dist/esm/editing/instanceEdits.js.map +1 -0
- package/dist/esm/editing/layoutTypeDescriptors.d.ts +5 -0
- package/dist/esm/editing/layoutTypeDescriptors.d.ts.map +1 -0
- package/dist/esm/editing/layoutTypeDescriptors.js +421 -0
- package/dist/esm/editing/layoutTypeDescriptors.js.map +1 -0
- package/dist/esm/editing/layoutTypeEdits.d.ts +4 -0
- package/dist/esm/editing/layoutTypeEdits.d.ts.map +1 -0
- package/dist/esm/editing/layoutTypeEdits.js +139 -0
- package/dist/esm/editing/layoutTypeEdits.js.map +1 -0
- package/dist/esm/editing/nodeIds.d.ts +14 -0
- package/dist/esm/editing/nodeIds.d.ts.map +1 -0
- package/dist/esm/editing/nodeIds.js +102 -0
- package/dist/esm/editing/nodeIds.js.map +1 -0
- package/dist/esm/editing/pathAccess.d.ts +7 -0
- package/dist/esm/editing/pathAccess.d.ts.map +1 -0
- package/dist/esm/editing/pathAccess.js +48 -0
- package/dist/esm/editing/pathAccess.js.map +1 -0
- package/dist/esm/editing/propertyEdits.d.ts +15 -0
- package/dist/esm/editing/propertyEdits.d.ts.map +1 -0
- package/dist/esm/editing/propertyEdits.js +120 -0
- package/dist/esm/editing/propertyEdits.js.map +1 -0
- package/dist/esm/editing/resolveEffectiveConfiguration.d.ts +5 -0
- package/dist/esm/editing/resolveEffectiveConfiguration.d.ts.map +1 -0
- package/dist/esm/editing/resolveEffectiveConfiguration.js +198 -0
- package/dist/esm/editing/resolveEffectiveConfiguration.js.map +1 -0
- package/dist/esm/editing/resolveTemplateChain.d.ts +4 -0
- package/dist/esm/editing/resolveTemplateChain.d.ts.map +1 -0
- package/dist/esm/editing/resolveTemplateChain.js +98 -0
- package/dist/esm/editing/resolveTemplateChain.js.map +1 -0
- package/dist/esm/editing/structureEdits.d.ts +6 -0
- package/dist/esm/editing/structureEdits.d.ts.map +1 -0
- package/dist/esm/editing/structureEdits.js +227 -0
- package/dist/esm/editing/structureEdits.js.map +1 -0
- package/dist/esm/editing/validateBinding.d.ts +7 -0
- package/dist/esm/editing/validateBinding.d.ts.map +1 -0
- package/dist/esm/editing/validateBinding.js +108 -0
- package/dist/esm/editing/validateBinding.js.map +1 -0
- package/dist/esm/editing/validateValue.d.ts +8 -0
- package/dist/esm/editing/validateValue.d.ts.map +1 -0
- package/dist/esm/editing/validateValue.js +111 -0
- package/dist/esm/editing/validateValue.js.map +1 -0
- package/dist/esm/icons/EffectiveIconCatalog.d.ts +25 -0
- package/dist/esm/icons/EffectiveIconCatalog.d.ts.map +1 -0
- package/dist/esm/icons/EffectiveIconCatalog.js +210 -0
- package/dist/esm/icons/EffectiveIconCatalog.js.map +1 -0
- package/dist/esm/icons/EffectiveIconEntry.d.ts +9 -0
- package/dist/esm/icons/EffectiveIconEntry.d.ts.map +1 -0
- package/dist/esm/icons/EffectiveIconEntry.js +20 -0
- package/dist/esm/icons/EffectiveIconEntry.js.map +1 -0
- package/dist/esm/icons/IconCatalogSource.d.ts +6 -0
- package/dist/esm/icons/IconCatalogSource.d.ts.map +1 -0
- package/dist/esm/icons/IconCatalogSource.js +2 -0
- package/dist/esm/icons/IconCatalogSource.js.map +1 -0
- package/dist/esm/icons/IconDiagnostic.d.ts +9 -0
- package/dist/esm/icons/IconDiagnostic.d.ts.map +1 -0
- package/dist/esm/icons/IconDiagnostic.js +2 -0
- package/dist/esm/icons/IconDiagnostic.js.map +1 -0
- package/dist/esm/icons/IconImpactReport.d.ts +18 -0
- package/dist/esm/icons/IconImpactReport.d.ts.map +1 -0
- package/dist/esm/icons/IconImpactReport.js +2 -0
- package/dist/esm/icons/IconImpactReport.js.map +1 -0
- package/dist/esm/icons/IconLibraryResolution.d.ts +7 -0
- package/dist/esm/icons/IconLibraryResolution.d.ts.map +1 -0
- package/dist/esm/icons/IconLibraryResolution.js +2 -0
- package/dist/esm/icons/IconLibraryResolution.js.map +1 -0
- package/dist/esm/icons/IconQuery.d.ts +7 -0
- package/dist/esm/icons/IconQuery.d.ts.map +1 -0
- package/dist/esm/icons/IconQuery.js +2 -0
- package/dist/esm/icons/IconQuery.js.map +1 -0
- package/dist/esm/icons/IconResolution.d.ts +14 -0
- package/dist/esm/icons/IconResolution.d.ts.map +1 -0
- package/dist/esm/icons/IconResolution.js +2 -0
- package/dist/esm/icons/IconResolution.js.map +1 -0
- package/dist/esm/icons/IconSearchResult.d.ts +7 -0
- package/dist/esm/icons/IconSearchResult.d.ts.map +1 -0
- package/dist/esm/icons/IconSearchResult.js +2 -0
- package/dist/esm/icons/IconSearchResult.js.map +1 -0
- package/dist/esm/icons/IconUsage.d.ts +6 -0
- package/dist/esm/icons/IconUsage.d.ts.map +1 -0
- package/dist/esm/icons/IconUsage.js +2 -0
- package/dist/esm/icons/IconUsage.js.map +1 -0
- package/dist/esm/icons/ResolvedIconLibrary.d.ts +8 -0
- package/dist/esm/icons/ResolvedIconLibrary.d.ts.map +1 -0
- package/dist/esm/icons/ResolvedIconLibrary.js +2 -0
- package/dist/esm/icons/ResolvedIconLibrary.js.map +1 -0
- package/dist/esm/icons/analyzeIconImpact.d.ts +5 -0
- package/dist/esm/icons/analyzeIconImpact.d.ts.map +1 -0
- package/dist/esm/icons/analyzeIconImpact.js +46 -0
- package/dist/esm/icons/analyzeIconImpact.js.map +1 -0
- package/dist/esm/icons/index.d.ts +14 -0
- package/dist/esm/icons/index.d.ts.map +1 -0
- package/dist/esm/icons/index.js +14 -0
- package/dist/esm/icons/index.js.map +1 -0
- package/dist/esm/icons/matchesIconQuery.d.ts +4 -0
- package/dist/esm/icons/matchesIconQuery.d.ts.map +1 -0
- package/dist/esm/icons/matchesIconQuery.js +20 -0
- package/dist/esm/icons/matchesIconQuery.js.map +1 -0
- package/dist/esm/icons/resolveIconLibraries.d.ts +4 -0
- package/dist/esm/icons/resolveIconLibraries.d.ts.map +1 -0
- package/dist/esm/icons/resolveIconLibraries.js +43 -0
- package/dist/esm/icons/resolveIconLibraries.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/editing/DescriptorCatalog.ts +51 -0
- package/editing/DocumentIndex.ts +73 -0
- package/editing/EditOutcome.ts +21 -0
- package/editing/EditSession.ts +50 -0
- package/editing/EditingContext.ts +34 -0
- package/editing/TemplateChain.ts +36 -0
- package/editing/applyEdit.ts +69 -0
- package/editing/applyEffectiveConfiguration.ts +53 -0
- package/editing/collectComponents.ts +36 -0
- package/editing/collectIconUsages.ts +78 -0
- package/editing/describeNode.ts +61 -0
- package/editing/diagnoseIcons.ts +60 -0
- package/editing/diagnostics.ts +30 -0
- package/editing/documentPaths.ts +40 -0
- package/editing/exposureEdits.ts +119 -0
- package/editing/exposureGrants.ts +159 -0
- package/editing/given/a_layout_document.ts +88 -0
- package/editing/given/a_scene_document.ts +135 -0
- package/editing/iconDiagnostics.ts +90 -0
- package/editing/index.ts +24 -0
- package/editing/indexDocument.ts +237 -0
- package/editing/inspect.ts +165 -0
- package/editing/instanceEdits.ts +251 -0
- package/editing/layoutTypeDescriptors.ts +191 -0
- package/editing/layoutTypeEdits.ts +135 -0
- package/editing/nodeIds.ts +111 -0
- package/editing/pathAccess.ts +81 -0
- package/editing/propertyEdits.ts +127 -0
- package/editing/resolveEffectiveConfiguration.ts +202 -0
- package/editing/resolveTemplateChain.ts +109 -0
- package/editing/structureEdits.ts +234 -0
- package/editing/validateBinding.ts +103 -0
- package/editing/validateValue.ts +130 -0
- package/icons/EffectiveIconCatalog.ts +199 -0
- package/icons/EffectiveIconEntry.ts +36 -0
- package/icons/IconCatalogSource.ts +23 -0
- package/icons/IconDiagnostic.ts +45 -0
- package/icons/IconImpactReport.ts +63 -0
- package/icons/IconLibraryResolution.ts +22 -0
- package/icons/IconQuery.ts +27 -0
- package/icons/IconResolution.ts +25 -0
- package/icons/IconSearchResult.ts +21 -0
- package/icons/IconUsage.ts +21 -0
- package/icons/ResolvedIconLibrary.ts +32 -0
- package/icons/analyzeIconImpact.ts +41 -0
- package/icons/index.ts +16 -0
- package/icons/matchesIconQuery.ts +19 -0
- package/icons/resolveIconLibraries.ts +47 -0
- package/index.ts +2 -0
- package/package.json +3 -3
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
|
|
5
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
6
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function isNonEmptyString(value) {
|
|
11
|
+
return typeof value === 'string' && value.length > 0;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks a value against a property descriptor.
|
|
15
|
+
*
|
|
16
|
+
* @param descriptor The property the value is for.
|
|
17
|
+
* @param value The value to check. `undefined` means "not set", which is fine unless the property is required.
|
|
18
|
+
* @returns The reason the value is not acceptable, or `undefined` when it is.
|
|
19
|
+
*/ function validateValue(descriptor, value) {
|
|
20
|
+
const constraints = descriptor.constraints ?? {};
|
|
21
|
+
if (value === undefined || value === null) {
|
|
22
|
+
return constraints.required ? 'a value is required' : undefined;
|
|
23
|
+
}
|
|
24
|
+
switch(descriptor.valueType){
|
|
25
|
+
case scene_model.PropertyValueType.String:
|
|
26
|
+
{
|
|
27
|
+
if (typeof value !== 'string') return 'expected a string';
|
|
28
|
+
if (constraints.minimumLength !== undefined && value.length < constraints.minimumLength) return `must be at least ${constraints.minimumLength} characters`;
|
|
29
|
+
if (constraints.maximumLength !== undefined && value.length > constraints.maximumLength) return `must be at most ${constraints.maximumLength} characters`;
|
|
30
|
+
if (constraints.pattern !== undefined && !new RegExp(`^(?:${constraints.pattern})$`).test(value)) return `must match ${constraints.pattern}`;
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
case scene_model.PropertyValueType.Number:
|
|
34
|
+
{
|
|
35
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return 'expected a number';
|
|
36
|
+
if (constraints.integer && !Number.isInteger(value)) return 'expected a whole number';
|
|
37
|
+
if (constraints.minimum !== undefined && value < constraints.minimum) return `must be at least ${constraints.minimum}`;
|
|
38
|
+
if (constraints.maximum !== undefined && value > constraints.maximum) return `must be at most ${constraints.maximum}`;
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
case scene_model.PropertyValueType.Boolean:
|
|
42
|
+
return typeof value === 'boolean' ? undefined : 'expected true or false';
|
|
43
|
+
case scene_model.PropertyValueType.Enum:
|
|
44
|
+
return (descriptor.choices ?? []).some((choice)=>choice.value === value) ? undefined : 'not one of the allowed choices';
|
|
45
|
+
case scene_model.PropertyValueType.Icon:
|
|
46
|
+
if (!isRecord(value) || !isNonEmptyString(value.library) || !isNonEmptyString(value.key)) return 'expected an icon reference with a library and a key';
|
|
47
|
+
return value.variant === undefined || typeof value.variant === 'string' ? undefined : 'the icon variant must be a string';
|
|
48
|
+
case scene_model.PropertyValueType.Destination:
|
|
49
|
+
if (!isRecord(value) || !isNonEmptyString(value.screen)) return 'expected a destination naming a screen';
|
|
50
|
+
return value.routeParameterBindings === undefined || isRecord(value.routeParameterBindings) ? undefined : 'routeParameterBindings must be an object';
|
|
51
|
+
case scene_model.PropertyValueType.QueryReference:
|
|
52
|
+
if (isNonEmptyString(value)) return undefined;
|
|
53
|
+
if (!isRecord(value) || !isNonEmptyString(value.queryId) || !isNonEmptyString(value.query)) return 'expected a query name or a query binding';
|
|
54
|
+
return Array.isArray(value.arguments) && Array.isArray(value.results) ? undefined : 'a query binding needs arguments and results lists';
|
|
55
|
+
case scene_model.PropertyValueType.Collection:
|
|
56
|
+
return validateCollection(descriptor, value);
|
|
57
|
+
default:
|
|
58
|
+
return isRecord(value) || Array.isArray(value) ? undefined : 'expected a structured value';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function validateCollection(descriptor, value) {
|
|
62
|
+
if (!Array.isArray(value)) return 'expected a list';
|
|
63
|
+
const constraints = descriptor.constraints ?? {};
|
|
64
|
+
if (constraints.minimumItems !== undefined && value.length < constraints.minimumItems) return `needs at least ${constraints.minimumItems} items`;
|
|
65
|
+
if (constraints.maximumItems !== undefined && value.length > constraints.maximumItems) return `allows at most ${constraints.maximumItems} items`;
|
|
66
|
+
const identities = new Set();
|
|
67
|
+
for (const item of value){
|
|
68
|
+
if (!isRecord(item) || !isNonEmptyString(item.id)) return 'every item needs an id';
|
|
69
|
+
if (identities.has(item.id)) return `the item id '${item.id}' is used twice`;
|
|
70
|
+
identities.add(item.id);
|
|
71
|
+
const { id: _identity, ...values } = item;
|
|
72
|
+
const problem = validateItemValues(descriptor.item, values).at(0);
|
|
73
|
+
if (problem) return `item '${item.id}': ${problem.field} ${problem.problem}`;
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Checks a collection item's field values against the collection's item descriptor.
|
|
79
|
+
*
|
|
80
|
+
* @param itemDescriptor What the items look like.
|
|
81
|
+
* @param values The item's field values, keyed by field path.
|
|
82
|
+
* @returns Every field that is unknown or has an unacceptable value.
|
|
83
|
+
*/ function validateItemValues(itemDescriptor, values) {
|
|
84
|
+
const fields = itemDescriptor?.properties ?? [];
|
|
85
|
+
const problems = [];
|
|
86
|
+
for (const [field, fieldValue] of Object.entries(values)){
|
|
87
|
+
const fieldDescriptor = fields.find((candidate)=>candidate.path === field);
|
|
88
|
+
if (!fieldDescriptor) {
|
|
89
|
+
problems.push({
|
|
90
|
+
field,
|
|
91
|
+
problem: 'is not a field of this collection\'s items'
|
|
92
|
+
});
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const problem = validateValue(fieldDescriptor, fieldValue);
|
|
96
|
+
if (problem) problems.push({
|
|
97
|
+
field,
|
|
98
|
+
problem
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
for (const fieldDescriptor of fields){
|
|
102
|
+
if (fieldDescriptor.constraints?.required && values[fieldDescriptor.path] === undefined) {
|
|
103
|
+
problems.push({
|
|
104
|
+
field: fieldDescriptor.path,
|
|
105
|
+
problem: 'a value is required'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return problems;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
exports.validateItemValues = validateItemValues;
|
|
113
|
+
exports.validateValue = validateValue;
|
|
114
|
+
//# sourceMappingURL=validateValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateValue.js","sources":["../../../editing/validateValue.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { CollectionItemDescriptor, PropertyDescriptor, PropertyValueType } from '@cratis/scene.model';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\n/**\n * Checks a value against a property descriptor.\n *\n * @param descriptor The property the value is for.\n * @param value The value to check. `undefined` means \"not set\", which is fine unless the property is required.\n * @returns The reason the value is not acceptable, or `undefined` when it is.\n */\nexport function validateValue(descriptor: PropertyDescriptor, value: unknown): string | undefined {\n const constraints = descriptor.constraints ?? {};\n if (value === undefined || value === null) {\n return constraints.required ? 'a value is required' : undefined;\n }\n\n switch (descriptor.valueType) {\n case PropertyValueType.String: {\n if (typeof value !== 'string') return 'expected a string';\n if (constraints.minimumLength !== undefined && value.length < constraints.minimumLength) return `must be at least ${constraints.minimumLength} characters`;\n if (constraints.maximumLength !== undefined && value.length > constraints.maximumLength) return `must be at most ${constraints.maximumLength} characters`;\n if (constraints.pattern !== undefined && !new RegExp(`^(?:${constraints.pattern})$`).test(value)) return `must match ${constraints.pattern}`;\n return undefined;\n }\n\n case PropertyValueType.Number: {\n if (typeof value !== 'number' || !Number.isFinite(value)) return 'expected a number';\n if (constraints.integer && !Number.isInteger(value)) return 'expected a whole number';\n if (constraints.minimum !== undefined && value < constraints.minimum) return `must be at least ${constraints.minimum}`;\n if (constraints.maximum !== undefined && value > constraints.maximum) return `must be at most ${constraints.maximum}`;\n return undefined;\n }\n\n case PropertyValueType.Boolean:\n return typeof value === 'boolean' ? undefined : 'expected true or false';\n\n case PropertyValueType.Enum:\n return (descriptor.choices ?? []).some(choice => choice.value === value) ? undefined : 'not one of the allowed choices';\n\n case PropertyValueType.Icon:\n if (!isRecord(value) || !isNonEmptyString(value.library) || !isNonEmptyString(value.key)) return 'expected an icon reference with a library and a key';\n return value.variant === undefined || typeof value.variant === 'string' ? undefined : 'the icon variant must be a string';\n\n case PropertyValueType.Destination:\n if (!isRecord(value) || !isNonEmptyString(value.screen)) return 'expected a destination naming a screen';\n return value.routeParameterBindings === undefined || isRecord(value.routeParameterBindings)\n ? undefined\n : 'routeParameterBindings must be an object';\n\n case PropertyValueType.QueryReference:\n if (isNonEmptyString(value)) return undefined;\n if (!isRecord(value) || !isNonEmptyString(value.queryId) || !isNonEmptyString(value.query)) return 'expected a query name or a query binding';\n return Array.isArray(value.arguments) && Array.isArray(value.results) ? undefined : 'a query binding needs arguments and results lists';\n\n case PropertyValueType.Collection:\n return validateCollection(descriptor, value);\n\n default:\n return isRecord(value) || Array.isArray(value) ? undefined : 'expected a structured value';\n }\n}\n\nfunction validateCollection(descriptor: PropertyDescriptor, value: unknown): string | undefined {\n if (!Array.isArray(value)) return 'expected a list';\n const constraints = descriptor.constraints ?? {};\n if (constraints.minimumItems !== undefined && value.length < constraints.minimumItems) return `needs at least ${constraints.minimumItems} items`;\n if (constraints.maximumItems !== undefined && value.length > constraints.maximumItems) return `allows at most ${constraints.maximumItems} items`;\n\n const identities = new Set<string>();\n for (const item of value) {\n if (!isRecord(item) || !isNonEmptyString(item.id)) return 'every item needs an id';\n if (identities.has(item.id)) return `the item id '${item.id}' is used twice`;\n identities.add(item.id);\n\n const { id: _identity, ...values } = item;\n const problem = validateItemValues(descriptor.item, values).at(0);\n if (problem) return `item '${item.id}': ${problem.field} ${problem.problem}`;\n }\n\n return undefined;\n}\n\n/**\n * One field of a collection item that does not fit its descriptor.\n */\nexport interface ItemFieldProblem {\n field: string;\n problem: string;\n}\n\n/**\n * Checks a collection item's field values against the collection's item descriptor.\n *\n * @param itemDescriptor What the items look like.\n * @param values The item's field values, keyed by field path.\n * @returns Every field that is unknown or has an unacceptable value.\n */\nexport function validateItemValues(itemDescriptor: CollectionItemDescriptor | undefined, values: Record<string, unknown>): ItemFieldProblem[] {\n const fields = itemDescriptor?.properties ?? [];\n const problems: ItemFieldProblem[] = [];\n\n for (const [field, fieldValue] of Object.entries(values)) {\n const fieldDescriptor = fields.find(candidate => candidate.path === field);\n if (!fieldDescriptor) {\n problems.push({ field, problem: 'is not a field of this collection\\'s items' });\n continue;\n }\n\n const problem = validateValue(fieldDescriptor, fieldValue);\n if (problem) problems.push({ field, problem });\n }\n\n for (const fieldDescriptor of fields) {\n if (fieldDescriptor.constraints?.required && values[fieldDescriptor.path] === undefined) {\n problems.push({ field: fieldDescriptor.path, problem: 'a value is required' });\n }\n }\n\n return problems;\n}\n"],"names":["isRecord","value","Array","isArray","isNonEmptyString","length","validateValue","descriptor","constraints","undefined","required","valueType","PropertyValueType","String","minimumLength","maximumLength","pattern","RegExp","test","Number","isFinite","integer","isInteger","minimum","maximum","Boolean","Enum","choices","some","choice","Icon","library","key","variant","Destination","screen","routeParameterBindings","QueryReference","queryId","query","arguments","results","Collection","validateCollection","minimumItems","maximumItems","identities","Set","item","id","has","add","_identity","values","problem","validateItemValues","at","field","itemDescriptor","fields","properties","problems","fieldValue","Object","entries","fieldDescriptor","find","candidate","path","push"],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
var EffectiveIconEntry = require('./EffectiveIconEntry.js');
|
|
5
|
+
var matchesIconQuery = require('./matchesIconQuery.js');
|
|
6
|
+
|
|
7
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
8
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
9
|
+
/**
|
|
10
|
+
* The icons a profile can actually use: the active libraries from {@link resolveIconLibraries}, with their
|
|
11
|
+
* catalogs loaded on demand.
|
|
12
|
+
*
|
|
13
|
+
* Opening it costs nothing - no catalog is read until a query or a lookup needs that library, and a
|
|
14
|
+
* query narrowed to one library reads only that one. A catalog is loaded once and kept; a load that
|
|
15
|
+
* fails is not kept, so the next call tries again. Everything that goes wrong is reported as an
|
|
16
|
+
* {@link IconDiagnostic}; nothing is ever answered with a different icon than the one asked for.
|
|
17
|
+
*/ class EffectiveIconCatalog {
|
|
18
|
+
resolution;
|
|
19
|
+
#sources;
|
|
20
|
+
#loads = new Map();
|
|
21
|
+
#loadedEntries = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* @param resolution The active libraries and the problems found with them.
|
|
24
|
+
* @param sources The catalog source of each library; a library with none is active but reports
|
|
25
|
+
* 'catalog-unavailable' when its icons are needed.
|
|
26
|
+
*/ constructor(resolution, sources){
|
|
27
|
+
this.resolution = resolution;
|
|
28
|
+
this.#sources = new Map(sources.map((source)=>[
|
|
29
|
+
source.library,
|
|
30
|
+
source
|
|
31
|
+
]));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The active libraries, with provenance.
|
|
35
|
+
*/ get libraries() {
|
|
36
|
+
return this.resolution.libraries;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Problems with the libraries themselves, known without loading any catalog.
|
|
40
|
+
*/ get diagnostics() {
|
|
41
|
+
return this.resolution.diagnostics;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether a library's catalog has been read yet.
|
|
45
|
+
*/ isLoaded(library) {
|
|
46
|
+
return this.#loadedEntries.has(library);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The entries of one library, loading its catalog if this is the first time it is needed.
|
|
50
|
+
* Resolves to `undefined` when the library is not active.
|
|
51
|
+
*
|
|
52
|
+
* @throws Whatever the library's source throws, or an Error when an active library has no source.
|
|
53
|
+
*/ async entriesOf(library) {
|
|
54
|
+
if (!this.libraries.some((resolved)=>resolved.library === library)) return undefined;
|
|
55
|
+
let load = this.#loads.get(library);
|
|
56
|
+
if (!load) {
|
|
57
|
+
const source = this.#sources.get(library);
|
|
58
|
+
if (!source) throw new Error(`The icon library '${library}' is active but has no catalog source`);
|
|
59
|
+
load = source.loadEntries();
|
|
60
|
+
this.#loads.set(library, load);
|
|
61
|
+
load.then((entries)=>this.#loadedEntries.set(library, entries), ()=>this.#loads.delete(library));
|
|
62
|
+
}
|
|
63
|
+
return load;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Searches the catalogs of the libraries the query covers - all of them, or the one it names.
|
|
67
|
+
*/ async search(query = {}) {
|
|
68
|
+
const covered = this.libraries.filter((resolved)=>query.library === undefined || resolved.library === query.library);
|
|
69
|
+
const outcomes = await Promise.all(covered.map(async (resolved)=>this.#entriesOrDiagnostic(resolved)));
|
|
70
|
+
const entries = [];
|
|
71
|
+
const diagnostics = [];
|
|
72
|
+
outcomes.forEach((outcome, position)=>{
|
|
73
|
+
const library = covered[position];
|
|
74
|
+
if ('diagnostic' in outcome) {
|
|
75
|
+
diagnostics.push(outcome.diagnostic);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (const entry of outcome.entries.filter((candidate)=>matchesIconQuery.matchesIconQuery(candidate, query))){
|
|
79
|
+
entries.push({
|
|
80
|
+
library,
|
|
81
|
+
entry,
|
|
82
|
+
references: EffectiveIconEntry.referencesOfEntry(library.library, entry)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
entries,
|
|
88
|
+
diagnostics
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Every active library's icons whose name or key is exactly `name` (ignoring case) - the several
|
|
93
|
+
* candidates a bare legacy icon name could have meant. More than one is a real answer, not a tie to
|
|
94
|
+
* break: it is the author's decision which library the icon comes from.
|
|
95
|
+
*/ async findByName(name) {
|
|
96
|
+
const wanted = name.trim().toLowerCase();
|
|
97
|
+
const { entries } = await this.search({});
|
|
98
|
+
return entries.filter(({ entry })=>entry.key.toLowerCase() === wanted || entry.name.toLowerCase() === wanted);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The categories in use, sorted, across all libraries or one.
|
|
102
|
+
*/ async categories(library) {
|
|
103
|
+
const { entries } = await this.search({
|
|
104
|
+
library
|
|
105
|
+
});
|
|
106
|
+
return [
|
|
107
|
+
...new Set(entries.flatMap(({ entry })=>entry.categories))
|
|
108
|
+
].sort();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Looks a reference up: the icon it names, or exactly why there is none.
|
|
112
|
+
*/ async resolve(reference) {
|
|
113
|
+
const library = this.libraries.find((resolved)=>resolved.library === reference.library);
|
|
114
|
+
if (library && !this.isLoaded(library.library) && !this.#incompatibility(library)) {
|
|
115
|
+
const outcome = await this.#entriesOrDiagnostic(library);
|
|
116
|
+
if ('diagnostic' in outcome) return {
|
|
117
|
+
isResolved: false,
|
|
118
|
+
reference,
|
|
119
|
+
diagnostic: {
|
|
120
|
+
...outcome.diagnostic,
|
|
121
|
+
reference
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return this.lookup(reference);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Looks a reference up without loading anything, for callers that cannot wait - an edit is applied
|
|
129
|
+
* synchronously. Resolves everything that is decidable from what is already known: a library that is not
|
|
130
|
+
* active, one at an incompatible version, and - once the library's catalog has been loaded - a missing
|
|
131
|
+
* icon or variant.
|
|
132
|
+
*
|
|
133
|
+
* @returns The resolution, or `undefined` when the library is active but its catalog has not been loaded,
|
|
134
|
+
* so nothing can be said about the icon yet. Call {@link load} first to make the answer definite.
|
|
135
|
+
*/ lookup(reference) {
|
|
136
|
+
const library = this.libraries.find((resolved)=>resolved.library === reference.library);
|
|
137
|
+
if (!library) {
|
|
138
|
+
return this.#unresolved(reference, 'missing-library', `The icon library '${reference.library}' is not active in this profile`);
|
|
139
|
+
}
|
|
140
|
+
const incompatible = this.#incompatibility(library);
|
|
141
|
+
if (incompatible) return {
|
|
142
|
+
isResolved: false,
|
|
143
|
+
reference,
|
|
144
|
+
diagnostic: {
|
|
145
|
+
...incompatible,
|
|
146
|
+
reference
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const entries = this.#loadedEntries.get(library.library);
|
|
150
|
+
if (!entries) return undefined;
|
|
151
|
+
const entry = entries.find((candidate)=>candidate.key === reference.key);
|
|
152
|
+
if (!entry) {
|
|
153
|
+
return this.#unresolved(reference, 'missing-icon', `The icon library '${library.library}' has no icon '${reference.key}'`);
|
|
154
|
+
}
|
|
155
|
+
if (reference.variant !== undefined && !(entry.variants ?? []).includes(reference.variant)) {
|
|
156
|
+
return this.#unresolved(reference, 'missing-variant', `The icon '${scene_model.formatIconReference({
|
|
157
|
+
library: library.library,
|
|
158
|
+
key: entry.key
|
|
159
|
+
})}' has no '${reference.variant}' variant`);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
isResolved: true,
|
|
163
|
+
reference,
|
|
164
|
+
library,
|
|
165
|
+
entry
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Loads the catalogs of one library, or of every active library, so that {@link lookup} can answer
|
|
170
|
+
* definitely. Libraries whose catalog cannot be loaded are reported, not thrown.
|
|
171
|
+
*/ async load(library) {
|
|
172
|
+
const covered = this.libraries.filter((resolved)=>library === undefined || resolved.library === library);
|
|
173
|
+
const outcomes = await Promise.all(covered.map(async (resolved)=>this.#entriesOrDiagnostic(resolved)));
|
|
174
|
+
return outcomes.flatMap((outcome)=>'diagnostic' in outcome ? [
|
|
175
|
+
outcome.diagnostic
|
|
176
|
+
] : []);
|
|
177
|
+
}
|
|
178
|
+
#incompatibility(library) {
|
|
179
|
+
return this.diagnostics.find((diagnostic)=>diagnostic.kind === 'incompatible-version' && diagnostic.library === library.library);
|
|
180
|
+
}
|
|
181
|
+
async #entriesOrDiagnostic(library) {
|
|
182
|
+
try {
|
|
183
|
+
return {
|
|
184
|
+
entries: await this.entriesOf(library.library) ?? []
|
|
185
|
+
};
|
|
186
|
+
} catch (error) {
|
|
187
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
188
|
+
return {
|
|
189
|
+
diagnostic: {
|
|
190
|
+
kind: 'catalog-unavailable',
|
|
191
|
+
library: library.library,
|
|
192
|
+
message: `The catalog of '${library.library}' could not be loaded: ${reason}`
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
#unresolved(reference, kind, message) {
|
|
198
|
+
return {
|
|
199
|
+
isResolved: false,
|
|
200
|
+
reference,
|
|
201
|
+
diagnostic: {
|
|
202
|
+
kind,
|
|
203
|
+
library: reference.library,
|
|
204
|
+
message,
|
|
205
|
+
reference
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
exports.EffectiveIconCatalog = EffectiveIconCatalog;
|
|
212
|
+
//# sourceMappingURL=EffectiveIconCatalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectiveIconCatalog.js","sources":["../../../icons/EffectiveIconCatalog.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconEntry, IconReference, formatIconReference } from '@cratis/scene.model';\nimport { EffectiveIconEntry, referencesOfEntry } from './EffectiveIconEntry';\nimport { IconCatalogSource } from './IconCatalogSource';\nimport { IconDiagnostic } from './IconDiagnostic';\nimport { IconLibraryResolution } from './IconLibraryResolution';\nimport { IconQuery } from './IconQuery';\nimport { IconResolution } from './IconResolution';\nimport { IconSearchResult } from './IconSearchResult';\nimport { ResolvedIconLibrary } from './ResolvedIconLibrary';\nimport { matchesIconQuery } from './matchesIconQuery';\n\n/**\n * The icons a profile can actually use: the active libraries from {@link resolveIconLibraries}, with their\n * catalogs loaded on demand.\n *\n * Opening it costs nothing - no catalog is read until a query or a lookup needs that library, and a\n * query narrowed to one library reads only that one. A catalog is loaded once and kept; a load that\n * fails is not kept, so the next call tries again. Everything that goes wrong is reported as an\n * {@link IconDiagnostic}; nothing is ever answered with a different icon than the one asked for.\n */\nexport class EffectiveIconCatalog {\n readonly #sources: Map<string, IconCatalogSource>;\n readonly #loads = new Map<string, Promise<IconEntry[]>>();\n readonly #loadedEntries = new Map<string, IconEntry[]>();\n\n /**\n * @param resolution The active libraries and the problems found with them.\n * @param sources The catalog source of each library; a library with none is active but reports\n * 'catalog-unavailable' when its icons are needed.\n */\n constructor(readonly resolution: IconLibraryResolution, sources: IconCatalogSource[]) {\n this.#sources = new Map(sources.map((source) => [source.library, source]));\n }\n\n /**\n * The active libraries, with provenance.\n */\n get libraries(): ResolvedIconLibrary[] {\n return this.resolution.libraries;\n }\n\n /**\n * Problems with the libraries themselves, known without loading any catalog.\n */\n get diagnostics(): IconDiagnostic[] {\n return this.resolution.diagnostics;\n }\n\n /**\n * Whether a library's catalog has been read yet.\n */\n isLoaded(library: string): boolean {\n return this.#loadedEntries.has(library);\n }\n\n /**\n * The entries of one library, loading its catalog if this is the first time it is needed.\n * Resolves to `undefined` when the library is not active.\n *\n * @throws Whatever the library's source throws, or an Error when an active library has no source.\n */\n async entriesOf(library: string): Promise<IconEntry[] | undefined> {\n if (!this.libraries.some((resolved) => resolved.library === library)) return undefined;\n\n let load = this.#loads.get(library);\n if (!load) {\n const source = this.#sources.get(library);\n if (!source) throw new Error(`The icon library '${library}' is active but has no catalog source`);\n\n load = source.loadEntries();\n this.#loads.set(library, load);\n load.then(\n (entries) => this.#loadedEntries.set(library, entries),\n () => this.#loads.delete(library)\n );\n }\n\n return load;\n }\n\n /**\n * Searches the catalogs of the libraries the query covers - all of them, or the one it names.\n */\n async search(query: IconQuery = {}): Promise<IconSearchResult> {\n const covered = this.libraries.filter((resolved) => query.library === undefined || resolved.library === query.library);\n const outcomes = await Promise.all(covered.map(async (resolved) => this.#entriesOrDiagnostic(resolved)));\n\n const entries: EffectiveIconEntry[] = [];\n const diagnostics: IconDiagnostic[] = [];\n outcomes.forEach((outcome, position) => {\n const library = covered[position];\n if ('diagnostic' in outcome) {\n diagnostics.push(outcome.diagnostic);\n return;\n }\n\n for (const entry of outcome.entries.filter((candidate) => matchesIconQuery(candidate, query))) {\n entries.push({ library, entry, references: referencesOfEntry(library.library, entry) });\n }\n });\n\n return { entries, diagnostics };\n }\n\n /**\n * Every active library's icons whose name or key is exactly `name` (ignoring case) - the several\n * candidates a bare legacy icon name could have meant. More than one is a real answer, not a tie to\n * break: it is the author's decision which library the icon comes from.\n */\n async findByName(name: string): Promise<EffectiveIconEntry[]> {\n const wanted = name.trim().toLowerCase();\n const { entries } = await this.search({});\n return entries.filter(({ entry }) => entry.key.toLowerCase() === wanted || entry.name.toLowerCase() === wanted);\n }\n\n /**\n * The categories in use, sorted, across all libraries or one.\n */\n async categories(library?: string): Promise<string[]> {\n const { entries } = await this.search({ library });\n return [...new Set(entries.flatMap(({ entry }) => entry.categories))].sort();\n }\n\n /**\n * Looks a reference up: the icon it names, or exactly why there is none.\n */\n async resolve(reference: IconReference): Promise<IconResolution> {\n const library = this.libraries.find((resolved) => resolved.library === reference.library);\n if (library && !this.isLoaded(library.library) && !this.#incompatibility(library)) {\n const outcome = await this.#entriesOrDiagnostic(library);\n if ('diagnostic' in outcome) return { isResolved: false, reference, diagnostic: { ...outcome.diagnostic, reference } };\n }\n\n return this.lookup(reference) as IconResolution;\n }\n\n /**\n * Looks a reference up without loading anything, for callers that cannot wait - an edit is applied\n * synchronously. Resolves everything that is decidable from what is already known: a library that is not\n * active, one at an incompatible version, and - once the library's catalog has been loaded - a missing\n * icon or variant.\n *\n * @returns The resolution, or `undefined` when the library is active but its catalog has not been loaded,\n * so nothing can be said about the icon yet. Call {@link load} first to make the answer definite.\n */\n lookup(reference: IconReference): IconResolution | undefined {\n const library = this.libraries.find((resolved) => resolved.library === reference.library);\n if (!library) {\n return this.#unresolved(reference, 'missing-library', `The icon library '${reference.library}' is not active in this profile`);\n }\n\n const incompatible = this.#incompatibility(library);\n if (incompatible) return { isResolved: false, reference, diagnostic: { ...incompatible, reference } };\n\n const entries = this.#loadedEntries.get(library.library);\n if (!entries) return undefined;\n\n const entry = entries.find((candidate) => candidate.key === reference.key);\n if (!entry) {\n return this.#unresolved(reference, 'missing-icon', `The icon library '${library.library}' has no icon '${reference.key}'`);\n }\n\n if (reference.variant !== undefined && !(entry.variants ?? []).includes(reference.variant)) {\n return this.#unresolved(reference, 'missing-variant', `The icon '${formatIconReference({ library: library.library, key: entry.key })}' has no '${reference.variant}' variant`);\n }\n\n return { isResolved: true, reference, library, entry };\n }\n\n /**\n * Loads the catalogs of one library, or of every active library, so that {@link lookup} can answer\n * definitely. Libraries whose catalog cannot be loaded are reported, not thrown.\n */\n async load(library?: string): Promise<IconDiagnostic[]> {\n const covered = this.libraries.filter((resolved) => library === undefined || resolved.library === library);\n const outcomes = await Promise.all(covered.map(async (resolved) => this.#entriesOrDiagnostic(resolved)));\n return outcomes.flatMap((outcome) => ('diagnostic' in outcome ? [outcome.diagnostic] : []));\n }\n\n #incompatibility(library: ResolvedIconLibrary): IconDiagnostic | undefined {\n return this.diagnostics.find((diagnostic) => diagnostic.kind === 'incompatible-version' && diagnostic.library === library.library);\n }\n\n async #entriesOrDiagnostic(library: ResolvedIconLibrary): Promise<{ entries: IconEntry[] } | { diagnostic: IconDiagnostic }> {\n try {\n return { entries: (await this.entriesOf(library.library)) ?? [] };\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return { diagnostic: { kind: 'catalog-unavailable', library: library.library, message: `The catalog of '${library.library}' could not be loaded: ${reason}` } };\n }\n }\n\n #unresolved(reference: IconReference, kind: IconDiagnostic['kind'], message: string): IconResolution & { isResolved: false } {\n return { isResolved: false, reference, diagnostic: { kind, library: reference.library, message, reference } };\n }\n}\n"],"names":["EffectiveIconCatalog","Map","resolution","sources","map","source","library","libraries","diagnostics","isLoaded","has","entriesOf","some","resolved","undefined","load","get","Error","loadEntries","set","then","entries","delete","search","query","covered","filter","outcomes","Promise","all","forEach","outcome","position","push","diagnostic","entry","candidate","matchesIconQuery","references","referencesOfEntry","findByName","name","wanted","trim","toLowerCase","key","categories","Set","flatMap","sort","resolve","reference","find","isResolved","lookup","incompatible","variant","variants","includes","formatIconReference","kind","error","reason","message","String"],"mappings":";;;;;;AAAA;AACA;AAaA;;;;;;;;AAQC,IACM,MAAMA,oBAAAA,CAAAA;;AACA,IAAA,QAAQ;IACR,MAAM,GAAG,IAAIC,GAAAA,EAAAA;IACb,cAAc,GAAG,IAAIA,GAAAA,EAAAA;AAE9B;;;;AAIC,QACD,WAAA,CAAqBC,UAAiC,EAAEC,OAA4B,CAAE;aAAjED,UAAAA,GAAAA,UAAAA;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAID,IAAIE,OAAAA,CAAQC,GAAG,CAAC,CAACC,MAAAA,GAAW;AAACA,gBAAAA,MAAAA,CAAOC,OAAO;AAAED,gBAAAA;AAAO,aAAA,CAAA,CAAA;AAC5E,IAAA;AAEA;;AAEC,QACD,IAAIE,SAAAA,GAAmC;AACnC,QAAA,OAAO,IAAI,CAACL,UAAU,CAACK,SAAS;AACpC,IAAA;AAEA;;AAEC,QACD,IAAIC,WAAAA,GAAgC;AAChC,QAAA,OAAO,IAAI,CAACN,UAAU,CAACM,WAAW;AACtC,IAAA;AAEA;;QAGAC,QAAAA,CAASH,OAAe,EAAW;AAC/B,QAAA,OAAO,IAAI,CAAC,cAAc,CAACI,GAAG,CAACJ,OAAAA,CAAAA;AACnC,IAAA;AAEA;;;;;QAMA,MAAMK,SAAAA,CAAUL,OAAe,EAAoC;AAC/D,QAAA,IAAI,CAAC,IAAI,CAACC,SAAS,CAACK,IAAI,CAAC,CAACC,QAAAA,GAAaA,QAAAA,CAASP,OAAO,KAAKA,UAAU,OAAOQ,SAAAA;AAE7E,QAAA,IAAIC,OAAO,IAAI,CAAC,MAAM,CAACC,GAAG,CAACV,OAAAA,CAAAA;AAC3B,QAAA,IAAI,CAACS,IAAAA,EAAM;AACP,YAAA,MAAMV,SAAS,IAAI,CAAC,QAAQ,CAACW,GAAG,CAACV,OAAAA,CAAAA;YACjC,IAAI,CAACD,MAAAA,EAAQ,MAAM,IAAIY,KAAAA,CAAM,CAAC,kBAAkB,EAAEX,OAAAA,CAAQ,qCAAqC,CAAC,CAAA;AAEhGS,YAAAA,IAAAA,GAAOV,OAAOa,WAAW,EAAA;AACzB,YAAA,IAAI,CAAC,MAAM,CAACC,GAAG,CAACb,OAAAA,EAASS,IAAAA,CAAAA;YACzBA,IAAAA,CAAKK,IAAI,CACL,CAACC,OAAAA,GAAY,IAAI,CAAC,cAAc,CAACF,GAAG,CAACb,OAAAA,EAASe,OAAAA,CAAAA,EAC9C,IAAM,IAAI,CAAC,MAAM,CAACC,MAAM,CAAChB,OAAAA,CAAAA,CAAAA;AAEjC,QAAA;QAEA,OAAOS,IAAAA;AACX,IAAA;AAEA;;AAEC,QACD,MAAMQ,MAAAA,CAAOC,KAAAA,GAAmB,EAAE,EAA6B;AAC3D,QAAA,MAAMC,UAAU,IAAI,CAAClB,SAAS,CAACmB,MAAM,CAAC,CAACb,QAAAA,GAAaW,KAAAA,CAAMlB,OAAO,KAAKQ,SAAAA,IAAaD,SAASP,OAAO,KAAKkB,MAAMlB,OAAO,CAAA;AACrH,QAAA,MAAMqB,QAAAA,GAAW,MAAMC,OAAAA,CAAQC,GAAG,CAACJ,OAAAA,CAAQrB,GAAG,CAAC,OAAOS,QAAAA,GAAa,IAAI,CAAC,oBAAoB,CAACA,QAAAA,CAAAA,CAAAA,CAAAA;AAE7F,QAAA,MAAMQ,UAAgC,EAAE;AACxC,QAAA,MAAMb,cAAgC,EAAE;QACxCmB,QAAAA,CAASG,OAAO,CAAC,CAACC,OAAAA,EAASC,QAAAA,GAAAA;YACvB,MAAM1B,OAAAA,GAAUmB,OAAO,CAACO,QAAAA,CAAS;AACjC,YAAA,IAAI,gBAAgBD,OAAAA,EAAS;gBACzBvB,WAAAA,CAAYyB,IAAI,CAACF,OAAAA,CAAQG,UAAU,CAAA;AACnC,gBAAA;AACJ,YAAA;YAEA,KAAK,MAAMC,KAAAA,IAASJ,OAAAA,CAAQV,OAAO,CAACK,MAAM,CAAC,CAACU,SAAAA,GAAcC,iCAAAA,CAAiBD,SAAAA,EAAWZ,KAAAA,CAAAA,CAAAA,CAAS;AAC3FH,gBAAAA,OAAAA,CAAQY,IAAI,CAAC;AAAE3B,oBAAAA,OAAAA;AAAS6B,oBAAAA,KAAAA;oBAAOG,UAAAA,EAAYC,oCAAAA,CAAkBjC,OAAAA,CAAQA,OAAO,EAAE6B,KAAAA;AAAO,iBAAA,CAAA;AACzF,YAAA;AACJ,QAAA,CAAA,CAAA;QAEA,OAAO;AAAEd,YAAAA,OAAAA;AAASb,YAAAA;AAAY,SAAA;AAClC,IAAA;AAEA;;;;QAKA,MAAMgC,UAAAA,CAAWC,IAAY,EAAiC;AAC1D,QAAA,MAAMC,MAAAA,GAASD,IAAAA,CAAKE,IAAI,EAAA,CAAGC,WAAW,EAAA;QACtC,MAAM,EAAEvB,OAAO,EAAE,GAAG,MAAM,IAAI,CAACE,MAAM,CAAC,EAAC,CAAA;AACvC,QAAA,OAAOF,QAAQK,MAAM,CAAC,CAAC,EAAES,KAAK,EAAE,GAAKA,KAAAA,CAAMU,GAAG,CAACD,WAAW,EAAA,KAAOF,MAAAA,IAAUP,MAAMM,IAAI,CAACG,WAAW,EAAA,KAAOF,MAAAA,CAAAA;AAC5G,IAAA;AAEA;;QAGA,MAAMI,UAAAA,CAAWxC,OAAgB,EAAqB;QAClD,MAAM,EAAEe,OAAO,EAAE,GAAG,MAAM,IAAI,CAACE,MAAM,CAAC;AAAEjB,YAAAA;AAAQ,SAAA,CAAA;QAChD,OAAO;eAAI,IAAIyC,GAAAA,CAAI1B,OAAAA,CAAQ2B,OAAO,CAAC,CAAC,EAAEb,KAAK,EAAE,GAAKA,KAAAA,CAAMW,UAAU,CAAA;AAAG,SAAA,CAACG,IAAI,EAAA;AAC9E,IAAA;AAEA;;QAGA,MAAMC,OAAAA,CAAQC,SAAwB,EAA2B;AAC7D,QAAA,MAAM7C,OAAAA,GAAU,IAAI,CAACC,SAAS,CAAC6C,IAAI,CAAC,CAACvC,QAAAA,GAAaA,QAAAA,CAASP,OAAO,KAAK6C,UAAU7C,OAAO,CAAA;AACxF,QAAA,IAAIA,OAAAA,IAAW,CAAC,IAAI,CAACG,QAAQ,CAACH,OAAAA,CAAQA,OAAO,CAAA,IAAK,CAAC,IAAI,CAAC,gBAAgB,CAACA,OAAAA,CAAAA,EAAU;AAC/E,YAAA,MAAMyB,UAAU,MAAM,IAAI,CAAC,oBAAoB,CAACzB,OAAAA,CAAAA;YAChD,IAAI,YAAA,IAAgByB,SAAS,OAAO;gBAAEsB,UAAAA,EAAY,KAAA;AAAOF,gBAAAA,SAAAA;gBAAWjB,UAAAA,EAAY;AAAE,oBAAA,GAAGH,QAAQG,UAAU;AAAEiB,oBAAAA;AAAU;AAAE,aAAA;AACzH,QAAA;QAEA,OAAO,IAAI,CAACG,MAAM,CAACH,SAAAA,CAAAA;AACvB,IAAA;AAEA;;;;;;;;QASAG,MAAAA,CAAOH,SAAwB,EAA8B;AACzD,QAAA,MAAM7C,OAAAA,GAAU,IAAI,CAACC,SAAS,CAAC6C,IAAI,CAAC,CAACvC,QAAAA,GAAaA,QAAAA,CAASP,OAAO,KAAK6C,UAAU7C,OAAO,CAAA;AACxF,QAAA,IAAI,CAACA,OAAAA,EAAS;AACV,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC6C,SAAAA,EAAW,iBAAA,EAAmB,CAAC,kBAAkB,EAAEA,SAAAA,CAAU7C,OAAO,CAAC,+BAA+B,CAAC,CAAA;AACjI,QAAA;AAEA,QAAA,MAAMiD,YAAAA,GAAe,IAAI,CAAC,gBAAgB,CAACjD,OAAAA,CAAAA;AAC3C,QAAA,IAAIiD,cAAc,OAAO;YAAEF,UAAAA,EAAY,KAAA;AAAOF,YAAAA,SAAAA;YAAWjB,UAAAA,EAAY;AAAE,gBAAA,GAAGqB,YAAY;AAAEJ,gBAAAA;AAAU;AAAE,SAAA;QAEpG,MAAM9B,OAAAA,GAAU,IAAI,CAAC,cAAc,CAACL,GAAG,CAACV,OAAAA,CAAQA,OAAO,CAAA;QACvD,IAAI,CAACe,SAAS,OAAOP,SAAAA;QAErB,MAAMqB,KAAAA,GAAQd,OAAAA,CAAQ+B,IAAI,CAAC,CAAChB,YAAcA,SAAAA,CAAUS,GAAG,KAAKM,SAAAA,CAAUN,GAAG,CAAA;AACzE,QAAA,IAAI,CAACV,KAAAA,EAAO;AACR,YAAA,OAAO,IAAI,CAAC,WAAW,CAACgB,SAAAA,EAAW,gBAAgB,CAAC,kBAAkB,EAAE7C,OAAAA,CAAQA,OAAO,CAAC,eAAe,EAAE6C,UAAUN,GAAG,CAAC,CAAC,CAAC,CAAA;AAC7H,QAAA;AAEA,QAAA,IAAIM,UAAUK,OAAO,KAAK1C,SAAAA,IAAa,CAAC,CAACqB,KAAAA,CAAMsB,QAAQ,IAAI,EAAE,EAAEC,QAAQ,CAACP,SAAAA,CAAUK,OAAO,CAAA,EAAG;YACxF,OAAO,IAAI,CAAC,WAAW,CAACL,WAAW,iBAAA,EAAmB,CAAC,UAAU,EAAEQ,+BAAAA,CAAoB;AAAErD,gBAAAA,OAAAA,EAASA,QAAQA,OAAO;AAAEuC,gBAAAA,GAAAA,EAAKV,MAAMU;AAAI,aAAA,CAAA,CAAG,UAAU,EAAEM,SAAAA,CAAUK,OAAO,CAAC,SAAS,CAAC,CAAA;AACjL,QAAA;QAEA,OAAO;YAAEH,UAAAA,EAAY,IAAA;AAAMF,YAAAA,SAAAA;AAAW7C,YAAAA,OAAAA;AAAS6B,YAAAA;AAAM,SAAA;AACzD,IAAA;AAEA;;;QAIA,MAAMpB,IAAAA,CAAKT,OAAgB,EAA6B;AACpD,QAAA,MAAMmB,OAAAA,GAAU,IAAI,CAAClB,SAAS,CAACmB,MAAM,CAAC,CAACb,QAAAA,GAAaP,OAAAA,KAAYQ,SAAAA,IAAaD,QAAAA,CAASP,OAAO,KAAKA,OAAAA,CAAAA;AAClG,QAAA,MAAMqB,QAAAA,GAAW,MAAMC,OAAAA,CAAQC,GAAG,CAACJ,OAAAA,CAAQrB,GAAG,CAAC,OAAOS,QAAAA,GAAa,IAAI,CAAC,oBAAoB,CAACA,QAAAA,CAAAA,CAAAA,CAAAA;AAC7F,QAAA,OAAOc,SAASqB,OAAO,CAAC,CAACjB,OAAAA,GAAa,gBAAgBA,OAAAA,GAAU;AAACA,gBAAAA,OAAAA,CAAQG;AAAW,aAAA,GAAG,EAAE,CAAA;AAC7F,IAAA;IAEA,gBAAgB,CAAC5B,OAA4B,EAAA;AACzC,QAAA,OAAO,IAAI,CAACE,WAAW,CAAC4C,IAAI,CAAC,CAAClB,UAAAA,GAAeA,UAAAA,CAAW0B,IAAI,KAAK,sBAAA,IAA0B1B,UAAAA,CAAW5B,OAAO,KAAKA,QAAQA,OAAO,CAAA;AACrI,IAAA;IAEA,MAAM,oBAAoB,CAACA,OAA4B,EAAA;QACnD,IAAI;YACA,OAAO;gBAAEe,OAAAA,EAAU,MAAM,IAAI,CAACV,SAAS,CAACL,OAAAA,CAAQA,OAAO,CAAA,IAAM;AAAG,aAAA;AACpE,QAAA,CAAA,CAAE,OAAOuD,KAAAA,EAAO;AACZ,YAAA,MAAMC,SAASD,KAAAA,YAAiB5C,KAAAA,GAAQ4C,KAAAA,CAAME,OAAO,GAAGC,MAAAA,CAAOH,KAAAA,CAAAA;YAC/D,OAAO;gBAAE3B,UAAAA,EAAY;oBAAE0B,IAAAA,EAAM,qBAAA;AAAuBtD,oBAAAA,OAAAA,EAASA,QAAQA,OAAO;oBAAEyD,OAAAA,EAAS,CAAC,gBAAgB,EAAEzD,OAAAA,CAAQA,OAAO,CAAC,uBAAuB,EAAEwD,MAAAA,CAAAA;AAAS;AAAE,aAAA;AAClK,QAAA;AACJ,IAAA;AAEA,IAAA,WAAW,CAACX,SAAwB,EAAES,IAA4B,EAAEG,OAAe,EAAA;QAC/E,OAAO;YAAEV,UAAAA,EAAY,KAAA;AAAOF,YAAAA,SAAAA;YAAWjB,UAAAA,EAAY;AAAE0B,gBAAAA,IAAAA;AAAMtD,gBAAAA,OAAAA,EAAS6C,UAAU7C,OAAO;AAAEyD,gBAAAA,OAAAA;AAASZ,gBAAAA;AAAU;AAAE,SAAA;AAChH,IAAA;AACJ;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* The references that name an entry of a library: one per variant, or one without a variant.
|
|
7
|
+
*/ function referencesOfEntry(library, entry) {
|
|
8
|
+
const variants = entry.variants ?? [];
|
|
9
|
+
return variants.length === 0 ? [
|
|
10
|
+
{
|
|
11
|
+
library,
|
|
12
|
+
key: entry.key
|
|
13
|
+
}
|
|
14
|
+
] : variants.map((variant)=>({
|
|
15
|
+
library,
|
|
16
|
+
key: entry.key,
|
|
17
|
+
variant
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.referencesOfEntry = referencesOfEntry;
|
|
22
|
+
//# sourceMappingURL=EffectiveIconEntry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectiveIconEntry.js","sources":["../../../icons/EffectiveIconEntry.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconEntry, IconReference } from '@cratis/scene.model';\nimport { ResolvedIconLibrary } from './ResolvedIconLibrary';\n\n/**\n * An icon as a picker shows it: the catalog entry, the library that provides it (so provenance and\n * attribution are one step away), and the references that name it.\n */\nexport interface EffectiveIconEntry {\n /**\n * The active library that provides the icon.\n */\n library: ResolvedIconLibrary;\n\n /**\n * The catalog entry.\n */\n entry: IconEntry;\n\n /**\n * One reference per variant the icon exists in, or the single variant-less reference when it has none.\n */\n references: IconReference[];\n}\n\n/**\n * The references that name an entry of a library: one per variant, or one without a variant.\n */\nexport function referencesOfEntry(library: string, entry: IconEntry): IconReference[] {\n const variants = entry.variants ?? [];\n return variants.length === 0\n ? [{ library, key: entry.key }]\n : variants.map((variant) => ({ library, key: entry.key, variant }));\n}\n"],"names":["referencesOfEntry","library","entry","variants","length","key","map","variant"],"mappings":";;AAAA;AACA;AA0BA;;AAEC,IACM,SAASA,iBAAAA,CAAkBC,OAAe,EAAEC,KAAgB,EAAA;AAC/D,IAAA,MAAMC,QAAAA,GAAWD,KAAAA,CAAMC,QAAQ,IAAI,EAAE;IACrC,OAAOA,QAAAA,CAASC,MAAM,KAAK,CAAA,GACrB;AAAC,QAAA;AAAEH,YAAAA,OAAAA;AAASI,YAAAA,GAAAA,EAAKH,MAAMG;AAAI;AAAE,KAAA,GAC7BF,QAAAA,CAASG,GAAG,CAAC,CAACC,WAAa;AAAEN,YAAAA,OAAAA;AAASI,YAAAA,GAAAA,EAAKH,MAAMG,GAAG;AAAEE,YAAAA;SAAQ,CAAA,CAAA;AACxE;;"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
|
|
5
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
6
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
7
|
+
/**
|
|
8
|
+
* Reports what changing a profile's icon libraries - removing one, upgrading one to a version that dropped
|
|
9
|
+
* icons, swapping one - would do to icon values already persisted, without touching them.
|
|
10
|
+
*
|
|
11
|
+
* Build `proposed` from the packages the profile would have after the change (with
|
|
12
|
+
* {@link resolveIconLibraries} and that package set's catalog sources) and compare it with the `current`
|
|
13
|
+
* one. A reference is *affected* when it does not resolve in `proposed`; `wasResolvable` says whether it did in
|
|
14
|
+
* `current`. Legacy bare strings are listed with the icons in `proposed` that share their name, but are never
|
|
15
|
+
* counted as affected and never rewritten - migrating them is an author's decision, one reference at a time.
|
|
16
|
+
*/ async function analyzeIconImpact(usages, current, proposed) {
|
|
17
|
+
const affected = [];
|
|
18
|
+
const legacy = [];
|
|
19
|
+
let unaffectedCount = 0;
|
|
20
|
+
for (const usage of usages){
|
|
21
|
+
if (!scene_model.isIconReference(usage.value)) {
|
|
22
|
+
legacy.push({
|
|
23
|
+
usage,
|
|
24
|
+
candidates: await proposed.findByName(String(usage.value))
|
|
25
|
+
});
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const after = await proposed.resolve(usage.value);
|
|
29
|
+
if (after.isResolved) {
|
|
30
|
+
unaffectedCount++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const before = await current.resolve(usage.value);
|
|
34
|
+
affected.push({
|
|
35
|
+
usage,
|
|
36
|
+
diagnostic: after.diagnostic,
|
|
37
|
+
wasResolvable: before.isResolved
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
affected,
|
|
42
|
+
unaffectedCount,
|
|
43
|
+
legacy
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.analyzeIconImpact = analyzeIconImpact;
|
|
48
|
+
//# sourceMappingURL=analyzeIconImpact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeIconImpact.js","sources":["../../../icons/analyzeIconImpact.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { isIconReference } from '@cratis/scene.model';\nimport { AffectedIconUsage, IconImpactReport, LegacyIconUsage } from './IconImpactReport';\nimport { EffectiveIconCatalog } from './EffectiveIconCatalog';\nimport { IconUsage } from './IconUsage';\n\n/**\n * Reports what changing a profile's icon libraries - removing one, upgrading one to a version that dropped\n * icons, swapping one - would do to icon values already persisted, without touching them.\n *\n * Build `proposed` from the packages the profile would have after the change (with\n * {@link resolveIconLibraries} and that package set's catalog sources) and compare it with the `current`\n * one. A reference is *affected* when it does not resolve in `proposed`; `wasResolvable` says whether it did in\n * `current`. Legacy bare strings are listed with the icons in `proposed` that share their name, but are never\n * counted as affected and never rewritten - migrating them is an author's decision, one reference at a time.\n */\nexport async function analyzeIconImpact(usages: IconUsage[], current: EffectiveIconCatalog, proposed: EffectiveIconCatalog): Promise<IconImpactReport> {\n const affected: AffectedIconUsage[] = [];\n const legacy: LegacyIconUsage[] = [];\n let unaffectedCount = 0;\n\n for (const usage of usages) {\n if (!isIconReference(usage.value)) {\n legacy.push({ usage, candidates: await proposed.findByName(String(usage.value)) });\n continue;\n }\n\n const after = await proposed.resolve(usage.value);\n if (after.isResolved) {\n unaffectedCount++;\n continue;\n }\n\n const before = await current.resolve(usage.value);\n affected.push({ usage, diagnostic: after.diagnostic, wasResolvable: before.isResolved });\n }\n\n return { affected, unaffectedCount, legacy };\n}\n"],"names":["analyzeIconImpact","usages","current","proposed","affected","legacy","unaffectedCount","usage","isIconReference","value","push","candidates","findByName","String","after","resolve","isResolved","before","diagnostic","wasResolvable"],"mappings":";;;;AAAA;AACA;AAOA;;;;;;;;;AASC,IACM,eAAeA,iBAAAA,CAAkBC,MAAmB,EAAEC,OAA6B,EAAEC,QAA8B,EAAA;AACtH,IAAA,MAAMC,WAAgC,EAAE;AACxC,IAAA,MAAMC,SAA4B,EAAE;AACpC,IAAA,IAAIC,eAAAA,GAAkB,CAAA;IAEtB,KAAK,MAAMC,SAASN,MAAAA,CAAQ;AACxB,QAAA,IAAI,CAACO,2BAAAA,CAAgBD,KAAAA,CAAME,KAAK,CAAA,EAAG;AAC/BJ,YAAAA,MAAAA,CAAOK,IAAI,CAAC;AAAEH,gBAAAA,KAAAA;AAAOI,gBAAAA,UAAAA,EAAY,MAAMR,QAAAA,CAASS,UAAU,CAACC,MAAAA,CAAON,MAAME,KAAK,CAAA;AAAG,aAAA,CAAA;AAChF,YAAA;AACJ,QAAA;AAEA,QAAA,MAAMK,QAAQ,MAAMX,QAAAA,CAASY,OAAO,CAACR,MAAME,KAAK,CAAA;QAChD,IAAIK,KAAAA,CAAME,UAAU,EAAE;AAClBV,YAAAA,eAAAA,EAAAA;AACA,YAAA;AACJ,QAAA;AAEA,QAAA,MAAMW,SAAS,MAAMf,OAAAA,CAAQa,OAAO,CAACR,MAAME,KAAK,CAAA;AAChDL,QAAAA,QAAAA,CAASM,IAAI,CAAC;AAAEH,YAAAA,KAAAA;AAAOW,YAAAA,UAAAA,EAAYJ,MAAMI,UAAU;AAAEC,YAAAA,aAAAA,EAAeF,OAAOD;AAAW,SAAA,CAAA;AAC1F,IAAA;IAEA,OAAO;AAAEZ,QAAAA,QAAAA;AAAUE,QAAAA,eAAAA;AAAiBD,QAAAA;AAAO,KAAA;AAC/C;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
4
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
5
|
+
/**
|
|
6
|
+
* Whether a catalog entry satisfies the entry-level parts of a query - text, category and variant. The
|
|
7
|
+
* library part is decided earlier, because it decides which catalogs get loaded at all.
|
|
8
|
+
*/ function matchesIconQuery(entry, query) {
|
|
9
|
+
if (query.category !== undefined && !entry.categories.includes(query.category)) return false;
|
|
10
|
+
if (query.variant !== undefined && !(entry.variants ?? []).includes(query.variant)) return false;
|
|
11
|
+
const text = query.text?.trim().toLowerCase();
|
|
12
|
+
if (!text) return true;
|
|
13
|
+
return [
|
|
14
|
+
entry.name,
|
|
15
|
+
entry.key,
|
|
16
|
+
...entry.aliases ?? [],
|
|
17
|
+
...entry.tags ?? []
|
|
18
|
+
].some((term)=>term.toLowerCase().includes(text));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.matchesIconQuery = matchesIconQuery;
|
|
22
|
+
//# sourceMappingURL=matchesIconQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchesIconQuery.js","sources":["../../../icons/matchesIconQuery.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconEntry } from '@cratis/scene.model';\nimport { IconQuery } from './IconQuery';\n\n/**\n * Whether a catalog entry satisfies the entry-level parts of a query - text, category and variant. The\n * library part is decided earlier, because it decides which catalogs get loaded at all.\n */\nexport function matchesIconQuery(entry: IconEntry, query: IconQuery): boolean {\n if (query.category !== undefined && !entry.categories.includes(query.category)) return false;\n if (query.variant !== undefined && !(entry.variants ?? []).includes(query.variant)) return false;\n\n const text = query.text?.trim().toLowerCase();\n if (!text) return true;\n\n return [entry.name, entry.key, ...(entry.aliases ?? []), ...(entry.tags ?? [])].some((term) => term.toLowerCase().includes(text));\n}\n"],"names":["matchesIconQuery","entry","query","category","undefined","categories","includes","variant","variants","text","trim","toLowerCase","name","key","aliases","tags","some","term"],"mappings":";;AAAA;AACA;AAKA;;;AAGC,IACM,SAASA,gBAAAA,CAAiBC,KAAgB,EAAEC,KAAgB,EAAA;AAC/D,IAAA,IAAIA,KAAAA,CAAMC,QAAQ,KAAKC,SAAAA,IAAa,CAACH,KAAAA,CAAMI,UAAU,CAACC,QAAQ,CAACJ,KAAAA,CAAMC,QAAQ,GAAG,OAAO,KAAA;AACvF,IAAA,IAAID,MAAMK,OAAO,KAAKH,aAAa,CAAEH,CAAAA,KAAAA,CAAMO,QAAQ,IAAI,EAAE,EAAEF,QAAQ,CAACJ,KAAAA,CAAMK,OAAO,GAAG,OAAO,KAAA;AAE3F,IAAA,MAAME,IAAAA,GAAOP,KAAAA,CAAMO,IAAI,EAAEC,IAAAA,EAAAA,CAAOC,WAAAA,EAAAA;IAChC,IAAI,CAACF,MAAM,OAAO,IAAA;IAElB,OAAO;AAACR,QAAAA,KAAAA,CAAMW,IAAI;AAAEX,QAAAA,KAAAA,CAAMY,GAAG;WAAMZ,KAAAA,CAAMa,OAAO,IAAI,EAAE;WAAOb,KAAAA,CAAMc,IAAI,IAAI;KAAI,CAACC,IAAI,CAAC,CAACC,IAAAA,GAASA,KAAKN,WAAW,EAAA,CAAGL,QAAQ,CAACG,IAAAA,CAAAA,CAAAA;AAC/H;;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
var resolvePackageDependencies = require('../resolvePackageDependencies.js');
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/**
|
|
9
|
+
* Finds the icon libraries a profile's packages make active - the ones it lists and the ones its other
|
|
10
|
+
* packages declare a dependency on - through the normal package resolver, so an icon library is
|
|
11
|
+
* selected, ordered and version-checked exactly as any other package is.
|
|
12
|
+
*
|
|
13
|
+
* Several libraries coexist. Nothing here ranks them: two libraries that both ship `home` stay two
|
|
14
|
+
* different icons, told apart by the library in their {@link IconReference}.
|
|
15
|
+
*
|
|
16
|
+
* @param selected The package names the profile lists.
|
|
17
|
+
* @param catalog Every package that could be selected.
|
|
18
|
+
*/ function resolveIconLibraries(selected, catalog) {
|
|
19
|
+
const selection = resolvePackageDependencies.resolvePackageDependencies(selected, catalog);
|
|
20
|
+
const index = new Map(catalog.map((scenePackage)=>[
|
|
21
|
+
scenePackage.name,
|
|
22
|
+
scenePackage
|
|
23
|
+
]));
|
|
24
|
+
const chosen = new Set(selected);
|
|
25
|
+
const active = selection.packages.map((name)=>index.get(name)).filter((scenePackage)=>scenePackage !== undefined);
|
|
26
|
+
const libraries = active.filter((scenePackage)=>scenePackage.kind === scene_model.PackageKind.IconLibrary).map((scenePackage)=>({
|
|
27
|
+
library: scenePackage.name,
|
|
28
|
+
package: scenePackage,
|
|
29
|
+
isSelected: chosen.has(scenePackage.name),
|
|
30
|
+
requiredBy: active.filter((other)=>other.dependencies.some((dependency)=>dependency.name === scenePackage.name)).map((other)=>other.name)
|
|
31
|
+
}));
|
|
32
|
+
const libraryNames = new Set(libraries.map((resolved)=>resolved.library));
|
|
33
|
+
const diagnostics = selection.versionConflicts.filter((conflict)=>libraryNames.has(conflict.dependsOn)).map((conflict)=>({
|
|
34
|
+
kind: 'incompatible-version',
|
|
35
|
+
library: conflict.dependsOn,
|
|
36
|
+
message: `'${conflict.package}' needs the icon library '${conflict.dependsOn}' at '${conflict.requiredRange}', but version ${conflict.actualVersion} is what is available`
|
|
37
|
+
}));
|
|
38
|
+
return {
|
|
39
|
+
libraries,
|
|
40
|
+
diagnostics
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.resolveIconLibraries = resolveIconLibraries;
|
|
45
|
+
//# sourceMappingURL=resolveIconLibraries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveIconLibraries.js","sources":["../../../icons/resolveIconLibraries.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { PackageKind, ScenePackage } from '@cratis/scene.model';\nimport { resolvePackageDependencies } from '../resolvePackageDependencies';\nimport { IconDiagnostic } from './IconDiagnostic';\nimport { IconLibraryResolution } from './IconLibraryResolution';\n\n/**\n * Finds the icon libraries a profile's packages make active - the ones it lists and the ones its other\n * packages declare a dependency on - through the normal package resolver, so an icon library is\n * selected, ordered and version-checked exactly as any other package is.\n *\n * Several libraries coexist. Nothing here ranks them: two libraries that both ship `home` stay two\n * different icons, told apart by the library in their {@link IconReference}.\n *\n * @param selected The package names the profile lists.\n * @param catalog Every package that could be selected.\n */\nexport function resolveIconLibraries(selected: string[], catalog: ScenePackage[]): IconLibraryResolution {\n const selection = resolvePackageDependencies(selected, catalog);\n const index = new Map(catalog.map((scenePackage) => [scenePackage.name, scenePackage]));\n const chosen = new Set(selected);\n const active = selection.packages.map((name) => index.get(name)).filter((scenePackage): scenePackage is ScenePackage => scenePackage !== undefined);\n\n const libraries = active\n .filter((scenePackage) => scenePackage.kind === PackageKind.IconLibrary)\n .map((scenePackage) => ({\n library: scenePackage.name,\n package: scenePackage,\n isSelected: chosen.has(scenePackage.name),\n requiredBy: active\n .filter((other) => other.dependencies.some((dependency) => dependency.name === scenePackage.name))\n .map((other) => other.name),\n }));\n\n const libraryNames = new Set(libraries.map((resolved) => resolved.library));\n const diagnostics: IconDiagnostic[] = selection.versionConflicts\n .filter((conflict) => libraryNames.has(conflict.dependsOn))\n .map((conflict) => ({\n kind: 'incompatible-version',\n library: conflict.dependsOn,\n message: `'${conflict.package}' needs the icon library '${conflict.dependsOn}' at '${conflict.requiredRange}', but version ${conflict.actualVersion} is what is available`,\n }));\n\n return { libraries, diagnostics };\n}\n"],"names":["resolveIconLibraries","selected","catalog","selection","resolvePackageDependencies","index","Map","map","scenePackage","name","chosen","Set","active","packages","get","filter","undefined","libraries","kind","PackageKind","IconLibrary","library","package","isSelected","has","requiredBy","other","dependencies","some","dependency","libraryNames","resolved","diagnostics","versionConflicts","conflict","dependsOn","message","requiredRange","actualVersion"],"mappings":";;;;;AAAA;AACA;AAOA;;;;;;;;;;AAUC,IACM,SAASA,oBAAAA,CAAqBC,QAAkB,EAAEC,OAAuB,EAAA;IAC5E,MAAMC,SAAAA,GAAYC,sDAA2BH,QAAAA,EAAUC,OAAAA,CAAAA;AACvD,IAAA,MAAMG,QAAQ,IAAIC,GAAAA,CAAIJ,QAAQK,GAAG,CAAC,CAACC,YAAAA,GAAiB;AAACA,YAAAA,YAAAA,CAAaC,IAAI;AAAED,YAAAA;AAAa,SAAA,CAAA,CAAA;IACrF,MAAME,MAAAA,GAAS,IAAIC,GAAAA,CAAIV,QAAAA,CAAAA;AACvB,IAAA,MAAMW,SAAST,SAAAA,CAAUU,QAAQ,CAACN,GAAG,CAAC,CAACE,IAAAA,GAASJ,KAAAA,CAAMS,GAAG,CAACL,IAAAA,CAAAA,CAAAA,CAAOM,MAAM,CAAC,CAACP,eAA+CA,YAAAA,KAAiBQ,SAAAA,CAAAA;AAEzI,IAAA,MAAMC,YAAYL,MAAAA,CACbG,MAAM,CAAC,CAACP,eAAiBA,YAAAA,CAAaU,IAAI,KAAKC,uBAAAA,CAAYC,WAAW,CAAA,CACtEb,GAAG,CAAC,CAACC,gBAAkB;AACpBa,YAAAA,OAAAA,EAASb,aAAaC,IAAI;YAC1Ba,OAAAA,EAASd,YAAAA;AACTe,YAAAA,UAAAA,EAAYb,MAAAA,CAAOc,GAAG,CAAChB,YAAAA,CAAaC,IAAI,CAAA;YACxCgB,UAAAA,EAAYb,MAAAA,CACPG,MAAM,CAAC,CAACW,QAAUA,KAAAA,CAAMC,YAAY,CAACC,IAAI,CAAC,CAACC,aAAeA,UAAAA,CAAWpB,IAAI,KAAKD,YAAAA,CAAaC,IAAI,CAAA,CAAA,CAC/FF,GAAG,CAAC,CAACmB,KAAAA,GAAUA,KAAAA,CAAMjB,IAAI;SAClC,CAAA,CAAA;IAEJ,MAAMqB,YAAAA,GAAe,IAAInB,GAAAA,CAAIM,SAAAA,CAAUV,GAAG,CAAC,CAACwB,QAAAA,GAAaA,QAAAA,CAASV,OAAO,CAAA,CAAA;AACzE,IAAA,MAAMW,cAAgC7B,SAAAA,CAAU8B,gBAAgB,CAC3DlB,MAAM,CAAC,CAACmB,QAAAA,GAAaJ,YAAAA,CAAaN,GAAG,CAACU,SAASC,SAAS,CAAA,CAAA,CACxD5B,GAAG,CAAC,CAAC2B,YAAc;YAChBhB,IAAAA,EAAM,sBAAA;AACNG,YAAAA,OAAAA,EAASa,SAASC,SAAS;YAC3BC,OAAAA,EAAS,CAAC,CAAC,EAAEF,QAAAA,CAASZ,OAAO,CAAC,0BAA0B,EAAEY,QAAAA,CAASC,SAAS,CAAC,MAAM,EAAED,QAAAA,CAASG,aAAa,CAAC,eAAe,EAAEH,QAAAA,CAASI,aAAa,CAAC,qBAAqB;SAC7K,CAAA,CAAA;IAEJ,OAAO;AAAErB,QAAAA,SAAAA;AAAWe,QAAAA;AAAY,KAAA;AACpC;;"}
|