@cratis/scene.engine 4.22.1 → 4.24.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.
Files changed (66) hide show
  1. package/descriptors/componentBadge.ts +41 -0
  2. package/descriptors/index.ts +7 -0
  3. package/descriptors/matchComponentQuery.ts +55 -0
  4. package/descriptors/rankFrequentlyUsedComponents.ts +29 -0
  5. package/descriptors/validateComponentDescriptors.ts +122 -0
  6. package/dist/cjs/descriptors/componentBadge.js +35 -0
  7. package/dist/cjs/descriptors/componentBadge.js.map +1 -0
  8. package/dist/cjs/descriptors/matchComponentQuery.js +56 -0
  9. package/dist/cjs/descriptors/matchComponentQuery.js.map +1 -0
  10. package/dist/cjs/descriptors/rankFrequentlyUsedComponents.js +18 -0
  11. package/dist/cjs/descriptors/rankFrequentlyUsedComponents.js.map +1 -0
  12. package/dist/cjs/descriptors/validateComponentDescriptors.js +116 -0
  13. package/dist/cjs/descriptors/validateComponentDescriptors.js.map +1 -0
  14. package/dist/cjs/index.js +13 -0
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/structure/ApplicationStructureIndex.js +139 -0
  17. package/dist/cjs/structure/ApplicationStructureIndex.js.map +1 -0
  18. package/dist/cjs/structure/StructureDiagnosticCode.js +15 -0
  19. package/dist/cjs/structure/StructureDiagnosticCode.js.map +1 -0
  20. package/dist/esm/descriptors/componentBadge.d.ts +3 -0
  21. package/dist/esm/descriptors/componentBadge.d.ts.map +1 -0
  22. package/dist/esm/descriptors/componentBadge.js +33 -0
  23. package/dist/esm/descriptors/componentBadge.js.map +1 -0
  24. package/dist/esm/descriptors/index.d.ts +5 -0
  25. package/dist/esm/descriptors/index.d.ts.map +1 -0
  26. package/dist/esm/descriptors/index.js +5 -0
  27. package/dist/esm/descriptors/index.js.map +1 -0
  28. package/dist/esm/descriptors/matchComponentQuery.d.ts +9 -0
  29. package/dist/esm/descriptors/matchComponentQuery.d.ts.map +1 -0
  30. package/dist/esm/descriptors/matchComponentQuery.js +54 -0
  31. package/dist/esm/descriptors/matchComponentQuery.js.map +1 -0
  32. package/dist/esm/descriptors/rankFrequentlyUsedComponents.d.ts +7 -0
  33. package/dist/esm/descriptors/rankFrequentlyUsedComponents.d.ts.map +1 -0
  34. package/dist/esm/descriptors/rankFrequentlyUsedComponents.js +15 -0
  35. package/dist/esm/descriptors/rankFrequentlyUsedComponents.js.map +1 -0
  36. package/dist/esm/descriptors/validateComponentDescriptors.d.ts +3 -0
  37. package/dist/esm/descriptors/validateComponentDescriptors.d.ts.map +1 -0
  38. package/dist/esm/descriptors/validateComponentDescriptors.js +114 -0
  39. package/dist/esm/descriptors/validateComponentDescriptors.js.map +1 -0
  40. package/dist/esm/index.d.ts +2 -0
  41. package/dist/esm/index.d.ts.map +1 -1
  42. package/dist/esm/index.js +6 -0
  43. package/dist/esm/index.js.map +1 -1
  44. package/dist/esm/structure/ApplicationStructureIndex.d.ts +22 -0
  45. package/dist/esm/structure/ApplicationStructureIndex.d.ts.map +1 -0
  46. package/dist/esm/structure/ApplicationStructureIndex.js +137 -0
  47. package/dist/esm/structure/ApplicationStructureIndex.js.map +1 -0
  48. package/dist/esm/structure/StructureDiagnostic.d.ts +7 -0
  49. package/dist/esm/structure/StructureDiagnostic.d.ts.map +1 -0
  50. package/dist/esm/structure/StructureDiagnostic.js +2 -0
  51. package/dist/esm/structure/StructureDiagnostic.js.map +1 -0
  52. package/dist/esm/structure/StructureDiagnosticCode.d.ts +5 -0
  53. package/dist/esm/structure/StructureDiagnosticCode.d.ts.map +1 -0
  54. package/dist/esm/structure/StructureDiagnosticCode.js +13 -0
  55. package/dist/esm/structure/StructureDiagnosticCode.js.map +1 -0
  56. package/dist/esm/structure/index.d.ts +4 -0
  57. package/dist/esm/structure/index.d.ts.map +1 -0
  58. package/dist/esm/structure/index.js +4 -0
  59. package/dist/esm/structure/index.js.map +1 -0
  60. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  61. package/index.ts +2 -0
  62. package/package.json +3 -3
  63. package/structure/ApplicationStructureIndex.ts +163 -0
  64. package/structure/StructureDiagnostic.ts +18 -0
  65. package/structure/StructureDiagnosticCode.ts +14 -0
  66. package/structure/index.ts +6 -0
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ var StructureDiagnosticCode = require('./StructureDiagnosticCode.js');
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
+ * Answers the questions navigation, toolbar and template applicability ask of an {@link ApplicationStructure}:
9
+ * does this module, feature or slice exist, which feature comes first in a module, and what kind of slice is it.
10
+ * Pure and read-only; when ids are duplicated the first declaration wins and {@link diagnostics} reports the rest.
11
+ *
12
+ * The C# engine (`ApplicationStructureIndex`) answers the same questions the same way; both are asserted
13
+ * against `application-structure-fixtures.json`.
14
+ */ class ApplicationStructureIndex {
15
+ structure;
16
+ modules = new Map();
17
+ features = new Map();
18
+ slices = new Map();
19
+ featuresByName = new Map();
20
+ /** The problems found while indexing, in declaration order. */ diagnostics = [];
21
+ /**
22
+ * Initializes a new instance of the {@link ApplicationStructureIndex} class.
23
+ * @param structure The application structure to index.
24
+ */ constructor(structure){
25
+ this.structure = structure;
26
+ const seen = new Map();
27
+ const names = new Map();
28
+ for (const module of structure.modules){
29
+ const qualified = module.id;
30
+ if (!this.claim(seen, qualified, 'module')) continue;
31
+ this.modules.set(qualified, module);
32
+ this.reportAmbiguousName(names, 'module', module.name, qualified);
33
+ this.indexContainer(qualified, module.features, module.slices ?? []);
34
+ }
35
+ }
36
+ /**
37
+ * Finds a module by its id.
38
+ * @param moduleId The module id, for example `sales`.
39
+ * @returns The module, or undefined when there is none.
40
+ */ findModule(moduleId) {
41
+ return this.modules.get(moduleId);
42
+ }
43
+ /**
44
+ * Finds a feature by its qualified id.
45
+ * @param qualifiedId The dotted id from the module down, for example `sales.orders` or `sales.orders.returns`.
46
+ * @returns The feature, or undefined when there is none.
47
+ */ findFeature(qualifiedId) {
48
+ return this.features.get(qualifiedId);
49
+ }
50
+ /**
51
+ * Gets the first feature of a module - the one a navigation target that names only the module goes to.
52
+ * @param moduleId The module id.
53
+ * @returns The module's first top-level feature, or undefined when the module is unknown or has no features.
54
+ */ firstFeature(moduleId) {
55
+ return this.findModule(moduleId)?.features[0];
56
+ }
57
+ /**
58
+ * Gets the qualified id of the first feature of a module.
59
+ * @param moduleId The module id.
60
+ * @returns The qualified id, or undefined when the module is unknown or has no features.
61
+ */ firstFeatureId(moduleId) {
62
+ const feature = this.firstFeature(moduleId);
63
+ return feature ? `${moduleId}.${feature.id}` : undefined;
64
+ }
65
+ /**
66
+ * Finds a slice by its qualified id.
67
+ * @param qualifiedId The dotted id from the module down, for example `sales.orders.PlaceOrder`.
68
+ * @returns The slice, or undefined when there is none.
69
+ */ findSlice(qualifiedId) {
70
+ return this.slices.get(qualifiedId);
71
+ }
72
+ /**
73
+ * Gets what kind a slice is.
74
+ * @param sliceId The slice's qualified id.
75
+ * @returns The kind, or undefined when there is no such slice.
76
+ */ kindOf(sliceId) {
77
+ return this.findSlice(sliceId)?.kind;
78
+ }
79
+ /**
80
+ * Finds every feature that has a given display name, in every module, so a caller can tell when a bare name is ambiguous.
81
+ * @param name The display name, compared without regard to case.
82
+ * @returns The qualified ids of the features with that name, in declaration order.
83
+ */ findFeaturesByName(name) {
84
+ return [
85
+ ...this.featuresByName.get(name.toLowerCase()) ?? []
86
+ ];
87
+ }
88
+ indexContainer(path, features, slices) {
89
+ const seen = new Map();
90
+ const featureNames = new Map();
91
+ const sliceNames = new Map();
92
+ for (const feature of features){
93
+ const qualified = `${path}.${feature.id}`;
94
+ if (!this.claim(seen, qualified, 'feature')) continue;
95
+ this.features.set(qualified, feature);
96
+ const key = feature.name.toLowerCase();
97
+ const byName = this.featuresByName.get(key) ?? [];
98
+ byName.push(qualified);
99
+ this.featuresByName.set(key, byName);
100
+ this.reportAmbiguousName(featureNames, 'feature', feature.name, qualified);
101
+ this.indexContainer(qualified, feature.features, feature.slices);
102
+ }
103
+ for (const slice of slices){
104
+ const qualified = `${path}.${slice.id}`;
105
+ if (!this.claim(seen, qualified, 'slice')) continue;
106
+ this.slices.set(qualified, slice);
107
+ this.reportAmbiguousName(sliceNames, 'slice', slice.name, qualified);
108
+ }
109
+ }
110
+ claim(seen, qualified, kind) {
111
+ const first = seen.get(qualified);
112
+ if (first === undefined) {
113
+ seen.set(qualified, kind);
114
+ return true;
115
+ }
116
+ this.diagnostics.push({
117
+ code: StructureDiagnosticCode.StructureDiagnosticCode.StructureDuplicateId,
118
+ message: `Id '${qualified}' is declared more than once; the first ${first} wins.`,
119
+ id: qualified
120
+ });
121
+ return false;
122
+ }
123
+ reportAmbiguousName(names, kind, name, qualified) {
124
+ const key = name.toLowerCase();
125
+ const first = names.get(key);
126
+ if (first !== undefined) {
127
+ this.diagnostics.push({
128
+ code: StructureDiagnosticCode.StructureDiagnosticCode.StructureAmbiguousName,
129
+ message: `The ${kind} name '${name}' is used by both '${first}' and '${qualified}'.`,
130
+ id: qualified
131
+ });
132
+ return;
133
+ }
134
+ names.set(key, qualified);
135
+ }
136
+ }
137
+
138
+ exports.ApplicationStructureIndex = ApplicationStructureIndex;
139
+ //# sourceMappingURL=ApplicationStructureIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApplicationStructureIndex.js","sources":["../../../structure/ApplicationStructureIndex.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 { ApplicationStructure, FeatureNode, ModuleNode, SliceKind, SliceNode } from '@cratis/scene.model';\nimport { StructureDiagnostic } from './StructureDiagnostic';\nimport { StructureDiagnosticCode } from './StructureDiagnosticCode';\n\n/**\n * Answers the questions navigation, toolbar and template applicability ask of an {@link ApplicationStructure}:\n * does this module, feature or slice exist, which feature comes first in a module, and what kind of slice is it.\n * Pure and read-only; when ids are duplicated the first declaration wins and {@link diagnostics} reports the rest.\n *\n * The C# engine (`ApplicationStructureIndex`) answers the same questions the same way; both are asserted\n * against `application-structure-fixtures.json`.\n */\nexport class ApplicationStructureIndex {\n private readonly modules = new Map<string, ModuleNode>();\n private readonly features = new Map<string, FeatureNode>();\n private readonly slices = new Map<string, SliceNode>();\n private readonly featuresByName = new Map<string, string[]>();\n\n /** The problems found while indexing, in declaration order. */\n readonly diagnostics: StructureDiagnostic[] = [];\n\n /**\n * Initializes a new instance of the {@link ApplicationStructureIndex} class.\n * @param structure The application structure to index.\n */\n constructor(readonly structure: ApplicationStructure) {\n const seen = new Map<string, string>();\n const names = new Map<string, string>();\n\n for (const module of structure.modules) {\n const qualified = module.id;\n if (!this.claim(seen, qualified, 'module')) continue;\n\n this.modules.set(qualified, module);\n this.reportAmbiguousName(names, 'module', module.name, qualified);\n this.indexContainer(qualified, module.features, module.slices ?? []);\n }\n }\n\n /**\n * Finds a module by its id.\n * @param moduleId The module id, for example `sales`.\n * @returns The module, or undefined when there is none.\n */\n findModule(moduleId: string): ModuleNode | undefined {\n return this.modules.get(moduleId);\n }\n\n /**\n * Finds a feature by its qualified id.\n * @param qualifiedId The dotted id from the module down, for example `sales.orders` or `sales.orders.returns`.\n * @returns The feature, or undefined when there is none.\n */\n findFeature(qualifiedId: string): FeatureNode | undefined {\n return this.features.get(qualifiedId);\n }\n\n /**\n * Gets the first feature of a module - the one a navigation target that names only the module goes to.\n * @param moduleId The module id.\n * @returns The module's first top-level feature, or undefined when the module is unknown or has no features.\n */\n firstFeature(moduleId: string): FeatureNode | undefined {\n return this.findModule(moduleId)?.features[0];\n }\n\n /**\n * Gets the qualified id of the first feature of a module.\n * @param moduleId The module id.\n * @returns The qualified id, or undefined when the module is unknown or has no features.\n */\n firstFeatureId(moduleId: string): string | undefined {\n const feature = this.firstFeature(moduleId);\n return feature ? `${moduleId}.${feature.id}` : undefined;\n }\n\n /**\n * Finds a slice by its qualified id.\n * @param qualifiedId The dotted id from the module down, for example `sales.orders.PlaceOrder`.\n * @returns The slice, or undefined when there is none.\n */\n findSlice(qualifiedId: string): SliceNode | undefined {\n return this.slices.get(qualifiedId);\n }\n\n /**\n * Gets what kind a slice is.\n * @param sliceId The slice's qualified id.\n * @returns The kind, or undefined when there is no such slice.\n */\n kindOf(sliceId: string): SliceKind | undefined {\n return this.findSlice(sliceId)?.kind;\n }\n\n /**\n * Finds every feature that has a given display name, in every module, so a caller can tell when a bare name is ambiguous.\n * @param name The display name, compared without regard to case.\n * @returns The qualified ids of the features with that name, in declaration order.\n */\n findFeaturesByName(name: string): string[] {\n return [...(this.featuresByName.get(name.toLowerCase()) ?? [])];\n }\n\n private indexContainer(path: string, features: FeatureNode[], slices: SliceNode[]): void {\n const seen = new Map<string, string>();\n const featureNames = new Map<string, string>();\n const sliceNames = new Map<string, string>();\n\n for (const feature of features) {\n const qualified = `${path}.${feature.id}`;\n if (!this.claim(seen, qualified, 'feature')) continue;\n\n this.features.set(qualified, feature);\n const key = feature.name.toLowerCase();\n const byName = this.featuresByName.get(key) ?? [];\n byName.push(qualified);\n this.featuresByName.set(key, byName);\n this.reportAmbiguousName(featureNames, 'feature', feature.name, qualified);\n this.indexContainer(qualified, feature.features, feature.slices);\n }\n\n for (const slice of slices) {\n const qualified = `${path}.${slice.id}`;\n if (!this.claim(seen, qualified, 'slice')) continue;\n\n this.slices.set(qualified, slice);\n this.reportAmbiguousName(sliceNames, 'slice', slice.name, qualified);\n }\n }\n\n private claim(seen: Map<string, string>, qualified: string, kind: string): boolean {\n const first = seen.get(qualified);\n if (first === undefined) {\n seen.set(qualified, kind);\n return true;\n }\n\n this.diagnostics.push({\n code: StructureDiagnosticCode.StructureDuplicateId,\n message: `Id '${qualified}' is declared more than once; the first ${first} wins.`,\n id: qualified,\n });\n return false;\n }\n\n private reportAmbiguousName(names: Map<string, string>, kind: string, name: string, qualified: string): void {\n const key = name.toLowerCase();\n const first = names.get(key);\n if (first !== undefined) {\n this.diagnostics.push({\n code: StructureDiagnosticCode.StructureAmbiguousName,\n message: `The ${kind} name '${name}' is used by both '${first}' and '${qualified}'.`,\n id: qualified,\n });\n return;\n }\n\n names.set(key, qualified);\n }\n}\n"],"names":["ApplicationStructureIndex","modules","Map","features","slices","featuresByName","diagnostics","structure","seen","names","module","qualified","id","claim","set","reportAmbiguousName","name","indexContainer","findModule","moduleId","get","findFeature","qualifiedId","firstFeature","firstFeatureId","feature","undefined","findSlice","kindOf","sliceId","kind","findFeaturesByName","toLowerCase","path","featureNames","sliceNames","key","byName","push","slice","first","code","StructureDiagnosticCode","StructureDuplicateId","message","StructureAmbiguousName"],"mappings":"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"}
@@ -0,0 +1,15 @@
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
+ * What is wrong with an application structure. The values are shared with the C# engine so both report
7
+ * the same code for the same structure.
8
+ */ var StructureDiagnosticCode = /*#__PURE__*/ function(StructureDiagnosticCode) {
9
+ /** Two siblings share one id, so their qualified id does not identify a single node. */ StructureDiagnosticCode["StructureDuplicateId"] = "structureDuplicateId";
10
+ /** Two siblings with different ids share one display name, so a picker or a name lookup cannot tell them apart. */ StructureDiagnosticCode["StructureAmbiguousName"] = "structureAmbiguousName";
11
+ return StructureDiagnosticCode;
12
+ }({});
13
+
14
+ exports.StructureDiagnosticCode = StructureDiagnosticCode;
15
+ //# sourceMappingURL=StructureDiagnosticCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureDiagnosticCode.js","sources":["../../../structure/StructureDiagnosticCode.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\n/**\n * What is wrong with an application structure. The values are shared with the C# engine so both report\n * the same code for the same structure.\n */\nexport enum StructureDiagnosticCode {\n /** Two siblings share one id, so their qualified id does not identify a single node. */\n StructureDuplicateId = 'structureDuplicateId',\n\n /** Two siblings with different ids share one display name, so a picker or a name lookup cannot tell them apart. */\n StructureAmbiguousName = 'structureAmbiguousName',\n}\n"],"names":["StructureDiagnosticCode"],"mappings":";;AAAA;AACA;AAEA;;;IAIO,IAAKA,uBAAAA,iBAAAA,SAAAA,uBAAAA,EAAAA;6FAC8E,uBAAA,CAAA,sBAAA,CAAA,GAAA,sBAAA;wHAG2B,uBAAA,CAAA,wBAAA,CAAA,GAAA,wBAAA;AAJzGA,IAAAA,OAAAA,uBAAAA;AAMX,CAAA,CAAA,EAAA;;"}
@@ -0,0 +1,3 @@
1
+ import { ComponentDescriptor } from '@cratis/scene.model';
2
+ export declare function componentBadge(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'badge'>): string;
3
+ //# sourceMappingURL=componentBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentBadge.d.ts","sourceRoot":"","sources":["../../../descriptors/componentBadge.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAY1D,wBAAgB,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,WAAW,GAAG,aAAa,GAAG,OAAO,CAAC,GAAG,MAAM,CAiBnH"}
@@ -0,0 +1,33 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ const vowels = 'aeiou';
4
+ /**
5
+ * The two-letter badge a component picker draws for a component that has no icon to show.
6
+ *
7
+ * An explicit `badge` wins (trimmed to two letters). Otherwise a name of several words (`Card grid`, `Stat card`) takes the
8
+ * initials of its first two words (`Cg`, `Sc`); a single word takes its first letter and the first consonant after it
9
+ * (`Button` -> `Bt`, `List` -> `Ls`), or its second letter when it has none. A camel-cased name is read as words
10
+ * (`dataTable` -> `Data table`). The first letter is upper case, the second lower case.
11
+ */ function componentBadge(descriptor) {
12
+ const explicit = descriptor.badge?.trim();
13
+ if (explicit) return capitalize(explicit.slice(0, 2));
14
+ const name = descriptor.displayName?.trim() || bareName(descriptor.component);
15
+ const words = name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').split(/[^A-Za-z0-9]+/).filter((word)=>word.length > 0);
16
+ if (words.length === 0) return '??';
17
+ if (words.length > 1) return capitalize(words[0][0] + words[1][0]);
18
+ const word = words[0];
19
+ if (word.length === 1) return word.toUpperCase();
20
+ const consonant = [
21
+ ...word.slice(1)
22
+ ].find((letter)=>/[a-z]/i.test(letter) && !vowels.includes(letter.toLowerCase()));
23
+ return capitalize(word[0] + (consonant ?? word[1]));
24
+ }
25
+ function bareName(component) {
26
+ return component.slice(component.lastIndexOf(':') + 1);
27
+ }
28
+ function capitalize(letters) {
29
+ return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase();
30
+ }
31
+
32
+ export { componentBadge };
33
+ //# sourceMappingURL=componentBadge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentBadge.js","sources":["../../../descriptors/componentBadge.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 { ComponentDescriptor } from '@cratis/scene.model';\n\nconst vowels = 'aeiou';\n\n/**\n * The two-letter badge a component picker draws for a component that has no icon to show.\n *\n * An explicit `badge` wins (trimmed to two letters). Otherwise a name of several words (`Card grid`, `Stat card`) takes the\n * initials of its first two words (`Cg`, `Sc`); a single word takes its first letter and the first consonant after it\n * (`Button` -> `Bt`, `List` -> `Ls`), or its second letter when it has none. A camel-cased name is read as words\n * (`dataTable` -> `Data table`). The first letter is upper case, the second lower case.\n */\nexport function componentBadge(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'badge'>): string {\n const explicit = descriptor.badge?.trim();\n if (explicit) return capitalize(explicit.slice(0, 2));\n\n const name = descriptor.displayName?.trim() || bareName(descriptor.component);\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .split(/[^A-Za-z0-9]+/)\n .filter(word => word.length > 0);\n\n if (words.length === 0) return '??';\n if (words.length > 1) return capitalize(words[0][0] + words[1][0]);\n\n const word = words[0];\n if (word.length === 1) return word.toUpperCase();\n const consonant = [...word.slice(1)].find(letter => /[a-z]/i.test(letter) && !vowels.includes(letter.toLowerCase()));\n return capitalize(word[0] + (consonant ?? word[1]));\n}\n\nfunction bareName(component: string): string {\n return component.slice(component.lastIndexOf(':') + 1);\n}\n\nfunction capitalize(letters: string): string {\n return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase();\n}\n"],"names":["vowels","componentBadge","descriptor","explicit","badge","trim","capitalize","slice","name","displayName","bareName","component","words","replace","split","filter","word","length","toUpperCase","consonant","find","letter","test","includes","toLowerCase","lastIndexOf","letters","charAt"],"mappings":"AAAA;AACA;AAIA,MAAMA,MAAAA,GAAS,OAAA;AAEf;;;;;;;IAQO,SAASC,cAAAA,CAAeC,UAA4E,EAAA;IACvG,MAAMC,QAAAA,GAAWD,UAAAA,CAAWE,KAAK,EAAEC,IAAAA,EAAAA;AACnC,IAAA,IAAIF,UAAU,OAAOG,UAAAA,CAAWH,QAAAA,CAASI,KAAK,CAAC,CAAA,EAAG,CAAA,CAAA,CAAA;AAElD,IAAA,MAAMC,OAAON,UAAAA,CAAWO,WAAW,EAAEJ,IAAAA,EAAAA,IAAUK,QAAAA,CAASR,WAAWS,SAAS,CAAA;AAC5E,IAAA,MAAMC,KAAAA,GAAQJ,IAAAA,CACTK,OAAO,CAAC,sBAAsB,OAAA,CAAA,CAC9BC,KAAK,CAAC,eAAA,CAAA,CACNC,MAAM,CAACC,CAAAA,IAAAA,GAAQA,IAAAA,CAAKC,MAAM,GAAG,CAAA,CAAA;AAElC,IAAA,IAAIL,KAAAA,CAAMK,MAAM,KAAK,CAAA,EAAG,OAAO,IAAA;AAC/B,IAAA,IAAIL,MAAMK,MAAM,GAAG,CAAA,EAAG,OAAOX,WAAWM,KAAK,CAAC,CAAA,CAAE,CAAC,EAAE,GAAGA,KAAK,CAAC,CAAA,CAAE,CAAC,CAAA,CAAE,CAAA;IAEjE,MAAMI,IAAAA,GAAOJ,KAAK,CAAC,CAAA,CAAE;AACrB,IAAA,IAAII,KAAKC,MAAM,KAAK,CAAA,EAAG,OAAOD,KAAKE,WAAW,EAAA;AAC9C,IAAA,MAAMC,SAAAA,GAAY;AAAIH,QAAAA,GAAAA,IAAAA,CAAKT,KAAK,CAAC,CAAA;AAAG,KAAA,CAACa,IAAI,CAACC,CAAAA,MAAAA,GAAU,QAAA,CAASC,IAAI,CAACD,MAAAA,CAAAA,IAAW,CAACrB,MAAAA,CAAOuB,QAAQ,CAACF,OAAOG,WAAW,EAAA,CAAA,CAAA;IAChH,OAAOlB,UAAAA,CAAWU,IAAI,CAAC,CAAA,CAAE,IAAIG,SAAAA,IAAaH,IAAI,CAAC,CAAA,CAAE,CAAD,CAAA;AACpD;AAEA,SAASN,SAASC,SAAiB,EAAA;AAC/B,IAAA,OAAOA,UAAUJ,KAAK,CAACI,SAAAA,CAAUc,WAAW,CAAC,GAAA,CAAA,GAAO,CAAA,CAAA;AACxD;AAEA,SAASnB,WAAWoB,OAAe,EAAA;IAC/B,OAAOA,OAAAA,CAAQC,MAAM,CAAC,CAAA,CAAA,CAAGT,WAAW,KAAKQ,OAAAA,CAAQnB,KAAK,CAAC,CAAA,CAAA,CAAGiB,WAAW,EAAA;AACzE;;"}
@@ -0,0 +1,5 @@
1
+ export * from './validateComponentDescriptors';
2
+ export * from './componentBadge';
3
+ export * from './matchComponentQuery';
4
+ export * from './rankFrequentlyUsedComponents';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../descriptors/index.ts"],"names":[],"mappings":"AAGA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './validateComponentDescriptors';
2
+ export * from './componentBadge';
3
+ export * from './matchComponentQuery';
4
+ export * from './rankFrequentlyUsedComponents';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../descriptors/index.ts"],"names":[],"mappings":"AAGA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { ComponentDescriptor } from '@cratis/scene.model';
2
+ export interface ComponentQueryMatch {
3
+ matched: boolean;
4
+ via?: 'name' | 'category' | 'keyword';
5
+ ranges: [number, number][];
6
+ keyword?: string;
7
+ }
8
+ export declare function matchComponentQuery(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'category' | 'keywords'>, query: string): ComponentQueryMatch;
9
+ //# sourceMappingURL=matchComponentQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchComponentQuery.d.ts","sourceRoot":"","sources":["../../../descriptors/matchComponentQuery.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAK1D,MAAM,WAAW,mBAAmB;IAEhC,OAAO,EAAE,OAAO,CAAC;IAGjB,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAGtC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAG3B,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAcpK"}
@@ -0,0 +1,54 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * Decides whether a component is shown for the text typed in a picker's filter, and why.
5
+ *
6
+ * Matching is case-insensitive. The display name (or, when the descriptor has none, the bare component name) and the keywords match by
7
+ * substring. The category matches by the start of one of its words - `nav` finds every Navigation component, while `ta` does not find
8
+ * everything under `Data display`, which a substring match on the category would. A component is shown when any of the three
9
+ * match; it reports the first of name, category, keyword that did, so the picker highlights the name and shows a hint only when a
10
+ * keyword alone brought the component in. An empty filter matches everything and highlights nothing.
11
+ */ function matchComponentQuery(descriptor, query) {
12
+ const needle = query.trim().toLowerCase();
13
+ if (needle.length === 0) return {
14
+ matched: true,
15
+ ranges: []
16
+ };
17
+ const name = descriptor.displayName ?? descriptor.component.slice(descriptor.component.lastIndexOf(':') + 1);
18
+ const ranges = occurrencesOf(name.toLowerCase(), needle);
19
+ if (ranges.length > 0) return {
20
+ matched: true,
21
+ via: 'name',
22
+ ranges
23
+ };
24
+ if (descriptor.category !== undefined && descriptor.category.toLowerCase().split(/\s+/).some((word)=>word.startsWith(needle))) {
25
+ return {
26
+ matched: true,
27
+ via: 'category',
28
+ ranges: []
29
+ };
30
+ }
31
+ const keyword = (descriptor.keywords ?? []).find((candidate)=>candidate.toLowerCase().includes(needle));
32
+ return keyword === undefined ? {
33
+ matched: false,
34
+ ranges: []
35
+ } : {
36
+ matched: true,
37
+ via: 'keyword',
38
+ ranges: [],
39
+ keyword
40
+ };
41
+ }
42
+ function occurrencesOf(text, needle) {
43
+ const found = [];
44
+ for(let at = text.indexOf(needle); at >= 0; at = text.indexOf(needle, at + needle.length)){
45
+ found.push([
46
+ at,
47
+ at + needle.length
48
+ ]);
49
+ }
50
+ return found;
51
+ }
52
+
53
+ export { matchComponentQuery };
54
+ //# sourceMappingURL=matchComponentQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchComponentQuery.js","sources":["../../../descriptors/matchComponentQuery.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 { ComponentDescriptor } from '@cratis/scene.model';\n\n/**\n * How a component answers a picker's filter text (spec PICK2).\n */\nexport interface ComponentQueryMatch {\n /** The component is shown for this filter. */\n matched: boolean;\n\n /** What matched, strongest first: the display name, the category, or one of the keywords. Absent when nothing matched. */\n via?: 'name' | 'category' | 'keyword';\n\n /** The `[start, end)` ranges of the display name to highlight. Empty unless the name matched. */\n ranges: [number, number][];\n\n /** The keyword the component matched through. Present only when `via` is `keyword`: the picker shows it as a hint. */\n keyword?: string;\n}\n\n/**\n * Decides whether a component is shown for the text typed in a picker's filter, and why.\n *\n * Matching is case-insensitive. The display name (or, when the descriptor has none, the bare component name) and the keywords match by\n * substring. The category matches by the start of one of its words - `nav` finds every Navigation component, while `ta` does not find\n * everything under `Data display`, which a substring match on the category would. A component is shown when any of the three\n * match; it reports the first of name, category, keyword that did, so the picker highlights the name and shows a hint only when a\n * keyword alone brought the component in. An empty filter matches everything and highlights nothing.\n */\nexport function matchComponentQuery(descriptor: Pick<ComponentDescriptor, 'component' | 'displayName' | 'category' | 'keywords'>, query: string): ComponentQueryMatch {\n const needle = query.trim().toLowerCase();\n if (needle.length === 0) return { matched: true, ranges: [] };\n\n const name = descriptor.displayName ?? descriptor.component.slice(descriptor.component.lastIndexOf(':') + 1);\n const ranges = occurrencesOf(name.toLowerCase(), needle);\n if (ranges.length > 0) return { matched: true, via: 'name', ranges };\n\n if (descriptor.category !== undefined && descriptor.category.toLowerCase().split(/\\s+/).some(word => word.startsWith(needle))) {\n return { matched: true, via: 'category', ranges: [] };\n }\n\n const keyword = (descriptor.keywords ?? []).find(candidate => candidate.toLowerCase().includes(needle));\n return keyword === undefined ? { matched: false, ranges: [] } : { matched: true, via: 'keyword', ranges: [], keyword };\n}\n\nfunction occurrencesOf(text: string, needle: string): [number, number][] {\n const found: [number, number][] = [];\n for (let at = text.indexOf(needle); at >= 0; at = text.indexOf(needle, at + needle.length)) {\n found.push([at, at + needle.length]);\n }\n\n return found;\n}\n"],"names":["matchComponentQuery","descriptor","query","needle","trim","toLowerCase","length","matched","ranges","name","displayName","component","slice","lastIndexOf","occurrencesOf","via","category","undefined","split","some","word","startsWith","keyword","keywords","find","candidate","includes","text","found","at","indexOf","push"],"mappings":"AAAA;AACA;AAqBA;;;;;;;;AAQC,IACM,SAASA,mBAAAA,CAAoBC,UAA4F,EAAEC,KAAa,EAAA;AAC3I,IAAA,MAAMC,MAAAA,GAASD,KAAAA,CAAME,IAAI,EAAA,CAAGC,WAAW,EAAA;AACvC,IAAA,IAAIF,MAAAA,CAAOG,MAAM,KAAK,CAAA,EAAG,OAAO;QAAEC,OAAAA,EAAS,IAAA;AAAMC,QAAAA,MAAAA,EAAQ;AAAG,KAAA;AAE5D,IAAA,MAAMC,IAAAA,GAAOR,UAAAA,CAAWS,WAAW,IAAIT,WAAWU,SAAS,CAACC,KAAK,CAACX,UAAAA,CAAWU,SAAS,CAACE,WAAW,CAAC,GAAA,CAAA,GAAO,CAAA,CAAA;AAC1G,IAAA,MAAML,MAAAA,GAASM,aAAAA,CAAcL,IAAAA,CAAKJ,WAAW,EAAA,EAAIF,MAAAA,CAAAA;AACjD,IAAA,IAAIK,MAAAA,CAAOF,MAAM,GAAG,CAAA,EAAG,OAAO;QAAEC,OAAAA,EAAS,IAAA;QAAMQ,GAAAA,EAAK,MAAA;AAAQP,QAAAA;AAAO,KAAA;AAEnE,IAAA,IAAIP,WAAWe,QAAQ,KAAKC,aAAahB,UAAAA,CAAWe,QAAQ,CAACX,WAAW,EAAA,CAAGa,KAAK,CAAC,KAAA,CAAA,CAAOC,IAAI,CAACC,CAAAA,OAAQA,IAAAA,CAAKC,UAAU,CAAClB,MAAAA,CAAAA,CAAAA,EAAU;QAC3H,OAAO;YAAEI,OAAAA,EAAS,IAAA;YAAMQ,GAAAA,EAAK,UAAA;AAAYP,YAAAA,MAAAA,EAAQ;AAAG,SAAA;AACxD,IAAA;AAEA,IAAA,MAAMc,UAAU,CAACrB,UAAAA,CAAWsB,QAAQ,IAAI,EAAC,EAAGC,IAAI,CAACC,CAAAA,SAAAA,GAAaA,UAAUpB,WAAW,EAAA,CAAGqB,QAAQ,CAACvB,MAAAA,CAAAA,CAAAA;AAC/F,IAAA,OAAOmB,YAAYL,SAAAA,GAAY;QAAEV,OAAAA,EAAS,KAAA;AAAOC,QAAAA,MAAAA,EAAQ;KAAG,GAAI;QAAED,OAAAA,EAAS,IAAA;QAAMQ,GAAAA,EAAK,SAAA;AAAWP,QAAAA,MAAAA,EAAQ,EAAE;AAAEc,QAAAA;AAAQ,KAAA;AACzH;AAEA,SAASR,aAAAA,CAAca,IAAY,EAAExB,MAAc,EAAA;AAC/C,IAAA,MAAMyB,QAA4B,EAAE;AACpC,IAAA,IAAK,IAAIC,EAAAA,GAAKF,IAAAA,CAAKG,OAAO,CAAC3B,SAAS0B,EAAAA,IAAM,CAAA,EAAGA,EAAAA,GAAKF,IAAAA,CAAKG,OAAO,CAAC3B,MAAAA,EAAQ0B,EAAAA,GAAK1B,MAAAA,CAAOG,MAAM,CAAA,CAAG;AACxFsB,QAAAA,KAAAA,CAAMG,IAAI,CAAC;AAACF,YAAAA,EAAAA;AAAIA,YAAAA,EAAAA,GAAK1B,OAAOG;AAAO,SAAA,CAAA;AACvC,IAAA;IAEA,OAAOsB,KAAAA;AACX;;"}
@@ -0,0 +1,7 @@
1
+ export interface ComponentUsage {
2
+ count: number;
3
+ last: number;
4
+ }
5
+ export declare const frequentlyUsedLimit = 6;
6
+ export declare function rankFrequentlyUsedComponents(usage: Readonly<Record<string, ComponentUsage>>, limit?: number): string[];
7
+ //# sourceMappingURL=rankFrequentlyUsedComponents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rankFrequentlyUsedComponents.d.ts","sourceRoot":"","sources":["../../../descriptors/rankFrequentlyUsedComponents.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAE3B,KAAK,EAAE,MAAM,CAAC;IAGd,IAAI,EAAE,MAAM,CAAC;CAChB;AAGD,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAOrC,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,KAAK,GAAE,MAA4B,GAAG,MAAM,EAAE,CAM3I"}
@@ -0,0 +1,15 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * How often and how recently one component was added to a canvas.
5
+ */ /** The number of components the "Frequently used" group lists (spec PICK3). */ const frequentlyUsedLimit = 6;
6
+ /**
7
+ * The components the "Frequently used" group lists: at most `limit` (6 by default), the most used first, ties broken by the most
8
+ * recent use, and any remaining tie by the component name so the order is stable. Components never used, or whose count is not a
9
+ * positive number, are not listed, so a picker hides the group when this is empty.
10
+ */ function rankFrequentlyUsedComponents(usage, limit = frequentlyUsedLimit) {
11
+ return Object.entries(usage).filter(([, entry])=>Number.isFinite(entry.count) && entry.count > 0).sort(([leftName, left], [rightName, right])=>right.count - left.count || right.last - left.last || leftName.localeCompare(rightName)).slice(0, Math.max(0, limit)).map(([name])=>name);
12
+ }
13
+
14
+ export { frequentlyUsedLimit, rankFrequentlyUsedComponents };
15
+ //# sourceMappingURL=rankFrequentlyUsedComponents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rankFrequentlyUsedComponents.js","sources":["../../../descriptors/rankFrequentlyUsedComponents.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\n/**\n * How often and how recently one component was added to a canvas.\n */\nexport interface ComponentUsage {\n /** How many times the component was added. */\n count: number;\n\n /** When it was last added, in milliseconds since the epoch. */\n last: number;\n}\n\n/** The number of components the \"Frequently used\" group lists (spec PICK3). */\nexport const frequentlyUsedLimit = 6;\n\n/**\n * The components the \"Frequently used\" group lists: at most `limit` (6 by default), the most used first, ties broken by the most\n * recent use, and any remaining tie by the component name so the order is stable. Components never used, or whose count is not a\n * positive number, are not listed, so a picker hides the group when this is empty.\n */\nexport function rankFrequentlyUsedComponents(usage: Readonly<Record<string, ComponentUsage>>, limit: number = frequentlyUsedLimit): string[] {\n return Object.entries(usage)\n .filter(([, entry]) => Number.isFinite(entry.count) && entry.count > 0)\n .sort(([leftName, left], [rightName, right]) => right.count - left.count || right.last - left.last || leftName.localeCompare(rightName))\n .slice(0, Math.max(0, limit))\n .map(([name]) => name);\n}\n"],"names":["frequentlyUsedLimit","rankFrequentlyUsedComponents","usage","limit","Object","entries","filter","entry","Number","isFinite","count","sort","leftName","left","rightName","right","last","localeCompare","slice","Math","max","map","name"],"mappings":"AAAA;AACA;AAEA;;AAEC,oFAUM,MAAMA,sBAAsB;AAEnC;;;;AAIC,IACM,SAASC,4BAAAA,CAA6BC,KAA+C,EAAEC,QAAgBH,mBAAmB,EAAA;AAC7H,IAAA,OAAOI,MAAAA,CAAOC,OAAO,CAACH,KAAAA,CAAAA,CACjBI,MAAM,CAAC,CAAC,GAAGC,KAAAA,CAAM,GAAKC,MAAAA,CAAOC,QAAQ,CAACF,KAAAA,CAAMG,KAAK,CAAA,IAAKH,KAAAA,CAAMG,KAAK,GAAG,CAAA,CAAA,CACpEC,IAAI,CAAC,CAAC,CAACC,QAAAA,EAAUC,IAAAA,CAAK,EAAE,CAACC,SAAAA,EAAWC,KAAAA,CAAM,GAAKA,KAAAA,CAAML,KAAK,GAAGG,IAAAA,CAAKH,KAAK,IAAIK,KAAAA,CAAMC,IAAI,GAAGH,IAAAA,CAAKG,IAAI,IAAIJ,QAAAA,CAASK,aAAa,CAACH,SAAAA,CAAAA,CAAAA,CAC5HI,KAAK,CAAC,CAAA,EAAGC,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGjB,KAAAA,CAAAA,CAAAA,CACrBkB,GAAG,CAAC,CAAC,CAACC,IAAAA,CAAK,GAAKA,IAAAA,CAAAA;AACzB;;"}
@@ -0,0 +1,3 @@
1
+ import { ComponentDescriptor, SceneDiagnostic } from '@cratis/scene.model';
2
+ export declare function validateComponentDescriptors(descriptors: readonly ComponentDescriptor[], registered?: readonly string[], knownCategories?: readonly string[]): SceneDiagnostic[];
3
+ //# sourceMappingURL=validateComponentDescriptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateComponentDescriptors.d.ts","sourceRoot":"","sources":["../../../descriptors/validateComponentDescriptors.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,mBAAmB,EACnB,eAAe,EAClB,MAAM,qBAAqB,CAAC;AAgB7B,wBAAgB,4BAA4B,CACxC,WAAW,EAAE,SAAS,mBAAmB,EAAE,EAC3C,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,EAC9B,eAAe,GAAE,SAAS,MAAM,EAAwB,GACzD,eAAe,EAAE,CA8BnB"}
@@ -0,0 +1,114 @@
1
+ import { componentCategories, DiagnosticSeverity, DiagnosticCode, PropertyValueType, PropertyEditorKind } from '@cratis/scene.model';
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
+ * Checks the component metadata a package ships - what a picker and a designer read without loading a component.
7
+ *
8
+ * - **CMP1** `componentCategoryMissing` (error): a registered component has no descriptor, or its descriptor declares no category.
9
+ * - `componentCategoryUnknown` (warning): the category is not one of the model's; a package may add its own, so this is a
10
+ * nudge towards the shared vocabulary, not a refusal.
11
+ * - `componentDesignModeInvalid` (error): the design-mode descriptor names an items or collection path that is not a `Collection`
12
+ * property of the component, or repeats an action id.
13
+ * - `propertyEditorOptionsInvalid` (error): an editor's parameters cannot work - a `reference` editor that does not say what it
14
+ * references, a step that is not positive, an empty list of slice kinds.
15
+ *
16
+ * `registered` is the bare or package-qualified names of the components the package registers; when given, each must be described.
17
+ * The result is in a stable order: registered components first (in the order given), then each descriptor's findings in its own order.
18
+ */ function validateComponentDescriptors(descriptors, registered, knownCategories = componentCategories) {
19
+ const diagnostics = [];
20
+ const described = new Map(descriptors.map((descriptor)=>[
21
+ descriptor.component,
22
+ descriptor
23
+ ]));
24
+ for (const component of registered ?? []){
25
+ if (!described.has(component)) {
26
+ diagnostics.push(missingCategory(component, `'${component}' is registered but has no descriptor, so it declares no category`));
27
+ }
28
+ }
29
+ for (const descriptor of descriptors){
30
+ const { component } = descriptor;
31
+ if (descriptor.category === undefined || descriptor.category.trim().length === 0) {
32
+ diagnostics.push(missingCategory(component, `'${component}' declares no category`));
33
+ } else if (!knownCategories.includes(descriptor.category)) {
34
+ diagnostics.push({
35
+ code: DiagnosticCode.ComponentCategoryUnknown,
36
+ severity: DiagnosticSeverity.Warning,
37
+ component,
38
+ message: `'${component}' declares the category '${descriptor.category}', which is not one of ${knownCategories.join(', ')}`
39
+ });
40
+ }
41
+ if (descriptor.designMode) {
42
+ diagnostics.push(...validateDesignMode(descriptor, descriptor.designMode));
43
+ }
44
+ diagnostics.push(...validateEditorOptions(component, descriptor.properties, ''));
45
+ }
46
+ return diagnostics;
47
+ }
48
+ function missingCategory(component, message) {
49
+ return {
50
+ code: DiagnosticCode.ComponentCategoryMissing,
51
+ severity: DiagnosticSeverity.Error,
52
+ component,
53
+ message
54
+ };
55
+ }
56
+ function invalidDesignMode(component, message) {
57
+ return {
58
+ code: DiagnosticCode.ComponentDesignModeInvalid,
59
+ severity: DiagnosticSeverity.Error,
60
+ component,
61
+ message
62
+ };
63
+ }
64
+ function validateDesignMode(descriptor, designMode) {
65
+ const { component } = descriptor;
66
+ const diagnostics = [];
67
+ const collections = new Set(descriptor.properties.filter((property)=>property.valueType === PropertyValueType.Collection).map((property)=>property.path));
68
+ if (designMode.itemsPath !== undefined && !collections.has(designMode.itemsPath)) {
69
+ diagnostics.push(invalidDesignMode(component, `'${component}' names '${designMode.itemsPath}' as its design-mode items, which is not one of its Collection properties`));
70
+ }
71
+ const seenAdd = new Set();
72
+ for (const action of designMode.addActions){
73
+ if (seenAdd.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode add action '${action.id}' more than once`));
74
+ seenAdd.add(action.id);
75
+ if (action.collectionPath !== undefined && !collections.has(action.collectionPath)) {
76
+ diagnostics.push(invalidDesignMode(component, `the design-mode add action '${action.id}' of '${component}' adds to '${action.collectionPath}', which is not one of its Collection properties`));
77
+ }
78
+ }
79
+ const seenItem = new Set();
80
+ for (const action of designMode.itemToolbar){
81
+ if (seenItem.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode item action '${action.id}' more than once`));
82
+ seenItem.add(action.id);
83
+ }
84
+ return diagnostics;
85
+ }
86
+ function validateEditorOptions(component, properties, parent) {
87
+ const diagnostics = [];
88
+ const invalid = (path, message)=>({
89
+ code: DiagnosticCode.PropertyEditorOptionsInvalid,
90
+ severity: DiagnosticSeverity.Error,
91
+ component,
92
+ path,
93
+ message: `'${component}' property '${path}' ${message}`
94
+ });
95
+ for (const property of properties){
96
+ const path = `${parent}${property.path}`;
97
+ const options = property.editorOptions;
98
+ if (property.editorKind === PropertyEditorKind.Reference && !options?.reference?.target) {
99
+ diagnostics.push(invalid(path, "uses the 'reference' editor without saying what it references (editorOptions.reference.target)"));
100
+ }
101
+ if (options?.step !== undefined && !(options.step > 0)) {
102
+ diagnostics.push(invalid(path, 'declares a step that is not greater than zero'));
103
+ }
104
+ if (options?.kinds !== undefined && options.kinds.length === 0) {
105
+ diagnostics.push(invalid(path, 'declares an empty list of kinds, which would offer nothing'));
106
+ }
107
+ if (property.item) diagnostics.push(...validateEditorOptions(component, property.item.properties, `${path}[].`));
108
+ if (property.properties) diagnostics.push(...validateEditorOptions(component, property.properties, `${path}.`));
109
+ }
110
+ return diagnostics;
111
+ }
112
+
113
+ export { validateComponentDescriptors };
114
+ //# sourceMappingURL=validateComponentDescriptors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateComponentDescriptors.js","sources":["../../../descriptors/validateComponentDescriptors.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 {\n ComponentDescriptor, ComponentDesignModeDescriptor, DiagnosticCode, DiagnosticSeverity, PropertyDescriptor, PropertyEditorKind, PropertyValueType,\n SceneDiagnostic, componentCategories,\n} from '@cratis/scene.model';\n\n/**\n * Checks the component metadata a package ships - what a picker and a designer read without loading a component.\n *\n * - **CMP1** `componentCategoryMissing` (error): a registered component has no descriptor, or its descriptor declares no category.\n * - `componentCategoryUnknown` (warning): the category is not one of the model's; a package may add its own, so this is a\n * nudge towards the shared vocabulary, not a refusal.\n * - `componentDesignModeInvalid` (error): the design-mode descriptor names an items or collection path that is not a `Collection`\n * property of the component, or repeats an action id.\n * - `propertyEditorOptionsInvalid` (error): an editor's parameters cannot work - a `reference` editor that does not say what it\n * references, a step that is not positive, an empty list of slice kinds.\n *\n * `registered` is the bare or package-qualified names of the components the package registers; when given, each must be described.\n * The result is in a stable order: registered components first (in the order given), then each descriptor's findings in its own order.\n */\nexport function validateComponentDescriptors(\n descriptors: readonly ComponentDescriptor[],\n registered?: readonly string[],\n knownCategories: readonly string[] = componentCategories\n): SceneDiagnostic[] {\n const diagnostics: SceneDiagnostic[] = [];\n const described = new Map(descriptors.map(descriptor => [descriptor.component, descriptor]));\n\n for (const component of registered ?? []) {\n if (!described.has(component)) {\n diagnostics.push(missingCategory(component, `'${component}' is registered but has no descriptor, so it declares no category`));\n }\n }\n\n for (const descriptor of descriptors) {\n const { component } = descriptor;\n\n if (descriptor.category === undefined || descriptor.category.trim().length === 0) {\n diagnostics.push(missingCategory(component, `'${component}' declares no category`));\n } else if (!knownCategories.includes(descriptor.category)) {\n diagnostics.push({\n code: DiagnosticCode.ComponentCategoryUnknown, severity: DiagnosticSeverity.Warning, component,\n message: `'${component}' declares the category '${descriptor.category}', which is not one of ${knownCategories.join(', ')}`,\n });\n }\n\n if (descriptor.designMode) {\n diagnostics.push(...validateDesignMode(descriptor, descriptor.designMode));\n }\n\n diagnostics.push(...validateEditorOptions(component, descriptor.properties, ''));\n }\n\n return diagnostics;\n}\n\nfunction missingCategory(component: string, message: string): SceneDiagnostic {\n return { code: DiagnosticCode.ComponentCategoryMissing, severity: DiagnosticSeverity.Error, component, message };\n}\n\nfunction invalidDesignMode(component: string, message: string): SceneDiagnostic {\n return { code: DiagnosticCode.ComponentDesignModeInvalid, severity: DiagnosticSeverity.Error, component, message };\n}\n\nfunction validateDesignMode(descriptor: ComponentDescriptor, designMode: ComponentDesignModeDescriptor): SceneDiagnostic[] {\n const { component } = descriptor;\n const diagnostics: SceneDiagnostic[] = [];\n const collections = new Set(descriptor.properties.filter(property => property.valueType === PropertyValueType.Collection).map(property => property.path));\n\n if (designMode.itemsPath !== undefined && !collections.has(designMode.itemsPath)) {\n diagnostics.push(invalidDesignMode(component, `'${component}' names '${designMode.itemsPath}' as its design-mode items, which is not one of its Collection properties`));\n }\n\n const seenAdd = new Set<string>();\n for (const action of designMode.addActions) {\n if (seenAdd.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode add action '${action.id}' more than once`));\n seenAdd.add(action.id);\n\n if (action.collectionPath !== undefined && !collections.has(action.collectionPath)) {\n diagnostics.push(invalidDesignMode(component, `the design-mode add action '${action.id}' of '${component}' adds to '${action.collectionPath}', which is not one of its Collection properties`));\n }\n }\n\n const seenItem = new Set<string>();\n for (const action of designMode.itemToolbar) {\n if (seenItem.has(action.id)) diagnostics.push(invalidDesignMode(component, `'${component}' declares the design-mode item action '${action.id}' more than once`));\n seenItem.add(action.id);\n }\n\n return diagnostics;\n}\n\nfunction validateEditorOptions(component: string, properties: readonly PropertyDescriptor[], parent: string): SceneDiagnostic[] {\n const diagnostics: SceneDiagnostic[] = [];\n const invalid = (path: string, message: string): SceneDiagnostic => ({\n code: DiagnosticCode.PropertyEditorOptionsInvalid, severity: DiagnosticSeverity.Error, component, path, message: `'${component}' property '${path}' ${message}`,\n });\n\n for (const property of properties) {\n const path = `${parent}${property.path}`;\n const options = property.editorOptions;\n\n if (property.editorKind === PropertyEditorKind.Reference && !options?.reference?.target) {\n diagnostics.push(invalid(path, \"uses the 'reference' editor without saying what it references (editorOptions.reference.target)\"));\n }\n\n if (options?.step !== undefined && !(options.step > 0)) {\n diagnostics.push(invalid(path, 'declares a step that is not greater than zero'));\n }\n\n if (options?.kinds !== undefined && options.kinds.length === 0) {\n diagnostics.push(invalid(path, 'declares an empty list of kinds, which would offer nothing'));\n }\n\n if (property.item) diagnostics.push(...validateEditorOptions(component, property.item.properties, `${path}[].`));\n if (property.properties) diagnostics.push(...validateEditorOptions(component, property.properties, `${path}.`));\n }\n\n return diagnostics;\n}\n"],"names":["validateComponentDescriptors","descriptors","registered","knownCategories","componentCategories","diagnostics","described","Map","map","descriptor","component","has","push","missingCategory","category","undefined","trim","length","includes","code","DiagnosticCode","ComponentCategoryUnknown","severity","DiagnosticSeverity","Warning","message","join","designMode","validateDesignMode","validateEditorOptions","properties","ComponentCategoryMissing","Error","invalidDesignMode","ComponentDesignModeInvalid","collections","Set","filter","property","valueType","PropertyValueType","Collection","path","itemsPath","seenAdd","action","addActions","id","add","collectionPath","seenItem","itemToolbar","parent","invalid","PropertyEditorOptionsInvalid","options","editorOptions","editorKind","PropertyEditorKind","Reference","reference","target","step","kinds","item"],"mappings":";;AAAA;AACA;AAOA;;;;;;;;;;;;;IAcO,SAASA,4BAAAA,CACZC,WAA2C,EAC3CC,UAA8B,EAC9BC,kBAAqCC,mBAAmB,EAAA;AAExD,IAAA,MAAMC,cAAiC,EAAE;AACzC,IAAA,MAAMC,YAAY,IAAIC,GAAAA,CAAIN,YAAYO,GAAG,CAACC,CAAAA,UAAAA,GAAc;AAACA,YAAAA,UAAAA,CAAWC,SAAS;AAAED,YAAAA;AAAW,SAAA,CAAA,CAAA;AAE1F,IAAA,KAAK,MAAMC,SAAAA,IAAaR,UAAAA,IAAc,EAAE,CAAE;AACtC,QAAA,IAAI,CAACI,SAAAA,CAAUK,GAAG,CAACD,SAAAA,CAAAA,EAAY;YAC3BL,WAAAA,CAAYO,IAAI,CAACC,eAAAA,CAAgBH,SAAAA,EAAW,CAAC,CAAC,EAAEA,SAAAA,CAAU,iEAAiE,CAAC,CAAA,CAAA;AAChI,QAAA;AACJ,IAAA;IAEA,KAAK,MAAMD,cAAcR,WAAAA,CAAa;QAClC,MAAM,EAAES,SAAS,EAAE,GAAGD,UAAAA;QAEtB,IAAIA,UAAAA,CAAWK,QAAQ,KAAKC,SAAAA,IAAaN,UAAAA,CAAWK,QAAQ,CAACE,IAAI,EAAA,CAAGC,MAAM,KAAK,CAAA,EAAG;YAC9EZ,WAAAA,CAAYO,IAAI,CAACC,eAAAA,CAAgBH,SAAAA,EAAW,CAAC,CAAC,EAAEA,SAAAA,CAAU,sBAAsB,CAAC,CAAA,CAAA;AACrF,QAAA,CAAA,MAAO,IAAI,CAACP,eAAAA,CAAgBe,QAAQ,CAACT,UAAAA,CAAWK,QAAQ,CAAA,EAAG;AACvDT,YAAAA,WAAAA,CAAYO,IAAI,CAAC;AACbO,gBAAAA,IAAAA,EAAMC,eAAeC,wBAAwB;AAAEC,gBAAAA,QAAAA,EAAUC,mBAAmBC,OAAO;AAAEd,gBAAAA,SAAAA;AACrFe,gBAAAA,OAAAA,EAAS,CAAC,CAAC,EAAEf,SAAAA,CAAU,yBAAyB,EAAED,UAAAA,CAAWK,QAAQ,CAAC,uBAAuB,EAAEX,eAAAA,CAAgBuB,IAAI,CAAC,IAAA,CAAA,CAAA;AACxH,aAAA,CAAA;AACJ,QAAA;QAEA,IAAIjB,UAAAA,CAAWkB,UAAU,EAAE;AACvBtB,YAAAA,WAAAA,CAAYO,IAAI,CAAA,GAAIgB,kBAAAA,CAAmBnB,UAAAA,EAAYA,WAAWkB,UAAU,CAAA,CAAA;AAC5E,QAAA;AAEAtB,QAAAA,WAAAA,CAAYO,IAAI,CAAA,GAAIiB,qBAAAA,CAAsBnB,SAAAA,EAAWD,UAAAA,CAAWqB,UAAU,EAAE,EAAA,CAAA,CAAA;AAChF,IAAA;IAEA,OAAOzB,WAAAA;AACX;AAEA,SAASQ,eAAAA,CAAgBH,SAAiB,EAAEe,OAAe,EAAA;IACvD,OAAO;AAAEN,QAAAA,IAAAA,EAAMC,eAAeW,wBAAwB;AAAET,QAAAA,QAAAA,EAAUC,mBAAmBS,KAAK;AAAEtB,QAAAA,SAAAA;AAAWe,QAAAA;AAAQ,KAAA;AACnH;AAEA,SAASQ,iBAAAA,CAAkBvB,SAAiB,EAAEe,OAAe,EAAA;IACzD,OAAO;AAAEN,QAAAA,IAAAA,EAAMC,eAAec,0BAA0B;AAAEZ,QAAAA,QAAAA,EAAUC,mBAAmBS,KAAK;AAAEtB,QAAAA,SAAAA;AAAWe,QAAAA;AAAQ,KAAA;AACrH;AAEA,SAASG,kBAAAA,CAAmBnB,UAA+B,EAAEkB,UAAyC,EAAA;IAClG,MAAM,EAAEjB,SAAS,EAAE,GAAGD,UAAAA;AACtB,IAAA,MAAMJ,cAAiC,EAAE;IACzC,MAAM8B,WAAAA,GAAc,IAAIC,GAAAA,CAAI3B,UAAAA,CAAWqB,UAAU,CAACO,MAAM,CAACC,CAAAA,QAAAA,GAAYA,SAASC,SAAS,KAAKC,kBAAkBC,UAAU,CAAA,CAAEjC,GAAG,CAAC8B,CAAAA,QAAAA,GAAYA,QAAAA,CAASI,IAAI,CAAA,CAAA;IAEvJ,IAAIf,UAAAA,CAAWgB,SAAS,KAAK5B,SAAAA,IAAa,CAACoB,YAAYxB,GAAG,CAACgB,UAAAA,CAAWgB,SAAS,CAAA,EAAG;AAC9EtC,QAAAA,WAAAA,CAAYO,IAAI,CAACqB,iBAAAA,CAAkBvB,SAAAA,EAAW,CAAC,CAAC,EAAEA,SAAAA,CAAU,SAAS,EAAEiB,UAAAA,CAAWgB,SAAS,CAAC,yEAAyE,CAAC,CAAA,CAAA;AAC1K,IAAA;AAEA,IAAA,MAAMC,UAAU,IAAIR,GAAAA,EAAAA;AACpB,IAAA,KAAK,MAAMS,MAAAA,IAAUlB,UAAAA,CAAWmB,UAAU,CAAE;QACxC,IAAIF,OAAAA,CAAQjC,GAAG,CAACkC,MAAAA,CAAOE,EAAE,CAAA,EAAG1C,WAAAA,CAAYO,IAAI,CAACqB,iBAAAA,CAAkBvB,WAAW,CAAC,CAAC,EAAEA,SAAAA,CAAU,uCAAuC,EAAEmC,MAAAA,CAAOE,EAAE,CAAC,gBAAgB,CAAC,CAAA,CAAA;QAC5JH,OAAAA,CAAQI,GAAG,CAACH,MAAAA,CAAOE,EAAE,CAAA;QAErB,IAAIF,MAAAA,CAAOI,cAAc,KAAKlC,SAAAA,IAAa,CAACoB,YAAYxB,GAAG,CAACkC,MAAAA,CAAOI,cAAc,CAAA,EAAG;AAChF5C,YAAAA,WAAAA,CAAYO,IAAI,CAACqB,iBAAAA,CAAkBvB,WAAW,CAAC,4BAA4B,EAAEmC,MAAAA,CAAOE,EAAE,CAAC,MAAM,EAAErC,UAAU,WAAW,EAAEmC,OAAOI,cAAc,CAAC,gDAAgD,CAAC,CAAA,CAAA;AACjM,QAAA;AACJ,IAAA;AAEA,IAAA,MAAMC,WAAW,IAAId,GAAAA,EAAAA;AACrB,IAAA,KAAK,MAAMS,MAAAA,IAAUlB,UAAAA,CAAWwB,WAAW,CAAE;QACzC,IAAID,QAAAA,CAASvC,GAAG,CAACkC,MAAAA,CAAOE,EAAE,CAAA,EAAG1C,WAAAA,CAAYO,IAAI,CAACqB,iBAAAA,CAAkBvB,WAAW,CAAC,CAAC,EAAEA,SAAAA,CAAU,wCAAwC,EAAEmC,MAAAA,CAAOE,EAAE,CAAC,gBAAgB,CAAC,CAAA,CAAA;QAC9JG,QAAAA,CAASF,GAAG,CAACH,MAAAA,CAAOE,EAAE,CAAA;AAC1B,IAAA;IAEA,OAAO1C,WAAAA;AACX;AAEA,SAASwB,qBAAAA,CAAsBnB,SAAiB,EAAEoB,UAAyC,EAAEsB,MAAc,EAAA;AACvG,IAAA,MAAM/C,cAAiC,EAAE;AACzC,IAAA,MAAMgD,OAAAA,GAAU,CAACX,IAAAA,EAAcjB,OAAAA,IAAsC;AACjEN,YAAAA,IAAAA,EAAMC,eAAekC,4BAA4B;AAAEhC,YAAAA,QAAAA,EAAUC,mBAAmBS,KAAK;AAAEtB,YAAAA,SAAAA;AAAWgC,YAAAA,IAAAA;YAAMjB,OAAAA,EAAS,CAAC,CAAC,EAAEf,SAAAA,CAAU,YAAY,EAAEgC,IAAAA,CAAK,EAAE,EAAEjB,OAAAA,CAAAA;SAC1J,CAAA;IAEA,KAAK,MAAMa,YAAYR,UAAAA,CAAY;AAC/B,QAAA,MAAMY,IAAAA,GAAO,CAAA,EAAGU,MAAAA,CAAAA,EAASd,QAAAA,CAASI,IAAI,CAAA,CAAE;QACxC,MAAMa,OAAAA,GAAUjB,SAASkB,aAAa;QAEtC,IAAIlB,QAAAA,CAASmB,UAAU,KAAKC,kBAAAA,CAAmBC,SAAS,IAAI,CAACJ,OAAAA,EAASK,SAAAA,EAAWC,MAAAA,EAAQ;YACrFxD,WAAAA,CAAYO,IAAI,CAACyC,OAAAA,CAAQX,IAAAA,EAAM,gGAAA,CAAA,CAAA;AACnC,QAAA;QAEA,IAAIa,OAAAA,EAASO,SAAS/C,SAAAA,IAAa,EAAEwC,OAAAA,CAAQO,IAAI,GAAG,CAAA,CAAA,EAAI;YACpDzD,WAAAA,CAAYO,IAAI,CAACyC,OAAAA,CAAQX,IAAAA,EAAM,+CAAA,CAAA,CAAA;AACnC,QAAA;QAEA,IAAIa,OAAAA,EAASQ,UAAUhD,SAAAA,IAAawC,OAAAA,CAAQQ,KAAK,CAAC9C,MAAM,KAAK,CAAA,EAAG;YAC5DZ,WAAAA,CAAYO,IAAI,CAACyC,OAAAA,CAAQX,IAAAA,EAAM,4DAAA,CAAA,CAAA;AACnC,QAAA;AAEA,QAAA,IAAIJ,SAAS0B,IAAI,EAAE3D,WAAAA,CAAYO,IAAI,IAAIiB,qBAAAA,CAAsBnB,SAAAA,EAAW4B,QAAAA,CAAS0B,IAAI,CAAClC,UAAU,EAAE,CAAA,EAAGY,IAAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAC9G,QAAA,IAAIJ,QAAAA,CAASR,UAAU,EAAEzB,WAAAA,CAAYO,IAAI,CAAA,GAAIiB,qBAAAA,CAAsBnB,SAAAA,EAAW4B,QAAAA,CAASR,UAAU,EAAE,CAAA,EAAGY,IAAAA,CAAK,CAAC,CAAC,CAAA,CAAA;AACjH,IAAA;IAEA,OAAOrC,WAAAA;AACX;;"}
@@ -16,6 +16,7 @@ export * from './panelKind';
16
16
  export * from './flowNodeKind';
