@cratis/scene.engine 4.12.0 → 4.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/navigation/NavigationDiagnosticCode.js +19 -0
- package/dist/cjs/navigation/NavigationDiagnosticCode.js.map +1 -0
- package/dist/cjs/navigation/collectOutlets.js +45 -0
- package/dist/cjs/navigation/collectOutlets.js.map +1 -0
- package/dist/cjs/navigation/diagnoseNavigation.js +116 -0
- package/dist/cjs/navigation/diagnoseNavigation.js.map +1 -0
- package/dist/cjs/navigation/findHostingCycles.js +43 -0
- package/dist/cjs/navigation/findHostingCycles.js.map +1 -0
- package/dist/cjs/navigation/navigationEntriesFrom.js +19 -0
- package/dist/cjs/navigation/navigationEntriesFrom.js.map +1 -0
- package/dist/cjs/navigation/navigationRoute.js +25 -0
- package/dist/cjs/navigation/navigationRoute.js.map +1 -0
- package/dist/cjs/packageVersionRange.js +16 -0
- package/dist/cjs/packageVersionRange.js.map +1 -1
- package/dist/cjs/templates/TemplateCatalogKind.js +15 -0
- package/dist/cjs/templates/TemplateCatalogKind.js.map +1 -0
- package/dist/cjs/templates/describeTemplateCatalog.js +89 -0
- package/dist/cjs/templates/describeTemplateCatalog.js.map +1 -0
- package/dist/cjs/templates/templateMetadataRules.js +32 -0
- package/dist/cjs/templates/templateMetadataRules.js.map +1 -0
- package/dist/cjs/templates/validateTemplateMetadata.js +50 -0
- package/dist/cjs/templates/validateTemplateMetadata.js.map +1 -0
- package/dist/cjs/validateNavigationDestinations.js +12 -38
- package/dist/cjs/validateNavigationDestinations.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +9 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/navigation/NavigationDiagnostic.d.ts +7 -0
- package/dist/esm/navigation/NavigationDiagnostic.d.ts.map +1 -0
- package/dist/esm/navigation/NavigationDiagnostic.js +2 -0
- package/dist/esm/navigation/NavigationDiagnostic.js.map +1 -0
- package/dist/esm/navigation/NavigationDiagnosticCode.d.ts +9 -0
- package/dist/esm/navigation/NavigationDiagnosticCode.d.ts.map +1 -0
- package/dist/esm/navigation/NavigationDiagnosticCode.js +17 -0
- package/dist/esm/navigation/NavigationDiagnosticCode.js.map +1 -0
- package/dist/esm/navigation/NavigationEntry.d.ts +6 -0
- package/dist/esm/navigation/NavigationEntry.d.ts.map +1 -0
- package/dist/esm/navigation/NavigationEntry.js +2 -0
- package/dist/esm/navigation/NavigationEntry.js.map +1 -0
- package/dist/esm/navigation/NavigationGraph.d.ts +10 -0
- package/dist/esm/navigation/NavigationGraph.d.ts.map +1 -0
- package/dist/esm/navigation/NavigationGraph.js +2 -0
- package/dist/esm/navigation/NavigationGraph.js.map +1 -0
- package/dist/esm/navigation/OutletOwner.d.ts +7 -0
- package/dist/esm/navigation/OutletOwner.d.ts.map +1 -0
- package/dist/esm/navigation/OutletOwner.js +2 -0
- package/dist/esm/navigation/OutletOwner.js.map +1 -0
- package/dist/esm/navigation/collectOutlets.d.ts +5 -0
- package/dist/esm/navigation/collectOutlets.d.ts.map +1 -0
- package/dist/esm/navigation/collectOutlets.js +43 -0
- package/dist/esm/navigation/collectOutlets.js.map +1 -0
- package/dist/esm/navigation/diagnoseNavigation.d.ts +5 -0
- package/dist/esm/navigation/diagnoseNavigation.d.ts.map +1 -0
- package/dist/esm/navigation/diagnoseNavigation.js +114 -0
- package/dist/esm/navigation/diagnoseNavigation.js.map +1 -0
- package/dist/esm/navigation/findHostingCycles.d.ts +2 -0
- package/dist/esm/navigation/findHostingCycles.d.ts.map +1 -0
- package/dist/esm/navigation/findHostingCycles.js +41 -0
- package/dist/esm/navigation/findHostingCycles.js.map +1 -0
- package/dist/esm/navigation/index.d.ts +8 -0
- package/dist/esm/navigation/index.d.ts.map +1 -0
- package/dist/esm/navigation/index.js +8 -0
- package/dist/esm/navigation/index.js.map +1 -0
- package/dist/esm/navigation/navigationEntriesFrom.d.ts +4 -0
- package/dist/esm/navigation/navigationEntriesFrom.d.ts.map +1 -0
- package/dist/esm/navigation/navigationEntriesFrom.js +17 -0
- package/dist/esm/navigation/navigationEntriesFrom.js.map +1 -0
- package/dist/esm/navigation/navigationRoute.d.ts +5 -0
- package/dist/esm/navigation/navigationRoute.d.ts.map +1 -0
- package/dist/esm/navigation/navigationRoute.js +22 -0
- package/dist/esm/navigation/navigationRoute.js.map +1 -0
- package/dist/esm/packageVersionRange.d.ts +2 -0
- package/dist/esm/packageVersionRange.d.ts.map +1 -1
- package/dist/esm/packageVersionRange.js +15 -1
- package/dist/esm/packageVersionRange.js.map +1 -1
- package/dist/esm/templates/TemplateCatalogEntry.d.ts +20 -0
- package/dist/esm/templates/TemplateCatalogEntry.d.ts.map +1 -0
- package/dist/esm/templates/TemplateCatalogEntry.js +2 -0
- package/dist/esm/templates/TemplateCatalogEntry.js.map +1 -0
- package/dist/esm/templates/TemplateCatalogKind.d.ts +6 -0
- package/dist/esm/templates/TemplateCatalogKind.d.ts.map +1 -0
- package/dist/esm/templates/TemplateCatalogKind.js +13 -0
- package/dist/esm/templates/TemplateCatalogKind.js.map +1 -0
- package/dist/esm/templates/TemplateSource.d.ts +8 -0
- package/dist/esm/templates/TemplateSource.d.ts.map +1 -0
- package/dist/esm/templates/TemplateSource.js +2 -0
- package/dist/esm/templates/TemplateSource.js.map +1 -0
- package/dist/esm/templates/describeTemplateCatalog.d.ts +4 -0
- package/dist/esm/templates/describeTemplateCatalog.d.ts.map +1 -0
- package/dist/esm/templates/describeTemplateCatalog.js +87 -0
- package/dist/esm/templates/describeTemplateCatalog.js.map +1 -0
- package/dist/esm/templates/index.d.ts +7 -0
- package/dist/esm/templates/index.d.ts.map +1 -0
- package/dist/esm/templates/index.js +7 -0
- package/dist/esm/templates/index.js.map +1 -0
- package/dist/esm/templates/templateMetadataRules.d.ts +3 -0
- package/dist/esm/templates/templateMetadataRules.d.ts.map +1 -0
- package/dist/esm/templates/templateMetadataRules.js +29 -0
- package/dist/esm/templates/templateMetadataRules.js.map +1 -0
- package/dist/esm/templates/validateTemplateMetadata.d.ts +3 -0
- package/dist/esm/templates/validateTemplateMetadata.d.ts.map +1 -0
- package/dist/esm/templates/validateTemplateMetadata.js +48 -0
- package/dist/esm/templates/validateTemplateMetadata.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/validateNavigationDestinations.d.ts +5 -5
- package/dist/esm/validateNavigationDestinations.d.ts.map +1 -1
- package/dist/esm/validateNavigationDestinations.js +12 -38
- package/dist/esm/validateNavigationDestinations.js.map +1 -1
- package/index.ts +2 -0
- package/navigation/NavigationDiagnostic.ts +18 -0
- package/navigation/NavigationDiagnosticCode.ts +26 -0
- package/navigation/NavigationEntry.ts +16 -0
- package/navigation/NavigationGraph.ts +26 -0
- package/navigation/OutletOwner.ts +13 -0
- package/navigation/collectOutlets.ts +36 -0
- package/navigation/diagnoseNavigation.ts +136 -0
- package/navigation/findHostingCycles.ts +41 -0
- package/navigation/index.ts +10 -0
- package/navigation/navigationEntriesFrom.ts +16 -0
- package/navigation/navigationRoute.ts +25 -0
- package/package.json +3 -3
- package/packageVersionRange.ts +18 -0
- package/templates/TemplateCatalogEntry.ts +35 -0
- package/templates/TemplateCatalogKind.ts +11 -0
- package/templates/TemplateSource.ts +15 -0
- package/templates/describeTemplateCatalog.ts +92 -0
- package/templates/index.ts +9 -0
- package/templates/templateMetadataRules.ts +25 -0
- package/templates/validateTemplateMetadata.ts +55 -0
- package/validateNavigationDestinations.ts +12 -32
package/dist/cjs/index.js
CHANGED
|
@@ -33,11 +33,19 @@ var resolvePackageDependencies = require('./resolvePackageDependencies.js');
|
|
|
33
33
|
var packageCatalog = require('./packageCatalog.js');
|
|
34
34
|
var resolveScreenTemplates = require('./resolveScreenTemplates.js');
|
|
35
35
|
var templateApplicability = require('./templateApplicability.js');
|
|
36
|
+
var TemplateCatalogKind = require('./templates/TemplateCatalogKind.js');
|
|
37
|
+
var describeTemplateCatalog = require('./templates/describeTemplateCatalog.js');
|
|
38
|
+
var templateMetadataRules = require('./templates/templateMetadataRules.js');
|
|
39
|
+
var validateTemplateMetadata = require('./templates/validateTemplateMetadata.js');
|
|
36
40
|
var buildStarterProfile = require('./buildStarterProfile.js');
|
|
37
41
|
var incompatibleStarterThemes = require('./incompatibleStarterThemes.js');
|
|
38
42
|
var runActions = require('./runActions.js');
|
|
39
43
|
var resolveBehaviors = require('./resolveBehaviors.js');
|
|
40
44
|
var resolveStrings = require('./resolveStrings.js');
|
|
45
|
+
var NavigationDiagnosticCode = require('./navigation/NavigationDiagnosticCode.js');
|
|
46
|
+
var diagnoseNavigation = require('./navigation/diagnoseNavigation.js');
|
|
47
|
+
var navigationEntriesFrom = require('./navigation/navigationEntriesFrom.js');
|
|
48
|
+
var navigationRoute = require('./navigation/navigationRoute.js');
|
|
41
49
|
var validateNavigationDestinations = require('./validateNavigationDestinations.js');
|
|
42
50
|
var diagnostics = require('./editing/diagnostics.js');
|
|
43
51
|
var nodeIds = require('./editing/nodeIds.js');
|
|
@@ -106,6 +114,8 @@ exports.applicableThemePackages = themeCompatibility.applicableThemePackages;
|
|
|
106
114
|
exports.incompatiblePackages = themeCompatibility.incompatiblePackages;
|
|
107
115
|
exports.isThemeCompatible = themeCompatibility.isThemeCompatible;
|
|
108
116
|
exports.isPackageSelectionValid = PackageSelection.isPackageSelectionValid;
|
|
117
|
+
exports.isValidVersion = packageVersionRange.isValidVersion;
|
|
118
|
+
exports.isValidVersionRange = packageVersionRange.isValidVersionRange;
|
|
109
119
|
exports.isVersionSatisfiedBy = packageVersionRange.isVersionSatisfiedBy;
|
|
110
120
|
exports.resolvePackageDependencies = resolvePackageDependencies.resolvePackageDependencies;
|
|
111
121
|
exports.availablePackagesFor = packageCatalog.availablePackagesFor;
|
|
@@ -119,6 +129,11 @@ exports.filterApplicableScreenTemplates = templateApplicability.filterApplicable
|
|
|
119
129
|
exports.validateDialogTemplateApplicability = templateApplicability.validateDialogTemplateApplicability;
|
|
120
130
|
exports.validateLayoutApplicability = templateApplicability.validateLayoutApplicability;
|
|
121
131
|
exports.validateScreenTemplateApplicability = templateApplicability.validateScreenTemplateApplicability;
|
|
132
|
+
exports.TemplateCatalogKind = TemplateCatalogKind.TemplateCatalogKind;
|
|
133
|
+
exports.describeTemplateCatalog = describeTemplateCatalog.describeTemplateCatalog;
|
|
134
|
+
exports.isAbsoluteHttpsUrl = templateMetadataRules.isAbsoluteHttpsUrl;
|
|
135
|
+
exports.isSpdxExpression = templateMetadataRules.isSpdxExpression;
|
|
136
|
+
exports.validateTemplateMetadata = validateTemplateMetadata.validateTemplateMetadata;
|
|
122
137
|
exports.buildStarterProfile = buildStarterProfile.buildStarterProfile;
|
|
123
138
|
exports.incompatibleStarterThemes = incompatibleStarterThemes.incompatibleStarterThemes;
|
|
124
139
|
exports.InteractionStop = runActions.InteractionStop;
|
|
@@ -131,6 +146,11 @@ exports.resolveIntervalBehaviors = resolveBehaviors.resolveIntervalBehaviors;
|
|
|
131
146
|
exports.isStringsReference = resolveStrings.isStringsReference;
|
|
132
147
|
exports.resolveStringsInElement = resolveStrings.resolveStringsInElement;
|
|
133
148
|
exports.resolveStringsValue = resolveStrings.resolveStringsValue;
|
|
149
|
+
exports.NavigationDiagnosticCode = NavigationDiagnosticCode.NavigationDiagnosticCode;
|
|
150
|
+
exports.diagnoseNavigation = diagnoseNavigation.diagnoseNavigation;
|
|
151
|
+
exports.navigationEntriesFrom = navigationEntriesFrom.navigationEntriesFrom;
|
|
152
|
+
exports.authoredRouteKey = navigationRoute.authoredRouteKey;
|
|
153
|
+
exports.navigationTarget = navigationRoute.navigationTarget;
|
|
134
154
|
exports.validateNavigationDestinations = validateNavigationDestinations.validateNavigationDestinations;
|
|
135
155
|
exports.errorDiagnostic = diagnostics.errorDiagnostic;
|
|
136
156
|
exports.hasErrors = diagnostics.hasErrors;
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -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,19 @@
|
|
|
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 a navigation destination. The values are shared with the C# engine so both report
|
|
7
|
+
* the same code for the same model.
|
|
8
|
+
*/ var NavigationDiagnosticCode = /*#__PURE__*/ function(NavigationDiagnosticCode) {
|
|
9
|
+
/** Two destinations that go to different targets share one URL. */ NavigationDiagnosticCode["DuplicateRoute"] = "duplicateRoute";
|
|
10
|
+
/** Two surfaces declare an outlet with the same name, so a destination cannot tell them apart. */ NavigationDiagnosticCode["DuplicateOutlet"] = "duplicateOutlet";
|
|
11
|
+
/** A destination names an outlet that no layout or screen template declares. */ NavigationDiagnosticCode["MissingOutlet"] = "missingOutlet";
|
|
12
|
+
/** A destination names an outlet that cannot host what it opens. */ NavigationDiagnosticCode["IncompatibleOutlet"] = "incompatibleOutlet";
|
|
13
|
+
/** Screens are placed in outlets owned by each other, so composition never terminates. */ NavigationDiagnosticCode["NavigationCycle"] = "navigationCycle";
|
|
14
|
+
/** A destination opens a screen or dialog that does not exist, or names nothing to open. */ NavigationDiagnosticCode["UnavailableTarget"] = "unavailableTarget";
|
|
15
|
+
return NavigationDiagnosticCode;
|
|
16
|
+
}({});
|
|
17
|
+
|
|
18
|
+
exports.NavigationDiagnosticCode = NavigationDiagnosticCode;
|
|
19
|
+
//# sourceMappingURL=NavigationDiagnosticCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavigationDiagnosticCode.js","sources":["../../../navigation/NavigationDiagnosticCode.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 a navigation destination. The values are shared with the C# engine so both report\n * the same code for the same model.\n */\nexport enum NavigationDiagnosticCode {\n /** Two destinations that go to different targets share one URL. */\n DuplicateRoute = 'duplicateRoute',\n\n /** Two surfaces declare an outlet with the same name, so a destination cannot tell them apart. */\n DuplicateOutlet = 'duplicateOutlet',\n\n /** A destination names an outlet that no layout or screen template declares. */\n MissingOutlet = 'missingOutlet',\n\n /** A destination names an outlet that cannot host what it opens. */\n IncompatibleOutlet = 'incompatibleOutlet',\n\n /** Screens are placed in outlets owned by each other, so composition never terminates. */\n NavigationCycle = 'navigationCycle',\n\n /** A destination opens a screen or dialog that does not exist, or names nothing to open. */\n UnavailableTarget = 'unavailableTarget',\n}\n"],"names":["NavigationDiagnosticCode"],"mappings":";;AAAA;AACA;AAEA;;;IAIO,IAAKA,wBAAAA,iBAAAA,SAAAA,wBAAAA,EAAAA;wEACyD,wBAAA,CAAA,gBAAA,CAAA,GAAA,gBAAA;uGAG+B,wBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAA;qFAGlB,wBAAA,CAAA,eAAA,CAAA,GAAA,eAAA;yEAGZ,wBAAA,CAAA,oBAAA,CAAA,GAAA,oBAAA;+FAGsB,wBAAA,CAAA,iBAAA,CAAA,GAAA,iBAAA;iGAGE,wBAAA,CAAA,mBAAA,CAAA,GAAA,mBAAA;AAhBlFA,IAAAA,OAAAA,wBAAAA;AAkBX,CAAA,CAAA,EAAA;;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var NavigationDiagnosticCode = require('./NavigationDiagnosticCode.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
|
+
* Indexes every declared outlet by name, keeping the first declaration and reporting each later one as a
|
|
9
|
+
* duplicate - a destination names an outlet only by name, so two of them are ambiguous.
|
|
10
|
+
*/ function collectOutlets(graph, diagnostics) {
|
|
11
|
+
const owners = new Map();
|
|
12
|
+
const surfaces = [
|
|
13
|
+
...(graph.layouts ?? []).map((layout)=>({
|
|
14
|
+
name: layout.name,
|
|
15
|
+
kind: 'Layout',
|
|
16
|
+
outlets: layout.outlets ?? []
|
|
17
|
+
})),
|
|
18
|
+
...(graph.screenTemplates ?? []).map((template)=>({
|
|
19
|
+
name: template.name,
|
|
20
|
+
kind: 'ScreenTemplate',
|
|
21
|
+
outlets: template.outlets ?? []
|
|
22
|
+
}))
|
|
23
|
+
];
|
|
24
|
+
for (const surface of surfaces){
|
|
25
|
+
for (const outlet of surface.outlets){
|
|
26
|
+
const existing = owners.get(outlet.name);
|
|
27
|
+
if (existing) {
|
|
28
|
+
diagnostics.push({
|
|
29
|
+
code: NavigationDiagnosticCode.NavigationDiagnosticCode.DuplicateOutlet,
|
|
30
|
+
message: `Outlet '${outlet.name}' is declared by both '${existing.owner}' and '${surface.name}'; destinations cannot tell them apart.`
|
|
31
|
+
});
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
owners.set(outlet.name, {
|
|
35
|
+
outlet,
|
|
36
|
+
owner: surface.name,
|
|
37
|
+
ownerKind: surface.kind
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return owners;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.collectOutlets = collectOutlets;
|
|
45
|
+
//# sourceMappingURL=collectOutlets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collectOutlets.js","sources":["../../../navigation/collectOutlets.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 { NavigationDiagnostic } from './NavigationDiagnostic';\nimport { NavigationDiagnosticCode } from './NavigationDiagnosticCode';\nimport { NavigationGraph } from './NavigationGraph';\nimport { OutletOwner } from './OutletOwner';\n\n/**\n * Indexes every declared outlet by name, keeping the first declaration and reporting each later one as a\n * duplicate - a destination names an outlet only by name, so two of them are ambiguous.\n */\nexport function collectOutlets(graph: NavigationGraph, diagnostics: NavigationDiagnostic[]): Map<string, OutletOwner> {\n const owners = new Map<string, OutletOwner>();\n const surfaces = [\n ...(graph.layouts ?? []).map(layout => ({ name: layout.name, kind: 'Layout' as const, outlets: layout.outlets ?? [] })),\n ...(graph.screenTemplates ?? []).map(template => ({ name: template.name, kind: 'ScreenTemplate' as const, outlets: template.outlets ?? [] })),\n ];\n\n for (const surface of surfaces) {\n for (const outlet of surface.outlets) {\n const existing = owners.get(outlet.name);\n if (existing) {\n diagnostics.push({\n code: NavigationDiagnosticCode.DuplicateOutlet,\n message: `Outlet '${outlet.name}' is declared by both '${existing.owner}' and '${surface.name}'; destinations cannot tell them apart.`,\n });\n continue;\n }\n\n owners.set(outlet.name, { outlet, owner: surface.name, ownerKind: surface.kind });\n }\n }\n\n return owners;\n}\n"],"names":["collectOutlets","graph","diagnostics","owners","Map","surfaces","layouts","map","layout","name","kind","outlets","screenTemplates","template","surface","outlet","existing","get","push","code","NavigationDiagnosticCode","DuplicateOutlet","message","owner","set","ownerKind"],"mappings":";;;;AAAA;AACA;AAOA;;;AAGC,IACM,SAASA,cAAAA,CAAeC,KAAsB,EAAEC,WAAmC,EAAA;AACtF,IAAA,MAAMC,SAAS,IAAIC,GAAAA,EAAAA;AACnB,IAAA,MAAMC,QAAAA,GAAW;WACV,CAACJ,KAAAA,CAAMK,OAAO,IAAI,EAAE,EAAEC,GAAG,CAACC,CAAAA,MAAAA,IAAW;AAAEC,gBAAAA,IAAAA,EAAMD,OAAOC,IAAI;gBAAEC,IAAAA,EAAM,QAAA;gBAAmBC,OAAAA,EAASH,MAAAA,CAAOG,OAAO,IAAI;aAAG,CAAA,CAAA;WACjH,CAACV,KAAAA,CAAMW,eAAe,IAAI,EAAE,EAAEL,GAAG,CAACM,CAAAA,QAAAA,IAAa;AAAEJ,gBAAAA,IAAAA,EAAMI,SAASJ,IAAI;gBAAEC,IAAAA,EAAM,gBAAA;gBAA2BC,OAAAA,EAASE,QAAAA,CAASF,OAAO,IAAI;aAAG,CAAA;AAC7I,KAAA;IAED,KAAK,MAAMG,WAAWT,QAAAA,CAAU;AAC5B,QAAA,KAAK,MAAMU,MAAAA,IAAUD,OAAAA,CAAQH,OAAO,CAAE;AAClC,YAAA,MAAMK,QAAAA,GAAWb,MAAAA,CAAOc,GAAG,CAACF,OAAON,IAAI,CAAA;AACvC,YAAA,IAAIO,QAAAA,EAAU;AACVd,gBAAAA,WAAAA,CAAYgB,IAAI,CAAC;AACbC,oBAAAA,IAAAA,EAAMC,kDAAyBC,eAAe;AAC9CC,oBAAAA,OAAAA,EAAS,CAAC,QAAQ,EAAEP,MAAAA,CAAON,IAAI,CAAC,uBAAuB,EAAEO,QAAAA,CAASO,KAAK,CAAC,OAAO,EAAET,QAAQL,IAAI,CAAC,uCAAuC;AACzI,iBAAA,CAAA;AACA,gBAAA;AACJ,YAAA;AAEAN,YAAAA,MAAAA,CAAOqB,GAAG,CAACT,MAAAA,CAAON,IAAI,EAAE;AAAEM,gBAAAA,MAAAA;AAAQQ,gBAAAA,KAAAA,EAAOT,QAAQL,IAAI;AAAEgB,gBAAAA,SAAAA,EAAWX,QAAQJ;AAAK,aAAA,CAAA;AACnF,QAAA;AACJ,IAAA;IAEA,OAAOP,MAAAA;AACX;;"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var scene_model = require('@cratis/scene.model');
|
|
4
|
+
var collectOutlets = require('./collectOutlets.js');
|
|
5
|
+
var findHostingCycles = require('./findHostingCycles.js');
|
|
6
|
+
var NavigationDiagnosticCode = require('./NavigationDiagnosticCode.js');
|
|
7
|
+
var navigationRoute = require('./navigationRoute.js');
|
|
8
|
+
|
|
9
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
10
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
11
|
+
/**
|
|
12
|
+
* Diagnoses how destinations, outlets, routes and targets fit together: duplicate routes, duplicate,
|
|
13
|
+
* missing or incompatible outlets, hosting cycles and unavailable targets.
|
|
14
|
+
*
|
|
15
|
+
* Routes are compared by `routeKey` - by default the authored route override, since the engine constructs no
|
|
16
|
+
* URLs. Nothing is rewritten. The C# engine (`NavigationDiagnostics.Diagnose`) reports the same codes and
|
|
17
|
+
* messages in the same order for the same model; both are asserted against `navigation-diagnostic-fixtures.json`.
|
|
18
|
+
*/ function diagnoseNavigation(graph, routeKey = navigationRoute.authoredRouteKey) {
|
|
19
|
+
const diagnostics = [];
|
|
20
|
+
const outlets = collectOutlets.collectOutlets(graph, diagnostics);
|
|
21
|
+
const screens = graph.screens ? new Map(graph.screens.map((screen)=>[
|
|
22
|
+
screen.name,
|
|
23
|
+
screen
|
|
24
|
+
])) : undefined;
|
|
25
|
+
const routes = new Map();
|
|
26
|
+
const hostedIn = new Map();
|
|
27
|
+
graph.entries.forEach((navigationEntry, index)=>{
|
|
28
|
+
const entry = navigationEntry.id ?? `#${index + 1}`;
|
|
29
|
+
const destination = navigationEntry.destination;
|
|
30
|
+
const kind = destination.kind ?? (destination.dialog ? scene_model.DestinationKind.Dialog : scene_model.DestinationKind.Outlet);
|
|
31
|
+
const report = (code, message)=>diagnostics.push({
|
|
32
|
+
code,
|
|
33
|
+
message,
|
|
34
|
+
entry
|
|
35
|
+
});
|
|
36
|
+
if (!destination.screen && !destination.module && !destination.route && !destination.dialog) {
|
|
37
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' names no screen, stable identity, route or dialog.`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
diagnoseTarget(graph, screens, destination, kind, entry, report);
|
|
41
|
+
const owner = diagnoseOutlet(graph, outlets, screens, destination, kind, entry, report);
|
|
42
|
+
if (owner?.ownerKind === 'ScreenTemplate' && destination.screen && screens?.has(destination.screen)) {
|
|
43
|
+
const hosts = graph.screens.filter((screen)=>screen.screenTemplate === owner.owner).map((screen)=>screen.name);
|
|
44
|
+
hostedIn.set(destination.screen, [
|
|
45
|
+
...new Set([
|
|
46
|
+
...hostedIn.get(destination.screen) ?? [],
|
|
47
|
+
...hosts
|
|
48
|
+
])
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
const route = kind === scene_model.DestinationKind.External ? undefined : routeKey(destination);
|
|
52
|
+
if (route) {
|
|
53
|
+
const target = navigationRoute.navigationTarget(destination, kind);
|
|
54
|
+
const existing = routes.get(route);
|
|
55
|
+
if (!existing) {
|
|
56
|
+
routes.set(route, {
|
|
57
|
+
entry,
|
|
58
|
+
target
|
|
59
|
+
});
|
|
60
|
+
} else if (existing.target !== target) {
|
|
61
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.DuplicateRoute, `Route '${destination.route ?? route}' is used by destinations '${existing.entry}' and '${entry}', which open different targets.`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
for (const cycle of findHostingCycles.findHostingCycles(graph.screens?.map((screen)=>screen.name) ?? [], hostedIn)){
|
|
66
|
+
diagnostics.push({
|
|
67
|
+
code: NavigationDiagnosticCode.NavigationDiagnosticCode.NavigationCycle,
|
|
68
|
+
message: `Navigation cycle ${[
|
|
69
|
+
...cycle,
|
|
70
|
+
cycle[0]
|
|
71
|
+
].join(' -> ')}: each screen is placed in an outlet owned by the next, so composition never terminates.`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return diagnostics;
|
|
75
|
+
}
|
|
76
|
+
function diagnoseTarget(graph, screens, destination, kind, entry, report) {
|
|
77
|
+
if (kind === scene_model.DestinationKind.Dialog) {
|
|
78
|
+
if (!destination.dialog) {
|
|
79
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.UnavailableTarget, `Dialog destination '${entry}' names no dialog.`);
|
|
80
|
+
} else if (graph.dialogTemplates && !graph.dialogTemplates.some((template)=>template.name === destination.dialog)) {
|
|
81
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' opens dialog '${destination.dialog}', which no dialog template provides.`);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (kind === scene_model.DestinationKind.Outlet && destination.screen && screens && !screens.has(destination.screen)) {
|
|
86
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' opens screen '${destination.screen}', which does not exist.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function diagnoseOutlet(graph, outlets, screens, destination, kind, entry, report) {
|
|
90
|
+
if (!destination.outlet) return undefined;
|
|
91
|
+
if (kind !== scene_model.DestinationKind.Outlet) {
|
|
92
|
+
const opens = kind === scene_model.DestinationKind.Dialog ? 'a dialog' : 'an external target';
|
|
93
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.IncompatibleOutlet, `Destination '${entry}' opens ${opens} but names outlet '${destination.outlet}'; only outlet destinations render in outlets.`);
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
const owner = outlets.get(destination.outlet);
|
|
97
|
+
if (!owner) {
|
|
98
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.MissingOutlet, `Destination '${entry}' targets missing outlet '${destination.outlet}'.`);
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const screen = destination.screen ? screens?.get(destination.screen) : undefined;
|
|
102
|
+
if (!screen) return owner;
|
|
103
|
+
if (owner.ownerKind === 'Layout' && screen.layout !== owner.owner) {
|
|
104
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.IncompatibleOutlet, `Outlet '${owner.outlet.name}' belongs to layout '${owner.owner}', but destination '${entry}' places '${screen.name}', which renders in layout '${screen.layout}'.`);
|
|
105
|
+
}
|
|
106
|
+
if (owner.outlet.accepts) {
|
|
107
|
+
const type = graph.screenTemplates?.find((template)=>template.name === screen.screenTemplate)?.metadata?.type;
|
|
108
|
+
if (!type || !owner.outlet.accepts.includes(type)) {
|
|
109
|
+
report(NavigationDiagnosticCode.NavigationDiagnosticCode.IncompatibleOutlet, `Outlet '${owner.outlet.name}' accepts ${owner.outlet.accepts.join(', ')} screens, but destination '${entry}' places '${screen.name}' of type '${type ?? 'untyped'}'.`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return owner;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.diagnoseNavigation = diagnoseNavigation;
|
|
116
|
+
//# sourceMappingURL=diagnoseNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnoseNavigation.js","sources":["../../../navigation/diagnoseNavigation.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 { DestinationKind, DestinationReference, Screen } from '@cratis/scene.model';\nimport { collectOutlets } from './collectOutlets';\nimport { findHostingCycles } from './findHostingCycles';\nimport { NavigationDiagnostic } from './NavigationDiagnostic';\nimport { NavigationDiagnosticCode } from './NavigationDiagnosticCode';\nimport { NavigationGraph } from './NavigationGraph';\nimport { NavigationRouteKey, authoredRouteKey, navigationTarget } from './navigationRoute';\nimport { OutletOwner } from './OutletOwner';\n\n/**\n * Diagnoses how destinations, outlets, routes and targets fit together: duplicate routes, duplicate,\n * missing or incompatible outlets, hosting cycles and unavailable targets.\n *\n * Routes are compared by `routeKey` - by default the authored route override, since the engine constructs no\n * URLs. Nothing is rewritten. The C# engine (`NavigationDiagnostics.Diagnose`) reports the same codes and\n * messages in the same order for the same model; both are asserted against `navigation-diagnostic-fixtures.json`.\n */\nexport function diagnoseNavigation(graph: NavigationGraph, routeKey: NavigationRouteKey = authoredRouteKey): NavigationDiagnostic[] {\n const diagnostics: NavigationDiagnostic[] = [];\n const outlets = collectOutlets(graph, diagnostics);\n const screens = graph.screens ? new Map(graph.screens.map(screen => [screen.name, screen])) : undefined;\n const routes = new Map<string, { entry: string; target: string }>();\n const hostedIn = new Map<string, string[]>();\n\n graph.entries.forEach((navigationEntry, index) => {\n const entry = navigationEntry.id ?? `#${index + 1}`;\n const destination = navigationEntry.destination;\n const kind = destination.kind ?? (destination.dialog ? DestinationKind.Dialog : DestinationKind.Outlet);\n const report = (code: NavigationDiagnosticCode, message: string) => diagnostics.push({ code, message, entry });\n\n if (!destination.screen && !destination.module && !destination.route && !destination.dialog) {\n report(NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' names no screen, stable identity, route or dialog.`);\n return;\n }\n\n diagnoseTarget(graph, screens, destination, kind, entry, report);\n const owner = diagnoseOutlet(graph, outlets, screens, destination, kind, entry, report);\n if (owner?.ownerKind === 'ScreenTemplate' && destination.screen && screens?.has(destination.screen)) {\n const hosts = graph.screens!.filter(screen => screen.screenTemplate === owner.owner).map(screen => screen.name);\n hostedIn.set(destination.screen, [...new Set([...(hostedIn.get(destination.screen) ?? []), ...hosts])]);\n }\n\n const route = kind === DestinationKind.External ? undefined : routeKey(destination);\n if (route) {\n const target = navigationTarget(destination, kind);\n const existing = routes.get(route);\n if (!existing) {\n routes.set(route, { entry, target });\n } else if (existing.target !== target) {\n report(NavigationDiagnosticCode.DuplicateRoute, `Route '${destination.route ?? route}' is used by destinations '${existing.entry}' and '${entry}', which open different targets.`);\n }\n }\n });\n\n for (const cycle of findHostingCycles(graph.screens?.map(screen => screen.name) ?? [], hostedIn)) {\n diagnostics.push({\n code: NavigationDiagnosticCode.NavigationCycle,\n message: `Navigation cycle ${[...cycle, cycle[0]].join(' -> ')}: each screen is placed in an outlet owned by the next, so composition never terminates.`,\n });\n }\n\n return diagnostics;\n}\n\ntype Report = (code: NavigationDiagnosticCode, message: string) => void;\n\nfunction diagnoseTarget(\n graph: NavigationGraph,\n screens: Map<string, Screen> | undefined,\n destination: DestinationReference,\n kind: DestinationKind,\n entry: string,\n report: Report,\n) {\n if (kind === DestinationKind.Dialog) {\n if (!destination.dialog) {\n report(NavigationDiagnosticCode.UnavailableTarget, `Dialog destination '${entry}' names no dialog.`);\n } else if (graph.dialogTemplates && !graph.dialogTemplates.some(template => template.name === destination.dialog)) {\n report(NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' opens dialog '${destination.dialog}', which no dialog template provides.`);\n }\n return;\n }\n\n if (kind === DestinationKind.Outlet && destination.screen && screens && !screens.has(destination.screen)) {\n report(NavigationDiagnosticCode.UnavailableTarget, `Destination '${entry}' opens screen '${destination.screen}', which does not exist.`);\n }\n}\n\nfunction diagnoseOutlet(\n graph: NavigationGraph,\n outlets: Map<string, OutletOwner>,\n screens: Map<string, Screen> | undefined,\n destination: DestinationReference,\n kind: DestinationKind,\n entry: string,\n report: Report,\n): OutletOwner | undefined {\n if (!destination.outlet) return undefined;\n\n if (kind !== DestinationKind.Outlet) {\n const opens = kind === DestinationKind.Dialog ? 'a dialog' : 'an external target';\n report(NavigationDiagnosticCode.IncompatibleOutlet, `Destination '${entry}' opens ${opens} but names outlet '${destination.outlet}'; only outlet destinations render in outlets.`);\n return undefined;\n }\n\n const owner = outlets.get(destination.outlet);\n if (!owner) {\n report(NavigationDiagnosticCode.MissingOutlet, `Destination '${entry}' targets missing outlet '${destination.outlet}'.`);\n return undefined;\n }\n\n const screen = destination.screen ? screens?.get(destination.screen) : undefined;\n if (!screen) return owner;\n\n if (owner.ownerKind === 'Layout' && screen.layout !== owner.owner) {\n report(\n NavigationDiagnosticCode.IncompatibleOutlet,\n `Outlet '${owner.outlet.name}' belongs to layout '${owner.owner}', but destination '${entry}' places '${screen.name}', which renders in layout '${screen.layout}'.`,\n );\n }\n\n if (owner.outlet.accepts) {\n const type = graph.screenTemplates?.find(template => template.name === screen.screenTemplate)?.metadata?.type;\n if (!type || !owner.outlet.accepts.includes(type)) {\n report(\n NavigationDiagnosticCode.IncompatibleOutlet,\n `Outlet '${owner.outlet.name}' accepts ${owner.outlet.accepts.join(', ')} screens, but destination '${entry}' places '${screen.name}' of type '${type ?? 'untyped'}'.`,\n );\n }\n }\n\n return owner;\n}\n"],"names":["diagnoseNavigation","graph","routeKey","authoredRouteKey","diagnostics","outlets","collectOutlets","screens","Map","map","screen","name","undefined","routes","hostedIn","entries","forEach","navigationEntry","index","entry","id","destination","kind","dialog","DestinationKind","Dialog","Outlet","report","code","message","push","module","route","NavigationDiagnosticCode","UnavailableTarget","diagnoseTarget","owner","diagnoseOutlet","ownerKind","has","hosts","filter","screenTemplate","set","Set","get","External","target","navigationTarget","existing","DuplicateRoute","cycle","findHostingCycles","NavigationCycle","join","dialogTemplates","some","template","outlet","opens","IncompatibleOutlet","MissingOutlet","layout","accepts","type","screenTemplates","find","metadata","includes"],"mappings":";;;;;;;;AAAA;AACA;AAWA;;;;;;;AAOC,IACM,SAASA,kBAAAA,CAAmBC,KAAsB,EAAEC,WAA+BC,gCAAgB,EAAA;AACtG,IAAA,MAAMC,cAAsC,EAAE;IAC9C,MAAMC,OAAAA,GAAUC,8BAAeL,KAAAA,EAAOG,WAAAA,CAAAA;AACtC,IAAA,MAAMG,OAAAA,GAAUN,KAAAA,CAAMM,OAAO,GAAG,IAAIC,GAAAA,CAAIP,KAAAA,CAAMM,OAAO,CAACE,GAAG,CAACC,CAAAA,MAAAA,GAAU;AAACA,YAAAA,MAAAA,CAAOC,IAAI;AAAED,YAAAA;SAAO,CAAA,CAAA,GAAKE,SAAAA;AAC9F,IAAA,MAAMC,SAAS,IAAIL,GAAAA,EAAAA;AACnB,IAAA,MAAMM,WAAW,IAAIN,GAAAA,EAAAA;AAErBP,IAAAA,KAAAA,CAAMc,OAAO,CAACC,OAAO,CAAC,CAACC,eAAAA,EAAiBC,KAAAA,GAAAA;QACpC,MAAMC,KAAAA,GAAQF,gBAAgBG,EAAE,IAAI,CAAC,CAAC,EAAEF,QAAQ,CAAA,CAAA,CAAG;QACnD,MAAMG,WAAAA,GAAcJ,gBAAgBI,WAAW;AAC/C,QAAA,MAAMC,IAAAA,GAAOD,WAAAA,CAAYC,IAAI,KAAKD,WAAAA,CAAYE,MAAM,GAAGC,2BAAAA,CAAgBC,MAAM,GAAGD,2BAAAA,CAAgBE,MAAM,CAAD;AACrG,QAAA,MAAMC,SAAS,CAACC,IAAAA,EAAgCC,OAAAA,GAAoBzB,WAAAA,CAAY0B,IAAI,CAAC;AAAEF,gBAAAA,IAAAA;AAAMC,gBAAAA,OAAAA;AAASV,gBAAAA;AAAM,aAAA,CAAA;AAE5G,QAAA,IAAI,CAACE,WAAAA,CAAYX,MAAM,IAAI,CAACW,WAAAA,CAAYU,MAAM,IAAI,CAACV,YAAYW,KAAK,IAAI,CAACX,WAAAA,CAAYE,MAAM,EAAE;YACzFI,MAAAA,CAAOM,iDAAAA,CAAyBC,iBAAiB,EAAE,CAAC,aAAa,EAAEf,KAAAA,CAAM,oDAAoD,CAAC,CAAA;AAC9H,YAAA;AACJ,QAAA;AAEAgB,QAAAA,cAAAA,CAAelC,KAAAA,EAAOM,OAAAA,EAASc,WAAAA,EAAaC,IAAAA,EAAMH,KAAAA,EAAOQ,MAAAA,CAAAA;AACzD,QAAA,MAAMS,QAAQC,cAAAA,CAAepC,KAAAA,EAAOI,SAASE,OAAAA,EAASc,WAAAA,EAAaC,MAAMH,KAAAA,EAAOQ,MAAAA,CAAAA;QAChF,IAAIS,KAAAA,EAAOE,SAAAA,KAAc,gBAAA,IAAoBjB,WAAAA,CAAYX,MAAM,IAAIH,OAAAA,EAASgC,GAAAA,CAAIlB,WAAAA,CAAYX,MAAM,CAAA,EAAG;AACjG,YAAA,MAAM8B,QAAQvC,KAAAA,CAAMM,OAAO,CAAEkC,MAAM,CAAC/B,CAAAA,MAAAA,GAAUA,MAAAA,CAAOgC,cAAc,KAAKN,KAAAA,CAAMA,KAAK,CAAA,CAAE3B,GAAG,CAACC,CAAAA,MAAAA,GAAUA,OAAOC,IAAI,CAAA;AAC9GG,YAAAA,QAAAA,CAAS6B,GAAG,CAACtB,WAAAA,CAAYX,MAAM,EAAE;AAAI,gBAAA,GAAA,IAAIkC,GAAAA,CAAI;AAAK9B,oBAAAA,GAAAA,QAAAA,CAAS+B,GAAG,CAACxB,WAAAA,CAAYX,MAAM,KAAK,EAAE;AAAM8B,oBAAAA,GAAAA;AAAM,iBAAA;AAAE,aAAA,CAAA;AAC1G,QAAA;AAEA,QAAA,MAAMR,QAAQV,IAAAA,KAASE,2BAAAA,CAAgBsB,QAAQ,GAAGlC,YAAYV,QAAAA,CAASmB,WAAAA,CAAAA;AACvE,QAAA,IAAIW,KAAAA,EAAO;YACP,MAAMe,MAAAA,GAASC,iCAAiB3B,WAAAA,EAAaC,IAAAA,CAAAA;YAC7C,MAAM2B,QAAAA,GAAWpC,MAAAA,CAAOgC,GAAG,CAACb,KAAAA,CAAAA;AAC5B,YAAA,IAAI,CAACiB,QAAAA,EAAU;gBACXpC,MAAAA,CAAO8B,GAAG,CAACX,KAAAA,EAAO;AAAEb,oBAAAA,KAAAA;AAAO4B,oBAAAA;AAAO,iBAAA,CAAA;AACtC,YAAA,CAAA,MAAO,IAAIE,QAAAA,CAASF,MAAM,KAAKA,MAAAA,EAAQ;AACnCpB,gBAAAA,MAAAA,CAAOM,kDAAyBiB,cAAc,EAAE,CAAC,OAAO,EAAE7B,YAAYW,KAAK,IAAIA,MAAM,2BAA2B,EAAEiB,SAAS9B,KAAK,CAAC,OAAO,EAAEA,KAAAA,CAAM,gCAAgC,CAAC,CAAA;AACrL,YAAA;AACJ,QAAA;AACJ,IAAA,CAAA,CAAA;AAEA,IAAA,KAAK,MAAMgC,KAAAA,IAASC,mCAAAA,CAAkBnD,KAAAA,CAAMM,OAAO,EAAEE,GAAAA,CAAIC,CAAAA,MAAAA,GAAUA,MAAAA,CAAOC,IAAI,CAAA,IAAK,EAAE,EAAEG,QAAAA,CAAAA,CAAW;AAC9FV,QAAAA,WAAAA,CAAY0B,IAAI,CAAC;AACbF,YAAAA,IAAAA,EAAMK,kDAAyBoB,eAAe;YAC9CxB,OAAAA,EAAS,CAAC,iBAAiB,EAAE;AAAIsB,gBAAAA,GAAAA,KAAAA;AAAOA,gBAAAA,KAAK,CAAC,CAAA;AAAG,aAAA,CAACG,IAAI,CAAC,MAAA,CAAA,CAAQ,wFAAwF;AAC3J,SAAA,CAAA;AACJ,IAAA;IAEA,OAAOlD,WAAAA;AACX;AAIA,SAAS+B,cAAAA,CACLlC,KAAsB,EACtBM,OAAwC,EACxCc,WAAiC,EACjCC,IAAqB,EACrBH,KAAa,EACbQ,MAAc,EAAA;IAEd,IAAIL,IAAAA,KAASE,2BAAAA,CAAgBC,MAAM,EAAE;QACjC,IAAI,CAACJ,WAAAA,CAAYE,MAAM,EAAE;YACrBI,MAAAA,CAAOM,iDAAAA,CAAyBC,iBAAiB,EAAE,CAAC,oBAAoB,EAAEf,KAAAA,CAAM,kBAAkB,CAAC,CAAA;AACvG,QAAA,CAAA,MAAO,IAAIlB,KAAAA,CAAMsD,eAAe,IAAI,CAACtD,MAAMsD,eAAe,CAACC,IAAI,CAACC,CAAAA,QAAAA,GAAYA,QAAAA,CAAS9C,IAAI,KAAKU,WAAAA,CAAYE,MAAM,CAAA,EAAG;AAC/GI,YAAAA,MAAAA,CAAOM,iDAAAA,CAAyBC,iBAAiB,EAAE,CAAC,aAAa,EAAEf,KAAAA,CAAM,gBAAgB,EAAEE,WAAAA,CAAYE,MAAM,CAAC,qCAAqC,CAAC,CAAA;AACxJ,QAAA;AACA,QAAA;AACJ,IAAA;AAEA,IAAA,IAAID,IAAAA,KAASE,2BAAAA,CAAgBE,MAAM,IAAIL,YAAYX,MAAM,IAAIH,OAAAA,IAAW,CAACA,OAAAA,CAAQgC,GAAG,CAAClB,WAAAA,CAAYX,MAAM,CAAA,EAAG;AACtGiB,QAAAA,MAAAA,CAAOM,iDAAAA,CAAyBC,iBAAiB,EAAE,CAAC,aAAa,EAAEf,KAAAA,CAAM,gBAAgB,EAAEE,WAAAA,CAAYX,MAAM,CAAC,wBAAwB,CAAC,CAAA;AAC3I,IAAA;AACJ;AAEA,SAAS2B,cAAAA,CACLpC,KAAsB,EACtBI,OAAiC,EACjCE,OAAwC,EACxCc,WAAiC,EACjCC,IAAqB,EACrBH,KAAa,EACbQ,MAAc,EAAA;AAEd,IAAA,IAAI,CAACN,WAAAA,CAAYqC,MAAM,EAAE,OAAO9C,SAAAA;IAEhC,IAAIU,IAAAA,KAASE,2BAAAA,CAAgBE,MAAM,EAAE;AACjC,QAAA,MAAMiC,KAAAA,GAAQrC,IAAAA,KAASE,2BAAAA,CAAgBC,MAAM,GAAG,UAAA,GAAa,oBAAA;AAC7DE,QAAAA,MAAAA,CAAOM,kDAAyB2B,kBAAkB,EAAE,CAAC,aAAa,EAAEzC,KAAAA,CAAM,QAAQ,EAAEwC,KAAAA,CAAM,mBAAmB,EAAEtC,WAAAA,CAAYqC,MAAM,CAAC,8CAA8C,CAAC,CAAA;QACjL,OAAO9C,SAAAA;AACX,IAAA;AAEA,IAAA,MAAMwB,KAAAA,GAAQ/B,OAAAA,CAAQwC,GAAG,CAACxB,YAAYqC,MAAM,CAAA;AAC5C,IAAA,IAAI,CAACtB,KAAAA,EAAO;AACRT,QAAAA,MAAAA,CAAOM,iDAAAA,CAAyB4B,aAAa,EAAE,CAAC,aAAa,EAAE1C,KAAAA,CAAM,0BAA0B,EAAEE,WAAAA,CAAYqC,MAAM,CAAC,EAAE,CAAC,CAAA;QACvH,OAAO9C,SAAAA;AACX,IAAA;IAEA,MAAMF,MAAAA,GAASW,YAAYX,MAAM,GAAGH,SAASsC,GAAAA,CAAIxB,WAAAA,CAAYX,MAAM,CAAA,GAAIE,SAAAA;IACvE,IAAI,CAACF,QAAQ,OAAO0B,KAAAA;IAEpB,IAAIA,KAAAA,CAAME,SAAS,KAAK,QAAA,IAAY5B,OAAOoD,MAAM,KAAK1B,KAAAA,CAAMA,KAAK,EAAE;AAC/DT,QAAAA,MAAAA,CACIM,iDAAAA,CAAyB2B,kBAAkB,EAC3C,CAAC,QAAQ,EAAExB,KAAAA,CAAMsB,MAAM,CAAC/C,IAAI,CAAC,qBAAqB,EAAEyB,KAAAA,CAAMA,KAAK,CAAC,oBAAoB,EAAEjB,KAAAA,CAAM,UAAU,EAAET,MAAAA,CAAOC,IAAI,CAAC,4BAA4B,EAAED,MAAAA,CAAOoD,MAAM,CAAC,EAAE,CAAC,CAAA;AAE3K,IAAA;AAEA,IAAA,IAAI1B,KAAAA,CAAMsB,MAAM,CAACK,OAAO,EAAE;AACtB,QAAA,MAAMC,IAAAA,GAAO/D,KAAAA,CAAMgE,eAAe,EAAEC,IAAAA,CAAKT,CAAAA,QAAAA,GAAYA,QAAAA,CAAS9C,IAAI,KAAKD,MAAAA,CAAOgC,cAAc,GAAGyB,QAAAA,EAAUH,IAAAA;QACzG,IAAI,CAACA,IAAAA,IAAQ,CAAC5B,KAAAA,CAAMsB,MAAM,CAACK,OAAO,CAACK,QAAQ,CAACJ,IAAAA,CAAAA,EAAO;AAC/CrC,YAAAA,MAAAA,CACIM,iDAAAA,CAAyB2B,kBAAkB,EAC3C,CAAC,QAAQ,EAAExB,KAAAA,CAAMsB,MAAM,CAAC/C,IAAI,CAAC,UAAU,EAAEyB,KAAAA,CAAMsB,MAAM,CAACK,OAAO,CAACT,IAAI,CAAC,IAAA,CAAA,CAAM,2BAA2B,EAAEnC,MAAM,UAAU,EAAET,MAAAA,CAAOC,IAAI,CAAC,WAAW,EAAEqD,IAAAA,IAAQ,SAAA,CAAU,EAAE,CAAC,CAAA;AAE9K,QAAA;AACJ,IAAA;IAEA,OAAO5B,KAAAA;AACX;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
* Finds cycles in a "renders inside" graph, where an edge from a screen to another means the first is
|
|
7
|
+
* placed in an outlet the second one's template owns. Screens are visited in the given order and edges in
|
|
8
|
+
* insertion order, so the same graph always yields the same cycles in the same order. Each set of screens
|
|
9
|
+
* is reported once, starting from the screen the walk reached it through.
|
|
10
|
+
*/ function findHostingCycles(screens, edges) {
|
|
11
|
+
const state = new Map();
|
|
12
|
+
const stack = [];
|
|
13
|
+
const reported = new Set();
|
|
14
|
+
const cycles = [];
|
|
15
|
+
const visit = (screen)=>{
|
|
16
|
+
state.set(screen, 'visiting');
|
|
17
|
+
stack.push(screen);
|
|
18
|
+
for (const host of edges.get(screen) ?? []){
|
|
19
|
+
const hostState = state.get(host);
|
|
20
|
+
if (hostState === 'visiting') {
|
|
21
|
+
const cycle = stack.slice(stack.indexOf(host));
|
|
22
|
+
const key = [
|
|
23
|
+
...cycle
|
|
24
|
+
].sort().join('\u0000');
|
|
25
|
+
if (!reported.has(key)) {
|
|
26
|
+
reported.add(key);
|
|
27
|
+
cycles.push(cycle);
|
|
28
|
+
}
|
|
29
|
+
} else if (hostState === undefined) {
|
|
30
|
+
visit(host);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
stack.pop();
|
|
34
|
+
state.set(screen, 'done');
|
|
35
|
+
};
|
|
36
|
+
for (const screen of screens){
|
|
37
|
+
if (!state.has(screen)) visit(screen);
|
|
38
|
+
}
|
|
39
|
+
return cycles;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.findHostingCycles = findHostingCycles;
|
|
43
|
+
//# sourceMappingURL=findHostingCycles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findHostingCycles.js","sources":["../../../navigation/findHostingCycles.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 * Finds cycles in a \"renders inside\" graph, where an edge from a screen to another means the first is\n * placed in an outlet the second one's template owns. Screens are visited in the given order and edges in\n * insertion order, so the same graph always yields the same cycles in the same order. Each set of screens\n * is reported once, starting from the screen the walk reached it through.\n */\nexport function findHostingCycles(screens: string[], edges: Map<string, string[]>): string[][] {\n const state = new Map<string, 'visiting' | 'done'>();\n const stack: string[] = [];\n const reported = new Set<string>();\n const cycles: string[][] = [];\n\n const visit = (screen: string) => {\n state.set(screen, 'visiting');\n stack.push(screen);\n for (const host of edges.get(screen) ?? []) {\n const hostState = state.get(host);\n if (hostState === 'visiting') {\n const cycle = stack.slice(stack.indexOf(host));\n const key = [...cycle].sort().join('\\u0000');\n if (!reported.has(key)) {\n reported.add(key);\n cycles.push(cycle);\n }\n } else if (hostState === undefined) {\n visit(host);\n }\n }\n stack.pop();\n state.set(screen, 'done');\n };\n\n for (const screen of screens) {\n if (!state.has(screen)) visit(screen);\n }\n\n return cycles;\n}\n"],"names":["findHostingCycles","screens","edges","state","Map","stack","reported","Set","cycles","visit","screen","set","push","host","get","hostState","cycle","slice","indexOf","key","sort","join","has","add","undefined","pop"],"mappings":";;AAAA;AACA;AAEA;;;;;AAKC,IACM,SAASA,iBAAAA,CAAkBC,OAAiB,EAAEC,KAA4B,EAAA;AAC7E,IAAA,MAAMC,QAAQ,IAAIC,GAAAA,EAAAA;AAClB,IAAA,MAAMC,QAAkB,EAAE;AAC1B,IAAA,MAAMC,WAAW,IAAIC,GAAAA,EAAAA;AACrB,IAAA,MAAMC,SAAqB,EAAE;AAE7B,IAAA,MAAMC,QAAQ,CAACC,MAAAA,GAAAA;QACXP,KAAAA,CAAMQ,GAAG,CAACD,MAAAA,EAAQ,UAAA,CAAA;AAClBL,QAAAA,KAAAA,CAAMO,IAAI,CAACF,MAAAA,CAAAA;AACX,QAAA,KAAK,MAAMG,IAAAA,IAAQX,KAAAA,CAAMY,GAAG,CAACJ,MAAAA,CAAAA,IAAW,EAAE,CAAE;YACxC,MAAMK,SAAAA,GAAYZ,KAAAA,CAAMW,GAAG,CAACD,IAAAA,CAAAA;AAC5B,YAAA,IAAIE,cAAc,UAAA,EAAY;AAC1B,gBAAA,MAAMC,QAAQX,KAAAA,CAAMY,KAAK,CAACZ,KAAAA,CAAMa,OAAO,CAACL,IAAAA,CAAAA,CAAAA;AACxC,gBAAA,MAAMM,GAAAA,GAAM;AAAIH,oBAAAA,GAAAA;iBAAM,CAACI,IAAI,EAAA,CAAGC,IAAI,CAAC,QAAA,CAAA;AACnC,gBAAA,IAAI,CAACf,QAAAA,CAASgB,GAAG,CAACH,GAAAA,CAAAA,EAAM;AACpBb,oBAAAA,QAAAA,CAASiB,GAAG,CAACJ,GAAAA,CAAAA;AACbX,oBAAAA,MAAAA,CAAOI,IAAI,CAACI,KAAAA,CAAAA;AAChB,gBAAA;YACJ,CAAA,MAAO,IAAID,cAAcS,SAAAA,EAAW;gBAChCf,KAAAA,CAAMI,IAAAA,CAAAA;AACV,YAAA;AACJ,QAAA;AACAR,QAAAA,KAAAA,CAAMoB,GAAG,EAAA;QACTtB,KAAAA,CAAMQ,GAAG,CAACD,MAAAA,EAAQ,MAAA,CAAA;AACtB,IAAA,CAAA;IAEA,KAAK,MAAMA,UAAUT,OAAAA,CAAS;AAC1B,QAAA,IAAI,CAACE,KAAAA,CAAMmB,GAAG,CAACZ,SAASD,KAAAA,CAAMC,MAAAA,CAAAA;AAClC,IAAA;IAEA,OAAOF,MAAAA;AACX;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
* Turns navigation contributions into entries for {@link diagnoseNavigation}. A legacy item carrying only
|
|
7
|
+
* `targetScreen` becomes a destination for that screen, so old and new content are checked the same way.
|
|
8
|
+
*/ function navigationEntriesFrom(items) {
|
|
9
|
+
return items.map((item)=>({
|
|
10
|
+
id: item.id,
|
|
11
|
+
destination: item.destination ?? {
|
|
12
|
+
screen: item.targetScreen,
|
|
13
|
+
routeParameterBindings: item.routeParameterBindings
|
|
14
|
+
}
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exports.navigationEntriesFrom = navigationEntriesFrom;
|
|
19
|
+
//# sourceMappingURL=navigationEntriesFrom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigationEntriesFrom.js","sources":["../../../navigation/navigationEntriesFrom.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 { NavigationItem } from '@cratis/scene.model';\nimport { NavigationEntry } from './NavigationEntry';\n\n/**\n * Turns navigation contributions into entries for {@link diagnoseNavigation}. A legacy item carrying only\n * `targetScreen` becomes a destination for that screen, so old and new content are checked the same way.\n */\nexport function navigationEntriesFrom(items: NavigationItem[]): NavigationEntry[] {\n return items.map(item => ({\n id: item.id,\n destination: item.destination ?? { screen: item.targetScreen, routeParameterBindings: item.routeParameterBindings },\n }));\n}\n"],"names":["navigationEntriesFrom","items","map","item","id","destination","screen","targetScreen","routeParameterBindings"],"mappings":";;AAAA;AACA;AAKA;;;IAIO,SAASA,qBAAAA,CAAsBC,KAAuB,EAAA;AACzD,IAAA,OAAOA,KAAAA,CAAMC,GAAG,CAACC,CAAAA,QAAS;AACtBC,YAAAA,EAAAA,EAAID,KAAKC,EAAE;YACXC,WAAAA,EAAaF,IAAAA,CAAKE,WAAW,IAAI;AAAEC,gBAAAA,MAAAA,EAAQH,KAAKI,YAAY;AAAEC,gBAAAA,sBAAAA,EAAwBL,KAAKK;AAAuB;SACtH,CAAA,CAAA;AACJ;;"}
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
/** The default route key: the authored route override, trimmed, or none. */ const authoredRouteKey = (destination)=>destination.route?.trim() || undefined;
|
|
6
|
+
/**
|
|
7
|
+
* What a destination opens, so two destinations sharing a route are only a conflict when they open
|
|
8
|
+
* different things.
|
|
9
|
+
*/ function navigationTarget(destination, kind) {
|
|
10
|
+
const identity = destination.screen ?? [
|
|
11
|
+
destination.module,
|
|
12
|
+
destination.feature,
|
|
13
|
+
destination.slice
|
|
14
|
+
].filter((part)=>part).join('.');
|
|
15
|
+
return [
|
|
16
|
+
kind,
|
|
17
|
+
identity,
|
|
18
|
+
destination.dialog ?? '',
|
|
19
|
+
destination.outlet ?? ''
|
|
20
|
+
].join('|');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.authoredRouteKey = authoredRouteKey;
|
|
24
|
+
exports.navigationTarget = navigationTarget;
|
|
25
|
+
//# sourceMappingURL=navigationRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigationRoute.js","sources":["../../../navigation/navigationRoute.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 { DestinationReference } from '@cratis/scene.model';\n\n/**\n * Decides which route a destination occupies, so destinations occupying the same one can be compared.\n *\n * The engine constructs no URLs (ADR-004), so it only compares what was authored. A renderer that derives\n * routes from stable identities, or treats parameter spellings as equivalent, supplies its own key - the same\n * derivation it uses when it builds the URL - and gets duplicate routes diagnosed by that rule instead.\n */\nexport type NavigationRouteKey = (destination: DestinationReference) => string | undefined;\n\n/** The default route key: the authored route override, trimmed, or none. */\nexport const authoredRouteKey: NavigationRouteKey = destination => destination.route?.trim() || undefined;\n\n/**\n * What a destination opens, so two destinations sharing a route are only a conflict when they open\n * different things.\n */\nexport function navigationTarget(destination: DestinationReference, kind: string): string {\n const identity = destination.screen ?? [destination.module, destination.feature, destination.slice].filter(part => part).join('.');\n return [kind, identity, destination.dialog ?? '', destination.outlet ?? ''].join('|');\n}\n"],"names":["authoredRouteKey","destination","route","trim","undefined","navigationTarget","kind","identity","screen","module","feature","slice","filter","part","join","dialog","outlet"],"mappings":";;AAAA;AACA;AAaA,6EACO,MAAMA,gBAAAA,GAAuCC,CAAAA,cAAeA,WAAAA,CAAYC,KAAK,EAAEC,IAAAA,EAAAA,IAAUC;AAEhG;;;AAGC,IACM,SAASC,gBAAAA,CAAiBJ,WAAiC,EAAEK,IAAY,EAAA;IAC5E,MAAMC,QAAAA,GAAWN,WAAAA,CAAYO,MAAM,IAAI;AAACP,QAAAA,WAAAA,CAAYQ,MAAM;AAAER,QAAAA,WAAAA,CAAYS,OAAO;AAAET,QAAAA,WAAAA,CAAYU;AAAM,KAAA,CAACC,MAAM,CAACC,CAAAA,IAAAA,GAAQA,IAAAA,CAAAA,CAAMC,IAAI,CAAC,GAAA,CAAA;IAC9H,OAAO;AAACR,QAAAA,IAAAA;AAAMC,QAAAA,QAAAA;AAAUN,QAAAA,WAAAA,CAAYc,MAAM,IAAI,EAAA;AAAId,QAAAA,WAAAA,CAAYe,MAAM,IAAI;AAAG,KAAA,CAACF,IAAI,CAAC,GAAA,CAAA;AACrF;;;"}
|
|
@@ -42,6 +42,20 @@
|
|
|
42
42
|
return compare(actual, required) === 0;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether a range is one {@link isVersionSatisfiedBy} understands. An empty range or `*` is valid and means
|
|
47
|
+
* "any version"; anything the parser cannot read is invalid, so declarations can be rejected up front
|
|
48
|
+
* instead of surfacing later as a conflict nobody can satisfy.
|
|
49
|
+
*/ function isValidVersionRange(range) {
|
|
50
|
+
const trimmed = range?.trim();
|
|
51
|
+
if (!trimmed || trimmed === '*') return true;
|
|
52
|
+
return parseVersion(splitRange(trimmed)[1]) !== undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether a value is a `major.minor.patch` version, optionally with a pre-release or build suffix.
|
|
56
|
+
*/ function isValidVersion(version) {
|
|
57
|
+
return version !== undefined && version.trim().length > 0 && parseVersion(version) !== undefined;
|
|
58
|
+
}
|
|
45
59
|
function splitRange(range) {
|
|
46
60
|
for (const operator of [
|
|
47
61
|
'>=',
|
|
@@ -109,5 +123,7 @@ function parseVersion(value) {
|
|
|
109
123
|
return components;
|
|
110
124
|
}
|
|
111
125
|
|
|
126
|
+
exports.isValidVersion = isValidVersion;
|
|
127
|
+
exports.isValidVersionRange = isValidVersionRange;
|
|
112
128
|
exports.isVersionSatisfiedBy = isVersionSatisfiedBy;
|
|
113
129
|
//# sourceMappingURL=packageVersionRange.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersionRange.js","sources":["../../packageVersionRange.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 * Checks a {@link PackageDependency.versionRange} against a package's actual version. A deliberately\n * small subset of semver — enough to express what a package declaration realistically needs, and small\n * enough that the C# twin in `Cratis.Scene.Engine` can match it exactly rather than approximately. Both\n * sides are asserted against the same shared fixture corpus.\n *\n * Supported: an empty range or `*` (anything), a bare or `=`-prefixed exact version, `^` (npm caret —\n * compatible within the leftmost non-zero component), `~` (patch-level changes), and the comparisons\n * `>=`, `>`, `<=`, `<`. Versions are read as `major.minor.patch` with any pre-release or build metadata\n * suffix ignored. Anything the parser does not recognize is treated as unsatisfiable rather than as\n * \"anything\", so a typo surfaces as a conflict instead of silently passing.\n */\nexport function isVersionSatisfiedBy(version: string, range: string | undefined): boolean {\n const trimmed = range?.trim();\n if (!trimmed || trimmed === '*') return true;\n\n const actual = parseVersion(version);\n if (!actual) return false;\n\n const [operator, literal] = splitRange(trimmed);\n const required = parseVersion(literal);\n if (!required) return false;\n\n switch (operator) {\n case '^':\n return compare(actual, required) >= 0 && compare(actual, caretUpperBound(required)) < 0;\n case '~':\n return compare(actual, required) >= 0 && compare(actual, [required[0], required[1] + 1, 0]) < 0;\n case '>=':\n return compare(actual, required) >= 0;\n case '>':\n return compare(actual, required) > 0;\n case '<=':\n return compare(actual, required) <= 0;\n case '<':\n return compare(actual, required) < 0;\n default:\n return compare(actual, required) === 0;\n }\n}\n\ntype Version = [number, number, number];\n\nfunction splitRange(range: string): [string, string] {\n for (const operator of ['>=', '<=', '^', '~', '>', '<', '=']) {\n if (range.startsWith(operator)) {\n return [operator === '=' ? '' : operator, range.substring(operator.length).trim()];\n }\n }\n\n return ['', range];\n}\n\n/**\n * npm's caret rule: compatibility is bounded by the leftmost non-zero component, so `^1.2.3` allows\n * anything below `2.0.0`, `^0.2.3` anything below `0.3.0`, and `^0.0.3` only `0.0.3` itself.\n */\nfunction caretUpperBound(version: Version): Version {\n if (version[0] > 0) return [version[0] + 1, 0, 0];\n if (version[1] > 0) return [0, version[1] + 1, 0];\n return [0, 0, version[2] + 1];\n}\n\nfunction compare(left: Version, right: Version): number {\n if (left[0] !== right[0]) return left[0] - right[0];\n if (left[1] !== right[1]) return left[1] - right[1];\n return left[2] - right[2];\n}\n\nfunction parseVersion(value: string): Version | undefined {\n let numeric = value.trim();\n const suffix = numeric.search(/[-+]/);\n if (suffix >= 0) {\n numeric = numeric.substring(0, suffix);\n }\n\n const parts = numeric.split('.');\n if (parts.length === 0 || parts.length > 3) return undefined;\n\n const components: Version = [0, 0, 0];\n for (let index = 0; index < parts.length; index++) {\n if (!/^\\d+$/.test(parts[index])) return undefined;\n components[index] = parseInt(parts[index], 10);\n }\n\n return components;\n}\n"],"names":["isVersionSatisfiedBy","version","range","trimmed","trim","actual","parseVersion","operator","literal","splitRange","required","compare","caretUpperBound","
|
|
1
|
+
{"version":3,"file":"packageVersionRange.js","sources":["../../packageVersionRange.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 * Checks a {@link PackageDependency.versionRange} against a package's actual version. A deliberately\n * small subset of semver — enough to express what a package declaration realistically needs, and small\n * enough that the C# twin in `Cratis.Scene.Engine` can match it exactly rather than approximately. Both\n * sides are asserted against the same shared fixture corpus.\n *\n * Supported: an empty range or `*` (anything), a bare or `=`-prefixed exact version, `^` (npm caret —\n * compatible within the leftmost non-zero component), `~` (patch-level changes), and the comparisons\n * `>=`, `>`, `<=`, `<`. Versions are read as `major.minor.patch` with any pre-release or build metadata\n * suffix ignored. Anything the parser does not recognize is treated as unsatisfiable rather than as\n * \"anything\", so a typo surfaces as a conflict instead of silently passing.\n */\nexport function isVersionSatisfiedBy(version: string, range: string | undefined): boolean {\n const trimmed = range?.trim();\n if (!trimmed || trimmed === '*') return true;\n\n const actual = parseVersion(version);\n if (!actual) return false;\n\n const [operator, literal] = splitRange(trimmed);\n const required = parseVersion(literal);\n if (!required) return false;\n\n switch (operator) {\n case '^':\n return compare(actual, required) >= 0 && compare(actual, caretUpperBound(required)) < 0;\n case '~':\n return compare(actual, required) >= 0 && compare(actual, [required[0], required[1] + 1, 0]) < 0;\n case '>=':\n return compare(actual, required) >= 0;\n case '>':\n return compare(actual, required) > 0;\n case '<=':\n return compare(actual, required) <= 0;\n case '<':\n return compare(actual, required) < 0;\n default:\n return compare(actual, required) === 0;\n }\n}\n\n/**\n * Whether a range is one {@link isVersionSatisfiedBy} understands. An empty range or `*` is valid and means\n * \"any version\"; anything the parser cannot read is invalid, so declarations can be rejected up front\n * instead of surfacing later as a conflict nobody can satisfy.\n */\nexport function isValidVersionRange(range: string | undefined): boolean {\n const trimmed = range?.trim();\n if (!trimmed || trimmed === '*') return true;\n return parseVersion(splitRange(trimmed)[1]) !== undefined;\n}\n\n/**\n * Whether a value is a `major.minor.patch` version, optionally with a pre-release or build suffix.\n */\nexport function isValidVersion(version: string | undefined): boolean {\n return version !== undefined && version.trim().length > 0 && parseVersion(version) !== undefined;\n}\n\ntype Version = [number, number, number];\n\nfunction splitRange(range: string): [string, string] {\n for (const operator of ['>=', '<=', '^', '~', '>', '<', '=']) {\n if (range.startsWith(operator)) {\n return [operator === '=' ? '' : operator, range.substring(operator.length).trim()];\n }\n }\n\n return ['', range];\n}\n\n/**\n * npm's caret rule: compatibility is bounded by the leftmost non-zero component, so `^1.2.3` allows\n * anything below `2.0.0`, `^0.2.3` anything below `0.3.0`, and `^0.0.3` only `0.0.3` itself.\n */\nfunction caretUpperBound(version: Version): Version {\n if (version[0] > 0) return [version[0] + 1, 0, 0];\n if (version[1] > 0) return [0, version[1] + 1, 0];\n return [0, 0, version[2] + 1];\n}\n\nfunction compare(left: Version, right: Version): number {\n if (left[0] !== right[0]) return left[0] - right[0];\n if (left[1] !== right[1]) return left[1] - right[1];\n return left[2] - right[2];\n}\n\nfunction parseVersion(value: string): Version | undefined {\n let numeric = value.trim();\n const suffix = numeric.search(/[-+]/);\n if (suffix >= 0) {\n numeric = numeric.substring(0, suffix);\n }\n\n const parts = numeric.split('.');\n if (parts.length === 0 || parts.length > 3) return undefined;\n\n const components: Version = [0, 0, 0];\n for (let index = 0; index < parts.length; index++) {\n if (!/^\\d+$/.test(parts[index])) return undefined;\n components[index] = parseInt(parts[index], 10);\n }\n\n return components;\n}\n"],"names":["isVersionSatisfiedBy","version","range","trimmed","trim","actual","parseVersion","operator","literal","splitRange","required","compare","caretUpperBound","isValidVersionRange","undefined","isValidVersion","length","startsWith","substring","left","right","value","numeric","suffix","search","parts","split","components","index","test","parseInt"],"mappings":";;AAAA;AACA;AAEA;;;;;;;;;;;AAWC,IACM,SAASA,oBAAAA,CAAqBC,OAAe,EAAEC,KAAyB,EAAA;AAC3E,IAAA,MAAMC,UAAUD,KAAAA,EAAOE,IAAAA,EAAAA;AACvB,IAAA,IAAI,CAACD,OAAAA,IAAWA,OAAAA,KAAY,GAAA,EAAK,OAAO,IAAA;AAExC,IAAA,MAAME,SAASC,YAAAA,CAAaL,OAAAA,CAAAA;IAC5B,IAAI,CAACI,QAAQ,OAAO,KAAA;AAEpB,IAAA,MAAM,CAACE,QAAAA,EAAUC,OAAAA,CAAQ,GAAGC,UAAAA,CAAWN,OAAAA,CAAAA;AACvC,IAAA,MAAMO,WAAWJ,YAAAA,CAAaE,OAAAA,CAAAA;IAC9B,IAAI,CAACE,UAAU,OAAO,KAAA;IAEtB,OAAQH,QAAAA;QACJ,KAAK,GAAA;AACD,YAAA,OAAOI,QAAQN,MAAAA,EAAQK,QAAAA,CAAAA,IAAa,KAAKC,OAAAA,CAAQN,MAAAA,EAAQO,gBAAgBF,QAAAA,CAAAA,CAAAA,GAAa,CAAA;QAC1F,KAAK,GAAA;AACD,YAAA,OAAOC,OAAAA,CAAQN,MAAAA,EAAQK,QAAAA,CAAAA,IAAa,CAAA,IAAKC,QAAQN,MAAAA,EAAQ;AAACK,gBAAAA,QAAQ,CAAC,CAAA,CAAE;gBAAEA,QAAQ,CAAC,EAAE,GAAG,CAAA;AAAG,gBAAA;aAAE,CAAA,GAAI,CAAA;QAClG,KAAK,IAAA;YACD,OAAOC,OAAAA,CAAQN,QAAQK,QAAAA,CAAAA,IAAa,CAAA;QACxC,KAAK,GAAA;YACD,OAAOC,OAAAA,CAAQN,QAAQK,QAAAA,CAAAA,GAAY,CAAA;QACvC,KAAK,IAAA;YACD,OAAOC,OAAAA,CAAQN,QAAQK,QAAAA,CAAAA,IAAa,CAAA;QACxC,KAAK,GAAA;YACD,OAAOC,OAAAA,CAAQN,QAAQK,QAAAA,CAAAA,GAAY,CAAA;AACvC,QAAA;YACI,OAAOC,OAAAA,CAAQN,QAAQK,QAAAA,CAAAA,KAAc,CAAA;AAC7C;AACJ;AAEA;;;;IAKO,SAASG,mBAAAA,CAAoBX,KAAyB,EAAA;AACzD,IAAA,MAAMC,UAAUD,KAAAA,EAAOE,IAAAA,EAAAA;AACvB,IAAA,IAAI,CAACD,OAAAA,IAAWA,OAAAA,KAAY,GAAA,EAAK,OAAO,IAAA;AACxC,IAAA,OAAOG,YAAAA,CAAaG,UAAAA,CAAWN,OAAAA,CAAQ,CAAC,EAAE,CAAA,KAAMW,SAAAA;AACpD;AAEA;;IAGO,SAASC,cAAAA,CAAed,OAA2B,EAAA;IACtD,OAAOA,OAAAA,KAAYa,aAAab,OAAAA,CAAQG,IAAI,GAAGY,MAAM,GAAG,CAAA,IAAKV,YAAAA,CAAaL,OAAAA,CAAAA,KAAaa,SAAAA;AAC3F;AAIA,SAASL,WAAWP,KAAa,EAAA;AAC7B,IAAA,KAAK,MAAMK,QAAAA,IAAY;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA,GAAA;AAAK,QAAA,GAAA;AAAK,QAAA,GAAA;AAAK,QAAA,GAAA;AAAK,QAAA;KAAI,CAAE;QAC1D,IAAIL,KAAAA,CAAMe,UAAU,CAACV,QAAAA,CAAAA,EAAW;YAC5B,OAAO;AAACA,gBAAAA,QAAAA,KAAa,MAAM,EAAA,GAAKA,QAAAA;AAAUL,gBAAAA,KAAAA,CAAMgB,SAAS,CAACX,QAAAA,CAASS,MAAM,EAAEZ,IAAI;AAAG,aAAA;AACtF,QAAA;AACJ,IAAA;IAEA,OAAO;AAAC,QAAA,EAAA;AAAIF,QAAAA;AAAM,KAAA;AACtB;AAEA;;;IAIA,SAASU,gBAAgBX,OAAgB,EAAA;AACrC,IAAA,IAAIA,OAAO,CAAC,CAAA,CAAE,GAAG,GAAG,OAAO;QAACA,OAAO,CAAC,EAAE,GAAG,CAAA;AAAG,QAAA,CAAA;AAAG,QAAA;AAAE,KAAA;AACjD,IAAA,IAAIA,OAAO,CAAC,CAAA,CAAE,GAAG,GAAG,OAAO;AAAC,QAAA,CAAA;QAAGA,OAAO,CAAC,EAAE,GAAG,CAAA;AAAG,QAAA;AAAE,KAAA;IACjD,OAAO;AAAC,QAAA,CAAA;AAAG,QAAA,CAAA;QAAGA,OAAO,CAAC,EAAE,GAAG;AAAE,KAAA;AACjC;AAEA,SAASU,OAAAA,CAAQQ,IAAa,EAAEC,KAAc,EAAA;AAC1C,IAAA,IAAID,IAAI,CAAC,CAAA,CAAE,KAAKC,KAAK,CAAC,CAAA,CAAE,EAAE,OAAOD,IAAI,CAAC,CAAA,CAAE,GAAGC,KAAK,CAAC,CAAA,CAAE;AACnD,IAAA,IAAID,IAAI,CAAC,CAAA,CAAE,KAAKC,KAAK,CAAC,CAAA,CAAE,EAAE,OAAOD,IAAI,CAAC,CAAA,CAAE,GAAGC,KAAK,CAAC,CAAA,CAAE;AACnD,IAAA,OAAOD,IAAI,CAAC,CAAA,CAAE,GAAGC,KAAK,CAAC,CAAA,CAAE;AAC7B;AAEA,SAASd,aAAae,KAAa,EAAA;IAC/B,IAAIC,OAAAA,GAAUD,MAAMjB,IAAI,EAAA;IACxB,MAAMmB,MAAAA,GAASD,OAAAA,CAAQE,MAAM,CAAC,MAAA,CAAA;AAC9B,IAAA,IAAID,UAAU,CAAA,EAAG;QACbD,OAAAA,GAAUA,OAAAA,CAAQJ,SAAS,CAAC,CAAA,EAAGK,MAAAA,CAAAA;AACnC,IAAA;IAEA,MAAME,KAAAA,GAAQH,OAAAA,CAAQI,KAAK,CAAC,GAAA,CAAA;IAC5B,IAAID,KAAAA,CAAMT,MAAM,KAAK,CAAA,IAAKS,MAAMT,MAAM,GAAG,GAAG,OAAOF,SAAAA;AAEnD,IAAA,MAAMa,UAAAA,GAAsB;AAAC,QAAA,CAAA;AAAG,QAAA,CAAA;AAAG,QAAA;AAAE,KAAA;AACrC,IAAA,IAAK,IAAIC,KAAAA,GAAQ,CAAA,EAAGA,QAAQH,KAAAA,CAAMT,MAAM,EAAEY,KAAAA,EAAAA,CAAS;QAC/C,IAAI,CAAC,QAAQC,IAAI,CAACJ,KAAK,CAACG,KAAAA,CAAM,GAAG,OAAOd,SAAAA;AACxCa,QAAAA,UAAU,CAACC,KAAAA,CAAM,GAAGE,SAASL,KAAK,CAACG,MAAM,EAAE,EAAA,CAAA;AAC/C,IAAA;IAEA,OAAOD,UAAAA;AACX;;;;"}
|
|
@@ -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
|
+
* Which kind of template a catalog entry describes.
|
|
7
|
+
*/ var TemplateCatalogKind = /*#__PURE__*/ function(TemplateCatalogKind) {
|
|
8
|
+
TemplateCatalogKind["Layout"] = "Layout";
|
|
9
|
+
TemplateCatalogKind["ScreenTemplate"] = "ScreenTemplate";
|
|
10
|
+
TemplateCatalogKind["DialogTemplate"] = "DialogTemplate";
|
|
11
|
+
return TemplateCatalogKind;
|
|
12
|
+
}({});
|
|
13
|
+
|
|
14
|
+
exports.TemplateCatalogKind = TemplateCatalogKind;
|
|
15
|
+
//# sourceMappingURL=TemplateCatalogKind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateCatalogKind.js","sources":["../../../templates/TemplateCatalogKind.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 * Which kind of template a catalog entry describes.\n */\nexport enum TemplateCatalogKind {\n Layout = 'Layout',\n ScreenTemplate = 'ScreenTemplate',\n DialogTemplate = 'DialogTemplate',\n}\n"],"names":["TemplateCatalogKind"],"mappings":";;AAAA;AACA;AAEA;;IAGO,IAAKA,mBAAAA,iBAAAA,SAAAA,mBAAAA,EAAAA;;;;AAAAA,IAAAA,OAAAA,mBAAAA;AAIX,CAAA,CAAA,EAAA;;"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var packageVersionRange = require('../packageVersionRange.js');
|
|
4
|
+
var TemplateCatalogKind = require('./TemplateCatalogKind.js');
|
|
5
|
+
var validateTemplateMetadata = require('./validateTemplateMetadata.js');
|
|
6
|
+
|
|
7
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
8
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
9
|
+
/**
|
|
10
|
+
* Describes every template the given packages provide, in package then layout, screen template, dialog
|
|
11
|
+
* template order, with its compatibility, attribution and license metadata and whether it can be used.
|
|
12
|
+
*
|
|
13
|
+
* A template is compatible when its metadata is complete and valid, the Scene version (when given) satisfies
|
|
14
|
+
* its Scene range, and every package it requires is among the given packages at a satisfying version and is
|
|
15
|
+
* either its own package or one that package depends on. Nothing is filtered out: a browser shows incompatible
|
|
16
|
+
* templates with their problems rather than hiding why they are unavailable.
|
|
17
|
+
*/ function describeTemplateCatalog(sources, sceneVersion) {
|
|
18
|
+
const versions = new Map(sources.map((source)=>[
|
|
19
|
+
source.manifest.name,
|
|
20
|
+
source.manifest.version
|
|
21
|
+
]));
|
|
22
|
+
const entries = [];
|
|
23
|
+
for (const source of sources){
|
|
24
|
+
const templates = [
|
|
25
|
+
...(source.layouts ?? []).map((template)=>({
|
|
26
|
+
kind: TemplateCatalogKind.TemplateCatalogKind.Layout,
|
|
27
|
+
template
|
|
28
|
+
})),
|
|
29
|
+
...(source.screenTemplates ?? []).map((template)=>({
|
|
30
|
+
kind: TemplateCatalogKind.TemplateCatalogKind.ScreenTemplate,
|
|
31
|
+
template
|
|
32
|
+
})),
|
|
33
|
+
...(source.dialogTemplates ?? []).map((template)=>({
|
|
34
|
+
kind: TemplateCatalogKind.TemplateCatalogKind.DialogTemplate,
|
|
35
|
+
template
|
|
36
|
+
}))
|
|
37
|
+
];
|
|
38
|
+
for (const { kind, template } of templates){
|
|
39
|
+
const metadata = template.metadata;
|
|
40
|
+
const describable = template;
|
|
41
|
+
const problems = [
|
|
42
|
+
...validateTemplateMetadata.validateTemplateMetadata(template.name, metadata),
|
|
43
|
+
...requirementProblems(template.name, metadata, source.manifest, versions, sceneVersion)
|
|
44
|
+
];
|
|
45
|
+
entries.push({
|
|
46
|
+
package: source.manifest.name,
|
|
47
|
+
packageVersion: source.manifest.version,
|
|
48
|
+
kind,
|
|
49
|
+
name: template.name,
|
|
50
|
+
displayName: describable.displayName,
|
|
51
|
+
description: describable.description,
|
|
52
|
+
type: metadata?.type,
|
|
53
|
+
category: metadata?.category,
|
|
54
|
+
scopes: metadata?.scopes,
|
|
55
|
+
compatibility: metadata?.compatibility,
|
|
56
|
+
attribution: metadata?.attribution,
|
|
57
|
+
license: metadata?.license,
|
|
58
|
+
licenseUrl: metadata?.licenseUrl,
|
|
59
|
+
compatible: problems.length === 0,
|
|
60
|
+
problems
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return entries;
|
|
65
|
+
}
|
|
66
|
+
function requirementProblems(name, metadata, owner, versions, sceneVersion) {
|
|
67
|
+
const problems = [];
|
|
68
|
+
const compatibility = metadata?.compatibility;
|
|
69
|
+
if (!compatibility) return problems;
|
|
70
|
+
if (sceneVersion !== undefined && compatibility.scene?.trim() && !packageVersionRange.isVersionSatisfiedBy(sceneVersion, compatibility.scene)) {
|
|
71
|
+
problems.push(`Template '${name}' requires Scene ${compatibility.scene} but the host runs ${sceneVersion}`);
|
|
72
|
+
}
|
|
73
|
+
for (const requirement of compatibility.packages ?? []){
|
|
74
|
+
if (!requirement.name?.trim()) continue;
|
|
75
|
+
if (requirement.name !== owner.name && !owner.dependencies.some((dependency)=>dependency.name === requirement.name)) {
|
|
76
|
+
problems.push(`Template '${name}' requires package '${requirement.name}', which its package '${owner.name}' does not depend on`);
|
|
77
|
+
}
|
|
78
|
+
const version = versions.get(requirement.name);
|
|
79
|
+
if (version === undefined) {
|
|
80
|
+
problems.push(`Template '${name}' requires package '${requirement.name}', which is not available`);
|
|
81
|
+
} else if (!packageVersionRange.isVersionSatisfiedBy(version, requirement.versionRange)) {
|
|
82
|
+
problems.push(`Template '${name}' requires package '${requirement.name}' ${requirement.versionRange} but version ${version} is available`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return problems;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
exports.describeTemplateCatalog = describeTemplateCatalog;
|
|
89
|
+
//# sourceMappingURL=describeTemplateCatalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describeTemplateCatalog.js","sources":["../../../templates/describeTemplateCatalog.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 { ScenePackage, TemplateMetadata } from '@cratis/scene.model';\nimport { isVersionSatisfiedBy } from '../packageVersionRange';\nimport { TemplateCatalogEntry } from './TemplateCatalogEntry';\nimport { TemplateCatalogKind } from './TemplateCatalogKind';\nimport { TemplateSource } from './TemplateSource';\nimport { validateTemplateMetadata } from './validateTemplateMetadata';\n\n/**\n * Describes every template the given packages provide, in package then layout, screen template, dialog\n * template order, with its compatibility, attribution and license metadata and whether it can be used.\n *\n * A template is compatible when its metadata is complete and valid, the Scene version (when given) satisfies\n * its Scene range, and every package it requires is among the given packages at a satisfying version and is\n * either its own package or one that package depends on. Nothing is filtered out: a browser shows incompatible\n * templates with their problems rather than hiding why they are unavailable.\n */\nexport function describeTemplateCatalog(sources: TemplateSource[], sceneVersion?: string): TemplateCatalogEntry[] {\n const versions = new Map(sources.map(source => [source.manifest.name, source.manifest.version]));\n const entries: TemplateCatalogEntry[] = [];\n\n for (const source of sources) {\n const templates = [\n ...(source.layouts ?? []).map(template => ({ kind: TemplateCatalogKind.Layout, template })),\n ...(source.screenTemplates ?? []).map(template => ({ kind: TemplateCatalogKind.ScreenTemplate, template })),\n ...(source.dialogTemplates ?? []).map(template => ({ kind: TemplateCatalogKind.DialogTemplate, template })),\n ];\n\n for (const { kind, template } of templates) {\n const metadata = template.metadata;\n const describable = template as { displayName?: string; description?: string };\n const problems = [\n ...validateTemplateMetadata(template.name, metadata),\n ...requirementProblems(template.name, metadata, source.manifest, versions, sceneVersion),\n ];\n\n entries.push({\n package: source.manifest.name,\n packageVersion: source.manifest.version,\n kind,\n name: template.name,\n displayName: describable.displayName,\n description: describable.description,\n type: metadata?.type,\n category: metadata?.category,\n scopes: metadata?.scopes,\n compatibility: metadata?.compatibility,\n attribution: metadata?.attribution,\n license: metadata?.license,\n licenseUrl: metadata?.licenseUrl,\n compatible: problems.length === 0,\n problems,\n });\n }\n }\n\n return entries;\n}\n\nfunction requirementProblems(\n name: string,\n metadata: TemplateMetadata | undefined,\n owner: ScenePackage,\n versions: Map<string, string>,\n sceneVersion: string | undefined,\n): string[] {\n const problems: string[] = [];\n const compatibility = metadata?.compatibility;\n if (!compatibility) return problems;\n\n if (sceneVersion !== undefined && compatibility.scene?.trim() && !isVersionSatisfiedBy(sceneVersion, compatibility.scene)) {\n problems.push(`Template '${name}' requires Scene ${compatibility.scene} but the host runs ${sceneVersion}`);\n }\n\n for (const requirement of compatibility.packages ?? []) {\n if (!requirement.name?.trim()) continue;\n if (requirement.name !== owner.name && !owner.dependencies.some(dependency => dependency.name === requirement.name)) {\n problems.push(`Template '${name}' requires package '${requirement.name}', which its package '${owner.name}' does not depend on`);\n }\n\n const version = versions.get(requirement.name);\n if (version === undefined) {\n problems.push(`Template '${name}' requires package '${requirement.name}', which is not available`);\n } else if (!isVersionSatisfiedBy(version, requirement.versionRange)) {\n problems.push(`Template '${name}' requires package '${requirement.name}' ${requirement.versionRange} but version ${version} is available`);\n }\n }\n\n return problems;\n}\n"],"names":["describeTemplateCatalog","sources","sceneVersion","versions","Map","map","source","manifest","name","version","entries","templates","layouts","template","kind","TemplateCatalogKind","Layout","screenTemplates","ScreenTemplate","dialogTemplates","DialogTemplate","metadata","describable","problems","validateTemplateMetadata","requirementProblems","push","package","packageVersion","displayName","description","type","category","scopes","compatibility","attribution","license","licenseUrl","compatible","length","owner","undefined","scene","trim","isVersionSatisfiedBy","requirement","packages","dependencies","some","dependency","get","versionRange"],"mappings":"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"}
|