packages feed

yarn-lock 0.4.1 → 0.5.0

raw patch · 6 files changed

+110/−29 lines, 6 files

Files

CHANGELOG.md view
@@ -5,7 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.5.0] - 2018-05-15+## [0.5.0] - 2018-06-12++### Changed++- `PackageKey`s now correctly parse scoped npm names+  - This means `Text` is now a sum of `SimplePackageKey`/`ScopedPackageKey`++### Fixed++- `PackageKey`s with versions containing `@` parse correctly+  - Like for example `git+ssh:git@github.com` links for some git packages++## [0.4.1] - 2018-05-15  ### Changed 
src/Yarn/Lock/File.hs view
@@ -95,6 +95,11 @@     text = FieldParser { parseField = either Just (const Nothing)                        , parserName = "text" } +    packageKey :: FieldParser T.PackageKeyName+    packageKey = FieldParser+      { parseField = parseField text >=> T.parsePackageKeyName+      , parserName = "package key" }+     -- | Parse a field nested one level to a list of 'PackageKey's.     keylist :: FieldParser [T.PackageKey]     keylist = FieldParser@@ -102,8 +107,9 @@       , parseField = either (const Nothing)              (\(Parse.PackageFields inner) ->                   for (M.toList inner) $ \(k, v) -> do+                    name <- parseField packageKey (Left k)                     npmVersionSpec <- parseField text v-                    pure $ T.PackageKey { T.name = k, ..}) }+                    pure $ T.PackageKey { name, npmVersionSpec }) }      -- | Appling heuristics to the field contents to find the     -- correct remote type.
src/Yarn/Lock/Parse.hs view
@@ -36,8 +36,9 @@  import qualified Yarn.Lock.Types as YLT -type Parser = Parsec Void Text +-- | We use a simple (pure) @Megaparsec@ parser.+type Parser = Parsec Void Text  -- | The @yarn.lock@ format doesn’t specifically include a fixed scheme, -- it’s just an unnecessary custom version of a list of fields.@@ -112,16 +113,37 @@     pkgKey valueChars = label "package key" $ do       key <- someTextOf (MP.noneOf valueChars)       -- okay, here’s the rub:-      -- `@` is used for separation, but package names containing `@`-      -- are totally a thing. As first character, as well.-      -- As are package keys without any semver whatsoever, thus ending-      -- with `@`.-      -- Did I mention this file format is big chunks of elephant shit?-      case (\(n, v) -> (T.dropEnd 1 n, v)) $ T.breakOnEnd "@" key of-        ("", _) -> fail "packageKey: package name can not be empty"-        (n, "") -> pure $ YLT.PackageKey n ""-        (n,  v) -> pure $ YLT.PackageKey n v+      -- `@` is used for separation, but package names can also+      -- start with the `@` character (so-called “scoped packages”).+      -- Furthermore, versions can contain `@` as well.+      -- This file format is a pile of elephant shit.+      case breakDrop '@' key of+        ("", rest) -> case breakDrop '@' rest of+          -- scoped key with empty name+          ("", _) -> emptyKeyErr key+          -- scoped key ("@scope/package")+          (scopedName, ver) -> YLT.PackageKey+            <$> scoped (T.cons '@' scopedName) <*> pure ver+        -- just a simple key+        (name, ver) -> pure $ YLT.PackageKey (YLT.SimplePackageKey name) ver +    emptyKeyErr :: Text -> Parser a+    emptyKeyErr key = fail+      ("packagekey: package name can not be empty (is: "+      <> toS key <> ")")++    -- | Like 'T.breakOn', but drops the separator char.+    breakDrop :: Char -> Text -> (Text, Text)+    breakDrop c str = case T.breakOn (T.singleton c) str of+      (s, "") -> (s, "")+      (s, s') -> (s, T.drop 1 s')++    -- | Parses a (scoped) package key and throws an error if misformatted.+    scoped n = maybe+      (fail $ "packageKey: scoped variable must be of form @scope/package"+           <> " (is: " <> toS n <> ")")+      pure $ YLT.parsePackageKeyName n+ -- | Either a simple or a nested field. field :: Parser (Text, Either Text PackageFields) field = try nested <|> simple <?> "field"@@ -175,6 +197,8 @@ -- -- Update: npm doesn’t specify the package name format, at all. -- Apart from the length.+-- Update: According to https://docs.npmjs.com/misc/scope+-- the package name format is “URL-safe characters, no leading dots or underscores” TODO symbolChars :: Parser Text symbolChars = label "key symbol" $ someTextOf $ MP.satisfy   (\c -> Ch.isAscii c &&
src/Yarn/Lock/Types.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFunctor, OverloadedStrings #-} {-| Module : Yarn.Lock.Types Description : Types for yarn.lock files@@ -8,6 +8,7 @@ module Yarn.Lock.Types where  import Protolude hiding (try)+import qualified Data.Text as T import qualified Data.MultiKeyedMap as MKM import qualified Data.List.NonEmpty as NE @@ -18,8 +19,7 @@ -- -- Attention: Might be changed to a newtype in a future release. type Lockfile = MKM.MKMap PackageKey Package--- TODO--- newtype Lockfile = Lockfile (MKM.MKMap PackageKey Package)+-- TODO newtype Lockfile = Lockfile (MKM.MKMap PackageKey Package)  -- | Proxy type for our MKMap intermediate key lockfileIkProxy :: Proxy Int@@ -27,11 +27,28 @@  -- | Key that indexes package for a specific version. data PackageKey = PackageKey-  { name           :: Text -- ^ package name+  { name           :: PackageKeyName -- ^ package name   , npmVersionSpec :: Text   -- ^ tring that specifies the version of a package;   -- sometimes a npm semver, sometimes an arbitrary string   } deriving (Show, Eq, Ord)++-- | The name of a package. They can be scoped, see+-- | <https://docs.npmjs.com/misc/scope> for an explanation.+data PackageKeyName+  = SimplePackageKey Text+  -- ^ just a package name+  | ScopedPackageKey Text Text+  -- ^ a scope and a package name (e.g. @types/foobar)+  deriving (Show, Eq, Ord)++-- | Try to parse a string into a package key name (scoped or not).+parsePackageKeyName :: Text -> Maybe PackageKeyName+parsePackageKeyName n = case T.stripPrefix "@" n of+  Nothing -> Just $ SimplePackageKey n+  Just sc -> case T.breakOn "/" sc of+    (_, "") -> Nothing+    (scope, pkg) -> Just $ ScopedPackageKey scope (T.drop 1 pkg)  -- | Something with a list of 'PackageKey's pointing to it. data Keyed a = Keyed (NE.NonEmpty PackageKey) a
tests/TestParse.hs view
@@ -27,7 +27,7 @@   parseSuccess packageList startComment     >>= \((Keyed keys _) : _) -> do       assertBool "only foo"-        (keys == pure (PackageKey "dummy-package" "foo"))+        (keys == pure (PackageKey (SimplePackageKey "dummy-package") "foo"))  -- registryPackage :: Text -- registryPackage = [text|@@ -56,8 +56,8 @@       assertBool "field2 member" (Map.member "field2" fields)       Map.lookup "field1" fields @=? (Just (Left "°§ℓ»«UAIERNT")) -nestedPackage :: Text-nestedPackage = [text|+nestedPackageExample :: Text+nestedPackageExample = [text|   readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0":     dependencies:       core-util-is "~1.0.0"@@ -81,8 +81,8 @@  case_NestedPackage :: Assertion case_NestedPackage = do-  assertBool "there is unicode" (all Ch.isAscii (toS nestedPackage :: [Char]))-  parseSuccess packageEntry nestedPackage+  assertBool "there is unicode" (all Ch.isAscii (toS nestedPackageExample :: [Char]))+  parseSuccess packageEntry nestedPackageExample     >>= \(Keyed _ (_, PackageFields fields)) -> do       case Map.lookup "dependencies" fields of         (Nothing) -> assertFailure "where’s the key"@@ -92,7 +92,7 @@           assertEqual "nested keys" 4 $ length nested           assertEqual "dep exists" (Just (Left "2.3.4"))             $ Map.lookup "johnny-dep" nested-          assertEqual "there can be @" (Just (Left "~0.10.x"))+          assertEqual "scoped packages start with @" (Just (Left "~0.10.x"))             $ Map.lookup "@types/string_decoder" nested  case_PackageField :: IO ()@@ -112,17 +112,39 @@  case_PackageKey :: Assertion case_PackageKey = do-  let key = "foo@^1.3.4, bar@blafoo234, xnu@, @types/foo@@:\n"+  let key = "foo@^1.3.4, bar@blafoo234, xnu@, @types/foo@:\n"   parseSuccess packageKeys key     >>= \keys -> do       keys @?= NE.fromList-               [ PackageKey "foo" "^1.3.4"-               , PackageKey "bar" "blafoo234"+               [ PackageKey (SimplePackageKey "foo") "^1.3.4"+               , PackageKey (SimplePackageKey "bar") "blafoo234"                -- yes, the version can be empty …-               , PackageKey "xnu" ""+               , PackageKey (SimplePackageKey "xnu") ""                -- and yes, package names can contain `@`-               , PackageKey "@types/foo@" ""+               , PackageKey (ScopedPackageKey "types" "foo") ""                ]+++-- | PackageKeys can contain arbitrary stuff apparently+case_complexKey :: Assertion+case_complexKey = do+  parseSuccess packageKeys+    "\"mango-components@git+ssh://git@github.com:stuff/#fe234\":"+    >>= \((PackageKey name version) NE.:| []) -> do+      assertEqual "complexKey name"+        (SimplePackageKey "mango-components") name+      assertEqual "complexKey version"+        "git+ssh://git@github.com:stuff/#fe234"+        version+  parseSuccess packageKeys+    "\"@types/mango-components@git@github\":"+    >>= \((PackageKey name version) NE.:| []) -> do+      assertEqual "complexKeyScoped name"+        (ScopedPackageKey "types" "mango-components") name+      assertEqual "complexKeyScoped version" "git@github" version+++-- HELPERS  parseSuccess :: Parser a -> Text -> IO a parseSuccess parser string = do
yarn-lock.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: bfe08f55682f41944db8ec965c30c279fd7d244188df301b7d3d22a65d0c9df7+-- hash: 9195f2d20c7a3cd78e9ef32e7e18b231b383f572887111142cd2df1d76891703  name:           yarn-lock-version:        0.4.1+version:        0.5.0 synopsis:       Represent and parse yarn.lock files description:    Types and parser for the lock file format of the npm successor yarn. All modules should be imported qualified. category:       Data