Skip to content

Commit

Permalink
fix: add domain parser hook and domain condition (#5413)
Browse files Browse the repository at this point in the history
* fix: add domain parser hook and domain condition

* fix: spell check error icann

* fix: add validate rule for domain field
  • Loading branch information
jainpawan21 authored Apr 16, 2024
1 parent f415bcf commit ac51cce
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@
"Vonage",
"runtimes",
"cafebabe",
"Icann",
"limitbar",
],
"flagWords": [],
Expand Down
15 changes: 11 additions & 4 deletions apps/web/src/pages/auth/components/QuestionnaireForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { JobTitleEnum, jobTitleToLabelMapper, ProductUseCasesEnum } from '@novu/
import type { ProductUseCases, IResponseError, ICreateOrganizationDto, IJwtPayload } from '@novu/shared';
import {
Button,
colors,
Digest,
HalfClock,
Input,
Expand All @@ -27,18 +26,21 @@ import { ROUTES } from '../../../constants/routes.enum';
import { DynamicCheckBox } from './dynamic-checkbox/DynamicCheckBox';
import styled from '@emotion/styled/macro';
import { OnboardingExperimentV2ModalKey } from '../../../constants/experimentsConstants';
import { useDomainParser } from './useDomainHook';

export function QuestionnaireForm() {
const [loading, setLoading] = useState<boolean>();
const {
handleSubmit,
formState: { errors },
control,
setError,
} = useForm<IOrganizationCreateForm>({});
const navigate = useNavigate();
const { setToken, token } = useAuthContext();
const { startVercelSetup } = useVercelIntegration();
const { isFromVercel } = useVercelParams();
const { parse } = useDomainParser();

const { mutateAsync: createOrganizationMutation } = useMutation<
{ _id: string },
Expand Down Expand Up @@ -162,9 +164,14 @@ export function QuestionnaireForm() {
name="domain"
control={control}
rules={{
pattern: {
value: /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/,
message: 'Please make sure you specified a valid domain',
validate: {
isValiDomain: (value) => {
const val = parse(value as string);

if (value && !val.isIcann) {
return 'Please provide a valid domain';
}
},
},
}}
render={({ field }) => {
Expand Down
62 changes: 62 additions & 0 deletions apps/web/src/pages/auth/components/useDomainHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useCallback, useEffect, useRef } from 'react';

interface DomainInfo {
domain: string;
domainWithoutSuffix: string;
hostname: string;
isIcann: boolean;
isIp: boolean;
isPrivate: boolean;
publicSuffix: string;
subdomain: string;
}

function stripProtocol(url: string): string {
return (url || '').replace(/(https?)?(:\/+)?/, '');
}

function fallbackParser(url: string) {
const parts = stripProtocol(url).split('.');

if (parts.length > 2) {
const [subdomain, ...domainParts] = parts;

return {
subdomain: subdomain || '',
domain: domainParts.join('.'),
};
}

return {
subdomain: '',
domain: url,
};
}

export function useDomainParser(): { parse: (url: string) => Partial<DomainInfo> } {
const tldParser = useRef(null);

useEffect(() => {
import(
/* webpackIgnore: true */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
'https://unpkg.com/tldts/dist/es6/index.js?module'
)
.then((mod) => (tldParser.current = mod))
.catch(() => (tldParser.current = null));
}, []);

const parse = useCallback((url: string) => {
url = stripProtocol(url);

if (tldParser.current) {
return (tldParser.current as any).parse(url, { allowPrivateDomains: true }) as DomainInfo;
}

return fallbackParser(url);
}, []);

return { parse };
}

0 comments on commit ac51cce

Please sign in to comment.