-- SPDX-FileCopyrightText: 2026 Alexandra de Wit
--
-- SPDX-License-Identifier: MIT

-- | Select npm installation and policy fields before constructing decoded values.
module Ecluse.Core.Registry.Npm.Streaming (
    NpmRead (..),
    NpmFieldOf (..),
    NpmField,
    NpmContainer (..),
    npmFields,
    versionFields,
    versionListFields,
) where

import Data.Aeson (Value (Array, Null, Number, Object, String))
import Data.JsonStream.Parser qualified as J

import Ecluse.Core.Registry.JsonStream (everyMember, namedMembers, retainedArrayWith, retainedObjectOr, retainedObjectWith, retainedScalar, retainedValue, withinRetainedDepth)

-- | Full serving data, one release, or the fields needed to recognise usable version entries.
data NpmRead = FullRead | SelectedRead Text | VersionListRead
    deriving stock (NpmRead -> NpmRead -> Bool
(NpmRead -> NpmRead -> Bool)
-> (NpmRead -> NpmRead -> Bool) -> Eq NpmRead
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NpmRead -> NpmRead -> Bool
== :: NpmRead -> NpmRead -> Bool
$c/= :: NpmRead -> NpmRead -> Bool
/= :: NpmRead -> NpmRead -> Bool
Eq, Int -> NpmRead -> ShowS
[NpmRead] -> ShowS
NpmRead -> String
(Int -> NpmRead -> ShowS)
-> (NpmRead -> String) -> ([NpmRead] -> ShowS) -> Show NpmRead
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NpmRead -> ShowS
showsPrec :: Int -> NpmRead -> ShowS
$cshow :: NpmRead -> String
show :: NpmRead -> String
$cshowList :: [NpmRead] -> ShowS
showList :: [NpmRead] -> ShowS
Show)

-- | Independent top-level maps, with first-container precedence retained by their consumer.
data NpmContainer = VersionsContainer | TimeContainer | TagsContainer
    deriving stock (NpmContainer -> NpmContainer -> Bool
(NpmContainer -> NpmContainer -> Bool)
-> (NpmContainer -> NpmContainer -> Bool) -> Eq NpmContainer
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NpmContainer -> NpmContainer -> Bool
== :: NpmContainer -> NpmContainer -> Bool
$c/= :: NpmContainer -> NpmContainer -> Bool
/= :: NpmContainer -> NpmContainer -> Bool
Eq, Eq NpmContainer
Eq NpmContainer =>
(NpmContainer -> NpmContainer -> Ordering)
-> (NpmContainer -> NpmContainer -> Bool)
-> (NpmContainer -> NpmContainer -> Bool)
-> (NpmContainer -> NpmContainer -> Bool)
-> (NpmContainer -> NpmContainer -> Bool)
-> (NpmContainer -> NpmContainer -> NpmContainer)
-> (NpmContainer -> NpmContainer -> NpmContainer)
-> Ord NpmContainer
NpmContainer -> NpmContainer -> Bool
NpmContainer -> NpmContainer -> Ordering
NpmContainer -> NpmContainer -> NpmContainer
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: NpmContainer -> NpmContainer -> Ordering
compare :: NpmContainer -> NpmContainer -> Ordering
$c< :: NpmContainer -> NpmContainer -> Bool
< :: NpmContainer -> NpmContainer -> Bool
$c<= :: NpmContainer -> NpmContainer -> Bool
<= :: NpmContainer -> NpmContainer -> Bool
$c> :: NpmContainer -> NpmContainer -> Bool
> :: NpmContainer -> NpmContainer -> Bool
$c>= :: NpmContainer -> NpmContainer -> Bool
>= :: NpmContainer -> NpmContainer -> Bool
$cmax :: NpmContainer -> NpmContainer -> NpmContainer
max :: NpmContainer -> NpmContainer -> NpmContainer
$cmin :: NpmContainer -> NpmContainer -> NpmContainer
min :: NpmContainer -> NpmContainer -> NpmContainer
Ord, Int -> NpmContainer -> ShowS
[NpmContainer] -> ShowS
NpmContainer -> String
(Int -> NpmContainer -> ShowS)
-> (NpmContainer -> String)
-> ([NpmContainer] -> ShowS)
-> Show NpmContainer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NpmContainer -> ShowS
showsPrec :: Int -> NpmContainer -> ShowS
$cshow :: NpmContainer -> String
show :: NpmContainer -> String
$cshowList :: [NpmContainer] -> ShowS
showList :: [NpmContainer] -> ShowS
Show)