17
17
  export * from './ComponentResolution';
18
18
  export * from './icons';
19
+ export * from './descriptors';
19
20
  export * from './resolveComponentName';
20
21
  export * from './computeSizeClass';
21
22
  export * from './evaluateFlowArrangement';
@@ -39,4 +40,5 @@ export * from './resolveStrings';
39
40
  export * from './navigation';
40
41
  export * from './validateNavigationDestinations';
41
42
  export * from './editing';
43
+ export * from './structure';
42
44
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kCAAkC,CAAC;AACjD,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kCAAkC,CAAC;AACjD,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
package/dist/esm/index.js CHANGED
@@ -25,6 +25,10 @@ export { resolveIconLibraries } from './icons/resolveIconLibraries.js';
25
25
  export { referencesOfEntry } from './icons/EffectiveIconEntry.js';
26
26
  export { EffectiveIconCatalog } from './icons/EffectiveIconCatalog.js';
27
27
  export { analyzeIconImpact } from './icons/analyzeIconImpact.js';
28
+ export { validateComponentDescriptors } from './descriptors/validateComponentDescriptors.js';
29
+ export { componentBadge } from './descriptors/componentBadge.js';
30
+ export { matchComponentQuery } from './descriptors/matchComponentQuery.js';
31
+ export { frequentlyUsedLimit, rankFrequentlyUsedComponents } from './descriptors/rankFrequentlyUsedComponents.js';
28
32
  export { corePackage, effectivePackages, resolveComponentName } from './resolveComponentName.js';
