@cratis/scene.engine 4.22.1 → 4.23.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 (33) hide show
  1. package/dist/cjs/index.js +4 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/structure/ApplicationStructureIndex.js +139 -0
  4. package/dist/cjs/structure/ApplicationStructureIndex.js.map +1 -0
  5. package/dist/cjs/structure/StructureDiagnosticCode.js +15 -0
  6. package/dist/cjs/structure/StructureDiagnosticCode.js.map +1 -0
  7. package/dist/esm/index.d.ts +1 -0
  8. package/dist/esm/index.d.ts.map +1 -1
  9. package/dist/esm/index.js +2 -0
  10. package/dist/esm/index.js.map +1 -1
  11. package/dist/esm/structure/ApplicationStructureIndex.d.ts +22 -0
  12. package/dist/esm/structure/ApplicationStructureIndex.d.ts.map +1 -0
  13. package/dist/esm/structure/ApplicationStructureIndex.js +137 -0
  14. package/dist/esm/structure/ApplicationStructureIndex.js.map +1 -0
  15. package/dist/esm/structure/StructureDiagnostic.d.ts +7 -0
  16. package/dist/esm/structure/StructureDiagnostic.d.ts.map +1 -0
  17. package/dist/esm/structure/StructureDiagnostic.js +2 -0
  18. package/dist/esm/structure/StructureDiagnostic.js.map +1 -0
  19. package/dist/esm/structure/StructureDiagnosticCode.d.ts +5 -0
  20. package/dist/esm/structure/StructureDiagnosticCode.d.ts.map +1 -0
  21. package/dist/esm/structure/StructureDiagnosticCode.js +13 -0
  22. package/dist/esm/structure/StructureDiagnosticCode.js.map +1 -0
  23. package/dist/esm/structure/index.d.ts +4 -0
  24. package/dist/esm/structure/index.d.ts.map +1 -0
  25. package/dist/esm/structure/index.js +4 -0
  26. package/dist/esm/structure/index.js.map +1 -0
  27. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  28. package/index.ts +1 -0
  29. package/package.json +3 -3
  30. package/structure/ApplicationStructureIndex.ts +163 -0
  31. package/structure/StructureDiagnostic.ts +18 -0
  32. package/structure/StructureDiagnosticCode.ts +14 -0
  33. package/structure/index.ts +6 -0
package/dist/cjs/index.js CHANGED
@@ -71,6 +71,8 @@ var applyEdit = require('./editing/applyEdit.js');
71
71
  var iconDiagnostics = require('./editing/iconDiagnostics.js');
72
72
  var diagnoseIcons = require('./editing/diagnoseIcons.js');
73
73
  var collectIconUsages = require('./editing/collectIconUsages.js');
74
+ var StructureDiagnosticCode = require('./structure/StructureDiagnosticCode.js');
75
+ var ApplicationStructureIndex = require('./structure/ApplicationStructureIndex.js');
74
76
 
75
77
 
76
78
 
@@ -209,4 +211,6 @@ exports.iconProblemsOfItems = iconDiagnostics.iconProblemsOfItems;
209
211
  exports.iconProblemsOfProperty = iconDiagnostics.iconProblemsOfProperty;
210
212
  exports.diagnoseIcons = diagnoseIcons.diagnoseIcons;
211
213
  exports.collectIconUsages = collectIconUsages.collectIconUsages;
214
+ exports.StructureDiagnosticCode = StructureDiagnosticCode.StructureDiagnosticCode;
215
+ exports.ApplicationStructureIndex = ApplicationStructureIndex.ApplicationStructureIndex;
212
216
  //# 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,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;;"}
@@ -39,4 +39,5 @@ export * from './resolveStrings';
39
39
  export * from './navigation';
40
40
  export * from './validateNavigationDestinations';
41
41
  export * from './editing';
42
+ export * from './structure';
42
43
  //# 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,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
@@ -69,4 +69,6 @@ export { applyEdit } from './editing/applyEdit.js';
69
69
  export { iconProblem, iconProblemsOfItems, iconProblemsOfProperty } from './editing/iconDiagnostics.js';
70
70
  export { diagnoseIcons } from './editing/diagnoseIcons.js';
71
71
  export { collectIconUsages } from './editing/collectIconUsages.js';
72
+ export { StructureDiagnosticCode } from './structure/StructureDiagnosticCode.js';
73
+ export { ApplicationStructureIndex } from './structure/ApplicationStructureIndex.js';
72
74
  //# 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"}