-- | Each field retains its source coordinate. Skipped releases still count towards the version cap.
data NpmFieldOf release
    = IgnoredField
    | BeginContainer NpmContainer
    | InvalidContainer NpmContainer
    | NameField Value
    | VersionField Text (Maybe release)
    | TimeField Text Value
    | TagField Text Value
    deriving stock (NpmFieldOf release -> NpmFieldOf release -> Bool
(NpmFieldOf release -> NpmFieldOf release -> Bool)
-> (NpmFieldOf release -> NpmFieldOf release -> Bool)
-> Eq (NpmFieldOf release)
forall release.
Eq release =>
NpmFieldOf release -> NpmFieldOf release -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall release.
Eq release =>
NpmFieldOf release -> NpmFieldOf release -> Bool
== :: NpmFieldOf release -> NpmFieldOf release -> Bool
$c/= :: forall release.
Eq release =>
NpmFieldOf release -> NpmFieldOf release -> Bool
/= :: NpmFieldOf release -> NpmFieldOf release -> Bool
Eq, Int -> NpmFieldOf release -> ShowS
[NpmFieldOf release] -> ShowS
NpmFieldOf release -> String
(Int -> NpmFieldOf release -> ShowS)
-> (NpmFieldOf release -> String)
-> ([NpmFieldOf release] -> ShowS)
-> Show (NpmFieldOf release)
forall release. Show release => Int -> NpmFieldOf release -> ShowS
forall release. Show release => [NpmFieldOf release] -> ShowS
forall release. Show release => NpmFieldOf release -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall release. Show release => Int -> NpmFieldOf release -> ShowS
showsPrec :: Int -> NpmFieldOf release -> ShowS
$cshow :: forall release. Show release => NpmFieldOf release -> String
show :: NpmFieldOf release -> String
$cshowList :: forall release. Show release => [NpmFieldOf release] -> ShowS
showList :: [NpmFieldOf release] -> ShowS
Show)

-- | A field whose release is aeson's tree.
type NpmField = NpmFieldOf Value

-- | Extract independent maps without assuming their ordering in the source.
npmFields :: Int -> NpmRead -> J.Parser NpmField
npmFields :: Int -> NpmRead -> Parser NpmField
npmFields Int
depth NpmRead
mode = Int -> Parser NpmField -> Parser NpmField
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
depth ((Text -> Parser NpmField) -> Parser NpmField
forall a. (Text -> Parser a) -> Parser a
J.objectKeyValues Text -> Parser NpmField
forall {a}. (Eq a, IsString a) => a -> Parser NpmField
topField)
  where
    topField :: a -> Parser NpmField
topField a
"name"
        | NpmRead
mode NpmRead -> NpmRead -> Bool
forall a. Eq a => a -> a -> Bool
/= NpmRead
VersionListRead = Value -> NpmField
forall release. Value -> NpmFieldOf release
NameField (Value -> NpmField) -> Parser Value -> Parser NpmField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
    topField a
"versions" = NpmContainer -> Parser NpmField -> Parser NpmField
forall {release}.
NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
VersionsContainer ((Text -> Parser NpmField) -> Parser NpmField
forall a. (Text -> Parser a) -> Parser a
J.objectKeyValues Text -> Parser NpmField
release)
    topField a
"time" = case NpmRead
mode of
        NpmRead
VersionListRead -> Parser NpmField
forall a. Monoid a => a
mempty
        SelectedRead Text
target -> NpmContainer -> Parser NpmField -> Parser NpmField
forall {release}.
NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
TimeContainer (Text -> Value -> NpmField
forall release. Text -> Value -> NpmFieldOf release
TimeField Text
target (Value -> NpmField) -> Parser Value -> Parser NpmField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Value -> Parser Value
forall a. Text -> Parser a -> Parser a
J.objectWithKey Text
target (Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)))
        NpmRead
