diff --git a/Source/DotNET/Model/Packages/ScenePackage.cs b/Source/DotNET/Model/Packages/ScenePackage.cs
index a86db6a..a018694 100644
--- a/Source/DotNET/Model/Packages/ScenePackage.cs
+++ b/Source/DotNET/Model/Packages/ScenePackage.cs
@@ -23,6 +23,16 @@ namespace Cratis.Scene.Model.Packages;
/// The module that implements the package - an npm package name for a web renderer. Design-time tooling
/// needs it to know what to import; the model itself never loads anything.
///
+///
+/// The license the package is available under, as a short human-readable name (MIT,
+/// PrimeUI Community). A package picker shows it, because "what am I taking on by selecting this"
+/// is a question an author needs answered before they select it, not after.
+///
+///
+/// Where the license terms actually live, so a reader can go and check rather than take
+/// on trust. Required in practice for anything that is not a permissive
+/// standard license - a name alone tells an author nothing about eligibility or obligations.
+///
public record ScenePackage(
string Name,
string Version,
@@ -35,4 +45,6 @@ public record ScenePackage(
IReadOnlyList Themes,
string? DisplayName = null,
string? Description = null,
- string? Module = null);
+ string? Module = null,
+ string? License = null,
+ string? LicenseUrl = null);
diff --git a/Source/DotNET/Model/Profiles/Theme.cs b/Source/DotNET/Model/Profiles/Theme.cs
index 3dcc76f..9bc706e 100644
--- a/Source/DotNET/Model/Profiles/Theme.cs
+++ b/Source/DotNET/Model/Profiles/Theme.cs
@@ -23,6 +23,7 @@ namespace Cratis.Scene.Model.Profiles;
///
/// A link to the original creator or the theme's home, shown alongside .
/// The license the theme is used under, so redistributing it stays honest.
+/// Where those license terms live, so a reader can check them rather than take on trust.
/// A one-line description for a theme picker.
public record Theme(
string Name,
@@ -32,4 +33,5 @@ public record Theme(
string? Author = null,
string? AuthorUrl = null,
string? License = null,
- string? Description = null);
+ string? Description = null,
+ string? LicenseUrl = null);
diff --git a/Source/JavaScript/blueprint.components/componentsBlueprint.ts b/Source/JavaScript/blueprint.components/componentsBlueprint.ts
index 44e8941..c645ecc 100644
--- a/Source/JavaScript/blueprint.components/componentsBlueprint.ts
+++ b/Source/JavaScript/blueprint.components/componentsBlueprint.ts
@@ -49,6 +49,8 @@ export const componentsBlueprintManifest: ScenePackage = {
displayName: 'Cratis Components Blueprint',
description: 'Arc-bound screen and dialog templates: whole pages built from the Cratis Components composites, for the default blueprint shell.',
module: '@cratis/scene.blueprint.components',
+ license: 'MIT',
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
};
/**
diff --git a/Source/JavaScript/blueprint.default/defaultBlueprint.ts b/Source/JavaScript/blueprint.default/defaultBlueprint.ts
index b9f79ab..be42f47 100644
--- a/Source/JavaScript/blueprint.default/defaultBlueprint.ts
+++ b/Source/JavaScript/blueprint.default/defaultBlueprint.ts
@@ -42,6 +42,8 @@ export const defaultBlueprintManifest: ScenePackage = {
displayName: 'Cratis Default Blueprint',
description: 'Application shells with eight menu modes, the components that fill their slots, and a full screen and dialog template set.',
module: '@cratis/scene.blueprint.default',
+ license: 'MIT',
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
};
/**
diff --git a/Source/JavaScript/components/cratisComponentsPackage.ts b/Source/JavaScript/components/cratisComponentsPackage.ts
index be46fcb..d7fdbec 100644
--- a/Source/JavaScript/components/cratisComponentsPackage.ts
+++ b/Source/JavaScript/components/cratisComponentsPackage.ts
@@ -90,6 +90,8 @@ export const cratisComponentsPackageManifest: ScenePackage = {
displayName: 'Cratis Components',
description: "Cratis' Arc-bound data, form and dialog composites, built on PrimeReact and Tailwind.",
module: '@cratis/scene.components',
+ license: 'MIT',
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
};
/**
diff --git a/Source/JavaScript/model/packages/ScenePackage.ts b/Source/JavaScript/model/packages/ScenePackage.ts
index 9e6e3ae..9a92ba8 100644
--- a/Source/JavaScript/model/packages/ScenePackage.ts
+++ b/Source/JavaScript/model/packages/ScenePackage.ts
@@ -72,6 +72,20 @@ export interface ScenePackage {
* tooling needs it to know what to import; the model itself never loads anything.
*/
module?: string;
+
+ /**
+ * The license the package is available under, as a short human-readable name (`MIT`,
+ * `PrimeUI Community`). A package picker shows it, because "what am I taking on by selecting this"
+ * is a question an author needs answered before they select it, not after.
+ */
+ license?: string;
+
+ /**
+ * Where the license terms actually live, so a reader can go and check rather than take `license` on
+ * trust. Required in practice for anything that is not a permissive standard license — a name alone
+ * tells an author nothing about eligibility or obligations.
+ */
+ licenseUrl?: string;
}
export const ScenePackagePropertyNames: (keyof ScenePackage)[] = [
@@ -87,4 +101,6 @@ export const ScenePackagePropertyNames: (keyof ScenePackage)[] = [
'displayName',
'description',
'module',
+ 'license',
+ 'licenseUrl',
];
diff --git a/Source/JavaScript/model/profiles/Theme.ts b/Source/JavaScript/model/profiles/Theme.ts
index e4807ed..1b8368c 100644
--- a/Source/JavaScript/model/profiles/Theme.ts
+++ b/Source/JavaScript/model/profiles/Theme.ts
@@ -50,6 +50,11 @@ export interface Theme {
* A one-line description for a theme picker.
*/
description?: string;
+
+ /**
+ * Where those license terms live, so a reader can check them rather than take `license` on trust.
+ */
+ licenseUrl?: string;
}
export const ThemePropertyNames: (keyof Theme)[] = [
@@ -61,4 +66,5 @@ export const ThemePropertyNames: (keyof Theme)[] = [
'authorUrl',
'license',
'description',
+ 'licenseUrl',
];
diff --git a/Source/JavaScript/primereact/for_primeReactThemes/when_checking_attribution.ts b/Source/JavaScript/primereact/for_primeReactThemes/when_checking_attribution.ts
index 44f2c2d..911d3ec 100644
--- a/Source/JavaScript/primereact/for_primeReactThemes/when_checking_attribution.ts
+++ b/Source/JavaScript/primereact/for_primeReactThemes/when_checking_attribution.ts
@@ -1,7 +1,7 @@
// Copyright (c) Cratis. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-import { primeReactThemes } from '../theme';
+import { primeReactThemeLicense, primeReactThemeLicenseUrl, primeReactThemes } from '../theme';
describe('when checking attribution', () => {
it('should credit an author on every theme', () => {
@@ -27,7 +27,17 @@ describe('when checking attribution', () => {
* catalog would have gone on advertising MIT indefinitely.
*/
it('should state the commercial license PrimeReact 11 actually ships under, not the MIT of v10', () => {
- primeReactThemes.filter((theme) => theme.license !== 'PrimeUI Commercial').should.deep.equal([]);
+ primeReactThemeLicense.should.equal('PrimeUI Community / Commercial');
+ primeReactThemes.filter((theme) => theme.license !== primeReactThemeLicense).should.deep.equal([]);
+ });
+
+ /**
+ * A license name on its own does not tell a reader whether they qualify for the free Community tier
+ * or owe a commercial fee. The link is the part that answers that, so it is pinned too.
+ */
+ it('should link to the terms on every theme, not just name them', () => {
+ primeReactThemeLicenseUrl.should.equal('https://primeui.dev/licenses/community');
+ primeReactThemes.filter((theme) => theme.licenseUrl !== primeReactThemeLicenseUrl).should.deep.equal([]);
});
it('should describe every theme for a picker', () => {
diff --git a/Source/JavaScript/primereact/primeReactPackage.ts b/Source/JavaScript/primereact/primeReactPackage.ts
index eebae95..0f7307d 100644
--- a/Source/JavaScript/primereact/primeReactPackage.ts
+++ b/Source/JavaScript/primereact/primeReactPackage.ts
@@ -71,6 +71,11 @@ export const primeReactPackageManifest: ScenePackage = {
displayName: 'PrimeReact',
description: 'PrimeReact 11 components and PrimeTek\'s @primeuix/themes presets, mapped onto Scene\'s abstract component names.',
module: '@cratis/scene.primereact',
+ // PrimeReact 11 is PrimeTek's commercial PrimeUI, not MIT as version 10 was. The Community
+ // tier is free for eligible projects but still requires a key, so an author selecting this
+ // package needs to see the terms before they select it, not after a banner appears.
+ license: 'PrimeUI Community / Commercial',
+ licenseUrl: 'https://primeui.dev/licenses/community',
};
/**
diff --git a/Source/JavaScript/primereact/theme/primeReactThemes.ts b/Source/JavaScript/primereact/theme/primeReactThemes.ts
index a1103d2..c780e7a 100644
--- a/Source/JavaScript/primereact/theme/primeReactThemes.ts
+++ b/Source/JavaScript/primereact/theme/primeReactThemes.ts
@@ -41,7 +41,14 @@ export const primeReactThemeCompatibility: string[] = ['PrimeReact', 'Tailwind',
* @see https://primeui.dev/licenses/community for the free community tier and its eligibility limits.
* @see https://primeui.dev/licenses/commercial for the paid tier.
*/
-export const primeReactThemeLicense = 'PrimeUI Commercial';
+export const primeReactThemeLicense = 'PrimeUI Community / Commercial';
+
+/**
+ * Where those terms live. A license name alone tells a reader nothing about whether they qualify for the
+ * free Community tier or owe a commercial fee, so the catalog carries the link rather than making them
+ * search for it.
+ */
+export const primeReactThemeLicenseUrl = 'https://primeui.dev/licenses/community';
/**
* Every theme this package ships, as Scene {@link Theme}s.
@@ -61,6 +68,7 @@ export const primeReactThemes: Theme[] = themePresets.map((preset) => ({
author: 'PrimeTek',
authorUrl: 'https://primereact.org',
license: primeReactThemeLicense,
+ licenseUrl: primeReactThemeLicenseUrl,
}));
/**
diff --git a/Source/JavaScript/react/core/corePackage.ts b/Source/JavaScript/react/core/corePackage.ts
index 5a5b120..17da3b4 100644
--- a/Source/JavaScript/react/core/corePackage.ts
+++ b/Source/JavaScript/react/core/corePackage.ts
@@ -25,6 +25,8 @@ export const corePackageManifest: ScenePackage = {
displayName: 'Core',
description: 'The built-in fallback vocabulary every ui profile resolves against.',
module: '@cratis/scene.react',
+ license: 'MIT',
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
};
/**
diff --git a/Source/JavaScript/tailwind/tailwindPackage.ts b/Source/JavaScript/tailwind/tailwindPackage.ts
index 1165cf6..cde78e5 100644
--- a/Source/JavaScript/tailwind/tailwindPackage.ts
+++ b/Source/JavaScript/tailwind/tailwindPackage.ts
@@ -27,6 +27,8 @@ export const tailwindPackageManifest: ScenePackage = {
displayName: 'Tailwind CSS',
description: 'Utility-first CSS. The styling system Cratis Components and the default layouts are written against.',
module: '@cratis/scene.tailwind',
+ license: 'MIT',
+ licenseUrl: 'https://github.com/Cratis/Scene/blob/main/LICENSE',
};
/**
diff --git a/scene-model-shape.json b/scene-model-shape.json
index 1e1a988..4ba7d2a 100644
--- a/scene-model-shape.json
+++ b/scene-model-shape.json
@@ -191,7 +191,8 @@
"author",
"authorUrl",
"license",
- "description"
+ "description",
+ "licenseUrl"
],
"PackageDependency": [
"name",
@@ -209,7 +210,9 @@
"themes",
"displayName",
"description",
- "module"
+ "module",
+ "license",
+ "licenseUrl"
],
"Screen": [
"name",