@@ -0,0 +1,137 @@
1
+ import { StructureDiagnosticCode } from './StructureDiagnosticCode.js';
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
+ * Answers the questions navigation, toolbar and template applicability ask of an {@link ApplicationStructure}:
7
+ * does this module, feature or slice exist, which feature comes first in a module, and what kind of slice is it.
8
+ * Pure and read-only; when ids are duplicated the first declaration wins and {@link diagnostics} reports the rest.
9
+ *
10
+ * The C# engine (`ApplicationStructureIndex`) answers the same questions the same way; both are asserted
11
+ * against `application-structure-fixtures.json`.
12
+ */ class ApplicationStructureIndex {
13
+ structure;
14
+ modules = new Map();
15
+ features = new Map();
16
+ slices = new Map();
17
+ featuresByName = new Map();
18
+ /** The problems found while indexing, in declaration order. */ diagnostics = [];
19
+ /**
20
+ * Initializes a new instance of the {@link ApplicationStructureIndex} class.
21
+ * @param structure The application structure to index.
22
+ */ constructor(structure){
23
+ this.structure = structure;
24
+ const seen = new Map();
25
+ const names = new Map();
26
+ for (const module of structure.modules){
27
+ const qualified = module.id;
28
+ if (!this.claim(seen, qualified, 'module')) continue;
29
+ this.modules.set(qualified, module);
30
+ this.reportAmbiguousName(names, 'module', module.name, qualified);
31
+ this.indexContainer(qualified, module.features, module.slices ?? []);
32
+ }
33
+ }
34
+ /**
35
+ * Finds a module by its id.
36
+ * @param moduleId The module id, for example `sales`.
37
+ * @returns The module, or undefined when there is none.
38
+ */ findModule(moduleId) {
39
+ return this.modules.get(moduleId);
40
+ }
41
+ /**
42
+ * Finds a feature by its qualified id.
43
+ * @param qualifiedId The dotted id from the module down, for example `sales.orders` or `sales.orders.returns`.
44
+ * @returns The feature, or undefined when there is none.
45
+ */ findFeature(qualifiedId) {
46
+ return this.features.get(qualifiedId);
47
+ }
48
+ /**
49
+ * Gets the first feature of a module - the one a navigation target that names only the module goes to.
50
+ * @param moduleId The module id.
51
+ * @returns The module's first top-level feature, or undefined when the module is unknown or has no features.
52
+ */ firstFeature(moduleId) {
53
+ return this.findModule(moduleId)?.features[0];
54
+ }
55
+ /**
56
+ * Gets the qualified id of the first feature of a module.
57
+ * @param moduleId The module id.
58
+ * @returns The qualified id, or undefined when the module is unknown or has no features.
59
+ */ firstFeatureId(moduleId) {
60
+ const feature = this.firstFeature(moduleId);
61
+ return feature ? `${moduleId}.${feature.id}` : undefined;
62
+ }
63
+ /**
64
+ * Finds a slice by its qualified id.
65
+ * @param qualifiedId The dotted id from the module down, for example `sales.orders.PlaceOrder`.
66
+ * @returns The slice, or undefined when there is none.
67
+ */ findSlice(qualifiedId) {
68
+ return this.slices.get(qualifiedId);
69
+ }
70
+ /**
71
+ * Gets what kind a slice is.
72
+ * @param sliceId The slice's qualified id.
73
+ * @returns The kind, or undefined when there is no such slice.
74
+ */ kindOf(sliceId) {
75
+ return this.findSlice(sliceId)?.kind;
76
+ }
77
+ /**
78
+ * Finds every feature that has a given display name, in every module, so a caller can tell when a bare name is ambiguous.
79
+ * @param name The display name, compared without regard to case.
80
+ * @returns The qualified ids of the features with that name, in declaration order.
81
+ */ findFeaturesByName(name) {
82
+ return [
83
+ ...this.featuresByName.get(name.toLowerCase()) ?? []
84
+ ];
85
+ }
86
+ indexContainer(path, features, slices) {
87
+ const seen = new Map();
88
+ const featureNames = new Map();
89
+ const sliceNames = new Map();
90
+ for (const feature of features){
91
+ const qualified = `${path}.${feature.id}`;
92
+ if (!this.claim(seen, qualified, 'feature')) continue;
93
+ this.features.set(qualified, feature);
94
+ const key = feature.name.toLowerCase();
95
+ const byName = this.featuresByName.get(key) ?? [];
96
+ byName.push(qualified);
97
+ this.featuresByName.set(key, byName);
98
+ this.reportAmbiguousName(featureNames, 'feature', feature.name, qualified);
99
+ this.indexContainer(qualified, feature.features, feature.slices);
100
+ }
101
+ for (const slice of slices){
102
+ const qualified = `${path}.${slice.id}`;
103
+ if (!this.claim(seen, qualified, 'slice')) continue;
104
+ this.slices.set(qualified, slice);
105
+ this.reportAmbiguousName(sliceNames, 'slice', slice.name, qualified);
106
+ }
107
+ }
108
+ claim(seen, qualified, kind) {
109
+ const first = seen.get(qualified);
110
+ if (first === undefined) {
111
+ seen.set(qualified, kind);
112
+ return true;
113
+ }
114
+ this.diagnostics.push({
115
+ code: StructureDiagnosticCode.StructureDuplicateId,
116
+ message: `Id '${qualified}' is declared more than once; the first ${first} wins.`,
117
+ id: qualified
118
+ });
119
+ return false;
120
+ }
121
+ reportAmbiguousName(names, kind, name, qualified) {
122
+ const key = name.toLowerCase();
123
+ const first = names.get(key);
124
+ if (first !== undefined) {
125
+ this.diagnostics.push({
126
+ code: StructureDiagnosticCode.StructureAmbiguousName,
127
+ message: `The ${kind} name '${name}' is used by both '${first}' and '${qualified}'.`,
128
+ id: qualified
129
+ });
130
+ return;
131
+ }
132
+ names.set(key, qualified);
133
+ }
134
+ }
135
+
136
+ export { ApplicationStructureIndex };
137
+ //# 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,7 @@
1
+ import { StructureDiagnosticCode } from './StructureDiagnosticCode';
2
+ export interface StructureDiagnostic {
3
+ code: StructureDiagnosticCode;
4
+ message: string;
5
+ id: string;
6
+ }
7
+ //# sourceMappingURL=StructureDiagnostic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureDiagnostic.d.ts","sourceRoot":"","sources":["../../../structure/StructureDiagnostic.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKpE,MAAM,WAAW,mBAAmB;IAEhC,IAAI,EAAE,uBAAuB,CAAC;IAG9B,OAAO,EAAE,MAAM,CAAC;IAGhB,EAAE,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=StructureDiagnostic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureDiagnostic.js","sourceRoot":"","sources":["../../../structure/StructureDiagnostic.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export declare enum StructureDiagnosticCode {
2
+ StructureDuplicateId = "structureDuplicateId",
3
+ StructureAmbiguousName = "structureAmbiguousName"
4
+ }
5
+ //# sourceMappingURL=StructureDiagnosticCode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureDiagnosticCode.d.ts","sourceRoot":"","sources":["../../../structure/StructureDiagnosticCode.ts"],"names":[],"mappings":"AAOA,oBAAY,uBAAuB;IAE/B,oBAAoB,yBAAyB;IAG7C,sBAAsB,2BAA2B;CACpD"}
@@ -0,0 +1,13 @@
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
+ * What is wrong with an application structure. The values are shared with the C# engine so both report
5
+ * the same code for the same structure.
6
+ */ var StructureDiagnosticCode = /*#__PURE__*/ function(StructureDiagnosticCode) {
7
+ /** Two siblings share one id, so their qualified id does not identify a single node. */ StructureDiagnosticCode["StructureDuplicateId"] = "structureDuplicateId";
8
+ /** Two siblings with different ids share one display name, so a picker or a name lookup cannot tell them apart. */ StructureDiagnosticCode["StructureAmbiguousName"] = "structureAmbiguousName";
9
+ return StructureDiagnosticCode;
10
+ }({});
11
+
12
+ export { StructureDiagnosticCode };
13
+ //# 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,4 @@
1
+ export * from './StructureDiagnosticCode';
2
+ export * from './StructureDiagnostic';
3
+ export * from './ApplicationStructureIndex';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../structure/index.ts"],"names":[],"mappings":"AAGA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './StructureDiagnosticCode';
2
+ export * from './StructureDiagnostic';
3
+ export * from './ApplicationStructureIndex';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../structure/index.ts"],"names":[],"mappings":"AAGA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC"}