FullRead -> NpmContainer -> Parser NpmField -> Parser NpmField
forall {release}.
NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
TimeContainer ((Text -> Parser NpmField) -> Parser NpmField
forall a. (Text -> Parser a) -> Parser a
J.objectKeyValues Text -> Parser NpmField
forall {release}. Text -> Parser (NpmFieldOf release)
timestamp)
    topField a
"dist-tags" = case NpmRead
mode of
        NpmRead
VersionListRead -> Parser NpmField
forall a. Monoid a => a
mempty
        SelectedRead Text
_ -> NpmContainer -> Parser NpmField -> Parser NpmField
forall {release}.
NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
TagsContainer (Text -> Value -> NpmField
forall release. Text -> Value -> NpmFieldOf release
TagField Text
"latest" (Value -> NpmField) -> Parser Value -> Parser NpmField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Value -> Parser Value
forall a. Text -> Parser a -> Parser a
J.objectWithKey Text
"latest" (Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)))
        NpmRead
FullRead -> NpmContainer -> Parser NpmField -> Parser NpmField
forall {release}.
NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
TagsContainer ((Text -> Parser NpmField) -> Parser NpmField
forall a. (Text -> Parser a) -> Parser a
J.objectKeyValues Text -> Parser NpmField
forall {release}. Text -> Parser (NpmFieldOf release)
tag)
    topField a
_ = Parser NpmField
forall a. Monoid a => a
mempty
    container :: NpmContainer
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
container NpmContainer
slot Parser (NpmFieldOf release)
parser =
        Int -> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Parser (NpmFieldOf release) -> Parser (NpmFieldOf release))
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
forall a b. (a -> b) -> a -> b
$
            NpmFieldOf release
-> NpmFieldOf release
-> Parser (NpmFieldOf release)
-> Parser (NpmFieldOf release)
forall a. a -> a -> Parser a -> Parser a
J.objectFound (NpmContainer -> NpmFieldOf release
forall release. NpmContainer -> NpmFieldOf release
BeginContainer NpmContainer
slot) NpmFieldOf release
forall release. NpmFieldOf release
IgnoredField Parser (NpmFieldOf release)
parser
                Parser (NpmFieldOf release)
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (NpmContainer -> NpmFieldOf release
forall release. NpmContainer -> NpmFieldOf release
BeginContainer NpmContainer
slot NpmFieldOf release -> Parser () -> Parser (NpmFieldOf release)
forall a b. a -> Parser b -> Parser a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser ()
J.jNull)
                Parser (NpmFieldOf release)
-> Parser (NpmFieldOf release) -> Parser (NpmFieldOf release)
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> NpmFieldOf release -> Parser (NpmFieldOf release)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NpmContainer -> NpmFieldOf release
forall release. NpmContainer -> NpmFieldOf release
InvalidContainer NpmContainer
slot)
    release :: Text -> Parser NpmField
release Text
key = case NpmRead
mode of
        SelectedRead Text
target | Text
key Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
target -> NpmField -> Parser NpmField
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Value -> NpmField
forall release. Text -> Maybe release -> NpmFieldOf release
VersionField Text
"" Maybe Value
forall a. Maybe a
Nothing)
        NpmRead
VersionListRead -> Text -> Maybe Value -> NpmField
forall release. Text -> Maybe release -> NpmFieldOf release
VersionField Text
key (Maybe Value -> NpmField)
-> (Value -> Maybe Value) -> Value -> NpmField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Maybe Value
forall a. a -> Maybe a
Just (Value -> NpmField) -> Parser Value -> Parser NpmField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) (Value -> Members -> Parser Value
retainedObjectOr Value
Null Members
listFields)
        NpmRead
_ -> Text -> Maybe Value -> NpmField
forall release. Text -> Maybe release -> NpmFieldOf release
VersionField Text
key (Maybe Value -> NpmField)
-> (Value -> Maybe Value) -> Value -> NpmField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Maybe Value
forall a. a -> Maybe a
Just (Value -> NpmField) -> Parser Value -> Parser NpmField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) (Value -> Members -> Parser Value
retainedObjectOr Value
Null Members
releaseFields)
    timestamp :: Text -> Parser (NpmFieldOf release)
timestamp Text
key = Text -> Value -> NpmFieldOf release
forall release. Text -> Value -> NpmFieldOf release
TimeField Text
key (Value -> NpmFieldOf release)
-> Parser Value -> Parser (NpmFieldOf release)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)
    tag :: Text -> Parser (NpmFieldOf release)