29
33
  export { computeSizeClass, defaultHeightBreakpoint, defaultWidthBreakpoint } from './computeSizeClass.js';
30
34
  export { evaluateFlowArrangement } from './evaluateFlowArrangement.js';
@@ -69,4 +73,6 @@ export { applyEdit } from './editing/applyEdit.js';
69
73
  export { iconProblem, iconProblemsOfItems, iconProblemsOfProperty } from './editing/iconDiagnostics.js';
70
74
  export { diagnoseIcons } from './editing/diagnoseIcons.js';
71
75
  export { collectIconUsages } from './editing/collectIconUsages.js';
76
+ export { StructureDiagnosticCode } from './structure/StructureDiagnosticCode.js';
77
+ export { ApplicationStructureIndex } from './structure/ApplicationStructureIndex.js';
72
78
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,22 @@
1
+ import { ApplicationStructure, FeatureNode, ModuleNode, SliceKind, SliceNode } from '@cratis/scene.model';
2
+ import { StructureDiagnostic } from './StructureDiagnostic';
3
+ export declare class ApplicationStructureIndex {
4
+ readonly structure: ApplicationStructure;
5
+ private readonly modules;
6
+ private readonly features;
7
+ private readonly slices;
8
+ private readonly featuresByName;
9
+ readonly diagnostics: StructureDiagnostic[];
10
+ constructor(structure: ApplicationStructure);
11
+ findModule(moduleId: string): ModuleNode | undefined;
12
+ findFeature(qualifiedId: string): FeatureNode | undefined;
13
+ firstFeature(moduleId: string): FeatureNode | undefined;
14
+ firstFeatureId(moduleId: string): string | undefined;
15
+ findSlice(qualifiedId: string): SliceNode | undefined;
16
+ kindOf(sliceId: string): SliceKind | undefined;
17
+ findFeaturesByName(name: string): string[];
18
+ private indexContainer;
19
+ private claim;
20
+ private reportAmbiguousName;
21
+ }
22
+ //# sourceMappingURL=ApplicationStructureIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApplicationStructureIndex.d.ts","sourceRoot":"","sources":["../../../structure/ApplicationStructureIndex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAW5D,qBAAa,yBAAyB;IAatB,QAAQ,CAAC,SAAS,EAAE,oBAAoB;IAZpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAG9D,QAAQ,CAAC,WAAW,EAAE,mBAAmB,EAAE,CAAM;IAMjD,YAAqB,SAAS,EAAE,oBAAoB,EAYnD;IAOD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEnD;IAOD,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExD;IAOD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEtD;IAOD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGnD;IAOD,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEpD;IAOD,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE7C;IAOD,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzC;IAED,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,mBAAmB;CAc9B"}