Migration Guide
This guide provides information on how to migrate between different versions of zxcvbn-ts.
Table of Contents
- 3.x.x to 4.x.x
- 2.x.x to 3.x.x
- 1.2.x to 2.x.x
- 0.3.x to 1.x.x
- 0.2.x to 0.3.x
- zxcvbn 4.4.2 to zxcvbn-ts 4.x.x
3.x.x to 4.x.x
Move from singleton options to class-based approach
The previous singleton-based approach (zxcvbnOptions.setOptions) has been replaced by a class-based approach using ZxcvbnFactory. This allows for multiple instances with different configurations.
NOTE: The top-level zxcvbn and zxcvbnAsync functions have been removed.
Old (3.x.x):
zxcvbnOptions.setOptions(options)
zxcvbn(password)
New (4.x.x):
const zxcvbn = new ZxcvbnFactory(options, customMatcher)
// Synchronous check
const result = zxcvbn.check(password)
// Asynchronous check (required if using async matchers like pwned)
const asyncResult = await zxcvbn.checkAsync(password)
Custom matcher setup changed
Generally, options no longer need to be transferred separately. Here is an example using the pwned matcher.
Old (3.x.x):
zxcvbnOptions.setOptions(options)
const pwnedOptions = {
url: '...',
networkErrorHandler: () => {}
}
const matcherPwned = matcherPwnedFactory(crossFetch, pwnedOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)
zxcvbn(password)
New (4.x.x):
const pwnedConfig = {
url: '...',
networkErrorHandler: () => {}
}
const customMatcher = {
pwned: matcherPwnedFactory(fetch, pwnedConfig),
}
const zxcvbn = new ZxcvbnFactory(options, customMatcher)
await zxcvbn.checkAsync(password)
Scoring thresholds naming changed in the output
The output structure for crack times has been unified and renamed for better clarity.
Old (3.x.x):
{
"crackTimesSeconds": {
"offlineFastHashing1e10PerSecond": 0.1,
"offlineSlowHashing1e4PerSecond": 100
// ...
},
"crackTimesDisplay": {
"offlineFastHashing1e10PerSecond": "less than a second",
"offlineSlowHashing1e4PerSecond": "1 minute"
// ...
}
}
New (4.x.x):
{
"crackTimes": {
"onlineThrottlingXPerHour": {
"base": null,
"seconds": 3600,
"display": "1 hour"
},
"onlineNoThrottlingXPerSecond": {
"base": null,
"seconds": 1,
"display": "1 second"
},
"offlineSlowHashingXPerSecond": {
"base": null,
"seconds": 100,
"display": "1 minute"
},
"offlineFastHashingXPerSecond": {
"base": null,
"seconds": 0.1,
"display": "less than a second"
}
}
}
Language packages dictionary keys changed
The dictionary keys in the language packages have changed from generic names to language-specific names (e.g., commonWords-en instead of commonWords) to prevent collisions when using multiple languages.
Old (3.x.x):
import { dictionary } from '@zxcvbn-ts/language-en'
/*
{
commonWords: [...],
firstnames: [...],
lastnames: [...],
wikipedia: [...]
}
*/
New (4.x.x):
import { dictionary } from '@zxcvbn-ts/language-en'
/*
{
'commonWords-en': [...],
'firstnames-en': [...],
'lastnames-en': [...],
'wikipedia-en': [...]
}
*/
Additionally, language packages now export wordSequences.
Distribution files changed extension
The distribution files in the packages changed their extensions to follow Node.js ESM/CJS standards.
Old:
dist/index.js(CommonJS)dist/index.esm.js(ESM)
New:
dist/index.cjs(CommonJS)dist/index.mjs(ESM)
New commonWords source
Moved from https://github.com/hermitdave/FrequencyWords from 2018 to directly use the source https://opus.nlpl.eu/datasets/OpenSubtitles from 2024. As this is a bigger and up-to-date list, it can result in a different scoring
BEWARE The commonWords.json file had always the license ODC-BY. It was just miscommunicated inside @zxcvbn-ts but now the correct license notice was added.
New word sequence matching
We added a new matcher for word sequences. This improves the estimation for passphrases. It is included in the dictionaries.
Example:
import { dictionary } from '@zxcvbn-ts/language-en'
const options = {
// ...
dictionary: {
...dictionary
}
}
Advanced translations (pluralization)
Time estimation translations now support functions for better pluralization support. This is especially useful for languages with complex plural rules.
Example:
const translations = {
// ...
timeEstimation: {
minute: (value: number) => {
if (value === 1) return '1 Minute'
return `${value} Minuten`
},
// ...
}
}
2.x.x to 3.x.x
Language packages no longer have a default export
Old (2.x.x):
import package from '@zxcvbn-ts/language-en'
New (3.x.x):
import { dictionary, translations } from '@zxcvbn-ts/language-en'
// or
import * as enPackage from '@zxcvbn-ts/language-en'
Pwned matcher doesn't have a default export anymore
Old (2.x.x):
import matcherPwnedFactory from '@zxcvbn-ts/matcher-pwned'
New (3.x.x):
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'
1.2.x to 2.x.x
To fix typing for async and non-async matchers, we separated the logic into two functions.
- If you are using an async matcher (e.g., pwned), you must use
zxcvbnAsync. ZxcvbnOptionsexport was renamed tozxcvbnOptions.@zxcvbn-ts/matcher-pwnednow requireszxcvbnOptionsas the second parameter.
0.3.x to 1.x.x
To decrease the bundle size of the core package, keyboard layouts are now optional and customizable. You need to add them to your setOptions call to maintain recommended scoring.
import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'
const options = {
translations: zxcvbnEnPackage.translations,
dictionary: {
...zxcvbnCommonPackage.dictionary,
...zxcvbnEnPackage.dictionary,
},
// Recommended to get accurate scoring for keyboard patterns
graphs: zxcvbnCommonPackage.adjacencyGraphs,
}
zxcvbnOptions.setOptions(options)
zxcvbn(password)
0.2.x to 0.3.x
Options handling was moved out of the zxcvbn call to improve performance (see issue #31).
@zxcvbn-ts/corenow has only named exports.- Options must be set via
zxcvbnOptions.setOptions(options).
Migration from zxcvbn 4.4.2 to zxcvbn-ts 4.x.x
This guide helps you migrate from the original zxcvbn (version 4.4.2) to the modern zxcvbn-ts (version 4.x.x).
Why Migrate?
- TypeScript Support: Native type definitions for better developer experience.
- Modular Architecture: Dictionaries are separate packages, allowing you to reduce your bundle size by only including what you need.
- Internationalization (i18n): Support for multiple languages, including translations for feedback.
- Modern Standards: Uses ESM/CJS standards and is optimized for modern build tools.
- Extensibility: Easily add custom matchers or extend existing logic.
Key Differences
1. Package Installation
The original zxcvbn was a single package. zxcvbn-ts is modular. You need to install the core package and the language packages you want to use.
Old:
npm install zxcvbn
New:
npm install @zxcvbn-ts/core @zxcvbn-ts/language-common @zxcvbn-ts/language-en
2. Initialization and Usage
In zxcvbn 4.4.2, you would import a single function. In zxcvbn-ts 4.x.x, you use ZxcvbnFactory to create an instance with your desired configuration.
Old:
import zxcvbn from 'zxcvbn'
const result = zxcvbn('password')
New:
import { ZxcvbnFactory } from '@zxcvbn-ts/core'
import { adjacencyGraphs, dictionary } from '@zxcvbn-ts/language-common'
import { dictionary as enDictionary, translations } from '@zxcvbn-ts/language-en'
const options = {
translations,
graphs: adjacencyGraphs,
dictionary: {
...dictionary,
...enDictionary,
},
}
const zxcvbn = new ZxcvbnFactory(options)
const result = zxcvbn.check('password')
3. Asynchronous Matching
If you use asynchronous matchers (like the Pwned matcher), you must use the checkAsync method.
New:
const result = await zxcvbn.checkAsync('password')
4. Output Structure
The output structure is mostly compatible, but there are some changes in how crack times and feedback are handled to support internationalization and better clarity.
- Feedback:
warningandsuggestionsare now translated if you providetranslationsin options. - Crack Times: The naming has been unified under the
crackTimesobject.
Old (zxcvbn 4.4.2):
{
"crack_times_seconds": {
"online_throttling_100_per_hour": 3600,
...
},
"crack_times_display": {
"online_throttling_100_per_hour": "1 hour",
...
}
}
New (zxcvbn-ts 4.x.x):
{
"crackTimes": {
"onlineThrottlingXPerHour": {
"seconds": 3600,
"display": "1 hour",
"base": null
},
...
}
}
5. Custom Dictionaries and User Inputs
In zxcvbn 4.4.2, user inputs were passed as a second argument to the zxcvbn function. In zxcvbn-ts, they are part of the dictionary object in options, or can be passed to the check method.
Old:
zxcvbn('password', ['user', 'inputs'])
New:
// Option A: During factory creation
const options = {
dictionary: {
...baseDictionaries,
userInputs: ['user', 'inputs']
}
}
const zxcvbn = new ZxcvbnFactory(options)
zxcvbn.check('password')
// Option B: During check (on the fly)
zxcvbn.check('password', ['user', 'inputs'])
Summary Table
| Feature | zxcvbn 4.4.2 | zxcvbn-ts 4.x.x |
|---|---|---|
| Language | JavaScript | TypeScript |
| Bundle Size | Fixed (~800KB) | Modular (Core is ~25KB) |
| I18n | English only | Multi-language support |
| Async Support | No | Yes (checkAsync) |
| Setup | Import and use | Factory-based configuration |