tag Text
key = Text -> Value -> NpmFieldOf release
forall release. Text -> Value -> NpmFieldOf release
TagField Text
key (Value -> NpmFieldOf release)
-> Parser Value -> Parser (NpmFieldOf release)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)
    -- Each table is built once per read, so every release shares its field names. The first
    -- entry for a name wins, so a witness or a shaped entry takes precedence over the generic one.
    listFields :: Members
listFields = [(Text, Parser Value)] -> Members
namedMembers ([(Text, Parser Value)]
listWitnesses [(Text, Parser Value)]
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. Semigroup a => a -> a -> a
<> ((Text, Parser Value) -> Bool)
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Text -> [Text] -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`elem` [Text]
versionListFields) (Text -> Bool)
-> ((Text, Parser Value) -> Text) -> (Text, Parser Value) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Parser Value) -> Text
forall a b. (a, b) -> a
fst) [(Text, Parser Value)]
releaseEntries)
    releaseFields :: Members
releaseFields = [(Text, Parser Value)] -> Members
namedMembers [(Text, Parser Value)]
releaseEntries
    releaseEntries :: [(Text, Parser Value)]
releaseEntries = [(Text, Parser Value)]
shapedFields [(Text, Parser Value)]
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. Semigroup a => a -> a -> a
<> [(Text
key, Int -> Parser Value
retainedValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3)) | Text
key <- [Text]
versionFields]
    listWitnesses :: [(Text, Parser Value)]
listWitnesses =
        [ (Text
"name", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Parser Value
witness)
        , (Text
"version", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Parser Value
witness)
        , (Text
"dist", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Value -> Members -> Parser Value
retainedObjectOr Value
Null ([(Text, Parser Value)] -> Members
namedMembers [(Text
slot, Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) Parser Value
witness) | Text
slot <- [Text
"tarball", Text
"shasum", Text
"integrity"]])))
        , (Text
"scripts", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Int -> Parser Value
stringMapWitness (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4)))
        , (Text
"deprecated", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Value -> Parser Value
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Value
Null))
        ]
    shapedFields :: [(Text, Parser Value)]
shapedFields =
        [ (Text
"_npmUser", [Text] -> Int -> Parser Value
personValue [Text
"name", Text
"email", Text
"url"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3))
        , (Text
"license", [Text] -> Int -> Parser Value
personValue [Text
"type", Text
"url"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3))
        , (Text
"dist", Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Members
distFields)
        , (Text
"peerDependenciesMeta", Parser Value
dependencyMeta)
        , (Text
"dependenciesMeta", Parser Value
dependencyMeta)
        , (Text
"directories", [Text] -> Int -> Parser Value
fixed [Text
"lib", Text
"bin", Text
"man", Text
"doc", Text
"example", Text
"test"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3))
        , (Text
"devEngines", Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) ([(Text, Parser Value)] -> Members
namedMembers [(Text
key, Parser Value
devEngine) | Text
key <- [Text
"cpu", Text
"os", Text
"libc", Text
"runtime", Text
"packageManager"]]))
        , (Text
"publishConfig", Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Members
publishFields)
        , (Text
"workspaces", Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Parser Value -> Parser Value -> Parser Value
retainedArrayWith (Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) Members
workspaceFields) (Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4))))
        ]
            [(Text, Parser Value)]
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. Semigroup a => a -> a -> a
<> [ (Text
key, Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Parser Value -> Members
everyMember (Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4))))
               | Text
key <- [Text
"dependencies", Text
"acceptDependencies", Text
"devDependencies", Text
"optionalDependencies", Text
"peerDependencies", Text
"engines", Text
"scripts", Text
"bin", Text
"browser"]
               ]
            [(Text, Parser Value)]
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. Semigroup a => a -> a -> a
<> [ (Text
key, Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3))
               | Text
key <- [Text
"name", Text
"version", Text
"_hasShrinkwrap", Text
"hasInstallScript", Text
"deprecated", Text
"main", Text
"module", Text
"type", Text
"types", Text
"typings", Text
"gypfile", Text
"preferGlobal", Text
"packageManager", Text
"engineStrict"]
               ]
    witness :: Parser Value
