NanoID 3.4.0.2 → 3.4.1
raw patch · 7 files changed
+152/−137 lines, 7 filesdep +bytestring-encodingsdep ~mwc-randomPVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring-encodings
Dependency ranges changed: mwc-random
API changes (from Hackage documentation)
Files
- LICENSE +1/−1
- NanoID.cabal +23/−12
- ReadMe.md +2/−2
- app/Main.hs +17/−13
- app/Options.hs +3/−3
- lib/Data/NanoID.hs +0/−106
- src/Data/NanoID.hs +106/−0
LICENSE view
@@ -1,4 +1,4 @@-NanoID, lib & app, Copyright (c) 2021-2024, Michel Boucey+NanoID, lib & app, Copyright (c) 2021-2025, Michel Boucey All rights reserved.
NanoID.cabal view
@@ -1,44 +1,55 @@ name: NanoID-version: 3.4.0.2+version: 3.4.1 synopsis: NanoID generator description: Library and CLI tool for NanoID generation license: BSD3 license-file: LICENSE author: Michel Boucey maintainer: michel.boucey@gmail.com-copyright: (c) 2021-2024 - Michel Boucey-category: Data+copyright: (c) 2021-2025 - Michel Boucey+category: Random, Data build-type: Simple cabal-version: >=1.10 extra-source-files: ReadMe.md -Tested-With: GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.5 || ==9.8.2+Tested-With:+ GHC ==8.8.4+ || ==8.10.7+ || ==9.0.2+ || ==9.2.8+ || ==9.4.8+ || ==9.6.7+ || ==9.8.4+ || ==9.10.2+ || ==9.12.2 source-repository head type: git location: https://github.com/MichelBoucey/NanoID.git library+ hs-source-dirs: src+ default-language: Haskell2010 exposed-modules: Data.NanoID build-depends: aeson >= 1.5.6 && < 1.6 || >= 2.0 && < 2.3- , base >= 4.7 && < 4.20+ , base >= 4.7 && < 5 , bytestring >= 0.10 && < 0.13 , cereal >= 0.5.8 && < 0.5.9- , extra >= 1.6 && < 1.8- , mwc-random >= 0.13 && < 0.16+ , extra >= 1.6 && < 1.9+ , mwc-random > 0.15 && < 0.16 , text >= 1.2.3 && < 2.2- hs-source-dirs: lib- default-language: Haskell2010 executable nanoid+ hs-source-dirs: app main-is: Main.hs+ default-language: Haskell2010+ GHC-Options: -Wall -O2 other-modules: Options Paths_NanoID- build-depends: base >= 4.7 && < 4.20+ build-depends: base >= 4.7 && < 5 , bytestring >= 0.10 && < 0.13 , mwc-random >= 0.13 && < 0.16 , NanoID , optparse-applicative >= 0.14 && < 0.19- hs-source-dirs: app- default-language: Haskell2010+ , bytestring-encodings >= 0.2 && < 1
ReadMe.md view
@@ -1,8 +1,8 @@-# NanoID generator, library and CLI tool +# NanoID generator, library and CLI  [](https://hackage.haskell.org/package/NanoID) ``` [user@box ~] $ nanoid -h-nanoid v3.4.0.2, (c) Michel Boucey 2022-2024+nanoid v3.4.1, (c) Michel Boucey 2022-2025 Usage: nanoid [-a|--alphabet ARG] [-l|--length ARG] [-p|--password] [-q|--quantity ARG] [-n|--newline] [-v|--version]
app/Main.hs view
@@ -1,15 +1,17 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RecordWildCards #-} import Control.Monad #if !MIN_VERSION_base(4,11,0)-import Data.Monoid ((<>))+import Data.Monoid ((<>)) #endif -import qualified Data.ByteString.Char8 as C-import Data.Either+import qualified Data.ByteString.Char8 as C+import Data.ByteString.Internal.Ascii import Options.Applicative+import Prelude hiding (length) import System.Exit import System.Random.MWC @@ -26,17 +28,19 @@ else if quantity < 1 then strFail "quantity" else do- let alphabet' =- if password- then specialPassword- else toAlphabet alphabet- replicateM_ quantity $- createSystemRandom- >>= customNanoID alphabet' (toEnum length)- >>= putNanoID newline- exitSuccess+ let mAlphabet =+ if | password -> Just specialPassword+ | alphabet == unAlphabet defaultAlphabet -> Just defaultAlphabet+ | isAscii alphabet -> Just (Alphabet alphabet)+ | otherwise -> Nothing+ case mAlphabet of+ Just a -> do+ replicateM_ quantity $+ createSystemRandom >>= customNanoID a (toEnum length) >>= putNanoID newline+ exitSuccess+ Nothing -> strFail "alphabet that is not made of ascii chars only" where strFail m = putStrLn ("Bad " <> m <> ". See help (-h).") >> exitFailure putNanoID nl = put nl . unNanoID- where put nl = if nl then C.putStrLn else C.putStr+ where put nl' = if nl' then C.putStrLn else C.putStr
app/Options.hs view
@@ -15,7 +15,7 @@ data Options = Options- { alphabet :: String+ { alphabet :: C.ByteString , length :: Int , password :: Bool , quantity :: Int@@ -29,7 +29,7 @@ <> progDesc "NanoID generator" <> header ( "nanoid " <> showVer- <> ", (c) Michel Boucey 2022-2023" ) )+ <> ", (c) Michel Boucey 2022-2025" ) ) options :: Parser Options options =@@ -39,7 +39,7 @@ ( short 'a' <> long "alphabet" <> help "Use an alternative alphabet (ascii chars only)"- <> value (C.unpack $ unAlphabet defaultAlphabet) )+ <> value (unAlphabet defaultAlphabet)) <*> option auto ( short 'l'
− lib/Data/NanoID.hs
@@ -1,106 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-}--module Data.NanoID where--import Control.Monad-import Data.Aeson-import qualified Data.ByteString.Char8 as C-import Data.Maybe--#if !MIN_VERSION_base(4,11,0)-import Data.Monoid ((<>))-#endif--import Data.Serialize (Serialize)-import Data.Text.Encoding-import GHC.Generics-import Numeric.Natural-import System.Random.MWC--newtype NanoID =- NanoID { unNanoID :: C.ByteString }- deriving (Eq, Generic)--newtype Alphabet =- Alphabet { unAlphabet :: C.ByteString }- deriving (Eq)--type Length = Natural--instance Show NanoID where- show = C.unpack . unNanoID--instance Show Alphabet where- show = C.unpack . unAlphabet--instance ToJSON NanoID where- toJSON n = String (decodeUtf8 $ unNanoID n)--instance FromJSON NanoID where- parseJSON (String s) = pure (NanoID $ encodeUtf8 s)- parseJSON _ = fail "A JSON String is expected to convert to NanoID"--instance Serialize NanoID---- | Create a new 'Alphabet' from a string of symbols of your choice-toAlphabet :: String -> Alphabet-toAlphabet = Alphabet . C.pack---- | Standard 'NanoID' generator function------ >λ: createSystemRandom >>= nanoID--- >x2f8yFadIm-Vp14ByJ8R3----nanoID :: GenIO -> IO NanoID-nanoID = customNanoID defaultAlphabet 21---- | Customable 'NanoID' generator function-customNanoID- :: Alphabet -- ^ An 'Alphabet' of your choice- -> Length -- ^ A 'NanoID' length (the standard length is 21 chars)- -> GenIO -- ^ The pseudo-random number generator state- -> IO NanoID-customNanoID a l g =- let- ua = unAlphabet a- al = C.length ua- l' = fromEnum l- in- NanoID . C.pack <$> replicateM l' ((\r -> C.index ua (r-1)) <$> uniformR (1,al) g)---- | The default 'Alphabet', made of URL-friendly symbols.-defaultAlphabet :: Alphabet-defaultAlphabet = toAlphabet "ABCDEFGHIJKLMNOPKRSTUVWXYZ_1234567890-abcdefghijklmnopqrstuvwxyz"---- * Some predefined 'Alphabet's, borrowed from https://github.com/CyberAP/nanoid-dictionary--numbers :: Alphabet-numbers = toAlphabet "1234567890"--hexadecimalLowercase :: Alphabet-hexadecimalLowercase = toAlphabet "0123456789abcdef"--hexadecimalUppercase :: Alphabet-hexadecimalUppercase = toAlphabet "0123456789ABCDEF"--lowercase :: Alphabet-lowercase = toAlphabet "abcdefghijklmnopqrstuvwxyz"--uppercase :: Alphabet-uppercase = toAlphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ"--alphanumeric :: Alphabet-alphanumeric = toAlphabet "ABCDEFGHIJKLMNOPKRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"--nolookalikes :: Alphabet-nolookalikes = toAlphabet "346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtwxyz"--nolookalikesSafe :: Alphabet-nolookalikesSafe = toAlphabet "6789ABCDEFGHJKLMNPQRTUWYabcdefghijkmnpqrtwyz"---- * Special password--specialPassword :: Alphabet-specialPassword = toAlphabet "67{8_9A!B>CDEF)GH=JKL(MNPQ%RTU]W.Ya@bc%def&g[hij}k<m#-npq:r+twyz"-
+ src/Data/NanoID.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}++module Data.NanoID where++import Control.Monad+import Data.Aeson+import qualified Data.ByteString.Char8 as C+import Data.Maybe++#if !MIN_VERSION_base(4,11,0)+import Data.Monoid ((<>))+#endif++import Data.Serialize (Serialize)+import Data.Text.Encoding+import GHC.Generics+import Numeric.Natural+import System.Random.MWC++newtype NanoID =+ NanoID { unNanoID :: C.ByteString }+ deriving (Eq, Generic)++newtype Alphabet =+ Alphabet { unAlphabet :: C.ByteString }+ deriving (Eq)++type Length = Natural++instance Show NanoID where+ show = C.unpack . unNanoID++instance Show Alphabet where+ show = C.unpack . unAlphabet++instance ToJSON NanoID where+ toJSON n = String (decodeUtf8 $ unNanoID n)++instance FromJSON NanoID where+ parseJSON (String s) = pure (NanoID $ encodeUtf8 s)+ parseJSON _ = fail "A JSON String is expected to convert to NanoID"++instance Serialize NanoID++-- | Create a new 'Alphabet' from a string of symbols of your choice+toAlphabet :: String -> Alphabet+toAlphabet = Alphabet . C.pack++-- | Standard 'NanoID' generator function+--+-- >λ: createSystemRandom >>= nanoID+-- >x2f8yFadIm-Vp14ByJ8R3+--+nanoID :: GenIO -> IO NanoID+nanoID = customNanoID defaultAlphabet 21++-- | Customable 'NanoID' generator function+customNanoID+ :: Alphabet -- ^ An 'Alphabet' of your choice+ -> Length -- ^ A 'NanoID' length (the standard length is 21 chars)+ -> GenIO -- ^ The pseudo-random number generator state+ -> IO NanoID+customNanoID a l g =+ let+ ua = unAlphabet a+ al = C.length ua+ l' = fromEnum l+ in+ NanoID . C.pack <$> replicateM l' ((\r -> C.index ua (r-1)) <$> uniformR (1,al) g)++-- | The default 'Alphabet', made of URL-friendly symbols.+defaultAlphabet :: Alphabet+defaultAlphabet = toAlphabet "ABCDEFGHIJKLMNOPKRSTUVWXYZ_1234567890-abcdefghijklmnopqrstuvwxyz"++-- * Some predefined 'Alphabet's, borrowed from https://github.com/CyberAP/nanoid-dictionary++numbers :: Alphabet+numbers = toAlphabet "1234567890"++hexadecimalLowercase :: Alphabet+hexadecimalLowercase = toAlphabet "0123456789abcdef"++hexadecimalUppercase :: Alphabet+hexadecimalUppercase = toAlphabet "0123456789ABCDEF"++lowercase :: Alphabet+lowercase = toAlphabet "abcdefghijklmnopqrstuvwxyz"++uppercase :: Alphabet+uppercase = toAlphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ"++alphanumeric :: Alphabet+alphanumeric = toAlphabet "ABCDEFGHIJKLMNOPKRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"++nolookalikes :: Alphabet+nolookalikes = toAlphabet "346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtwxyz"++nolookalikesSafe :: Alphabet+nolookalikesSafe = toAlphabet "6789ABCDEFGHJKLMNPQRTUWYabcdefghijkmnpqrtwyz"++-- * Special password++specialPassword :: Alphabet+specialPassword = toAlphabet "67{8_9A!B>CDEF)GH=JKL(MNPQ%RTU]W.Ya@bc%def&g[hij}k<m#-npq:r+twyz"+