Skip to content

Commit

Permalink
refactor: use MatcherNames const for setting up custom matchers
Browse files Browse the repository at this point in the history
  • Loading branch information
kobi-carmeli-payu-gpo committed Dec 2, 2024
1 parent fd9a877 commit 5e4d755
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 73 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ import {
uppercaseMatcher,
minLengthMatcher,
maxLengthMatcher,
customMatchersTranslations
MatchersTranslations,
MatcherNames
} from 'zxcvbn-custom-matchers';
import { merge } from 'lodash';

// Add the custom matchers and their translations
const options = {
translations: merge({}, zxcvbnEnPackage.translations, customMatchersTranslations)
translations: merge({}, zxcvbnEnPackage.translations, MatchersTranslations)
};
const customMatchers = {
minLength: minLengthMatcher(MIN_PASSWORD_LENGTH),
maxLength: maxLengthMatcher(MAX_PASSWORD_LENGTH),
specialRequired: specialMatcher,
numberRequired: numberMatcher,
lowercaseRequired: lowercaseMatcher,
uppercaseRequired: uppercaseMatcher
[MatcherNames.minLengh]: minLengthMatcher(MIN_PASSWORD_LENGTH),
[MatcherNames.maxLength]: maxLengthMatcher(MAX_PASSWORD_LENGTH),
[MatcherNames.special]: specialMatcher,
[MatcherNames.numberRequired]: numberMatcher,
[MatcherNames.lowercase]: lowercaseMatcher,
[MatcherNames.uppercase]: uppercaseMatcher
};
const zxcvbn = new ZxcvbnFactory(options, customMatchers);