witness = (Text -> Value
String Text
"" Value -> Parser Text -> Parser Value
forall a b. a -> Parser b -> Parser a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
J.string) Parser Value -> Parser Value -> Parser Value
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Value
Null Value -> Parser () -> Parser Value
forall a b. a -> Parser b -> Parser a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser ()
J.jNull) Parser Value -> Parser Value -> Parser Value
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Value -> Parser Value
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Scientific -> Value
Number Scientific
0)
    personValue :: [Text] -> Int -> Parser Value
personValue [Text]
keys Int
budget = Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
budget ((Text -> Value
String (Text -> Value) -> Parser Text -> Parser Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
J.string) Parser Value -> Parser Value -> Parser Value
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> [Text] -> Int -> Parser Value
fixed [Text]
keys Int
budget)
    scalar :: Int -> Parser Value
scalar Int
budget = Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
budget (Parser Value
retainedScalar Parser Value -> Parser Value -> Parser Value
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Value -> Parser Value
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Array -> Value
Array Array
forall a. Monoid a => a
mempty))
    objectValue :: Int -> Members -> Parser Value
objectValue Int
budget Members
members = Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
budget (Parser Value -> Members -> Parser Value
retainedObjectWith (Int -> Parser Value
scalar Int
budget) Members
members)
    arrayValue :: Int -> Parser Value -> Parser Value
arrayValue Int
budget Parser Value
entry = Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
budget (Parser Value -> Parser Value -> Parser Value
retainedArrayWith (Int -> Parser Value
scalar Int
budget) Parser Value
entry)
    fixed :: [Text] -> Int -> Parser Value
fixed [Text]
keys Int
budget = Int -> Members -> Parser Value
objectValue Int
budget ([(Text, Parser Value)] -> Members
namedMembers [(Text
key, Int -> Parser Value
scalar (Int
budget Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) | Text
key <- [Text]
keys])
    distFields :: Members
distFields =
        [(Text, Parser Value)] -> Members
namedMembers
            ( [ (Text
"signatures", Int -> Parser Value -> Parser Value
arrayValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) ([Text] -> Int -> Parser Value
fixed [Text
"keyid", Text
"sig"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
5)))
              , (Text
"attestations", Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) ([(Text, Parser Value)] -> Members
namedMembers [(Text
"url", Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
5)), (Text
"provenance", [Text] -> Int -> Parser Value
fixed [Text
"predicateType"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
5))]))
              ]
                [(Text, Parser Value)]
-> [(Text, Parser Value)] -> [(Text, Parser Value)]
forall a. Semigroup a => a -> a -> a
<> [(Text
key, Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4)) | Text
key <- [Text]
distScalars]
            )
    dependencyMeta :: Parser Value
dependencyMeta = Int -> Members -> Parser Value
objectValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) (Parser Value -> Members
everyMember ([Text] -> Int -> Parser Value
fixed [Text
"optional"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4)))
    devEngine :: Parser Value
devEngine = Int -> Parser Value -> Parser Value
forall a. Int -> Parser a -> Parser a
withinRetainedDepth (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) (Parser Value -> Parser Value -> Parser Value
retainedArrayWith ([Text] -> Int -> Parser Value
fixed [Text
"name", Text
"version", Text
"onFail"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4)) ([Text] -> Int -> Parser Value
fixed [Text
"name", Text
"version", Text
"onFail"] (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
5)))
    publishFields :: Members
publishFields = [(Text, Parser Value)] -> Members
namedMembers [(Text
key, Int -> Parser Value
retainedValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4)) | Text
key <- [Text
"registry", Text
"tag", Text
"access", Text
"provenance", Text
"ignore-scripts", Text
"directory", Text
"linkDirectory", Text
"executableFiles", Text
"main", Text
"module", Text
"types", Text
"typings", Text
"exports", Text
"imports", Text
"bin", Text
"browser"]]
    workspaceFields :: Members
workspaceFields = [(Text, Parser Value)] -> Members
namedMembers [(Text
key, Int -> Parser Value -> Parser Value
arrayValue (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) (Int -> Parser Value
scalar (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
5))) | Text
key <- [Text
"packages", Text
"nohoist"]]

-- | Supported release fields for installation, runtime resolution, policy and mirrored publication.
versionFields :: [Text]
versionFields :: [Text]
versionFields =
    [Text]
