Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/titanium/modules/detect-ti-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@ import { snooplogg } from 'snooplogg';

const { log, warn } = snooplogg('ti:modules');

/**
* The `license` values the module scaffolding writes, which mean the author
* never filled one in.
*
* The SDK's module templates seed `Specify your license`, and nothing prompts
* anyone to replace it. Three modules under tidev have shipped releases with it
* still in place — `titanium-identity`, `titanium-onboarding` and
* `ti.previewinteraction` — and it reaches anywhere the manifest is surfaced.
*/
const PLACEHOLDER_LICENSES = new Set(['specify your license', 'your license here']);

/**
* Whether a manifest's `license` is one of the template defaults, meaning no
* licence was ever chosen.
*
* Exported so a packaging or release step can reject what this only warns about:
* failing an app build because a *dependency's* metadata is unfilled would
* punish the wrong person.
*/
export function isPlaceholderLicense(license: string | undefined): boolean {
return license !== undefined && PLACEHOLDER_LICENSES.has(license.trim().toLowerCase());
}

/**
* Detects Titanium modules in the Titanium SDK install locations and user search paths, then
* returns a registry of found modules.
Expand Down Expand Up @@ -334,6 +357,13 @@ async function readManifest(manifestFile: string) {
throw new Error(`Module manifest has invalid version: ${manifest.version}`);
}

if (isPlaceholderLicense(manifest.license)) {
warn(
`Module ${manifest.moduleid} has not set a license (${manifestFile}): ` +
`choose an SPDX license such as "Apache-2.0".`
);
}

const platform = platformAliases[manifest.platform] || manifest.platform;

return {
Expand Down
26 changes: 26 additions & 0 deletions test/titanium/modules/placeholder-license.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { isPlaceholderLicense } from '../../../src/titanium/index.js';
import { describe, expect, it } from 'vitest';

describe('isPlaceholderLicense()', () => {
it('recognises the scaffolding default', () => {
expect(isPlaceholderLicense('Specify your license')).toBe(true);
});

it('ignores case and surrounding whitespace', () => {
// The templates emit it with a trailing newline, and manifests are
// hand-edited, so neither is a reliable shape.
expect(isPlaceholderLicense(' specify your LICENSE ')).toBe(true);
});

it('accepts a real licence', () => {
for (const license of ['Apache-2.0', 'MIT', 'Apache Public License v2', 'Proprietary']) {
expect(isPlaceholderLicense(license)).toBe(false);
}
});

it('treats a missing licence as not a placeholder', () => {
// Absent is a different problem from unfilled, and is not this check's.
expect(isPlaceholderLicense(undefined)).toBe(false);
expect(isPlaceholderLicense('')).toBe(false);
});
});
Loading