Expand Down
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export { maxLengthMatcher } from './matchers/maxLengthMatcher';
export { uppercaseMatcher } from './matchers/uppercaseMatcher';
export { lowercaseMatcher } from './matchers/lowercaseMatcher';
export { numberMatcher } from './matchers/numberMatcher';
export { specialMatcher } from './matchers/specialMatcher';
export { customMatchersTranslations } from './translations';
export { specialMatcher } from './matchers/specialCharMatcher';
export { MatchersTranslations } from './translations';
export { MatcherNames } from './matcherNames';
8 changes: 8 additions & 0 deletions src/matcherNames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const MatcherNames = {
lowercase: 'lowercase',
uppercase: 'uppercase',
number: 'number',
specialChar: 'specialChar',
minLength: 'minLength',
maxLength: 'maxLength',
};
8 changes: 5 additions & 3 deletions src/matchers/lowercaseMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.lowercase;
export const lowercaseMatcher: Matcher = {
Matching: class LowercaseMatcher {
match({ password }: { password: string }): Match[] {
Expand All @@ -9,14 +11,14 @@ export const lowercaseMatcher: Matcher = {
return matches;
}
}
matches.push({ pattern: 'lowercaseRequired', token: password, i: 0, j: password.length - 1 });
matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['lowercaseRequired'] || 'lowercaseRequired',
suggestions: [options.translations.suggestions['lowercaseRequired'] || 'lowercaseRequired'],
warning: options.translations.warnings[matcher] || matcher,
suggestions: [options.translations.suggestions[matcher] || matcher],
};
},
scoring() {
Expand Down
8 changes: 5 additions & 3 deletions src/matchers/maxLengthMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.maxLength;
export const maxLengthMatcher = (maxLength: number): Matcher => ({
Matching: class MaxLengthMatcher {
match({ password }: { password: string }): Match[] {
const matches: Match[] = [];
if (password.length > maxLength) {
matches.push({ pattern: 'maxLength', token: password, i: 0, j: password.length - 1 });
matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
}
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['maxLength']?.replace('%s', maxLength) || 'maxLength',
suggestions: [options.translations.suggestions['maxLength']?.replace('%s', maxLength) || 'maxLength'],
warning: options.translations.warnings[matcher]?.replace('%s', maxLength) || matcher,
suggestions: [options.translations.suggestions[matcher]?.replace('%s', maxLength) || matcher],
};
},
scoring() {
Expand Down
8 changes: 5 additions & 3 deletions src/matchers/minLengthMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.minLength;
export const minLengthMatcher = (minLength: number): Matcher => ({
Matching: class MinLengthMatcher {
match({ password }: { password: string }): Match[] {
const matches: Match[] = [];
if (password.length < minLength) {
matches.push({ pattern: 'minLength', token: password, i: 0, j: password.length - 1 });
matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
}
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['minLength']?.replace('%s', minLength) || 'minLength',
suggestions: [options.translations.suggestions['minLength']?.replace('%s', minLength) || 'minLength'],
warning: options.translations.warnings[matcher]?.replace('%s', minLength) || matcher,
suggestions: [options.translations.suggestions[matcher]?.replace('%s', minLength) || matcher],
};
},
scoring() {
Expand Down
8 changes: 5 additions & 3 deletions src/matchers/numberMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.number;
export const numberMatcher: Matcher = {
Matching: class NumberMatcher {
match({ password }: { password: string }): Match[] {
Expand All @@ -9,14 +11,14 @@ export const numberMatcher: Matcher = {
return matches;
}
}
matches.push({ pattern: 'numberRequired', token: password, i: 0, j: password.length - 1 });
matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['numberRequired'] || 'numberRequired',
suggestions: [options.translations.suggestions['numberRequired'] || 'numberRequired'],
warning: options.translations.warnings[matcher] || matcher,
suggestions: [options.translations.suggestions[matcher] || matcher],
};
},
scoring() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.specialChar;
export const specialMatcher: Matcher = {
Matching: class SpecialMatcher {
match({ password }: { password: string }): Match[] {
Expand All @@ -10,14 +12,14 @@ export const specialMatcher: Matcher = {
return matches;
}
}
matches.push({ pattern: 'specialRequired', token: password, i: 0, j: password.length - 1 });
matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['specialRequired'] || 'specialRequired',
suggestions: [options.translations.suggestions['specialRequired'] || 'specialRequired'],
warning: options.translations.warnings[matcher] || matcher,
suggestions: [options.translations.suggestions[matcher] || matcher],
};
},
scoring() {
Expand Down
9 changes: 6 additions & 3 deletions src/matchers/uppercaseMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Matcher, Match } from '@zxcvbn-ts/core';
import { MatcherNames } from '../matcherNames';

const matcher = MatcherNames.uppercase;
export const uppercaseMatcher: Matcher = {
Matching: class UppercaseMatcher {
match({ password }: { password: string }): Match[] {
Expand All @@ -9,14 +11,15 @@ export const uppercaseMatcher: Matcher = {
return matches;
}
}
matches.push({ pattern: 'uppercaseRequired', token: password, i: 0, j: password.length - 1 });

matches.push({ pattern: matcher, token: password, i: 0, j: password.length - 1 });
return matches;
}
},
feedback: options => {
return {
warning: options.translations.warnings['uppercaseRequired'] || 'uppercaseRequired',
suggestions: [options.translations.suggestions['uppercaseRequired'] || 'uppercaseRequired'],
warning: options.translations.warnings[matcher] || matcher,
suggestions: [options.translations.suggestions[matcher] || matcher],
};
},
scoring() {
Expand Down
29 changes: 16 additions & 13 deletions src/translations.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
export const customMatchersTranslations = {
// translations.ts
import { MatcherNames } from './matcherNames';

export const MatchersTranslations = {
warnings: {
lowercaseRequired: 'At least one lowercase letter is required.',
minLength: 'Password must be at least %s characters long.',
maxLength: 'Password must be no more than %s characters long.',
numberRequired: 'At least one number is required.',
specialRequired: 'At least one special character is required.',
uppercaseRequired: 'At least one uppercase letter is required.',
[MatcherNames.lowercase]: 'At least one lowercase letter is required.',
[MatcherNames.minLength]: 'Password must be at least %s characters long.',
[MatcherNames.maxLength]: 'Password must be no more than %s characters long.',
[MatcherNames.number]: 'At least one number is required.',
[MatcherNames.specialChar]: 'At least one special character is required.',
[MatcherNames.uppercase]: 'At least one uppercase letter is required.',
},
suggestions: {
lowercaseRequired: 'Include at least one lowercase letter.',
minLength: 'Make your password at least %s characters long.',
maxLength: 'Reduce your password to no more than %s characters.',
numberRequired: 'Include at least one number.',
specialRequired: 'Include at least one special character.',
uppercaseRequired: 'Include at least one uppercase letter.',
[MatcherNames.lowercase]: 'Include at least one lowercase letter.',
[MatcherNames.minLength]: 'Make your password at least %s characters long.',
[MatcherNames.maxLength]: 'Reduce your password to no more than %s characters.',
[MatcherNames.number]: 'Include at least one number.',
[MatcherNames.specialChar]: 'Include at least one special character.',
[MatcherNames.uppercase]: 'Include at least one uppercase letter.',
},
timeEstimation: {},
};
Loading

0 comments on commit 5e4d755

Please sign in to comment.