ui(deploy): add deriveAppName pure function + tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { deriveAppName } from './deriveAppName';
|
||||
|
||||
describe('deriveAppName', () => {
|
||||
it('truncates at first digit', () => {
|
||||
expect(deriveAppName('payment-gateway-1.2.0.jar')).toBe('Payment Gateway');
|
||||
});
|
||||
|
||||
it('returns clean title-cased name without digits', () => {
|
||||
expect(deriveAppName('order-service.jar')).toBe('Order Service');
|
||||
});
|
||||
|
||||
it('strips orphan 1-char token after truncation (v from my-app-v2)', () => {
|
||||
expect(deriveAppName('my-app-v2.jar')).toBe('My App');
|
||||
});
|
||||
|
||||
it('treats underscore like dash', () => {
|
||||
expect(deriveAppName('acme_billing-3.jar')).toBe('Acme Billing');
|
||||
});
|
||||
|
||||
it('strips the .jar extension when no digits present', () => {
|
||||
expect(deriveAppName('acme-billing.jar')).toBe('Acme Billing');
|
||||
});
|
||||
|
||||
it('returns empty string for empty input', () => {
|
||||
expect(deriveAppName('')).toBe('');
|
||||
});
|
||||
|
||||
it('returns empty string when filename starts with a digit', () => {
|
||||
expect(deriveAppName('1-my-thing.jar')).toBe('');
|
||||
});
|
||||
|
||||
it('mixed separators are both collapsed to spaces', () => {
|
||||
expect(deriveAppName('foo_bar-baz.jar')).toBe('Foo Bar Baz');
|
||||
});
|
||||
|
||||
it('strips trailing orphan regardless of letter identity', () => {
|
||||
expect(deriveAppName('release-x9.jar')).toBe('Release');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Derive a human-readable app name from a JAR filename.
|
||||
*
|
||||
* Rule:
|
||||
* 1. Strip the `.jar` extension.
|
||||
* 2. Truncate at the first digit (0-9) or `.`.
|
||||
* 3. Replace `-` and `_` with spaces.
|
||||
* 4. Collapse multiple spaces and trim.
|
||||
* 5. Drop 1-char orphan tokens (e.g. the trailing `v` in `my-app-v2`).
|
||||
* 6. Title-case each remaining word.
|
||||
*
|
||||
* The result is a suggestion — the caller is expected to let the user override.
|
||||
*/
|
||||
export function deriveAppName(filename: string): string {
|
||||
if (!filename) return '';
|
||||
|
||||
let stem = filename.replace(/\.jar$/i, '');
|
||||
|
||||
// Truncate at first digit or dot
|
||||
const match = stem.match(/[0-9.]/);
|
||||
if (match && match.index !== undefined) {
|
||||
stem = stem.slice(0, match.index);
|
||||
}
|
||||
|
||||
// Separators → space
|
||||
stem = stem.replace(/[-_]+/g, ' ');
|
||||
|
||||
// Collapse whitespace + trim
|
||||
stem = stem.replace(/\s+/g, ' ').trim();
|
||||
if (!stem) return '';
|
||||
|
||||
// Drop 1-char orphan tokens
|
||||
const tokens = stem.split(' ').filter((t) => t.length > 1);
|
||||
if (tokens.length === 0) return '';
|
||||
|
||||
// Title-case
|
||||
return tokens.map((t) => t.charAt(0).toUpperCase() + t.slice(1).toLowerCase()).join(' ');
|
||||
}
|
||||
Reference in New Issue
Block a user