versionListFields
        [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [ Text
"dependencies"
           , Text
"dependenciesMeta"
           , Text
"acceptDependencies"
           , Text
"_hasShrinkwrap"
           , Text
"devDependencies"
           , Text
"optionalDependencies"
           , Text
"peerDependencies"
           , Text
"peerDependenciesMeta"
           , Text
"bundleDependencies"
           , Text
"bundledDependencies"
           , Text
"engines"
           , Text
"engineStrict"
           , Text
"os"
           , Text
"cpu"
           , Text
"libc"
           , Text
"bin"
           , Text
"man"
           , Text
"directories"
           , Text
"main"
           , Text
"module"
           , Text
"browser"
           , Text
"exports"
           , Text
"imports"
           , Text
"type"
           , Text
"types"
           , Text
"typings"
           , Text
"typesVersions"
           , Text
"files"
           , Text
"gypfile"
           , Text
"preferGlobal"
           , Text
"config"
           , Text
"workspaces"
           , Text
"packageManager"
           , Text
"devEngines"
           , Text
"publishConfig"
           , Text
"sideEffects"
           ]

-- | VersionEntry's required fields and optional discriminators, excluding installer-only fields.
versionListFields :: [Text]
versionListFields :: [Text]
versionListFields = [Text
"name", Text
"version", Text
"dist", Text
"deprecated", Text
"hasInstallScript", Text
"scripts", Text
"license", Text
"_npmUser"]

distScalars :: [Text]
distScalars :: [Text]
distScalars = [Text
"tarball", Text
"shasum", Text
"integrity", Text
"unpackedSize", Text
"fileCount"]

data StringMapShape = ValidStringMap | InvalidStringMap | NullStringMap

stringMapWitness :: Int -> J.Parser Value
stringMapWitness :: Int -> Parser Value
stringMapWitness Int
budget = StringMapShape -> Value
result (StringMapShape -> Value) -> Parser StringMapShape -> Parser Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (StringMapShape -> StringMapShape -> StringMapShape)
-> StringMapShape -> Parser StringMapShape -> Parser StringMapShape
forall b a. (b -> a -> b) -> b -> Parser a -> Parser b
J.foldI StringMapShape -> StringMapShape -> StringMapShape
collect StringMapShape
NullStringMap Parser StringMapShape
events
  where
    events :: Parser StringMapShape
events =
        StringMapShape
-> StringMapShape -> Parser StringMapShape -> Parser StringMapShape
forall a. a -> a -> Parser a -> Parser a
J.objectFound StringMapShape
ValidStringMap StringMapShape
ValidStringMap (Parser StringMapShape -> Parser StringMapShape
forall a. Parser a -> Parser a
J.objectValues (Int -> Parser StringMapShape -> Parser StringMapShape
forall a. Int -> Parser a -> Parser a
withinRetainedDepth Int
budget ((StringMapShape
ValidStringMap StringMapShape -> Parser Text -> Parser StringMapShape
forall a b. a -> Parser b -> Parser a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
J.string) Parser StringMapShape
-> Parser StringMapShape -> Parser StringMapShape
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> StringMapShape -> Parser StringMapShape
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure StringMapShape
InvalidStringMap)))
            Parser StringMapShape
-> Parser StringMapShape -> Parser StringMapShape
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (StringMapShape
NullStringMap StringMapShape -> Parser () -> Parser StringMapShape
forall a b. a -> Parser b -> Parser a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser ()
J.jNull)
            Parser StringMapShape
-> Parser StringMapShape -> Parser StringMapShape
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> StringMapShape -> Parser StringMapShape
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure StringMapShape
InvalidStringMap
    collect :: StringMapShape -> StringMapShape -> StringMapShape
collect StringMapShape
InvalidStringMap StringMapShape
_ = StringMapShape
InvalidStringMap
    collect StringMapShape
_ StringMapShape
next = StringMapShape
next
    result :: StringMapShape -> Value
result StringMapShape
ValidStringMap = Object -> Value
Object Object
forall a. Monoid a => a
mempty
    result StringMapShape
InvalidStringMap = Scientific -> Value
Number Scientific
0
    result StringMapShape
NullStringMap = Value
Null