Nitpick: psl types (#12925)

Close https://github.com/twentyhq/twenty/issues/12917
This commit is contained in:
Paul Rastoin
2025-06-27 14:31:27 +02:00
committed by GitHub
parent 8a7a86b3c6
commit 3c5595e4ff
7 changed files with 167 additions and 7 deletions

View File

@ -83,6 +83,7 @@
"@types/lodash.uniqby": "^4.7.9",
"@types/lodash.upperfirst": "^4.3.7",
"@types/openid-client": "^3.7.0",
"@types/psl": "^1.1.3",
"@types/react": "^18.2.39",
"@types/unzipper": "^0",
"rimraf": "^5.0.5",

View File

@ -0,0 +1,8 @@
import psl, { ParsedDomain } from 'psl';
import { isDefined } from 'twenty-shared/utils';
export const isParsedDomain = (
result: ReturnType<typeof psl.parse>,
): result is ParsedDomain =>
!isDefined(result.error) &&
Object.prototype.hasOwnProperty.call(result, 'sld');

View File

@ -0,0 +1,60 @@
import { EachTestingContext } from 'twenty-shared/testing';
import { getCompanyNameFromDomainName } from 'src/modules/contact-creation-manager/utils/get-company-name-from-domain-name.util';
type GetCompanyNameFromDomainNameTestCase = EachTestingContext<{
input: string;
expected: string;
}>;
describe('getCompanyNameFromDomainName', () => {
const testCases: GetCompanyNameFromDomainNameTestCase[] = [
{
title: 'should extract and capitalize company name from simple domain',
context: {
input: 'twenty.dev',
expected: 'Twenty',
},
},
{
title: 'should extract and capitalize company name from subdomain',
context: {
input: 'app.twenty.dev',
expected: 'Twenty',
},
},
{
title:
'should extract and capitalize company name from multiple subdomains',
context: {
input: 'test.app.twenty.dev',
expected: 'Twenty',
},
},
{
title: 'should handle domain with multiple parts',
context: {
input: 'twenty.co.uk',
expected: 'Twenty',
},
},
{
title: 'should handle empty string',
context: {
input: '',
expected: '',
},
},
{
title: 'should handle invalid domain',
context: {
input: 'not-a-valid-domain',
expected: '',
},
},
];
test.each(testCases)('$title', ({ context: { input, expected } }) => {
expect(getCompanyNameFromDomainName(input)).toBe(expected);
});
});

View File

@ -0,0 +1,73 @@
import { EachTestingContext } from 'twenty-shared/testing';
import { getDomainNameFromHandle } from 'src/modules/contact-creation-manager/utils/get-domain-name-from-handle.util';
type GetDomainNameFromHandleTestCase = EachTestingContext<{
input: string;
expected: string;
}>;
describe('getDomainNameFromHandle', () => {
const testCases: GetDomainNameFromHandleTestCase[] = [
{
title: 'should extract domain from email handle',
context: {
input: 'user@twenty.dev',
expected: 'twenty.dev',
},
},
{
title: 'should extract domain from email handle with subdomain',
context: {
input: 'user@app.twenty.dev',
expected: 'twenty.dev',
},
},
{
title: 'should extract domain from email handle with multiple subdomains',
context: {
input: 'user@test.app.twenty.dev',
expected: 'twenty.dev',
},
},
{
title: 'should handle domain with multiple parts',
context: {
input: 'user@twenty.co.uk',
expected: 'twenty.co.uk',
},
},
{
title: 'should handle empty string',
context: {
input: '',
expected: '',
},
},
{
title: 'should handle string without @ symbol',
context: {
input: 'not-an-email',
expected: '',
},
},
{
title: 'should handle undefined handle part after @',
context: {
input: 'user@',
expected: '',
},
},
{
title: 'should handle invalid domain',
context: {
input: 'user@not-a-valid-domain',
expected: '',
},
},
];
test.each(testCases)('$title', ({ context: { input, expected } }) => {
expect(getDomainNameFromHandle(input)).toBe(expected);
});
});

View File

@ -1,9 +1,14 @@
// @ts-expect-error legacy noImplicitAny
import psl from 'psl';
import { capitalize } from 'twenty-shared/utils';
export const getCompanyNameFromDomainName = (domainName: string) => {
const { sld } = psl.parse(domainName);
import { isParsedDomain } from 'src/modules/contact-creation-manager/types/is-psl-parsed-domain.type';
return sld ? capitalize(sld) : '';
export const getCompanyNameFromDomainName = (domainName: string) => {
const result = psl.parse(domainName);
if (!isParsedDomain(result)) {
return '';
}
return result.sld ? capitalize(result.sld) : '';
};

View File

@ -1,10 +1,15 @@
// @ts-expect-error legacy noImplicitAny
import psl from 'psl';
import { isParsedDomain } from 'src/modules/contact-creation-manager/types/is-psl-parsed-domain.type';
export const getDomainNameFromHandle = (handle: string): string => {
const wholeDomain = handle?.split('@')?.[1] || '';
const { domain } = psl.parse(wholeDomain);
const result = psl.parse(wholeDomain);
return domain || '';
if (!isParsedDomain(result)) {
return '';
}
return result.domain ?? '';
};