Skip to content

Commit

Permalink
Merge pull request #244 from zxcvbn-ts/feat!/change-usage-of-library
Browse files Browse the repository at this point in the history
Change usage of library
  • Loading branch information
MrWook authored Jan 17, 2024
2 parents 6e083d5 + 02824b7 commit 4633c79
Show file tree
Hide file tree
Showing 85 changed files with 882 additions and 644 deletions.
8 changes: 4 additions & 4 deletions data-scripts/_generators/PasswordGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import sprintfClass from 'sprintf-js'
import { MatchExtended } from '@zxcvbn-ts/core/src/types'
import Matching from '../../packages/libraries/main/src/Matching'
import estimateGuesses from '../../packages/libraries/main/src/scoring/estimate'
import { zxcvbnOptions } from '../../packages/libraries/main/src/Options'
import Options from '../../packages/libraries/main/src/Options'

const CUTOFF = 10
const BATCH_SIZE = 1000000

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { sprintf } = sprintfClass

zxcvbnOptions.setOptions()
const matching = new Matching()
const zxcvbnOptions = new Options()
const matching = new Matching(zxcvbnOptions)

interface Counts {
[key: string]: number
Expand Down Expand Up @@ -49,7 +49,7 @@ export default class PasswordGenerator {

// eslint-disable-next-line no-restricted-syntax
for (const match of matches) {
if (estimateGuesses(match, password).guesses < xatoRank) {
if (estimateGuesses(zxcvbnOptions, match, password).guesses < xatoRank) {
return false
}
}
Expand Down
11 changes: 5 additions & 6 deletions docs/.vuepress/components/Comparison.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
</template>

<script>
import {
zxcvbnAsync as zxcvbnTsAsync,
zxcvbnOptions,
} from '../../../packages/libraries/main/dist/index.esm'
import { ZxcvbnFactory } from '../../../packages/libraries/main/dist/index.esm'
import * as zxcvbnCommonPackage from '../../../packages/languages/common/dist/index.esm'
import * as zxcvbnEnPackage from '../../../packages/languages/en/dist/index.esm'
import zxcvbn from 'zxcvbn'
Expand Down Expand Up @@ -78,6 +75,7 @@ export default {
],
data: [],
loading: true,
zxcvbn: null,
}
},
async mounted() {
Expand All @@ -94,14 +92,15 @@ export default {
graphs: zxcvbnCommonPackage.adjacencyGraphs,
useLevenshteinDistance: true,
}
zxcvbnOptions.setOptions(options)
this.zxcvbn = new ZxcvbnFactory(options)
},
async setData() {
this.loading = true
await this.$nextTick()
for (const password of this.passwords) {
const zxcvbnResult = zxcvbn(password)
const zxcvbnTsResult = await zxcvbnTsAsync(password)
const zxcvbnTsResult = await this.zxcvbn.checkAsync(password)
console.log(zxcvbnResult, zxcvbnTsResult)
this.data.push({
password: password,
Expand Down
27 changes: 14 additions & 13 deletions docs/.vuepress/components/ZxcvbnInteractive.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@
<script>
import crossFetch from 'cross-fetch'
import {
zxcvbnAsync,
zxcvbnOptions,
ZxcvbnFactory,
debounce,
} from '../../../packages/libraries/main/dist/index.esm'
import * as zxcvbnCommonPackage from '../../../packages/languages/common/dist/index.esm'
import * as zxcvbnEnPackage from '../../../packages/languages/en/dist/index.esm'
import translationKeys from '../../../packages/libraries/main/dist/data/translationKeys.esm'
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'
const matcherPwned = matcherPwnedFactory(crossFetch)
export default {
name: 'ZxcvbnInteractive',
data() {
Expand All @@ -89,17 +89,17 @@ export default {
useLevenshteinDistance: true,
debounce: debounce(this.useZxcvbn, 200),
userInputs: '',
zxcvbn: null,
}
},
mounted() {
this.setOptions()
this.addPwnedMatcher()
this.setOptions(true)
},
methods: {
setResult(result) {
this.result = result
},
setOptions() {
setOptions(hasPwnedMatcher = false) {
const options = {
dictionary: {},
translations: translationKeys,
Expand All @@ -118,21 +118,22 @@ export default {
if (this.useGraphs) {
options.graphs = zxcvbnCommonPackage.adjacencyGraphs
}
zxcvbnOptions.setOptions(options)
const customMatcher = {}
if (hasPwnedMatcher) {
customMatcher.pwned = matcherPwned
}
this.zxcvbn = new ZxcvbnFactory(options, customMatcher)
},
async useZxcvbn() {
if (this.password) {
const userInputs = this.userInputs.split(',')
this.result = await zxcvbnAsync(this.password, userInputs)
this.result = await this.zxcvbn.checkAsync(this.password, userInputs)
} else {
this.result = null
}
console.log(this.result)
},
addPwnedMatcher() {
const matcherPwned = matcherPwnedFactory(crossFetch, zxcvbnOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)
},
},
watch: {
password() {
Expand Down Expand Up @@ -161,9 +162,9 @@ export default {
usePwned(newValue) {
this.password = ''
if (newValue) {
this.addPwnedMatcher()
this.setOptions(true)
} else {
delete zxcvbnOptions.matchers.pwned
this.setOptions()
}
},
},
Expand Down
85 changes: 29 additions & 56 deletions docs/guide/framework-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ Those examples are using the full feature set of zxcvbn, and are marked with `re
Use a plugin to only update the options once

```ts
import { zxcvbnOptions } from '@zxcvbn-ts/core'
import { ZxcvbnFactory } from '@zxcvbn-ts/core'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'
import * as zxcvbnDePackage from '@zxcvbn-ts/language-de'
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'

const myPlugin = {
install() {
install(Vue) {
// optional
const matcherPwned = matcherPwnedFactory(fetch, zxcvbnOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)
const matcherPwned = matcherPwnedFactory(fetch)
const customMatcher = {
pwned: matcherPwned
}

const options = {
// recommended
Expand All @@ -34,7 +36,8 @@ const myPlugin = {
// optional
translations: zxcvbnEnPackage.translations,
}
zxcvbnOptions.setOptions(options)

Vue.prototype.$zxcvbn = new ZxcvbnFactory(options, customMatcher)
},
}
```
Expand All @@ -53,7 +56,7 @@ const myPlugin = {
</template>
<script>
import { zxcvbn, debounce } from '@zxcvbn-ts/core'
import { debounce } from '@zxcvbn-ts/core'
export default {
name: 'ZxcvbnInput',
Expand All @@ -71,7 +74,7 @@ export default {
},
async useZxcvbn() {
if (this.password) {
this.result = await zxcvbn(this.password)
this.result = await this.$zxcvbn.checkAsync(this.password)
} else {
this.result = null
}
Expand All @@ -91,52 +94,21 @@ export default {
Use a module to define the options on the server side or/and a client only plugin for the client.
Most of the time you don't need to add the module because the user works only on the client and doesn't type passwords for the server renderer.

/modules/zxcvbn.ts

```ts
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'
import { zxcvbnOptions } from '@zxcvbn-ts/core'
import { OptionsType } from '@zxcvbn-ts/core/dist/types'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'
import { ModuleOptions, Nuxt } from '@nuxt/schema'

export default function zxcvbnModule(moduleOptions: ModuleOptions, nuxt: Nuxt) {
nuxt.hook('ready', async () => {
const matcherPwned = matcherPwnedFactory(fetch, zxcvbnOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)

const options: OptionsType = {
// recommended
dictionary: {
...zxcvbnCommonPackage.dictionary,
...zxcvbnEnPackage.dictionary,
},
// recommended
graphs: zxcvbnCommonPackage.adjacencyGraphs,
// recommended
useLevenshteinDistance: true,
// optional
translations: zxcvbnEnPackage.translations,
}
zxcvbnOptions.setOptions(options)
})
}
```

/plugins/zxcvbn.ts

```ts
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'
import { zxcvbnOptions } from '@zxcvbn-ts/core'
import { ZxcvbnFactory } from '@zxcvbn-ts/core'
import { OptionsType } from '@zxcvbn-ts/core/dist/types'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'
import { ModuleOptions, Nuxt } from '@nuxt/schema'

export default defineNuxtPlugin(() => {
const matcherPwned = matcherPwnedFactory(fetch, zxcvbnOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)
export default defineNuxtPlugin(({app}, inject) => {
const matcherPwned = matcherPwnedFactory(fetch)
const customMatcher = {
pwned: matcherPwned
}

const options: OptionsType = {
// recommended
Expand All @@ -151,7 +123,8 @@ export default defineNuxtPlugin(() => {
// optional
translations: zxcvbnEnPackage.translations,
}
zxcvbnOptions.setOptions(options)

inject('zxcvbn', new ZxcvbnFactory(options, customMatcher))
})
```

Expand All @@ -161,8 +134,6 @@ nuxt.config.ts
export default defineNuxtConfig({
// add plugin for client only to load the options on the client side
plugins: [{ src: '~/plugins/zxcvbn.ts', mode: 'client' }],
// add module to load the options once for server side
modules: ['~/modules/zxcvbn.ts'],
build: {
// add if needed for your setup
transpile: ['@zxcvbn-ts/matcher-pwned'],
Expand All @@ -186,15 +157,15 @@ ZxcvbnInput.vue
</template>
<script lang="ts" setup>
import { zxcvbnAsync, debounce, ZxcvbnResult } from '@zxcvbn-ts/core'
import { debounce, ZxcvbnResult } from '@zxcvbn-ts/core'
import { Ref, watch } from '@vue/runtime-core'
let password = ref()
let result: Ref<ZxcvbnResult | null> = ref(null)
const useZxcvbn = async () => {
if (password) {
result.value = await zxcvbnAsync(password.value)
result.value = await this.$zxcvbn.checkAsync(password.value)
} else {
result.value = null
}
Expand All @@ -210,16 +181,12 @@ watch(password, zxcvbnDebounce)

```jsx
import { useState, useEffect, useDeferredValue } from 'react'
import { zxcvbnOptions, zxcvbnAsync, ZxcvbnResult } from '@zxcvbn-ts/core'
import { ZxcvbnFactory, ZxcvbnResult } from '@zxcvbn-ts/core'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'
import * as zxcvbnDePackage from '@zxcvbn-ts/language-de'
import { matcherPwnedFactory } from '@zxcvbn-ts/matcher-pwned'

// optional
const matcherPwned = matcherPwnedFactory(fetch, zxcvbnOptions)
zxcvbnOptions.addMatcher('pwned', matcherPwned)

const options = {
// recommended
dictionary: {
Expand All @@ -235,15 +202,21 @@ const options = {
// optional
translations: zxcvbnEnPackage.translations,
}
zxcvbnOptions.setOptions(options)

// optional
const matcherPwned = matcherPwnedFactory(fetch)
const customMatcher = {
pwned: matcherPwned
}
const zxcvbn = new ZxcvbnFactory(options, customMatcher)

const usePasswordStrength = (password: string) => {
const [result, setResult] = (useState < ZxcvbnResult) | (null > null)
// NOTE: useDeferredValue is React v18 only, for v17 or lower use debouncing
const deferredPassword = useDeferredValue(password)

useEffect(() => {
zxcvbnAsync(deferredPassword).then((response) => setResult(response))
zxcvbn.checkAsync(deferredPassword).then((response) => setResult(response))
}, [deferredPassword])

return result
Expand Down
13 changes: 7 additions & 6 deletions docs/guide/getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
### Bundler like webpack

```js
import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core'
import { ZxcvbnFactory } from '@zxcvbn-ts/core'
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common'
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en'

Expand All @@ -29,9 +29,8 @@ const options = {
},
}

zxcvbnOptions.setOptions(options)

zxcvbn(password)
const zxcvbn = new ZxcvbnFactory(options)
zxcvbn.check(password)
```

### As script tag
Expand All @@ -57,8 +56,10 @@ Example using jsdelivr (a CDN)
...zxcvbnts['language-en'].dictionary,
},
}
zxcvbnts.core.zxcvbnOptions.setOptions(options)
console.log(zxcvbnts.core.zxcvbn('somePassword'))
const zxcvbn = new zxcvbnts.core.ZxcvbnFactory(options)
const results = zxcvbn.check('somePassword')
console.log(results)
})()
</script>
</body>
Expand Down
Loading

0 comments on commit 4633c79

Please sign in to comment.