From d4e7dbb2350ac6b6cb5c00d8ed46e7445df64fa8 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Sun, 9 Jun 2024 12:17:47 +0300 Subject: [PATCH] Port from codec-argonaut to codec-json (#1227) --- bin/spago.yaml | 14 +- bin/src/Main.purs | 13 +- core/spago.yaml | 8 +- core/src/Config.purs | 310 +++++++++--------- core/src/FS.purs | 19 +- core/src/Json.purs | 31 +- core/src/Log.purs | 8 +- core/src/Prelude.purs | 2 +- core/src/Yaml.purs | 32 +- docs-search/client-halogen/spago.yaml | 4 +- .../src/Docs/Search/BrowserEngine.purs | 32 +- docs-search/common/spago.yaml | 6 +- .../common/src/Docs/Search/DocsJson.purs | 23 +- .../common/src/Docs/Search/JsonCodec.purs | 22 +- .../common/src/Docs/Search/Loader.purs | 16 +- docs-search/common/src/Docs/Search/Meta.purs | 10 +- .../common/src/Docs/Search/ModuleIndex.purs | 29 +- .../common/src/Docs/Search/PackageIndex.purs | 45 +-- .../common/src/Docs/Search/SearchResult.purs | 55 ++-- .../common/src/Docs/Search/TypeDecoder.purs | 61 ++-- .../common/src/Docs/Search/TypeIndex.purs | 26 +- docs-search/common/src/Docs/Search/Types.purs | 21 +- docs-search/index/spago.yaml | 6 +- .../index/src/Docs/Search/IndexBuilder.purs | 75 +++-- flake.lock | 6 +- spago.lock | 136 ++++++-- spago.yaml | 29 +- src/Spago/Command/Fetch.purs | 38 ++- src/Spago/Command/Graph.purs | 7 +- src/Spago/Command/Ls.purs | 46 +-- src/Spago/Command/Publish.purs | 9 +- src/Spago/Command/Registry.purs | 12 +- src/Spago/Command/Run.purs | 4 +- src/Spago/Command/Sources.purs | 4 +- src/Spago/Config.purs | 28 +- src/Spago/Db.purs | 7 +- src/Spago/Lock.purs | 126 +++---- src/Spago/Prelude.purs | 7 +- src/Spago/Psa.purs | 7 +- src/Spago/Psa/Printer.purs | 8 +- src/Spago/Psa/Types.purs | 52 +-- src/Spago/Purs.purs | 18 +- src/Spago/Purs/Graph.purs | 24 +- .../package-name-too-long-stderr.txt | 4 + test-fixtures/spago-yml-check-stderr.txt | 6 +- test/Spago.purs | 4 +- test/Spago/Errors.purs | 22 ++ test/Spago/Lock.purs | 4 +- test/Spago/Test.purs | 5 - 49 files changed, 839 insertions(+), 642 deletions(-) create mode 100644 test-fixtures/package-name-too-long-stderr.txt create mode 100644 test/Spago/Errors.purs diff --git a/bin/spago.yaml b/bin/spago.yaml index 695163977..709bd7833 100644 --- a/bin/spago.yaml +++ b/bin/spago.yaml @@ -10,20 +10,24 @@ package: dependencies: - aff - arrays - - codec-argonaut - - console - - js-date + - avar + - codec-json + - control + - foldable-traversable - lists - - node-fs + - maybe - node-path - node-process + - now - optparse - ordered-collections + - prelude - record - - refs - registry-lib - spago - spago-core + - strings + - transformers - unsafe-coerce bundle: module: Main diff --git a/bin/src/Main.purs b/bin/src/Main.purs index eb20058c5..bd54c5a76 100644 --- a/bin/src/Main.purs +++ b/bin/src/Main.purs @@ -7,7 +7,7 @@ import Control.Monad.Reader as Reader import Data.Array as Array import Data.Array.NonEmpty as NEA import Data.Array.NonEmpty as NonEmptyArray -import Data.Codec.Argonaut.Common as CA.Common +import Data.Codec.JSON.Common as CJ.Common import Data.Foldable as Foldable import Data.List as List import Data.Maybe as Maybe @@ -52,6 +52,7 @@ import Spago.Generated.BuildInfo as BuildInfo import Spago.Git as Git import Spago.Json as Json import Spago.Log (LogVerbosity(..)) +import Spago.Log as Log import Spago.Paths as Paths import Spago.Purs as Purs import Spago.Registry as Registry @@ -535,10 +536,14 @@ main = do void $ runSpago env (Sources.run { json: args.json }) Init args@{ useSolver } -> do -- Figure out the package name from the current dir - let candidateName = fromMaybe (String.take 50 $ Path.basename Paths.cwd) args.name + let candidateName = fromMaybe (String.take 150 $ Path.basename Paths.cwd) args.name logDebug [ show Paths.cwd, show candidateName ] packageName <- case PackageName.parse (PackageName.stripPureScriptPrefix candidateName) of - Left err -> die [ "Could not figure out a name for the new package. Error:", show err ] + Left err -> die + [ toDoc "Could not figure out a name for the new package. Error:" + , Log.break + , Log.indent2 $ toDoc err + ] Right p -> pure p setVersion <- for args.setVersion $ parseLenientVersion >>> case _ of Left err -> die [ "Could not parse provided set version. Error:", show err ] @@ -831,7 +836,7 @@ mkTestEnv testArgs { dependencies, purs } = do Just { head, tail } -> pure $ map mkSelectedTest $ NonEmptyArray.cons' head tail Nothing -> die "No package found to test." - logDebug $ "Selected packages to test: " <> Json.stringifyJson (CA.Common.nonEmptyArray PackageName.codec) (map _.selected.package.name selectedPackages) + logDebug $ "Selected packages to test: " <> Json.stringifyJson (CJ.Common.nonEmptyArray PackageName.codec) (map _.selected.package.name selectedPackages) let newWorkspace = workspace { buildOptions { output = testArgs.output <|> workspace.buildOptions.output } } let testEnv = { logOptions, workspace: newWorkspace, selectedPackages, node, dependencies, purs } diff --git a/core/spago.yaml b/core/spago.yaml index b1e85e2e2..075d2dd48 100644 --- a/core/spago.yaml +++ b/core/spago.yaml @@ -4,10 +4,10 @@ package: strict: true dependencies: - aff - - argonaut-core - arrays - bifunctors - - codec-argonaut + - codec + - codec-json - console - control - datetime @@ -19,6 +19,8 @@ package: - foldable-traversable - functions - identity + - integers + - json - lists - maybe - newtype @@ -26,6 +28,7 @@ package: - node-fs - node-path - node-process + - now - ordered-collections - partial - prelude @@ -33,5 +36,6 @@ package: - refs - registry-lib - strings + - stringutils - transformers - tuples diff --git a/core/src/Config.purs b/core/src/Config.purs index 49ef6738d..81b389e96 100644 --- a/core/src/Config.purs +++ b/core/src/Config.purs @@ -1,25 +1,25 @@ module Spago.Core.Config ( BackendConfig - , WorkspaceBuildOptionsInput - , CensorBuildWarnings(..) - , WarningCensorTest(..) - , StatVerbosity(..) - , PackageBuildOptionsInput , BundleConfig , BundlePlatform(..) , BundleType(..) + , CensorBuildWarnings(..) , Config , Dependencies(..) , ExtraPackage(..) , GitPackage , LegacyPackageSetEntry , LocalPackage + , PackageBuildOptionsInput , PackageConfig , PublishConfig , RemotePackage(..) , RunConfig , SetAddress(..) + , StatVerbosity(..) , TestConfig + , WarningCensorTest(..) + , WorkspaceBuildOptionsInput , WorkspaceConfig , configCodec , dependenciesCodec @@ -38,10 +38,12 @@ module Spago.Core.Config import Spago.Core.Prelude +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Array.NonEmpty as NonEmptyArray -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Record as CAR -import Data.Codec.Argonaut.Sum as CA.Sum +import Data.Codec as Codec +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record +import Data.Codec.JSON.Sum as CJ.Sum import Data.Either as Either import Data.List as List import Data.Map as Map @@ -61,11 +63,11 @@ type Config = , workspace :: Maybe WorkspaceConfig } -configCodec :: JsonCodec Config -configCodec = CA.object "Config" - $ CA.recordPropOptional (Proxy :: _ "package") packageConfigCodec - $ CA.recordPropOptional (Proxy :: _ "workspace") workspaceConfigCodec - $ CA.record +configCodec :: CJ.Codec Config +configCodec = CJ.object + $ CJ.recordPropOptional (Proxy :: _ "package") packageConfigCodec + $ CJ.recordPropOptional (Proxy :: _ "workspace") workspaceConfigCodec + $ CJ.record type PackageConfig = { name :: PackageName @@ -78,17 +80,17 @@ type PackageConfig = , publish :: Maybe PublishConfig } -packageConfigCodec :: JsonCodec PackageConfig -packageConfigCodec = CA.object "PackageConfig" - $ CA.recordProp (Proxy :: _ "name") PackageName.codec - $ CA.recordPropOptional (Proxy :: _ "description") CA.string - $ CA.recordProp (Proxy :: _ "dependencies") dependenciesCodec - $ CA.recordPropOptional (Proxy :: _ "build") packageBuildOptionsCodec - $ CA.recordPropOptional (Proxy :: _ "bundle") bundleConfigCodec - $ CA.recordPropOptional (Proxy :: _ "run") runConfigCodec - $ CA.recordPropOptional (Proxy :: _ "test") testConfigCodec - $ CA.recordPropOptional (Proxy :: _ "publish") publishConfigCodec - $ CA.record +packageConfigCodec :: CJ.Codec PackageConfig +packageConfigCodec = CJ.named "PackageConfig" $ CJ.object + $ CJ.recordProp (Proxy :: _ "name") PackageName.codec + $ CJ.recordPropOptional (Proxy :: _ "description") CJ.string + $ CJ.recordProp (Proxy :: _ "dependencies") dependenciesCodec + $ CJ.recordPropOptional (Proxy :: _ "build") packageBuildOptionsCodec + $ CJ.recordPropOptional (Proxy :: _ "bundle") bundleConfigCodec + $ CJ.recordPropOptional (Proxy :: _ "run") runConfigCodec + $ CJ.recordPropOptional (Proxy :: _ "test") testConfigCodec + $ CJ.recordPropOptional (Proxy :: _ "publish") publishConfigCodec + $ CJ.record type PublishConfig = { version :: Version @@ -98,25 +100,25 @@ type PublishConfig = , exclude :: Maybe (Array FilePath) } -publishConfigCodec :: JsonCodec PublishConfig -publishConfigCodec = CA.object "PublishConfig" - $ CA.recordProp (Proxy :: _ "version") Version.codec - $ CA.recordProp (Proxy :: _ "license") License.codec - $ CA.recordPropOptional (Proxy :: _ "location") Location.codec - $ CA.recordPropOptional (Proxy :: _ "include") (CA.array CA.string) - $ CA.recordPropOptional (Proxy :: _ "exclude") (CA.array CA.string) - $ CA.record +publishConfigCodec :: CJ.Codec PublishConfig +publishConfigCodec = CJ.named "PublishConfig" $ CJ.object + $ CJ.recordProp (Proxy :: _ "version") Version.codec + $ CJ.recordProp (Proxy :: _ "license") License.codec + $ CJ.recordPropOptional (Proxy :: _ "location") Location.codec + $ CJ.recordPropOptional (Proxy :: _ "include") (CJ.array CJ.string) + $ CJ.recordPropOptional (Proxy :: _ "exclude") (CJ.array CJ.string) + $ CJ.record type RunConfig = { main :: Maybe String , execArgs :: Maybe (Array String) } -runConfigCodec :: JsonCodec RunConfig -runConfigCodec = CA.object "RunConfig" - $ CA.recordPropOptional (Proxy :: _ "main") CA.string - $ CA.recordPropOptional (Proxy :: _ "execArgs") (CA.array CA.string) - $ CA.record +runConfigCodec :: CJ.Codec RunConfig +runConfigCodec = CJ.named "RunConfig" $ CJ.object + $ CJ.recordPropOptional (Proxy :: _ "main") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "execArgs") (CJ.array CJ.string) + $ CJ.record type TestConfig = { main :: String @@ -127,26 +129,26 @@ type TestConfig = , pedanticPackages :: Maybe Boolean } -testConfigCodec :: JsonCodec TestConfig -testConfigCodec = CA.object "TestConfig" - $ CA.recordProp (Proxy :: _ "main") CA.string - $ CA.recordPropOptional (Proxy :: _ "execArgs") (CA.array CA.string) - $ CA.recordPropOptional (Proxy :: _ "censorTestWarnings") censorBuildWarningsCodec - $ CA.recordPropOptional (Proxy :: _ "strict") CA.boolean - $ CA.recordPropOptional (Proxy :: _ "pedanticPackages") CA.boolean - $ CA.recordProp (Proxy :: _ "dependencies") dependenciesCodec - $ CA.record +testConfigCodec :: CJ.Codec TestConfig +testConfigCodec = CJ.named "TestConfig" $ CJ.object + $ CJ.recordProp (Proxy :: _ "main") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "execArgs") (CJ.array CJ.string) + $ CJ.recordPropOptional (Proxy :: _ "censorTestWarnings") censorBuildWarningsCodec + $ CJ.recordPropOptional (Proxy :: _ "strict") CJ.boolean + $ CJ.recordPropOptional (Proxy :: _ "pedanticPackages") CJ.boolean + $ CJ.recordProp (Proxy :: _ "dependencies") dependenciesCodec + $ CJ.record type BackendConfig = { cmd :: String , args :: Maybe (Array String) } -backendConfigCodec :: JsonCodec BackendConfig -backendConfigCodec = CA.object "BackendConfig" - $ CA.recordProp (Proxy :: _ "cmd") CA.string - $ CA.recordPropOptional (Proxy :: _ "args") (CA.array CA.string) - $ CA.record +backendConfigCodec :: CJ.Codec BackendConfig +backendConfigCodec = CJ.named "BackendConfig" $ CJ.object + $ CJ.recordProp (Proxy :: _ "cmd") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "args") (CJ.array CJ.string) + $ CJ.record type PackageBuildOptionsInput = { censorProjectWarnings :: Maybe CensorBuildWarnings @@ -154,12 +156,12 @@ type PackageBuildOptionsInput = , pedanticPackages :: Maybe Boolean } -packageBuildOptionsCodec :: JsonCodec PackageBuildOptionsInput -packageBuildOptionsCodec = CA.object "PackageBuildOptionsInput" - $ CA.recordPropOptional (Proxy :: _ "censorProjectWarnings") censorBuildWarningsCodec - $ CA.recordPropOptional (Proxy :: _ "strict") CA.boolean - $ CA.recordPropOptional (Proxy :: _ "pedanticPackages") CA.boolean - $ CA.record +packageBuildOptionsCodec :: CJ.Codec PackageBuildOptionsInput +packageBuildOptionsCodec = CJ.named "PackageBuildOptionsInput" $ CJ.object + $ CJ.recordPropOptional (Proxy :: _ "censorProjectWarnings") censorBuildWarningsCodec + $ CJ.recordPropOptional (Proxy :: _ "strict") CJ.boolean + $ CJ.recordPropOptional (Proxy :: _ "pedanticPackages") CJ.boolean + $ CJ.record type BundleConfig = { minify :: Maybe Boolean @@ -170,15 +172,15 @@ type BundleConfig = , extraArgs :: Maybe (Array String) } -bundleConfigCodec :: JsonCodec BundleConfig -bundleConfigCodec = CA.object "BundleConfig" - $ CA.recordPropOptional (Proxy :: _ "minify") CA.boolean - $ CA.recordPropOptional (Proxy :: _ "module") CA.string - $ CA.recordPropOptional (Proxy :: _ "outfile") CA.string - $ CA.recordPropOptional (Proxy :: _ "platform") bundlePlatformCodec - $ CA.recordPropOptional (Proxy :: _ "type") bundleTypeCodec - $ CA.recordPropOptional (Proxy :: _ "extraArgs") (CA.array CA.string) - $ CA.record +bundleConfigCodec :: CJ.Codec BundleConfig +bundleConfigCodec = CJ.named "BundleConfig" $ CJ.object + $ CJ.recordPropOptional (Proxy :: _ "minify") CJ.boolean + $ CJ.recordPropOptional (Proxy :: _ "module") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "outfile") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "platform") bundlePlatformCodec + $ CJ.recordPropOptional (Proxy :: _ "type") bundleTypeCodec + $ CJ.recordPropOptional (Proxy :: _ "extraArgs") (CJ.array CJ.string) + $ CJ.record data BundlePlatform = BundleNode | BundleBrowser @@ -193,8 +195,8 @@ parsePlatform = case _ of "browser" -> Just BundleBrowser _ -> Nothing -bundlePlatformCodec :: JsonCodec BundlePlatform -bundlePlatformCodec = CA.Sum.enumSum show (parsePlatform) +bundlePlatformCodec :: CJ.Codec BundlePlatform +bundlePlatformCodec = CJ.Sum.enumSum show (parsePlatform) -- | This is the equivalent of "WithMain" in the old Spago. -- App bundles with a main fn, while Module does not include a main. @@ -211,8 +213,8 @@ parseBundleType = case _ of "module" -> Just BundleModule _ -> Nothing -bundleTypeCodec :: JsonCodec BundleType -bundleTypeCodec = CA.Sum.enumSum show (parseBundleType) +bundleTypeCodec :: CJ.Codec BundleType +bundleTypeCodec = CJ.Sum.enumSum show (parseBundleType) newtype Dependencies = Dependencies (Map PackageName (Maybe Range)) @@ -233,8 +235,8 @@ instance Semigroup Dependencies where instance Monoid Dependencies where mempty = Dependencies (Map.empty) -dependenciesCodec :: JsonCodec Dependencies -dependenciesCodec = Profunctor.dimap to from $ CA.array dependencyCodec +dependenciesCodec :: CJ.Codec Dependencies +dependenciesCodec = Profunctor.dimap to from $ CJ.array dependencyCodec where packageSingletonCodec = Internal.Codec.packageMap spagoRangeCodec @@ -254,23 +256,23 @@ dependenciesCodec = Profunctor.dimap to from $ CA.array dependencyCodec Right m -> rmap Just $ unsafeFromJust (List.head (Map.toUnfoldable m)) ) - dependencyCodec :: JsonCodec (Either PackageName (Map PackageName Range)) - dependencyCodec = CA.codec' decode encode + dependencyCodec :: CJ.Codec (Either PackageName (Map PackageName Range)) + dependencyCodec = Codec.codec' decode encode where encode = case _ of - Left name -> CA.encode PackageName.codec name - Right singletonMap -> CA.encode packageSingletonCodec singletonMap + Left name -> CJ.encode PackageName.codec name + Right singletonMap -> CJ.encode packageSingletonCodec singletonMap decode json = - map Left (CA.decode PackageName.codec json) - <|> map Right (CA.decode packageSingletonCodec json) + map Left (Codec.decode PackageName.codec json) + <|> map Right (Codec.decode packageSingletonCodec json) widestRange :: Range widestRange = Either.fromRight' (\_ -> unsafeCrashWith "Fake range failed") $ Range.parse ">=0.0.0 <2147483647.0.0" -spagoRangeCodec :: JsonCodec Range -spagoRangeCodec = CA.prismaticCodec "SpagoRange" rangeParse printSpagoRange CA.string +spagoRangeCodec :: CJ.Codec Range +spagoRangeCodec = CJ.prismaticCodec "SpagoRange" rangeParse printSpagoRange CJ.string where rangeParse str = if str == "*" then Just widestRange @@ -288,13 +290,13 @@ type WorkspaceConfig = , buildOpts :: Maybe WorkspaceBuildOptionsInput } -workspaceConfigCodec :: JsonCodec WorkspaceConfig -workspaceConfigCodec = CA.object "WorkspaceConfig" - $ CA.recordPropOptional (Proxy :: _ "packageSet") setAddressCodec - $ CA.recordPropOptional (Proxy :: _ "backend") backendConfigCodec - $ CA.recordPropOptional (Proxy :: _ "buildOpts") buildOptionsCodec - $ CA.recordPropOptional (Proxy :: _ "extraPackages") (Internal.Codec.packageMap extraPackageCodec) - $ CA.record +workspaceConfigCodec :: CJ.Codec WorkspaceConfig +workspaceConfigCodec = CJ.named "WorkspaceConfig" $ CJ.object + $ CJ.recordPropOptional (Proxy :: _ "packageSet") setAddressCodec + $ CJ.recordPropOptional (Proxy :: _ "backend") backendConfigCodec + $ CJ.recordPropOptional (Proxy :: _ "buildOpts") buildOptionsCodec + $ CJ.recordPropOptional (Proxy :: _ "extraPackages") (Internal.Codec.packageMap extraPackageCodec) + $ CJ.record type WorkspaceBuildOptionsInput = { output :: Maybe FilePath @@ -302,12 +304,12 @@ type WorkspaceBuildOptionsInput = , statVerbosity :: Maybe StatVerbosity } -buildOptionsCodec :: JsonCodec WorkspaceBuildOptionsInput -buildOptionsCodec = CA.object "WorkspaceBuildOptionsInput" - $ CA.recordPropOptional (Proxy :: _ "output") CA.string - $ CA.recordPropOptional (Proxy :: _ "censorLibraryWarnings") censorBuildWarningsCodec - $ CA.recordPropOptional (Proxy :: _ "statVerbosity") statVerbosityCodec - $ CA.record +buildOptionsCodec :: CJ.Codec WorkspaceBuildOptionsInput +buildOptionsCodec = CJ.named "WorkspaceBuildOptionsInput" $ CJ.object + $ CJ.recordPropOptional (Proxy :: _ "output") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "censorLibraryWarnings") censorBuildWarningsCodec + $ CJ.recordPropOptional (Proxy :: _ "statVerbosity") statVerbosityCodec + $ CJ.record data CensorBuildWarnings = CensorAllWarnings @@ -320,22 +322,22 @@ instance Show CensorBuildWarnings where CensorAllWarnings -> "CensorAllWarnings" CensorSpecificWarnings censorTests -> "(CensorSpecificWarnings " <> show censorTests <> ")" -censorBuildWarningsCodec :: JsonCodec CensorBuildWarnings -censorBuildWarningsCodec = CA.codec' parse print +censorBuildWarningsCodec :: CJ.Codec CensorBuildWarnings +censorBuildWarningsCodec = Codec.codec' decode encode where - print = case _ of - CensorAllWarnings -> CA.encode CA.string "all" - CensorSpecificWarnings censorTests -> CA.encode (CA.array warningCensorTestCodec) $ NonEmptyArray.toArray censorTests + encode = case _ of + CensorAllWarnings -> CJ.encode CJ.string "all" + CensorSpecificWarnings censorTests -> CJ.encode (CJ.array warningCensorTestCodec) $ NonEmptyArray.toArray censorTests - parse j = decodeNoneOrAll <|> decodeSpecific + decode json = decodeNoneOrAll <|> decodeSpecific where - decodeNoneOrAll = CA.decode CA.string j >>= case _ of + decodeNoneOrAll = except $ CJ.decode CJ.string json >>= case _ of "all" -> Right CensorAllWarnings - _ -> Left $ CA.UnexpectedValue j + _ -> Left $ CJ.DecodeError.basic "Expected 'all' for all warnings" decodeSpecific = CensorSpecificWarnings <$> do - arr <- CA.decode (CA.array warningCensorTestCodec) j - Either.note (CA.UnexpectedValue j) $ NonEmptyArray.fromArray arr + arr <- Codec.decode (CJ.array warningCensorTestCodec) json + except $ Either.note (CJ.DecodeError.basic "Expected array of warning codes") $ NonEmptyArray.fromArray arr data WarningCensorTest = ByCode String @@ -347,19 +349,19 @@ instance Show WarningCensorTest where ByCode str -> "(ByCode" <> str <> ")" ByMessagePrefix str -> "(ByMessagePrefix" <> str <> ")" -warningCensorTestCodec :: JsonCodec WarningCensorTest -warningCensorTestCodec = CA.codec' parse print +warningCensorTestCodec :: CJ.Codec WarningCensorTest +warningCensorTestCodec = Codec.codec' decode encode where - print = case _ of - ByCode str -> CA.encode CA.string str - ByMessagePrefix str -> CA.encode byMessagePrefixCodec { byPrefix: str } + encode = case _ of + ByCode str -> CJ.encode CJ.string str + ByMessagePrefix str -> CJ.encode byMessagePrefixCodec { byPrefix: str } - parse j = byCode <|> byPrefix + decode json = byCode <|> byPrefix where - byCode = ByCode <$> CA.decode CA.string j - byPrefix = (ByMessagePrefix <<< _.byPrefix) <$> CA.decode byMessagePrefixCodec j + byCode = ByCode <$> Codec.decode CJ.string json + byPrefix = (ByMessagePrefix <<< _.byPrefix) <$> Codec.decode byMessagePrefixCodec json - byMessagePrefixCodec = CAR.object "ByMessagePrefix" { byPrefix: CA.string } + byMessagePrefixCodec = CJ.named "ByMessagePrefix" $ CJ.Record.object { byPrefix: CJ.string } data StatVerbosity = NoStats @@ -372,8 +374,8 @@ instance Show StatVerbosity where CompactStats -> "CompactStats" VerboseStats -> "VerboseStats" -statVerbosityCodec :: JsonCodec StatVerbosity -statVerbosityCodec = CA.Sum.enumSum print parse +statVerbosityCodec :: CJ.Codec StatVerbosity +statVerbosityCodec = CJ.Sum.enumSum print parse where print = case _ of NoStats -> "no-stats" @@ -392,20 +394,20 @@ data SetAddress derive instance Eq SetAddress -setAddressCodec :: JsonCodec SetAddress -setAddressCodec = CA.codec' decode encode +setAddressCodec :: CJ.Codec SetAddress +setAddressCodec = Codec.codec' decode encode where - setFromRegistryCodec = CAR.object "SetFromRegistry" { registry: Version.codec } - setFromUrlCodec = CAR.object "SetFromUrl" { url: CA.string, hash: CAR.optional Sha256.codec } - setFromPathCodec = CAR.object "SetFromPath" { path: CA.string } + setFromRegistryCodec = CJ.named "SetFromRegistry" $ CJ.Record.object { registry: Version.codec } + setFromUrlCodec = CJ.named "SetFromUrl" $ CJ.Record.object { url: CJ.string, hash: CJ.Record.optional Sha256.codec } + setFromPathCodec = CJ.named "SetFromPath" $ CJ.Record.object { path: CJ.string } - encode (SetFromRegistry r) = CA.encode setFromRegistryCodec r - encode (SetFromUrl u) = CA.encode setFromUrlCodec u - encode (SetFromPath p) = CA.encode setFromPathCodec p + encode (SetFromRegistry r) = CJ.encode setFromRegistryCodec r + encode (SetFromUrl u) = CJ.encode setFromUrlCodec u + encode (SetFromPath p) = CJ.encode setFromPathCodec p - decode json = map SetFromRegistry (CA.decode setFromRegistryCodec json) - <|> map SetFromUrl (CA.decode setFromUrlCodec json) - <|> map SetFromPath (CA.decode setFromPathCodec json) + decode json = map SetFromRegistry (Codec.decode setFromRegistryCodec json) + <|> map SetFromUrl (Codec.decode setFromUrlCodec json) + <|> map SetFromPath (Codec.decode setFromPathCodec json) data ExtraPackage = ExtraLocalPackage LocalPackage @@ -413,19 +415,19 @@ data ExtraPackage derive instance Eq ExtraPackage -extraPackageCodec :: JsonCodec ExtraPackage -extraPackageCodec = CA.codec' decode encode +extraPackageCodec :: CJ.Codec ExtraPackage +extraPackageCodec = Codec.codec' decode encode where - encode (ExtraLocalPackage lp) = CA.encode localPackageCodec lp - encode (ExtraRemotePackage rp) = CA.encode remotePackageCodec rp + encode (ExtraLocalPackage lp) = CJ.encode localPackageCodec lp + encode (ExtraRemotePackage rp) = CJ.encode remotePackageCodec rp - decode json = map ExtraLocalPackage (CA.decode localPackageCodec json) - <|> map ExtraRemotePackage (CA.decode remotePackageCodec json) + decode json = map ExtraLocalPackage (Codec.decode localPackageCodec json) + <|> map ExtraRemotePackage (Codec.decode remotePackageCodec json) type LocalPackage = { path :: FilePath } -localPackageCodec :: JsonCodec LocalPackage -localPackageCodec = CAR.object "LocalPackage" { path: CA.string } +localPackageCodec :: CJ.Codec LocalPackage +localPackageCodec = CJ.named "LocalPackage" $ CJ.Record.object { path: CJ.string } data RemotePackage = RemoteGitPackage GitPackage @@ -434,16 +436,16 @@ data RemotePackage derive instance Eq RemotePackage -remotePackageCodec :: JsonCodec RemotePackage -remotePackageCodec = CA.codec' decode encode +remotePackageCodec :: CJ.Codec RemotePackage +remotePackageCodec = Codec.codec' decode encode where - encode (RemoteRegistryVersion v) = CA.encode Version.codec v - encode (RemoteGitPackage p) = CA.encode gitPackageCodec p - encode (RemoteLegacyPackage p) = CA.encode legacyPackageSetEntryCodec p + encode (RemoteRegistryVersion v) = CJ.encode Version.codec v + encode (RemoteGitPackage p) = CJ.encode gitPackageCodec p + encode (RemoteLegacyPackage p) = CJ.encode legacyPackageSetEntryCodec p - decode json = map RemoteRegistryVersion (CA.decode Version.codec json) - <|> map RemoteGitPackage (CA.decode gitPackageCodec json) - <|> map RemoteLegacyPackage (CA.decode legacyPackageSetEntryCodec json) + decode json = map RemoteRegistryVersion (Codec.decode Version.codec json) + <|> map RemoteGitPackage (Codec.decode gitPackageCodec json) + <|> map RemoteLegacyPackage (Codec.decode legacyPackageSetEntryCodec json) type GitPackage = { git :: String @@ -452,13 +454,13 @@ type GitPackage = , dependencies :: Maybe Dependencies } -gitPackageCodec :: JsonCodec GitPackage -gitPackageCodec = CA.object "GitPackage" - $ CA.recordProp (Proxy :: _ "git") CA.string - $ CA.recordProp (Proxy :: _ "ref") CA.string - $ CA.recordPropOptional (Proxy :: _ "subdir") CA.string - $ CA.recordPropOptional (Proxy :: _ "dependencies") dependenciesCodec - $ CA.record +gitPackageCodec :: CJ.Codec GitPackage +gitPackageCodec = CJ.named "GitPackage" $ CJ.object + $ CJ.recordProp (Proxy :: _ "git") CJ.string + $ CJ.recordProp (Proxy :: _ "ref") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "subdir") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "dependencies") dependenciesCodec + $ CJ.record -- | The format of a legacy packages.json package set entry for an individual -- | package. @@ -468,9 +470,9 @@ type LegacyPackageSetEntry = , version :: String } -legacyPackageSetEntryCodec :: JsonCodec LegacyPackageSetEntry -legacyPackageSetEntryCodec = CA.object "LegacyPackageSetEntry" - $ CA.recordProp (Proxy :: _ "repo") CA.string - $ CA.recordProp (Proxy :: _ "version") CA.string - $ CA.recordProp (Proxy :: _ "dependencies") (CA.array PackageName.codec) - $ CA.record +legacyPackageSetEntryCodec :: CJ.Codec LegacyPackageSetEntry +legacyPackageSetEntryCodec = CJ.named "LegacyPackageSetEntry" $ CJ.object + $ CJ.recordProp (Proxy :: _ "repo") CJ.string + $ CJ.recordProp (Proxy :: _ "version") CJ.string + $ CJ.recordProp (Proxy :: _ "dependencies") (CJ.array PackageName.codec) + $ CJ.record diff --git a/core/src/FS.purs b/core/src/FS.purs index 9ffe402d2..a25594e31 100644 --- a/core/src/FS.purs +++ b/core/src/FS.purs @@ -24,7 +24,8 @@ module Spago.FS import Spago.Core.Prelude -import Data.Codec.Argonaut as CA +import Codec.JSON.DecodeError as CJ.DecodeError +import Data.Codec.JSON as CJ import Data.String as String import Effect.Aff as Aff import Effect.Uncurried (EffectFn2, runEffectFn2) @@ -84,32 +85,32 @@ chmod :: forall m. MonadAff m => FilePath -> Perms -> m Unit chmod path perms = liftAff $ FS.Aff.chmod path perms -- | Encode data as formatted JSON and write it to the provided filepath -writeJsonFile :: forall a. JsonCodec a -> FilePath -> a -> Aff Unit +writeJsonFile :: forall a. CJ.Codec a -> FilePath -> a -> Aff Unit writeJsonFile codec path = FS.Aff.writeTextFile UTF8 path <<< (_ <> "\n") <<< Json.printJson codec -- | Decode data from a JSON file at the provided filepath -readJsonFile :: forall a. JsonCodec a -> FilePath -> Aff (Either String a) +readJsonFile :: forall a. CJ.Codec a -> FilePath -> Aff (Either String a) readJsonFile codec path = do result <- Aff.attempt $ FS.Aff.readTextFile UTF8 path - pure (lmap Aff.message result >>= Json.parseJson codec >>> lmap CA.printJsonDecodeError) + pure (lmap Aff.message result >>= Json.parseJson codec >>> lmap CJ.DecodeError.print) -- | Encode data as formatted YAML and write it to the provided filepath -writeYamlFile :: forall a. JsonCodec a -> FilePath -> a -> Aff Unit +writeYamlFile :: forall a. CJ.Codec a -> FilePath -> a -> Aff Unit writeYamlFile codec path = FS.Aff.writeTextFile UTF8 path <<< (_ <> "\n") <<< String.trim <<< Yaml.printYaml codec -- | Decode data from a YAML file at the provided filepath -readYamlFile :: forall a. JsonCodec a -> FilePath -> Aff (Either String a) +readYamlFile :: forall a. CJ.Codec a -> FilePath -> Aff (Either String a) readYamlFile codec path = do result <- Aff.attempt $ FS.Aff.readTextFile UTF8 path - pure (lmap Aff.message result >>= Yaml.parseYaml codec >>> lmap CA.printJsonDecodeError) + pure (lmap Aff.message result >>= Yaml.parseYaml codec >>> lmap CJ.DecodeError.print) writeYamlDocFile :: forall a. FilePath -> Yaml.YamlDoc a -> Aff Unit writeYamlDocFile path = FS.Aff.writeTextFile UTF8 path <<< (_ <> "\n") <<< String.trim <<< Yaml.toString -readYamlDocFile :: forall a. JsonCodec a -> FilePath -> Aff (Either String { doc :: Yaml.YamlDoc a, yaml :: a }) +readYamlDocFile :: forall a. CJ.Codec a -> FilePath -> Aff (Either String { doc :: Yaml.YamlDoc a, yaml :: a }) readYamlDocFile codec path = do result <- Aff.attempt $ FS.Aff.readTextFile UTF8 path - pure (lmap Aff.message result >>= Yaml.parseYamlDoc codec >>> lmap CA.printJsonDecodeError) + pure (lmap Aff.message result >>= Yaml.parseYamlDoc codec >>> lmap CJ.DecodeError.print) stat :: forall m. MonadAff m => FilePath -> m (Either Error Stats) stat path = liftAff $ try (FS.Aff.stat path) diff --git a/core/src/Json.purs b/core/src/Json.purs index 63d95f533..8cc061065 100644 --- a/core/src/Json.purs +++ b/core/src/Json.purs @@ -2,21 +2,32 @@ module Spago.Json where import Prelude -import Data.Argonaut.Core as Argonaut -import Data.Argonaut.Parser as Argonaut.Parser +import Codec.JSON.DecodeError (DecodeError(..)) +import Codec.JSON.DecodeError as CJ.DecodeError +import Data.Array as Array import Data.Bifunctor (lmap) -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.Either (Either) +import JSON as JSON +import JSON.Path as JSON.Path -- | Print a type as a formatted JSON string -printJson :: forall a. JsonCodec a -> a -> String -printJson codec = Argonaut.stringifyWithIndent 2 <<< CA.encode codec +printJson :: forall a. CJ.Codec a -> a -> String +printJson codec = JSON.printIndented <<< CJ.encode codec -- | Print a type as a JSON string without formatting -stringifyJson :: forall a. JsonCodec a -> a -> String -stringifyJson codec = Argonaut.stringify <<< CA.encode codec +stringifyJson :: forall a. CJ.Codec a -> a -> String +stringifyJson codec = JSON.print <<< CJ.encode codec -- | Parse a type from a string of JSON data. -parseJson :: forall a. JsonCodec a -> String -> Either JsonDecodeError a -parseJson codec = CA.decode codec <=< lmap (\err -> CA.TypeMismatch ("JSON: " <> err)) <<< Argonaut.Parser.jsonParser +parseJson :: forall a. CJ.Codec a -> String -> Either CJ.DecodeError a +parseJson codec = CJ.decode codec <=< lmap (\err -> CJ.DecodeError.basic ("JSON: " <> err)) <<< JSON.parse + +-- | Pretty print a DecodeError that happened while parsing a spago.yaml file +printConfigError :: CJ.DecodeError -> Array String +printConfigError (DecodeError { path, message, causes }) = + case Array.null causes of + -- If there are causes then we can just throw away the current message and recurse in + false -> Array.foldMap printConfigError causes + -- If there are none, then we have reached a leaf, and can print the actual error + true -> [ JSON.Path.print path <> ": " <> message ] diff --git a/core/src/Log.purs b/core/src/Log.purs index 9f2472b11..a24f893cd 100644 --- a/core/src/Log.purs +++ b/core/src/Log.purs @@ -32,7 +32,7 @@ import Data.Array ((:)) import Data.Array as Array import Data.Array.NonEmpty (NonEmptyArray) import Data.Array.NonEmpty (toArray) as NEA -import Data.Codec.Argonaut (JsonCodec) +import Data.Codec.JSON as CJ import Data.DateTime.Instant (Instant) import Data.DateTime.Instant as Instant import Data.Either (Either(..)) @@ -44,7 +44,7 @@ import Data.String.Utils as Strings import Data.Time.Duration (Milliseconds) import Data.Traversable (traverse) import Dodo (Doc, print, twoSpaces) -import Dodo (indent, break) as DodoExport +import Dodo (indent, break, softBreak) as DodoExport import Dodo as Dodo import Dodo as Log import Dodo.Ansi (GraphicsParam) @@ -195,8 +195,8 @@ rightOrDieWith' value toMsg = case value of die' $ toMsg err data OutputFormat a - = OutputJson (JsonCodec a) a - | OutputYaml (JsonCodec a) a + = OutputJson (CJ.Codec a) a + | OutputYaml (CJ.Codec a) a | OutputTable { titles :: Array String, rows :: Array (Array String) } | OutputLines (Array String) diff --git a/core/src/Prelude.purs b/core/src/Prelude.purs index b3d365b96..d490731fc 100644 --- a/core/src/Prelude.purs +++ b/core/src/Prelude.purs @@ -10,13 +10,13 @@ import Prelude import Control.Alt ((<|>)) as Extra import Control.Monad.Error.Class (class MonadError, class MonadThrow, try, catchError) as Extra +import Control.Monad.Except (Except, except) as Extra import Control.Monad.Reader (ask, asks, local) as Extra import Control.Monad.Reader (class MonadAsk, class MonadReader, ReaderT, runReaderT) import Control.Monad.State (StateT) as Extra import Data.Array ((..)) as Extra import Data.Array.NonEmpty (NonEmptyArray) as Extra import Data.Bifunctor (bimap, rmap, lmap) as Extra -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) as Extra import Data.DateTime.Instant (Instant) as Extra import Data.Either (Either(..), isLeft, isRight, either, hush) as Extra import Data.Filterable (partition, partitionMap) as Extra diff --git a/core/src/Yaml.purs b/core/src/Yaml.purs index eb4168661..4e3d2edeb 100644 --- a/core/src/Yaml.purs +++ b/core/src/Yaml.purs @@ -11,18 +11,18 @@ module Spago.Yaml import Prelude -import Data.Argonaut.Core as Core +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Bifunctor (lmap) -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.Either (Either(..)) import Data.Function.Uncurried (Fn1, Fn3, runFn1, runFn3) +import JSON (JSON) -foreign import yamlParserImpl :: forall a. Fn3 (String -> a) (Core.Json -> a) String a +foreign import yamlParserImpl :: forall a. Fn3 (String -> a) (JSON -> a) String a foreign import yamlDocParserImpl :: forall a b. Fn3 (String -> a) (YamlDoc b -> a) String a -foreign import toJsonImpl :: forall a. Fn1 (YamlDoc a) Core.Json +foreign import toJsonImpl :: forall a. Fn1 (YamlDoc a) JSON foreign import toStringImpl :: forall a. Fn1 (YamlDoc a) String @@ -34,33 +34,33 @@ parser yaml = runFn3 yamlDocParserImpl Left Right yaml toString :: forall a. YamlDoc a -> String toString = runFn1 toStringImpl -toJson :: forall a. YamlDoc a -> Core.Json +toJson :: forall a. YamlDoc a -> JSON toJson = runFn1 toJsonImpl -- | Converts a `Toml` value to a JSON string. To retrieve a string from a `Toml` -- | string value, see `fromString`. -foreign import stringify :: Core.Json -> String +foreign import stringify :: JSON -> String -- | Converts a `Json` value to a JSON string. -- | The first `Int` argument specifies the amount of white space characters to use as indentation. -- | This number is capped at 10 (if it is greater, the value is just 10). Values less than 1 indicate that no space should be used. -foreign import stringifyWithIndent :: Int -> Core.Json -> String +foreign import stringifyWithIndent :: Int -> JSON -> String -- | Print a type as a formatted YAML string -printYaml :: forall a. JsonCodec a -> a -> String -printYaml codec = stringifyWithIndent 2 <<< CA.encode codec +printYaml :: forall a. CJ.Codec a -> a -> String +printYaml codec = stringifyWithIndent 2 <<< CJ.encode codec -- | Print a type as a YAML string without formatting -stringifyYaml :: forall a. JsonCodec a -> a -> String -stringifyYaml codec = stringify <<< CA.encode codec +stringifyYaml :: forall a. CJ.Codec a -> a -> String +stringifyYaml codec = stringify <<< CJ.encode codec -- | Parse a type from a string of JSON data. -parseYaml :: forall a. JsonCodec a -> String -> Either JsonDecodeError a +parseYaml :: forall a. CJ.Codec a -> String -> Either CJ.DecodeError a parseYaml codec = parseYamlDoc codec >>> map _.yaml -- | Parse a type from a string of YAML data. -parseYamlDoc :: forall a. JsonCodec a -> String -> Either JsonDecodeError { doc :: YamlDoc a, yaml :: a } +parseYamlDoc :: forall a. CJ.Codec a -> String -> Either CJ.DecodeError { doc :: YamlDoc a, yaml :: a } parseYamlDoc codec yamlStr = do - doc <- lmap (\err -> CA.TypeMismatch ("YAML: " <> err)) (parser yamlStr) - yaml <- CA.decode codec (toJson doc) + doc <- lmap (\err -> CJ.DecodeError.basic ("YAML: " <> err)) (parser yamlStr) + yaml <- CJ.decode codec (toJson doc) pure { doc, yaml } diff --git a/docs-search/client-halogen/spago.yaml b/docs-search/client-halogen/spago.yaml index 16d416a48..49cfe8ae9 100644 --- a/docs-search/client-halogen/spago.yaml +++ b/docs-search/client-halogen/spago.yaml @@ -3,9 +3,8 @@ package: dependencies: - aff - aff-promise - - argonaut-core - arrays - - codec-argonaut + - codec-json - control - css - docs-search-common @@ -16,6 +15,7 @@ package: - halogen-css - halogen-subscriptions - js-uri + - json - language-purescript - lists - markdown-it diff --git a/docs-search/client-halogen/src/Docs/Search/BrowserEngine.purs b/docs-search/client-halogen/src/Docs/Search/BrowserEngine.purs index e6b2c31db..82abc6c64 100644 --- a/docs-search/client-halogen/src/Docs/Search/BrowserEngine.purs +++ b/docs-search/client-halogen/src/Docs/Search/BrowserEngine.purs @@ -1,22 +1,12 @@ -- | A search engine that is used in the browser. module Docs.Search.BrowserEngine where -import Docs.Search.Config as Config -import Docs.Search.Engine (Engine, EngineState, Index) -import Docs.Search.ModuleIndex as ModuleIndex -import Docs.Search.PackageIndex as PackageIndex -import Docs.Search.SearchResult (SearchResult) -import Docs.Search.SearchResult as SearchResult -import Docs.Search.TypeIndex (TypeIndex) -import Docs.Search.TypeIndex as TypeIndex -import Docs.Search.Types (PartId, URL) - import Prelude import Control.Promise (Promise, toAffE) -import Data.Argonaut.Core (Json) import Data.Array as Array -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Either (hush) import Data.List (List) import Data.List as List @@ -28,8 +18,18 @@ import Data.Search.Trie (Trie) import Data.Search.Trie as Trie import Data.String.CodeUnits as String import Data.Tuple (Tuple(..)) +import Docs.Search.Config as Config +import Docs.Search.Engine (Engine, EngineState, Index) +import Docs.Search.ModuleIndex as ModuleIndex +import Docs.Search.PackageIndex as PackageIndex +import Docs.Search.SearchResult (SearchResult) +import Docs.Search.SearchResult as SearchResult +import Docs.Search.TypeIndex (TypeIndex) +import Docs.Search.TypeIndex as TypeIndex +import Docs.Search.Types (PartId, URL) import Effect (Effect) import Effect.Aff (Aff, try) +import JSON (JSON) newtype PartialIndex = PartialIndex (Map PartId Index) @@ -64,13 +64,13 @@ query index@(PartialIndex indexMap) input = do try $ toAffE $ loadIndex_ partId $ Config.mkIndexPartLoadPath partId let - resultsCodec :: CA.JsonCodec (Array (Tuple String (Array SearchResult))) - resultsCodec = CA.array $ CA.tuple CA.string $ CA.array SearchResult.searchResultCodec + resultsCodec :: CJ.Codec (Array (Tuple String (Array SearchResult))) + resultsCodec = CJ.array $ CJ.Common.tuple CJ.string $ CJ.array SearchResult.searchResultCodec mbNewTrie :: Maybe (Trie Char (List SearchResult)) mbNewTrie = do json <- hush eiPartJson - results <- hush $ CA.decode resultsCodec json + results <- hush $ CJ.decode resultsCodec json pure $ Array.foldr insertResults mempty results case mbNewTrie of @@ -115,4 +115,4 @@ browserSearchEngine = foreign import loadIndex_ :: PartId -> URL - -> Effect (Promise Json) + -> Effect (Promise JSON) diff --git a/docs-search/common/spago.yaml b/docs-search/common/spago.yaml index e1d943ba6..258645134 100644 --- a/docs-search/common/spago.yaml +++ b/docs-search/common/spago.yaml @@ -10,12 +10,15 @@ package: - aff-promise - argonaut-core - arrays - - codec-argonaut + - bifunctors + - codec + - codec-json - control - effect - either - exceptions - foldable-traversable + - json - json-codecs - language-purescript - lists @@ -31,4 +34,5 @@ package: - strings - transformers - tuples + - unsafe-coerce - variant diff --git a/docs-search/common/src/Docs/Search/DocsJson.purs b/docs-search/common/src/Docs/Search/DocsJson.purs index 4abef894f..e43a3845e 100644 --- a/docs-search/common/src/Docs/Search/DocsJson.purs +++ b/docs-search/common/src/Docs/Search/DocsJson.purs @@ -5,26 +5,25 @@ module Docs.Search.DocsJson import Prelude -import Data.Codec.Argonaut (JsonCodec) -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.Profunctor (wrapIso) import Language.PureScript.AST.SourcePos (SourceSpan(..), SourcePos(..)) -sourceSpanCodec :: JsonCodec SourceSpan +sourceSpanCodec :: CJ.Codec SourceSpan sourceSpanCodec = - wrapIso SourceSpan $ - CAR.object "SourceSpan" + wrapIso SourceSpan $ CJ.named "SourceSpan" $ + CJ.Record.object { start: sourcePosCodec , end: sourcePosCodec - , name: CA.string + , name: CJ.string } -sourcePosCodec :: JsonCodec SourcePos +sourcePosCodec :: CJ.Codec SourcePos sourcePosCodec = - wrapIso SourcePos $ - CAR.object "SourcePos" - { line: CA.int - , column: CA.int + wrapIso SourcePos $ CJ.named "SourcePos" $ + CJ.Record.object + { line: CJ.int + , column: CJ.int } diff --git a/docs-search/common/src/Docs/Search/JsonCodec.purs b/docs-search/common/src/Docs/Search/JsonCodec.purs index d547262e5..8ff097581 100644 --- a/docs-search/common/src/Docs/Search/JsonCodec.purs +++ b/docs-search/common/src/Docs/Search/JsonCodec.purs @@ -6,15 +6,19 @@ module Docs.Search.JsonCodec import Prelude -import Prim.Row (class Cons) +import Codec.JSON.DecodeError as CJ +import Codec.JSON.DecodeError as CJ.DecodeError import Codec.Json.Unidirectional.Value (DecodeError, printDecodeError) +import Control.Monad.Except (Except, except) import Data.Argonaut.Core (Json) -import Data.Codec.Argonaut (JsonDecodeError(..)) +import Data.Bifunctor (lmap) import Data.Either (Either) -import Data.Profunctor.Choice (left) import Data.Symbol (class IsSymbol) import Data.Variant (Variant, inj) +import JSON (JSON) +import Prim.Row (class Cons) import Type.Proxy (Proxy(..)) +import Unsafe.Coerce (unsafeCoerce) -- | Equivalent to `Data.Variant.inj`, just uses a Visible Type Application instead of Proxy -- | Useful for deriving codecs for sum types @@ -24,9 +28,11 @@ inject = inj (Proxy :: _ sym) fromUni :: forall a . (Json -> Either DecodeError a) - -> (Json -> Either JsonDecodeError a) - -fromUni = map $ left convertError + -> (JSON -> Except CJ.DecodeError a) +fromUni fn = except <<< lmap convertError <<< (fn <<< toArgonaut) where - convertError :: DecodeError -> JsonDecodeError - convertError = printDecodeError >>> TypeMismatch + convertError :: DecodeError -> CJ.DecodeError + convertError = printDecodeError >>> CJ.DecodeError.basic + + toArgonaut :: JSON -> Json + toArgonaut = unsafeCoerce diff --git a/docs-search/common/src/Docs/Search/Loader.purs b/docs-search/common/src/Docs/Search/Loader.purs index 64835394c..aeddd820d 100644 --- a/docs-search/common/src/Docs/Search/Loader.purs +++ b/docs-search/common/src/Docs/Search/Loader.purs @@ -1,36 +1,36 @@ module Docs.Search.Loader where -import Docs.Search.Types (GlobalIdentifier, URL) - import Prelude +import Codec.JSON.DecodeError as CJ.DecodeError import Control.Monad.Error.Class (throwError) import Control.Promise (Promise, toAffE) -import Data.Argonaut.Core (Json) -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON.Common as CJ import Data.Either (either) import Data.Newtype (unwrap) +import Docs.Search.Types (GlobalIdentifier, URL) import Effect (Effect) import Effect.Aff (Aff) import Effect.Exception (error) +import JSON (JSON) load :: forall a - . CA.JsonCodec a + . CJ.Codec a -> GlobalIdentifier -> URL -> Aff a load codec globalIdentifier url = do json <- toAffE (loadFromScript globalIdentifier url) - either throw pure $ CA.decode codec json + either throw pure $ CJ.decode codec json where throw err = throwError $ error $ "Couldn't load content from window." <> unwrap globalIdentifier <> ": " - <> CA.printJsonDecodeError err + <> CJ.DecodeError.print err foreign import loadFromScript :: GlobalIdentifier -> URL - -> Effect (Promise Json) + -> Effect (Promise JSON) diff --git a/docs-search/common/src/Docs/Search/Meta.purs b/docs-search/common/src/Docs/Search/Meta.purs index b737dfb7d..86b96223c 100644 --- a/docs-search/common/src/Docs/Search/Meta.purs +++ b/docs-search/common/src/Docs/Search/Meta.purs @@ -2,8 +2,8 @@ module Docs.Search.Meta where import Prelude -import Data.Codec.Argonaut (JsonCodec) -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Docs.Search.Config as Config import Docs.Search.Loader as Loader import Docs.Search.Types (PackageName) @@ -14,9 +14,9 @@ type Meta = { localPackageName :: PackageName } -metaCodec :: JsonCodec Meta -metaCodec = - CAR.object "Meta" +metaCodec :: CJ.Codec Meta +metaCodec = CJ.named "Meta" $ + CJ.Record.object { localPackageName: Package.packageNameCodec } diff --git a/docs-search/common/src/Docs/Search/ModuleIndex.purs b/docs-search/common/src/Docs/Search/ModuleIndex.purs index bcc195e6e..62b35a5ee 100644 --- a/docs-search/common/src/Docs/Search/ModuleIndex.purs +++ b/docs-search/common/src/Docs/Search/ModuleIndex.purs @@ -1,21 +1,12 @@ module Docs.Search.ModuleIndex where -import Docs.Search.Config as Config -import Docs.Search.Declarations (Declarations(..)) -import Docs.Search.Extra (stringToList) -import Docs.Search.Score (Scores, getPackageScore) -import Docs.Search.SearchResult (SearchResult(..)) -import Docs.Search.Types (ModuleName, PackageInfo(..), PackageScore) -import Docs.Search.Types as Package - import Prelude import Control.Monad.State (execState, modify_) import Control.Promise (Promise, toAffE) -import Data.Argonaut.Core (Json) import Data.Array as Array -import Data.Codec.Argonaut (JsonCodec) -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Either (hush) import Data.Foldable (foldl) import Data.Lens ((%~)) @@ -34,15 +25,23 @@ import Data.String.Common (split, toLower) as String import Data.String.Pattern (Pattern(..)) import Data.Traversable (foldr, for_) import Data.Tuple.Nested ((/\)) +import Docs.Search.Config as Config +import Docs.Search.Declarations (Declarations(..)) +import Docs.Search.Extra (stringToList) +import Docs.Search.Score (Scores, getPackageScore) +import Docs.Search.SearchResult (SearchResult(..)) +import Docs.Search.Types (ModuleName, PackageInfo(..), PackageScore) +import Docs.Search.Types as Package import Effect (Effect) import Effect.Aff (Aff) +import JSON (JSON) import Type.Proxy (Proxy(..)) -- | Module index that is actually stored in a JS file. type PackedModuleIndex = Map PackageInfo (Set ModuleName) -packedModuleIndexCodec :: JsonCodec PackedModuleIndex -packedModuleIndexCodec = CA.map Package.packageInfoCodec (CA.set Package.moduleNameCodec) +packedModuleIndexCodec :: CJ.Codec PackedModuleIndex +packedModuleIndexCodec = CJ.Common.map Package.packageInfoCodec (CJ.Common.set Package.moduleNameCodec) -- | "Expanded" module index that can be queried quickly. type ModuleIndex = @@ -123,11 +122,11 @@ mkPackedModuleIndex (Declarations trie) moduleNames = loadModuleIndex :: Aff PackedModuleIndex loadModuleIndex = do json <- toAffE $ load Config.moduleIndexLoadPath - pure $ fromMaybe Map.empty $ hush $ CA.decode packedModuleIndexCodec json + pure $ fromMaybe Map.empty $ hush $ CJ.decode packedModuleIndexCodec json foreign import load :: String - -> Effect (Promise Json) + -> Effect (Promise JSON) _modulePackages :: forall a b rest. (a -> b) -> { modulePackages :: a | rest } -> { modulePackages :: b | rest } _modulePackages = prop (Proxy :: Proxy "modulePackages") diff --git a/docs-search/common/src/Docs/Search/PackageIndex.purs b/docs-search/common/src/Docs/Search/PackageIndex.purs index 0f9b0f1b5..048037fb2 100644 --- a/docs-search/common/src/Docs/Search/PackageIndex.purs +++ b/docs-search/common/src/Docs/Search/PackageIndex.purs @@ -1,18 +1,12 @@ module Docs.Search.PackageIndex where -import Docs.Search.JsonCodec as JsonCodec -import Docs.Search.Config as Config -import Docs.Search.Extra (stringToList) -import Docs.Search.Score (Scores, getPackageScoreForPackageName) -import Docs.Search.Types (PackageScore) -import Docs.Search.Types as Package -import Docs.Search.Loader as Loader - import Prelude +import Data.Argonaut.Core (Json) import Data.Array as Array -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Codec as Codec +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe) @@ -20,7 +14,16 @@ import Data.Newtype (unwrap) import Data.Search.Trie (Trie) import Data.Search.Trie as Trie import Data.Tuple as Tuple +import Docs.Search.Config as Config +import Docs.Search.Extra (stringToList) +import Docs.Search.JsonCodec as JsonCodec +import Docs.Search.Loader as Loader +import Docs.Search.Score (Scores, getPackageScoreForPackageName) +import Docs.Search.Types (PackageScore) +import Docs.Search.Types as Package import Effect.Aff (Aff) +import JSON (JSON) +import Unsafe.Coerce (unsafeCoerce) import Web.Bower.PackageMeta (PackageMeta(..), PackageName) import Web.Bower.PackageMeta as Bower @@ -32,14 +35,14 @@ type PackageResult = , repository :: Maybe String } -packageResultCodec :: CA.JsonCodec PackageResult -packageResultCodec = - CAR.object "PackageResult" $ +packageResultCodec :: CJ.Codec PackageResult +packageResultCodec = CJ.named "PackageResult" $ + CJ.Record.object { name: Package.packageNameCodec - , description: CAR.optional CA.string + , description: CJ.Record.optional CJ.string , score: Package.packageScoreCodec - , dependencies: CA.array Package.packageNameCodec - , repository: CAR.optional CA.string + , dependencies: CJ.array Package.packageNameCodec + , repository: CJ.Record.optional CJ.string } type PackageIndex = Trie Char PackageResult @@ -83,8 +86,8 @@ loadPackageIndex :: Aff PackageIndex loadPackageIndex = mkPackageIndex <$> Loader.load packageInfoCodec Config.packageInfoItem Config.packageInfoLoadPath where - packageInfoCodec :: CA.JsonCodec PackageInfo - packageInfoCodec = CA.array packageResultCodec + packageInfoCodec :: CJ.Codec PackageInfo + packageInfoCodec = CJ.array packageResultCodec mkPackageIndex :: PackageInfo -> PackageIndex mkPackageIndex = @@ -107,8 +110,8 @@ queryPackageIndex index query = , results: Array.fromFoldable $ Trie.queryValues (stringToList query) index } -packageMetaCodec :: CA.JsonCodec PackageMeta -packageMetaCodec = CA.codec' decode encode +packageMetaCodec :: CJ.Codec PackageMeta +packageMetaCodec = Codec.codec' decode encode where decode = JsonCodec.fromUni Bower.toPackageMeta - encode = Bower.fromPackageMeta + encode = Bower.fromPackageMeta >>> (unsafeCoerce :: Json -> JSON) diff --git a/docs-search/common/src/Docs/Search/SearchResult.purs b/docs-search/common/src/Docs/Search/SearchResult.purs index 3418fe4a4..5bdf3865f 100644 --- a/docs-search/common/src/Docs/Search/SearchResult.purs +++ b/docs-search/common/src/Docs/Search/SearchResult.purs @@ -2,10 +2,9 @@ module Docs.Search.SearchResult where import Prelude -import Data.Codec.Argonaut (JsonCodec) -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR -import Data.Codec.Argonaut.Variant as CAV +import Data.Codec.JSON.Variant as CJ.Variant +import Data.Codec.JSON.Common as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.Either (Either(..)) import Data.Maybe (Maybe(..)) import Data.Newtype (class Newtype, un) @@ -49,36 +48,36 @@ data ResultInfo | TypeAliasResult | ExternKindResult -resultInfoCodec :: CA.JsonCodec ResultInfo +resultInfoCodec :: CJ.Codec ResultInfo resultInfoCodec = - dimap toVariant fromVariant $ CAV.variantMatch - { data: Right $ - CAR.object "DataResult" - { typeArguments: CA.array TypeDecoder.typeArgumentCodec + dimap toVariant fromVariant $ CJ.Variant.variantMatch + { data: Right $ CJ.named "DataResult" $ + CJ.Record.object + { typeArguments: CJ.array TypeDecoder.typeArgumentCodec , dataDeclType: TypeDecoder.dataDeclTypeCodec } , externData: Right TypeDecoder.typeCodec - , typeSynonym: Right $ - CAR.object "TypeSynonymResult" - { arguments: CA.array TypeDecoder.typeArgumentCodec + , typeSynonym: Right $ CJ.named "TypeSynonymResult" $ + CJ.Record.object + { arguments: CJ.array TypeDecoder.typeArgumentCodec , type: TypeDecoder.typeCodec } - , dataConstructor: Right $ - CAR.object "DataConstructorResult" + , dataConstructor: Right $ CJ.named "DataConstructorResult" $ + CJ.Record.object { dataDeclType: TypeDecoder.dataDeclTypeCodec , type: TypeDecoder.typeCodec } - , typeClassMember: Right $ - CAR.object "TypeClassMemberResult" + , typeClassMember: Right $ CJ.named "TypeClassMemberResult" $ + CJ.Record.object { type: TypeDecoder.typeCodec , typeClass: TypeDecoder.qualifiedNameCodec - , typeClassArguments: CA.array TypeDecoder.typeArgumentCodec + , typeClassArguments: CJ.array TypeDecoder.typeArgumentCodec } - , typeClass: Right $ - CAR.object "TypeClassResult" + , typeClass: Right $ CJ.named "TypeClassResult" $ + CJ.Record.object { fundeps: TypeDecoder.funDepsCodec - , arguments: CA.array TypeDecoder.typeArgumentCodec - , superclasses: CA.array TypeDecoder.constraintCodec + , arguments: CJ.array TypeDecoder.typeArgumentCodec + , superclasses: CJ.array TypeDecoder.constraintCodec } , value: Right TypeDecoder.typeCodec , valueAlias: Left unit @@ -138,16 +137,16 @@ newtype SearchResult = SearchResult derive instance Newtype SearchResult _ -searchResultCodec :: JsonCodec SearchResult -searchResultCodec = wrapIso SearchResult $ - CAR.object "SearchResult" - { name: wrapIso Identifier $ CA.string - , comments: CAR.optional CA.string - , hashAnchor: CA.string +searchResultCodec :: CJ.Codec SearchResult +searchResultCodec = wrapIso SearchResult $ CJ.named "SearchResult" $ + CJ.Record.object + { name: wrapIso Identifier $ CJ.string + , comments: CJ.Record.optional CJ.string + , hashAnchor: CJ.string , moduleName: Package.moduleNameCodec , packageInfo: Package.packageInfoCodec , score: Package.packageScoreCodec - , sourceSpan: CAR.optional Docs.sourceSpanCodec + , sourceSpan: CJ.Record.optional Docs.sourceSpanCodec , info: resultInfoCodec } diff --git a/docs-search/common/src/Docs/Search/TypeDecoder.purs b/docs-search/common/src/Docs/Search/TypeDecoder.purs index a1ddb69f0..1ad0e1601 100644 --- a/docs-search/common/src/Docs/Search/TypeDecoder.purs +++ b/docs-search/common/src/Docs/Search/TypeDecoder.purs @@ -16,59 +16,70 @@ import Prelude import Prim hiding (Constraint) import Codec.Json.Unidirectional.Value as Json -import Data.Argonaut.Core as Argonaut -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Argonaut.Core (Json) +import Data.Codec as Codec +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common +import Data.Codec.JSON.Record as CJ.Record import Data.Maybe (Maybe) import Data.Tuple (Tuple) import Docs.Search.DocTypes (AnyOpName, ChildDeclaration(..), ChildDeclarationInfo(..), ClassName, Constraint(..), Constraint', ConstraintData(..), ConstructorName, DataDeclType(..), Declaration(..), DeclarationInfo(..), DocLink(..), DocModule(..), GithubRepo(..), GithubUser(..), Ident(..), InPackage(..), InternalIdentData(..), KindInfo(..), Label(..), LinkLocation(..), LinksContext(..), ManifestError(..), ModuleName(..), Name(..), Namespace, NotYetKnown(..), OpName(..), OpNameType, Package(..), PackageError(..), ProperName(..), ProperNameType, Qualified(..), QualifiedBy(..), RowListItem(..), SkolemScope(..), SourceAnn(..), SourceConstraint, SourcePos(..), SourceSpan(..), SourceType, Type(..), Type', TypeName, TypeOpName, TypeVarVisibility(..), UploadedPackage, ValueOpName, VerifiedPackage, WildcardData(..), _ss, _sss, byNullSourcePos, compareConstraint, compareMaybeType, compareType, eqConstraint, eqMaybeType, eqType, fromChildDeclaration, fromChildDeclarationInfo, fromConstraint, fromConstraintData, fromDataDeclType, fromDeclaration, fromDeclarationInfo, fromDocModule, fromGithubRepo, fromGithubUser, fromISO8601, fromIdent, fromInPackage, fromInternalIdentData, fromKindInfo, fromLabel, fromModuleName, fromNotYetKnown, fromOpName, fromPackage, fromProperName, fromQualified, fromQualifiedBy, fromSkolemScope, fromSourceAnn, fromSourcePos, fromSourceSpan, fromType, fromTypeVarVisibility, fromVersion, fromWildcardData, hh_mm, kindType, nullSourceAnn, nullSourcePos, nullSourceSpan, showDataDeclType, srcTypeConstructor, toAsConstrantUnit, toChildDeclaration, toChildDeclarationInfo, toConstraint', toConstraintData, toConstraintUnit, toDataDeclType, toDeclaration, toDeclarationInfo, toDocModule, toFunDeps, toGithubRepo, toGithubUser, toISO8601, toIdent, toInPackage, toInternalIdentData, toKindInfo, toLabel, toModuleName, toNotYetKnown, toOpName, toPackage, toProperName, toQualified, toQualifiedBy, toSkolemScope, toSourceAnn, toSourceConstraint, toSourcePos, toSourceSpan, toSourceType, toType', toTypeArguments, toTypeUnit, toTypeVarVisibility, toUploadedPackage, toVersion, toWildcardData, yyyy_mm_dd) as ReExport import Docs.Search.DocTypes (Constraint, DataDeclType, ProperName, Qualified, Type') import Docs.Search.DocTypes as DocTypes import Docs.Search.JsonCodec as JsonCodec +import JSON (JSON) +import JSON as JSON +import Unsafe.Coerce (unsafeCoerce) type QualifiedName tag = Qualified (ProperName tag) -qualifiedNameCodec :: forall tag. CA.JsonCodec (QualifiedName tag) -qualifiedNameCodec = CA.codec' +qualifiedNameCodec :: forall tag. CJ.Codec (QualifiedName tag) +qualifiedNameCodec = Codec.codec' (JsonCodec.fromUni $ DocTypes.toQualified DocTypes.toProperName) - (DocTypes.fromQualified DocTypes.fromProperName) + (fromArgonaut <<< DocTypes.fromQualified DocTypes.fromProperName) type FunDeps = Array FunDep type FunDep = Tuple (Array String) (Array String) -funDepsCodec :: CA.JsonCodec FunDeps -funDepsCodec = CA.array $ CA.tuple typeVarsCodec typeVarsCodec +funDepsCodec :: CJ.Codec FunDeps +funDepsCodec = CJ.array $ CJ.Common.tuple typeVarsCodec typeVarsCodec where - typeVarsCodec = CA.array CA.string + typeVarsCodec = CJ.array CJ.string type TypeArgument = { name :: String , kind :: Maybe Type' } -typeArgumentCodec :: CA.JsonCodec TypeArgument -typeArgumentCodec = - CAR.object "TypeArgument" - { name: CA.string - , kind: CAR.optional typeCodec +typeArgumentCodec :: CJ.Codec TypeArgument +typeArgumentCodec = CJ.named "TypeArgument" $ + CJ.Record.object + { name: CJ.string + , kind: CJ.Record.optional typeCodec } -dataDeclTypeCodec :: CA.JsonCodec DataDeclType +dataDeclTypeCodec :: CJ.Codec DataDeclType dataDeclTypeCodec = - CA.codec' - (JsonCodec.fromUni $ DocTypes.toDataDeclType) - (DocTypes.fromDataDeclType) + Codec.codec' + (JsonCodec.fromUni DocTypes.toDataDeclType) + (fromArgonaut <<< DocTypes.fromDataDeclType) -typeCodec :: CA.JsonCodec Type' +typeCodec :: CJ.Codec Type' typeCodec = - CA.codec' - (JsonCodec.fromUni $ DocTypes.toTypeUnit) - (DocTypes.fromType $ const Argonaut.jsonNull) + Codec.codec' + (JsonCodec.fromUni DocTypes.toTypeUnit) + (fromArgonaut <<< DocTypes.fromType \_ -> toArgonaut JSON.null) type Constraint' = Constraint Unit -constraintCodec :: CA.JsonCodec Constraint' +constraintCodec :: CJ.Codec Constraint' constraintCodec = - CA.codec' + Codec.codec' (JsonCodec.fromUni $ DocTypes.toConstraintUnit Json.toJNull) - (DocTypes.fromConstraint $ const Argonaut.jsonNull) + (fromArgonaut <<< DocTypes.fromConstraint \_ -> toArgonaut JSON.null) + +fromArgonaut :: Json -> JSON +fromArgonaut = unsafeCoerce + +toArgonaut :: JSON -> Json +toArgonaut = unsafeCoerce diff --git a/docs-search/common/src/Docs/Search/TypeIndex.purs b/docs-search/common/src/Docs/Search/TypeIndex.purs index 0670dee50..42284ab80 100644 --- a/docs-search/common/src/Docs/Search/TypeIndex.purs +++ b/docs-search/common/src/Docs/Search/TypeIndex.purs @@ -1,28 +1,28 @@ -- | Partial type index, can be loaded on demand in the browser. module Docs.Search.TypeIndex where -import Docs.Search.Config as Config -import Docs.Search.Declarations (resultsForDeclaration) -import Docs.Search.DocTypes (Type') -import Docs.Search.Score (Scores) -import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..)) -import Docs.Search.SearchResult as SearchResult -import Docs.Search.TypeQuery (TypeQuery) -import Docs.Search.TypeShape (shapeOfType, shapeOfTypeQuery, stringifyShape) - import Prelude + import Control.Promise (Promise, toAffE) -import Data.Argonaut.Core (Json) import Data.Array as Array -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON as CJ import Data.Either (hush) import Data.Foldable (fold, foldr) import Data.Map (Map) import Data.Map as Map import Data.Maybe (Maybe(..), fromMaybe', isJust) import Data.Newtype (class Newtype, over) +import Docs.Search.Config as Config +import Docs.Search.Declarations (resultsForDeclaration) +import Docs.Search.DocTypes (Type') +import Docs.Search.Score (Scores) +import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..)) +import Docs.Search.SearchResult as SearchResult +import Docs.Search.TypeQuery (TypeQuery) +import Docs.Search.TypeShape (shapeOfType, shapeOfTypeQuery, stringifyShape) import Effect (Effect) import Effect.Aff (Aff, try) +import JSON (JSON) import Language.PureScript.Docs.Types (DocModule(..)) newtype TypeIndex = TypeIndex (Map String (Maybe (Array SearchResult))) @@ -83,7 +83,7 @@ lookup key index@(TypeIndex map) = (\_ -> { index: insert key Nothing index, results: [] }) do json <- hush eiJson - results <- hush (CA.decode (CA.array SearchResult.searchResultCodec) json) + results <- hush (CJ.decode (CJ.array SearchResult.searchResultCodec) json) pure { index: insert key (Just results) index, results } where @@ -105,4 +105,4 @@ query typeIndex typeQuery = do foreign import lookup_ :: String -> String - -> Effect (Promise Json) + -> Effect (Promise JSON) diff --git a/docs-search/common/src/Docs/Search/Types.purs b/docs-search/common/src/Docs/Search/Types.purs index 76af6015c..9c730ea37 100644 --- a/docs-search/common/src/Docs/Search/Types.purs +++ b/docs-search/common/src/Docs/Search/Types.purs @@ -15,9 +15,8 @@ module Docs.Search.Types import Prelude -import Data.Codec.Argonaut (JsonCodec) -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Variant as CAV +import Data.Codec.JSON.Variant as CJ.Variant +import Data.Codec.JSON.Common as CJ import Data.Either (Either(..)) import Data.Generic.Rep (class Generic) import Data.Newtype (class Newtype) @@ -38,8 +37,8 @@ derive newtype instance eqIdentifier :: Eq Identifier derive newtype instance ordIdentifier :: Ord Identifier derive newtype instance showIdentifier :: Show Identifier -moduleNameCodec :: JsonCodec ModuleName -moduleNameCodec = wrapIso ModuleName CA.string +moduleNameCodec :: CJ.Codec ModuleName +moduleNameCodec = wrapIso ModuleName CJ.string data PackageInfo = LocalPackage | Builtin | Package PackageName | UnknownPackage @@ -49,12 +48,12 @@ derive instance genericPackageInfo :: Generic PackageInfo _ instance showPackageInfo :: Show PackageInfo where show = genericShow -packageNameCodec :: JsonCodec PackageName -packageNameCodec = wrapIso PackageName CA.string +packageNameCodec :: CJ.Codec PackageName +packageNameCodec = wrapIso PackageName CJ.string -packageInfoCodec :: JsonCodec PackageInfo +packageInfoCodec :: CJ.Codec PackageInfo packageInfoCodec = - dimap toVariant fromVariant $ CAV.variantMatch + dimap toVariant fromVariant $ CJ.Variant.variantMatch { local: Left unit , builtin: Left unit , unknown: Left unit @@ -84,8 +83,8 @@ derive newtype instance semiringPackageScore :: Semiring PackageScore derive newtype instance ringPackageScore :: Ring PackageScore derive newtype instance showPackageScore :: Show PackageScore -packageScoreCodec :: JsonCodec PackageScore -packageScoreCodec = wrapIso PackageScore CA.int +packageScoreCodec :: CJ.Codec PackageScore +packageScoreCodec = wrapIso PackageScore CJ.int newtype URL = URL String diff --git a/docs-search/index/spago.yaml b/docs-search/index/spago.yaml index 23be5c1d2..e2bf0c7a5 100644 --- a/docs-search/index/spago.yaml +++ b/docs-search/index/spago.yaml @@ -6,14 +6,14 @@ package: - aff - argonaut-core - arrays - - codec-argonaut + - codec-json - console - - control - docs-search-common - effect - either - foldable-traversable - identity + - json - json-codecs - language-purescript - lists @@ -21,6 +21,7 @@ package: - newtype - node-buffer - node-fs + - node-path - node-process - ordered-collections - prelude @@ -29,6 +30,7 @@ package: - string-parsers - strings - tuples + - unsafe-coerce test: main: Test.Docs.Search.Main dependencies: diff --git a/docs-search/index/src/Docs/Search/IndexBuilder.purs b/docs-search/index/src/Docs/Search/IndexBuilder.purs index e5e3f0834..4038bc2fe 100644 --- a/docs-search/index/src/Docs/Search/IndexBuilder.purs +++ b/docs-search/index/src/Docs/Search/IndexBuilder.purs @@ -1,32 +1,17 @@ module Docs.Search.IndexBuilder where -import Docs.Search.Config as Config -import Docs.Search.Declarations (Declarations(..), mkDeclarations) -import Docs.Search.Extra ((>#>)) -import Docs.Search.Meta (Meta) -import Docs.Search.Meta as Meta -import Docs.Search.ModuleIndex (PackedModuleIndex) -import Docs.Search.ModuleIndex as ModuleIndex -import Docs.Search.ModuleParser as ModuleParser -import Docs.Search.PackageIndex (PackageInfo) -import Docs.Search.PackageIndex as PackageIndex -import Docs.Search.Score (mkScores) -import Docs.Search.SearchResult (SearchResult) -import Docs.Search.SearchResult as SearchResult -import Docs.Search.TypeIndex (TypeIndex) -import Docs.Search.TypeIndex as TypeIndex -import Docs.Search.Types (ModuleName, PackageName, PartId) - import Prelude -import Data.Argonaut.Core (stringify) -import Data.Argonaut.Parser (jsonParser) +import Codec.JSON.DecodeError as CJ.DecodeError +import Codec.Json.Unidirectional.Value as CJ.Codec +import Data.Argonaut.Core (Json) import Data.Array (concat) -import Data.Foldable as Fold import Data.Array as Array -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Either (Either(..), either) import Data.Foldable (sum) +import Data.Foldable as Fold import Data.List (List) import Data.List as List import Data.Map (Map) @@ -43,20 +28,38 @@ import Data.String.Pattern (Pattern(..), Replacement(..)) import Data.Traversable (for, for_) import Data.Tuple (Tuple(..), fst) import Data.Tuple.Nested ((/\)) +import Docs.Search.Config as Config +import Docs.Search.Declarations (Declarations(..), mkDeclarations) +import Docs.Search.DocTypes (DocModule) +import Docs.Search.DocTypes as Docs +import Docs.Search.Extra ((>#>)) +import Docs.Search.Meta (Meta) +import Docs.Search.Meta as Meta +import Docs.Search.ModuleIndex (PackedModuleIndex) +import Docs.Search.ModuleIndex as ModuleIndex +import Docs.Search.ModuleParser as ModuleParser +import Docs.Search.PackageIndex (PackageInfo) +import Docs.Search.PackageIndex as PackageIndex +import Docs.Search.Score (mkScores) +import Docs.Search.SearchResult (SearchResult) +import Docs.Search.SearchResult as SearchResult +import Docs.Search.TypeIndex (TypeIndex) +import Docs.Search.TypeIndex as TypeIndex +import Docs.Search.Types (ModuleName, PackageName, PartId) import Effect (Effect) import Effect.Aff (Aff, launchAff_, parallel, sequential) import Effect.Class (liftEffect) import Effect.Console (log) +import JSON (JSON) +import JSON as JSON import Node.Encoding (Encoding(UTF8)) import Node.FS.Aff (mkdir, readFile, readTextFile, readdir, stat, writeFile, writeTextFile) import Node.FS.Stats (isDirectory, isFile) import Node.FS.Sync (exists) import Node.Path as Path import Node.Process as Process +import Unsafe.Coerce (unsafeCoerce) import Web.Bower.PackageMeta (PackageMeta(..)) -import Codec.Json.Unidirectional.Value as JsonCodec -import Docs.Search.DocTypes (DocModule) -import Docs.Search.DocTypes as Docs type Config = { docsFiles :: Array String @@ -172,8 +175,8 @@ decodeDocsJsons cfg@{ docsFiles } = do let eiResult :: Either String DocModule eiResult = - jsonParser contents >>= - (Docs.toDocModule >>> left JsonCodec.printDecodeError) + JSON.parse contents >>= + ((unsafeCoerce :: JSON -> Json) >>> Docs.toDocModule >>> left CJ.Codec.printDecodeError) case eiResult of Left error -> do @@ -237,9 +240,9 @@ decodeBowerJsons { bowerFiles } = do join <$> withExisting jsonFileName \contents -> either (logError jsonFileName) (pure <<< Just) - ( jsonParser contents >>= - CA.decode (PackageIndex.packageMetaCodec) >>> - left CA.printJsonDecodeError + ( JSON.parse contents >>= + CJ.decode (PackageIndex.packageMetaCodec) >>> + left CJ.DecodeError.print ) where @@ -257,7 +260,7 @@ writeTypeIndex :: TypeIndex -> Aff Unit writeTypeIndex typeIndex = for_ entries \(Tuple typeShape results) -> do writeTextFile UTF8 (unwrap Config.typeIndexDirectory <> "/" <> typeShape <> ".js") - (mkHeader typeShape <> stringify (CA.encode codec results)) + (mkHeader typeShape <> JSON.print (CJ.encode codec results)) where mkHeader typeShape = "// This file was generated by docs-search\n" @@ -265,7 +268,7 @@ writeTypeIndex typeIndex = <> typeShape <> "\"] = " - codec = CA.maybe $ CA.array SearchResult.searchResultCodec + codec = CJ.Common.maybe $ CJ.array SearchResult.searchResultCodec entries :: Array _ entries = Map.toUnfoldableUnordered (unwrap typeIndex) @@ -274,7 +277,7 @@ writePackageInfo :: PackageInfo -> Aff Unit writePackageInfo packageInfo = do writeTextFile UTF8 (unwrap Config.packageInfoPath) $ - header <> stringify (CA.encode (CA.array PackageIndex.packageResultCodec) packageInfo) + header <> JSON.print (CJ.encode (CJ.array PackageIndex.packageResultCodec) packageInfo) where header = "window.DocsSearchPackageIndex = " @@ -282,14 +285,14 @@ writePackageInfo packageInfo = do writeModuleIndex :: PackedModuleIndex -> Aff Unit writeModuleIndex moduleIndex = do writeTextFile UTF8 (unwrap Config.moduleIndexPath) $ - header <> stringify (CA.encode ModuleIndex.packedModuleIndexCodec moduleIndex) + header <> JSON.print (CJ.encode ModuleIndex.packedModuleIndexCodec moduleIndex) where header = "window.DocsSearchModuleIndex = " writeMeta :: Meta -> Aff Unit writeMeta meta = do writeTextFile UTF8 (unwrap Config.metaPath) $ - header <> stringify (CA.encode Meta.metaCodec meta) + header <> JSON.print (CJ.encode Meta.metaCodec meta) where header = "window." <> unwrap Config.metaItem <> " = " @@ -341,9 +344,9 @@ writeIndex { generatedDocs } = getIndex >>> \resultsMap -> do <> "\"] = " writeTextFile UTF8 (generatedDocs <> Config.mkIndexPartPath indexPartId) $ - header <> stringify (CA.encode codec results) + header <> JSON.print (CJ.encode codec results) where - codec = CA.array $ CA.tuple CA.string $ CA.array SearchResult.searchResultCodec + codec = CJ.array $ CJ.Common.tuple CJ.string $ CJ.array SearchResult.searchResultCodec patchHtml :: String -> Maybe String patchHtml html = diff --git a/flake.lock b/flake.lock index 47faf1c5b..918bb0a1f 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ "slimlock": "slimlock" }, "locked": { - "lastModified": 1712144948, - "narHash": "sha256-hPnJ8BUr7FeoaX21Mr+asfJU5d6+E228Rn+YS2GPZ5w=", + "lastModified": 1717764611, + "narHash": "sha256-qz1c0JSvKOx2vpNcIZ37EAHtx2gJCJuIURQB2jcNh3c=", "owner": "thomashoneyman", "repo": "purescript-overlay", - "rev": "5cc5505bc99898eb13aa075841810aeb7181e98c", + "rev": "c8833cdd4cbabd195421eb55b11a4e4fb91e537a", "type": "github" }, "original": { diff --git a/spago.lock b/spago.lock index 45707e50e..06062bc2e 100644 --- a/spago.lock +++ b/spago.lock @@ -5,9 +5,8 @@ workspace: dependencies: - aff - aff-promise - - argonaut-core - arrays - - codec-argonaut + - codec-json - control - css - docs-search-common @@ -18,6 +17,7 @@ workspace: - halogen-css - halogen-subscriptions - js-uri + - json - language-purescript - lists - markdown-it @@ -45,7 +45,7 @@ workspace: - bifunctors - catenable-lists - codec - - codec-argonaut + - codec-json - colors - console - const @@ -83,6 +83,7 @@ workspace: - js-date - js-promise - js-uri + - json - json-codecs - language-purescript - lazy @@ -144,12 +145,15 @@ workspace: - aff-promise - argonaut-core - arrays - - codec-argonaut + - bifunctors + - codec + - codec-json - control - effect - either - exceptions - foldable-traversable + - json - json-codecs - language-purescript - lists @@ -165,6 +169,7 @@ workspace: - strings - transformers - tuples + - unsafe-coerce - variant test_dependencies: [] build_plan: @@ -174,7 +179,7 @@ workspace: - arrays - bifunctors - codec - - codec-argonaut + - codec-json - console - const - contravariant @@ -197,6 +202,7 @@ workspace: - identity - integers - invariant + - json - json-codecs - language-purescript - lazy @@ -242,14 +248,14 @@ workspace: - aff - argonaut-core - arrays - - codec-argonaut + - codec-json - console - - control - docs-search-common - effect - either - foldable-traversable - identity + - json - json-codecs - language-purescript - lists @@ -257,6 +263,7 @@ workspace: - newtype - node-buffer - node-fs + - node-path - node-process - ordered-collections - prelude @@ -265,6 +272,7 @@ workspace: - string-parsers - strings - tuples + - unsafe-coerce test_dependencies: - exceptions - spec @@ -279,7 +287,7 @@ workspace: - bifunctors - catenable-lists - codec - - codec-argonaut + - codec-json - console - const - contravariant @@ -306,6 +314,7 @@ workspace: - integers - invariant - js-date + - json - json-codecs - language-purescript - lazy @@ -360,24 +369,38 @@ workspace: path: ./ dependencies: - aff + - aff-promise - affjax - affjax-node + - ansi - argonaut-core - arrays - - codec-argonaut + - avar + - codec + - codec-json + - console + - control - datetime + - docs-search-common - docs-search-index - dodo-printer - effect - either + - enums + - filterable - foldable-traversable - foreign-object + - formatters - functions + - graphs - http-methods - integers + - json - lists - maybe + - newtype - node-buffer + - node-child-process - node-execa - node-fs - node-path @@ -387,18 +410,24 @@ workspace: - ordered-collections - parallel - partial + - posix-types - prelude - profunctor - record - refs - registry-lib + - routing-duplex - spago-core - strings - - stringutils - transformers - tuples + - unfoldable + - unicode - unsafe-coerce test_dependencies: + - exceptions + - identity + - quickcheck - spec build_plan: - aff @@ -414,7 +443,7 @@ workspace: - bifunctors - catenable-lists - codec - - codec-argonaut + - codec-json - console - const - contravariant @@ -449,6 +478,7 @@ workspace: - js-date - js-timers - js-uri + - json - json-codecs - language-cst-parser - language-purescript @@ -521,20 +551,24 @@ workspace: dependencies: - aff - arrays - - codec-argonaut - - console - - js-date + - avar + - codec-json + - control + - foldable-traversable - lists - - node-fs + - maybe - node-path - node-process + - now - optparse - ordered-collections + - prelude - record - - refs - registry-lib - spago - spago-core + - strings + - transformers - unsafe-coerce test_dependencies: [] build_plan: @@ -551,7 +585,7 @@ workspace: - bifunctors - catenable-lists - codec - - codec-argonaut + - codec-json - console - const - contravariant @@ -587,6 +621,7 @@ workspace: - js-date - js-timers - js-uri + - json - json-codecs - language-cst-parser - language-purescript @@ -662,10 +697,10 @@ workspace: path: core dependencies: - aff - - argonaut-core - arrays - bifunctors - - codec-argonaut + - codec + - codec-json - console - control - datetime @@ -677,6 +712,8 @@ workspace: - foldable-traversable - functions - identity + - integers + - json - lists - maybe - newtype @@ -684,6 +721,7 @@ workspace: - node-fs - node-path - node-process + - now - ordered-collections - partial - prelude @@ -691,13 +729,13 @@ workspace: - refs - registry-lib - strings + - stringutils - transformers - tuples test_dependencies: [] build_plan: - aff - ansi - - argonaut-core - arraybuffer-types - arrays - assert @@ -705,7 +743,7 @@ workspace: - bifunctors - catenable-lists - codec - - codec-argonaut + - codec-json - console - const - contravariant @@ -734,6 +772,7 @@ workspace: - invariant - js-date - js-uri + - json - language-cst-parser - lazy - lcg @@ -768,6 +807,7 @@ workspace: - safe-coerce - st - strings + - stringutils - tailrec - transformers - tuples @@ -779,11 +819,12 @@ workspace: - variant package_set: address: - registry: 50.8.0 + registry: 51.0.0 compiler: ">=0.15.15 <0.16.0" content: abc-parser: 2.0.1 ace: 9.1.0 + address-rfc2821: 0.1.1 aff: 7.1.0 aff-bus: 6.0.0 aff-coroutines: 9.0.0 @@ -793,6 +834,7 @@ workspace: affjax-node: 1.0.0 affjax-web: 1.0.0 ansi: 7.0.0 + apexcharts: 0.5.0 applicative-phases: 1.0.0 argonaut: 9.0.0 argonaut-aeson-generic: 0.4.1 @@ -826,6 +868,7 @@ workspace: canvas-action: 9.0.0 cartesian: 1.0.6 catenable-lists: 7.0.0 + cbor-stream: 1.0.4 chameleon: 1.0.0 chameleon-halogen: 1.0.3 chameleon-react-basic: 1.1.0 @@ -854,9 +897,11 @@ workspace: coroutines: 7.0.0 css: 6.0.0 css-frameworks: 1.0.1 + csv-stream: 2.0.2 data-mvc: 0.0.2 datetime: 6.1.0 datetime-parsing: 0.2.0 + debounce: 0.1.0 debug: 6.0.2 decimals: 7.1.0 default-values: 1.0.1 @@ -866,6 +911,7 @@ workspace: distributive: 6.0.0 dom-filereader: 7.0.0 dom-indexed: 12.0.0 + dom-simple: 0.4.0 dotenv: 4.0.3 droplet: 0.6.0 dts: 1.0.0 @@ -985,7 +1031,7 @@ workspace: js-promise-aff: 1.0.0 js-timers: 6.1.0 js-uri: 3.1.0 - json: 1.0.0 + json: 1.1.0 json-codecs: 5.0.0 justifill: 0.5.0 jwt: 0.0.9 @@ -1051,6 +1097,7 @@ workspace: node-process: 11.2.0 node-readline: 8.1.0 node-sqlite3: 8.0.0 + node-stream-pipes: 1.4.1 node-streams: 9.0.0 node-tls: 0.3.1 node-url: 7.0.1 @@ -1090,7 +1137,7 @@ workspace: pointed-list: 0.5.1 polymorphic-vectors: 4.0.0 posix-types: 6.0.0 - postgresql: 1.3.0 + postgresql: 1.6.3 precise: 6.0.0 precise-datetime: 7.0.0 prelude: 6.0.1 @@ -1121,10 +1168,11 @@ workspace: react-basic-storybook: 2.0.0 react-dom: 8.0.0 react-halo: 3.0.0 - react-icons: 1.1.4 + react-icons: 1.1.5 react-markdown: 0.1.0 react-testing-library: 4.0.1 react-virtuoso: 1.0.0 + reactix: 0.6.1 read: 1.0.1 recharts: 1.1.0 record: 4.0.0 @@ -1154,6 +1202,7 @@ workspace: simple-emitter: 3.0.1 simple-i18n: 2.0.1 simple-json: 9.0.0 + simple-json-generics: 0.2.1 simple-ulid: 3.0.0 sized-matrices: 1.0.0 sized-vectors: 5.0.2 @@ -1186,6 +1235,7 @@ workspace: thermite: 6.3.1 thermite-dom: 0.3.1 these: 6.0.0 + toestand: 0.9.0 transformation-matrix: 1.0.1 transformers: 6.0.0 tree-rose: 4.0.2 @@ -1200,6 +1250,7 @@ workspace: typelevel-prelude: 7.0.0 typelevel-regex: 0.0.3 typelevel-rows: 0.1.0 + typisch: 0.4.0 uint: 7.0.0 ulid: 3.0.1 uncurried-transformers: 1.1.0 @@ -1261,6 +1312,7 @@ workspace: z3: 0.0.2 zipperarray: 2.0.0 extra_packages: + codec-json: 1.2.0 dodo-printer: git: https://github.com/natefaubion/purescript-dodo-printer.git ref: v2.2.1 @@ -1411,7 +1463,7 @@ workspace: - tuples registry-lib: git: https://github.com/purescript/registry-dev.git - ref: 6feb62497ef7c3668bea89d11e9c2edb3a12dbd4 + ref: be0d7ffd1c16aa70e8f065a928e941ebc053c013 subdir: lib search-trie: git: https://github.com/klntsky/purescript-search-trie.git @@ -1640,15 +1692,16 @@ packages: dependencies: - bifunctors - profunctor - codec-argonaut: + codec-json: type: registry - version: 10.0.0 - integrity: sha256-n80U8KiBk333qfQwDobSZWiyNg9BA3CL/EwFznIdRwI= + version: 1.2.0 + integrity: sha256-59+uYYe/5uTFa/Q6EqF8ekvP/Y4SOjUNfwIqIYtNiGI= dependencies: - - argonaut-core - codec - foreign-object + - json - ordered-collections + - transformers - type-equality - variant colors: @@ -2130,6 +2183,21 @@ packages: dependencies: - functions - maybe + json: + type: registry + version: 1.1.0 + integrity: sha256-LuN8PyX/gvRR4/7X7M9P+zL7BKbv34NcUE/7MILXQSA= + dependencies: + - either + - foldable-traversable + - functions + - gen + - integers + - maybe + - prelude + - strings + - tuples + - unfoldable json-codecs: type: registry version: 4.0.0 @@ -2781,14 +2849,14 @@ packages: registry-lib: type: git url: https://github.com/purescript/registry-dev.git - rev: 6feb62497ef7c3668bea89d11e9c2edb3a12dbd4 + rev: be0d7ffd1c16aa70e8f065a928e941ebc053c013 subdir: lib dependencies: - aff - - argonaut-core - arrays - bifunctors - - codec-argonaut + - codec + - codec-json - control - datetime - effect @@ -2801,6 +2869,7 @@ packages: - functors - graphs - integers + - json - language-cst-parser - lists - maybe @@ -2817,6 +2886,7 @@ packages: - profunctor-lenses - routing-duplex - safe-coerce + - st - strings - transformers - tuples diff --git a/spago.yaml b/spago.yaml index f211b406e..d72e4e614 100644 --- a/spago.yaml +++ b/spago.yaml @@ -13,24 +13,38 @@ package: - ImplicitQualifiedImportReExport dependencies: - aff + - aff-promise - affjax - affjax-node + - ansi - argonaut-core - arrays - - codec-argonaut + - avar + - codec + - codec-json + - console + - control - datetime + - docs-search-common - docs-search-index - dodo-printer - effect - either + - enums + - filterable - foldable-traversable - foreign-object + - formatters - functions + - graphs - http-methods - integers + - json - lists - maybe + - newtype - node-buffer + - node-child-process - node-execa - node-fs - node-path @@ -40,16 +54,19 @@ package: - ordered-collections - parallel - partial + - posix-types - prelude - profunctor - record - refs - registry-lib + - routing-duplex - spago-core - strings - - stringutils - transformers - tuples + - unfoldable + - unicode - unsafe-coerce test: main: Test.Spago @@ -57,14 +74,18 @@ package: - ImplicitQualifiedImportReExport - ImplicitQualifiedImport dependencies: + - exceptions + - identity + - quickcheck - spec workspace: packageSet: - registry: 50.8.0 + registry: 51.0.0 extraPackages: + codec-json: 1.2.0 registry-lib: git: https://github.com/purescript/registry-dev.git - ref: 6feb62497ef7c3668bea89d11e9c2edb3a12dbd4 + ref: be0d7ffd1c16aa70e8f065a928e941ebc053c013 subdir: lib html-parser-halogen: dependencies: diff --git a/src/Spago/Command/Fetch.purs b/src/Spago/Command/Fetch.purs index 8ab3c07ef..688699c06 100644 --- a/src/Spago/Command/Fetch.purs +++ b/src/Spago/Command/Fetch.purs @@ -19,8 +19,8 @@ import Affjax.StatusCode (StatusCode(..)) import Control.Monad.State as State import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Common as CA.Common +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Either as Either import Data.HTTP.Method as Method import Data.Int as Int @@ -28,6 +28,7 @@ import Data.Map as Map import Data.Newtype (wrap) import Data.Set as Set import Data.Traversable (sequence) +import Effect.Aff as Aff import Effect.Ref as Ref import Node.Buffer as Buffer import Node.Encoding as Encoding @@ -77,7 +78,7 @@ type FetchOpts = run :: forall a. FetchOpts -> Spago (FetchEnv a) PackageTransitiveDeps run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do - logDebug $ "Requested to install these packages: " <> printJson (CA.array PackageName.codec) packagesRequestedToInstall + logDebug $ "Requested to install these packages: " <> printJson (CJ.array PackageName.codec) packagesRequestedToInstall { workspace: currentWorkspace, offline } <- ask @@ -110,8 +111,8 @@ run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do newWorkspacePackage = case isTest of false -> currentWorkspacePackage { package { dependencies = package.dependencies <> newPackageDependencies } } true -> currentWorkspacePackage { package { test = package.test # map (\t -> t { dependencies = t.dependencies <> newPackageDependencies }) } } - logDebug $ "Overlapping packages: " <> printJson (CA.Common.set PackageName.codec) overlappingPackages - logDebug $ "Actual packages to install: " <> printJson (CA.array PackageName.codec) actualPackagesToInstall + logDebug $ "Overlapping packages: " <> printJson (CJ.Common.set PackageName.codec) overlappingPackages + logDebug $ "Actual packages to install: " <> printJson (CJ.array PackageName.codec) actualPackagesToInstall -- If we are installing new packages, we need to add them to the config -- We also warn the user if they are already present in the config unless (Set.isEmpty overlappingPackages) do @@ -121,7 +122,7 @@ run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do case Array.null actualPackagesToInstall of true -> pure Nothing false -> do - logDebug $ "Packages to install: " <> printJson (CA.array PackageName.codec) actualPackagesToInstall + logDebug $ "Packages to install: " <> printJson (CJ.array PackageName.codec) actualPackagesToInstall pure $ Just { configPath, yamlDoc, actualPackagesToInstall, newWorkspacePackage } let @@ -223,13 +224,19 @@ run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do _, _, Online -> do let packageUrl = "https://packages.registry.purescript.org/" <> PackageName.print name <> "/" <> versionString <> ".tar.gz" logInfo $ "Fetching package " <> packageVersion - response <- liftAff $ withBackoff' $ Http.request - ( Http.defaultRequest - { method = Left Method.GET - , responseFormat = Response.arrayBuffer - , url = packageUrl - } - ) + response <- liftAff $ withBackoff' do + res <- Http.request + ( Http.defaultRequest + { method = Left Method.GET + , responseFormat = Response.arrayBuffer + , url = packageUrl + } + ) + -- If we get a 503, we want the backoff to kick in, so we wait here and we'll eventually be retried + case res of + Right { status } | status == StatusCode 503 -> Aff.delay (Aff.Milliseconds 30_000.0) + _ -> pure unit + pure res case response of Nothing -> die $ "Couldn't reach the registry at " <> packageUrl Just (Left err) -> die $ "Couldn't fetch package " <> packageVersion <> ":\n " <> Http.printError err @@ -405,7 +412,10 @@ getPackageDependencies packageName package = case package of Config.readConfig (Path.concat [ configLocation, "spago.yaml" ]) >>= case _ of Right { yaml: { package: Just { dependencies: (Dependencies deps) } } } -> do pure (Just (map (fromMaybe Config.widestRange) deps)) - Right _ -> die [ "Read valid configuration from " <> configLocation, "However, there was no `package` section to be read." ] + Right _ -> die + [ "Read the configuration at path " <> configLocation + , "However, it didn't contain a `package` section." + ] Left errLines -> die [ toDoc $ "Could not read config at " <> configLocation , toDoc "Error: " diff --git a/src/Spago/Command/Graph.purs b/src/Spago/Command/Graph.purs index c215e07b9..ba2481788 100644 --- a/src/Spago/Command/Graph.purs +++ b/src/Spago/Command/Graph.purs @@ -4,7 +4,8 @@ import Spago.Prelude import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.Codec.Argonaut.Common as CA +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Graph as Data.Graph import Data.List as List import Data.Map as Map @@ -61,7 +62,7 @@ graphModules { dot, json, topo } = do $ map (\{ depends } -> Tuple unit $ List.fromFoldable depends) moduleGraph in output case json of - true -> OutputJson (CA.list CA.string) list + true -> OutputJson (CJ.Common.list CJ.string) list false -> OutputLines $ Array.fromFoldable list graphPackages :: forall a. GraphPackagesArgs -> Spago (GraphEnv a) Unit @@ -87,7 +88,7 @@ graphPackages { dot, json, topo } = do $ map (\{ depends } -> Tuple unit $ List.fromFoldable depends) packageGraph in output case json of - true -> OutputJson (CA.list PackageName.codec) list + true -> OutputJson (CJ.Common.list PackageName.codec) list false -> OutputLines $ map PackageName.print $ Array.fromFoldable list packagesToDot :: NonEmptyArray WorkspacePackage -> PackageGraph -> Array String diff --git a/src/Spago/Command/Ls.purs b/src/Spago/Command/Ls.purs index 10893ed1b..6bec852b0 100644 --- a/src/Spago/Command/Ls.purs +++ b/src/Spago/Command/Ls.purs @@ -10,9 +10,11 @@ module Spago.Command.Ls import Spago.Prelude -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Common as CAC -import Data.Codec.Argonaut.Record as CAR +import Codec.JSON.DecodeError as CJ.DecodeError +import Data.Codec as Codec +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common +import Data.Codec.JSON.Record as CJ.Record import Data.Foldable (elem) import Data.Map (filterKeys) import Data.Map as Map @@ -66,7 +68,7 @@ listPaths { json } = do logDebug "Running `listPaths`" case json of true -> - output $ OutputJson (CAC.map CA.string CA.string) $ Map.fromFoldable keyValuePairs + output $ OutputJson (CJ.Common.map CJ.string CJ.string) $ Map.fromFoldable keyValuePairs false -> output $ OutputTable { titles: [ "Name", "Path" ] @@ -125,34 +127,34 @@ formatPackagesJson packages = output $ OutputJson (packageMap packageCodec) (map WorkspacePackage _ -> "workspace" } - packageCodec :: JsonCodec { type :: String, value :: Package } - packageCodec = CAR.object "Package" { type: CA.string, value: innerCodec } + packageCodec :: CJ.Codec { type :: String, value :: Package } + packageCodec = CJ.named "Package" $ CJ.Record.object { type: CJ.string, value: innerCodec } where - innerCodec = CA.codec' decode encode + innerCodec = Codec.codec' decode encode - registryVersionCodec = CAR.object "RegistryVersion" { version: Version.codec } + registryVersionCodec = CJ.named "RegistryVersion" $ CJ.Record.object { version: Version.codec } encode = case _ of - RegistryVersion x -> CA.encode registryVersionCodec { version: x } - GitPackage x -> CA.encode Config.gitPackageCodec x - LocalPackage x -> CA.encode Config.localPackageCodec x - WorkspacePackage x -> CA.encode workspacePackageCodec x + RegistryVersion x -> CJ.encode registryVersionCodec { version: x } + GitPackage x -> CJ.encode Config.gitPackageCodec x + LocalPackage x -> CJ.encode Config.localPackageCodec x + WorkspacePackage x -> CJ.encode workspacePackageCodec x decode json = - map (RegistryVersion <<< _.version) (CA.decode registryVersionCodec json) - <|> map GitPackage (CA.decode Config.gitPackageCodec json) - <|> map LocalPackage (CA.decode Config.localPackageCodec json) - <|> map WorkspacePackage (CA.decode workspacePackageCodec json) + map (RegistryVersion <<< _.version) (Codec.decode registryVersionCodec json) + <|> map GitPackage (Codec.decode Config.gitPackageCodec json) + <|> map LocalPackage (Codec.decode Config.localPackageCodec json) + <|> map WorkspacePackage (Codec.decode workspacePackageCodec json) - workspacePackageCodec = CA.codec' decode encode + workspacePackageCodec = Codec.codec' decode encode where - decode _json = Left CA.MissingValue + decode _json = except $ Left $ CJ.DecodeError.basic "Decoding workspace packages is not supported." encode = - CA.encode - ( CAR.object "WorkspacePackage" - { path: CA.string + CJ.encode + ( CJ.named "WorkspacePackage" $ CJ.Record.object + { path: CJ.string , package: Config.packageConfigCodec - , hasTests: CA.boolean + , hasTests: CJ.boolean } ) <<< Record.delete (Proxy :: _ "doc") diff --git a/src/Spago/Command/Publish.purs b/src/Spago/Command/Publish.purs index f6c71cc5d..cf56491e3 100644 --- a/src/Spago/Command/Publish.purs +++ b/src/Spago/Command/Publish.purs @@ -6,9 +6,10 @@ import Affjax.Node as Http import Affjax.RequestBody as RequestBody import Affjax.ResponseFormat as ResponseFormat import Affjax.StatusCode (StatusCode(..)) +import Data.Argonaut.Core (Json) import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.DateTime (DateTime) import Data.Formatter.DateTime as DateTime import Data.List as List @@ -17,6 +18,7 @@ import Data.String as String import Effect.Aff (Milliseconds(..)) import Effect.Aff as Aff import Effect.Ref as Ref +import JSON (JSON) import Node.Path as Path import Node.Process as Process import Record as Record @@ -47,6 +49,7 @@ import Spago.Purs (Purs) import Spago.Purs.Graph as Graph import Spago.Registry (PreRegistryEnv) import Spago.Registry as Registry +import Unsafe.Coerce (unsafeCoerce) type PublishData = { name :: PackageName @@ -387,11 +390,11 @@ publish _args = do } action -callRegistry :: forall env a b. String -> JsonCodec b -> Maybe { codec :: JsonCodec a, data :: a } -> Spago (PublishEnv env) b +callRegistry :: forall env a b. String -> CJ.Codec b -> Maybe { codec :: CJ.Codec a, data :: a } -> Spago (PublishEnv env) b callRegistry url outputCodec maybeInput = handleError do logDebug $ "Calling registry at " <> url response <- liftAff $ withBackoff' $ case maybeInput of - Just { codec: inputCodec, data: input } -> Http.post ResponseFormat.string url (Just $ RequestBody.json $ CA.encode inputCodec input) + Just { codec: inputCodec, data: input } -> Http.post ResponseFormat.string url (Just $ RequestBody.json $ (unsafeCoerce :: JSON -> Json) $ CJ.encode inputCodec input) Nothing -> Http.get ResponseFormat.string url case response of Nothing -> pure $ Left $ "Could not reach the registry at " <> url diff --git a/src/Spago/Command/Registry.purs b/src/Spago/Command/Registry.purs index 81caba8c8..27db1f8d5 100644 --- a/src/Spago/Command/Registry.purs +++ b/src/Spago/Command/Registry.purs @@ -3,8 +3,8 @@ module Spago.Command.Registry where import Spago.Prelude import Data.Array as Array -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Record as CA.Record +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.DateTime (DateTime(..)) import Data.Formatter.DateTime as DateTime import Data.Map as Map @@ -54,9 +54,9 @@ search { package: searchString, json } = do output $ case json of true -> let - infoDataCodec = CA.Record.object "InfoData" - { publishedTime: CA.Record.optional Internal.Codec.iso8601DateTime - , version: CA.Record.optional Version.codec + infoDataCodec = CJ.named "InfoData" $ CJ.Record.object + { publishedTime: CJ.Record.optional Internal.Codec.iso8601DateTime + , version: CJ.Record.optional Version.codec } in OutputJson (Internal.packageMap infoDataCodec) infos @@ -119,7 +119,7 @@ packageSets { latest, json } = do availableSets output case json of - true -> OutputJson (CA.array Db.packageSetCodec) sets + true -> OutputJson (CJ.array Db.packageSetCodec) sets false -> OutputTable { titles: [ "VERSION", "DATE", "COMPILER" ] , rows: sets # map \{ version, date, compiler } -> diff --git a/src/Spago/Command/Run.purs b/src/Spago/Command/Run.purs index 382efb3ab..1d9bd713b 100644 --- a/src/Spago/Command/Run.purs +++ b/src/Spago/Command/Run.purs @@ -8,9 +8,9 @@ module Spago.Command.Run import Spago.Prelude +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.Codec.Argonaut as CA import Data.Map as Map import Node.FS.Perms as Perms import Node.Path as Path @@ -104,7 +104,7 @@ run = do , selected: NEA.singleton selected } Purs.graph globs [] >>= case _ of - Left err -> logWarn $ "Could not decode the output of `purs graph`, error: " <> CA.printJsonDecodeError err + Left err -> logWarn $ "Could not decode the output of `purs graph`, error: " <> CJ.DecodeError.print err Right (ModuleGraph graph) -> do when (isNothing $ Map.lookup opts.moduleName graph) do die [ opts.failureMessage, "Module " <> opts.moduleName <> " not found! Are you including it in your build?" ] diff --git a/src/Spago/Command/Sources.purs b/src/Spago/Command/Sources.purs index d3ee23a90..8ad3474f0 100644 --- a/src/Spago/Command/Sources.purs +++ b/src/Spago/Command/Sources.purs @@ -4,7 +4,7 @@ import Spago.Prelude import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.Map as Map import Spago.Command.Fetch (FetchEnv) import Spago.Command.Fetch as Fetch @@ -34,5 +34,5 @@ run { json } = do (Map.toUnfoldable transitivePackages :: Array (Tuple PackageName Package)) output case json of - true -> OutputJson (CA.array CA.string) globs + true -> OutputJson (CJ.array CJ.string) globs false -> OutputLines globs diff --git a/src/Spago/Config.purs b/src/Spago/Config.purs index 948b402f9..12cdea56b 100644 --- a/src/Spago/Config.purs +++ b/src/Spago/Config.purs @@ -28,11 +28,12 @@ import Spago.Prelude import Affjax.Node as Http import Affjax.ResponseFormat as Response import Affjax.StatusCode (StatusCode(..)) +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Array as Array import Data.Array.NonEmpty as NEA import Data.CodePoint.Unicode as Unicode -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.Enum as Enum import Data.Graph as Graph import Data.HTTP.Method as Method @@ -58,12 +59,13 @@ import Registry.Range as Range import Registry.Version as Version import Spago.Core.Config as Core import Spago.FS as FS +import Spago.Glob as Glob +import Spago.Json as Json import Spago.Lock (Lockfile, PackageSetInfo) import Spago.Lock as Lock import Spago.Paths as Paths import Spago.Registry as Registry import Spago.Yaml as Yaml -import Spago.Glob as Glob type Workspace = { selected :: Maybe WorkspacePackage @@ -104,7 +106,7 @@ newtype LegacyPackageSet = LegacyPackageSet (Map PackageName Core.LegacyPackageS derive instance Newtype LegacyPackageSet _ derive newtype instance Eq LegacyPackageSet -legacyPackageSetCodec :: JsonCodec LegacyPackageSet +legacyPackageSetCodec :: CJ.Codec LegacyPackageSet legacyPackageSetCodec = Profunctor.wrapIso LegacyPackageSet $ Internal.Codec.packageMap Core.legacyPackageSetEntryCodec @@ -115,8 +117,8 @@ newtype RemotePackageSet = RemotePackageSet , version :: Version } -remotePackageSetCodec :: JsonCodec RemotePackageSet -remotePackageSetCodec = Profunctor.wrapIso RemotePackageSet $ CAR.object "PackageSet" +remotePackageSetCodec :: CJ.Codec RemotePackageSet +remotePackageSetCodec = Profunctor.wrapIso RemotePackageSet $ CJ.named "PackageSet" $ CJ.Record.object { version: Version.codec , compiler: Version.codec , packages: Internal.Codec.packageMap Core.remotePackageCodec @@ -184,7 +186,9 @@ readWorkspace { maybeSelectedPackage, pureBuild, migrateConfig } = do Left errLines -> die [ toDoc "Couldn't parse Spago config, error:" + , Log.break , indent $ toDoc errLines + , Log.break , toDoc "The configuration file help can be found here https://github.com/purescript/spago#the-configuration-file" ] Right { yaml: { workspace: Nothing } } -> die @@ -559,18 +563,18 @@ readConfig path = do "spago.yaml", Nothing -> [ "Did not find `" <> path <> "`. Run `spago init` to initialize a new project." ] "spago.yaml", Just y -> - [ "Did not find `" <> path <> "`. Spago's configuration files must end with `.yaml`, not `.yml`. " + [ "Did not find `" <> path <> "`. Spago's configuration files must end with `.yaml`, not `.yml`." , "Try renaming `" <> y <> "` to `" <> path <> "` or run `spago init` to initialize a new project." ] _, Nothing -> [ "Did not find `" <> path <> "`." ] _, Just y -> - [ "Did not find `" <> path <> "`. Spago's configuration files must end with `.yaml`, not `.yml`. " + [ "Did not find `" <> path <> "`. Spago's configuration files must end with `.yaml`, not `.yml`." , "Try renaming `" <> y <> "` to `" <> path <> "`." ] Right yamlString -> do - case lmap (\err -> CA.TypeMismatch ("YAML: " <> err)) (Yaml.parser yamlString) of - Left err -> pure $ Left [ CA.printJsonDecodeError err ] + case lmap (\err -> CJ.DecodeError.basic ("YAML: " <> err)) (Yaml.parser yamlString) of + Left err -> pure $ Left [ CJ.DecodeError.print err ] Right doc -> do -- At this point we are sure that we have a valid Yaml document in `doc`, -- and it's just a matter of decoding it into our `Config` type. @@ -584,9 +588,9 @@ readConfig path = do -- TODO: revisit this once we have #1165, to parse more strictly let maybeMigratedDoc = Nullable.toMaybe (migrateV1ConfigImpl doc) pure $ bimap - (Array.singleton <<< CA.printJsonDecodeError) + Json.printConfigError (\yaml -> { doc, yaml, wasMigrated: isJust maybeMigratedDoc }) - (CA.decode Core.configCodec (Yaml.toJson $ fromMaybe doc maybeMigratedDoc)) + (CJ.decode Core.configCodec (Yaml.toJson $ fromMaybe doc maybeMigratedDoc)) setPackageSetVersionInConfig :: forall m. MonadAff m => MonadEffect m => YamlDoc Core.Config -> Version -> m Unit setPackageSetVersionInConfig doc version = do diff --git a/src/Spago/Db.purs b/src/Spago/Db.purs index 82276e271..5bad68b92 100644 --- a/src/Spago/Db.purs +++ b/src/Spago/Db.purs @@ -21,7 +21,8 @@ module Spago.Db import Spago.Prelude import Data.Array as Array -import Data.Codec.Argonaut.Record as CA.Record +import Data.Codec.JSON.Record as CJ.Record +import Data.Codec.JSON as CJ import Data.DateTime (Date, DateTime(..)) import Data.DateTime as Date import Data.Either as Either @@ -191,8 +192,8 @@ packageSetEntryFromJs p = hush do -------------------------------------------------------------------------------- -- Codecs -packageSetCodec :: JsonCodec PackageSet -packageSetCodec = CA.Record.object "PackageSet" +packageSetCodec :: CJ.Codec PackageSet +packageSetCodec = CJ.named "PackageSet" $ CJ.Record.object { date: Internal.Codec.iso8601Date , version: Version.codec , compiler: Version.codec diff --git a/src/Spago/Lock.purs b/src/Spago/Lock.purs index 3edca3a17..72a4b2a4a 100644 --- a/src/Spago/Lock.purs +++ b/src/Spago/Lock.purs @@ -13,8 +13,10 @@ module Spago.Lock import Spago.Prelude -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Common as CA.Common +import Codec.JSON.DecodeError as CJ.DecodeError +import Data.Codec as Codec +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common import Data.Profunctor as Profunctor import Record as Record import Registry.Internal.Codec as Registry.Codec @@ -57,45 +59,45 @@ type WorkspaceLockPackage = , build_plan :: Set PackageName } -lockfileCodec :: JsonCodec Lockfile -lockfileCodec = CA.object "Lockfile" - $ CA.recordProp (Proxy :: _ "workspace") workspaceLockCodec - $ CA.recordProp (Proxy :: _ "packages") (Registry.Codec.packageMap lockEntryCodec) - $ CA.record - -workspaceLockCodec :: JsonCodec WorkspaceLock -workspaceLockCodec = CA.object "WorkspaceLock" - $ CA.recordProp (Proxy :: _ "packages") (Registry.Codec.packageMap dependenciesCodec) - $ CA.recordPropOptional (Proxy :: _ "package_set") packageSetCodec - $ CA.recordProp (Proxy :: _ "extra_packages") (Registry.Codec.packageMap Config.extraPackageCodec) - $ CA.record +lockfileCodec :: CJ.Codec Lockfile +lockfileCodec = CJ.named "Lockfile" $ CJ.object + $ CJ.recordProp (Proxy :: _ "workspace") workspaceLockCodec + $ CJ.recordProp (Proxy :: _ "packages") (Registry.Codec.packageMap lockEntryCodec) + $ CJ.record + +workspaceLockCodec :: CJ.Codec WorkspaceLock +workspaceLockCodec = CJ.named "WorkspaceLock" $ CJ.object + $ CJ.recordProp (Proxy :: _ "packages") (Registry.Codec.packageMap dependenciesCodec) + $ CJ.recordPropOptional (Proxy :: _ "package_set") packageSetCodec + $ CJ.recordProp (Proxy :: _ "extra_packages") (Registry.Codec.packageMap Config.extraPackageCodec) + $ CJ.record where - dependenciesCodec = CA.object "Dependencies" - $ CA.recordProp (Proxy :: _ "path") CA.string - $ CA.recordProp (Proxy :: _ "dependencies") Config.dependenciesCodec - $ CA.recordProp (Proxy :: _ "test_dependencies") Config.dependenciesCodec - $ CA.recordProp (Proxy :: _ "build_plan") (CA.Common.set PackageName.codec) - $ CA.record - -packageSetCodec :: JsonCodec PackageSetInfo -packageSetCodec = CA.object "PackageSetInfo" - $ CA.recordProp (Proxy :: _ "address") Config.setAddressCodec - $ CA.recordProp (Proxy :: _ "compiler") Range.codec - $ CA.recordProp (Proxy :: _ "content") (Registry.Codec.packageMap Core.remotePackageCodec) - $ CA.record - -lockEntryCodec :: JsonCodec LockEntry -lockEntryCodec = CA.codec' decode encode + dependenciesCodec = CJ.named "Dependencies" $ CJ.object + $ CJ.recordProp (Proxy :: _ "path") CJ.string + $ CJ.recordProp (Proxy :: _ "dependencies") Config.dependenciesCodec + $ CJ.recordProp (Proxy :: _ "test_dependencies") Config.dependenciesCodec + $ CJ.recordProp (Proxy :: _ "build_plan") (CJ.Common.set PackageName.codec) + $ CJ.record + +packageSetCodec :: CJ.Codec PackageSetInfo +packageSetCodec = CJ.named "PackageSetInfo" $ CJ.object + $ CJ.recordProp (Proxy :: _ "address") Config.setAddressCodec + $ CJ.recordProp (Proxy :: _ "compiler") Range.codec + $ CJ.recordProp (Proxy :: _ "content") (Registry.Codec.packageMap Core.remotePackageCodec) + $ CJ.record + +lockEntryCodec :: CJ.Codec LockEntry +lockEntryCodec = Codec.codec' decode encode where encode = case _ of - FromPath lock -> CA.encode pathLockCodec lock - FromGit lock -> CA.encode gitLockCodec lock - FromRegistry lock -> CA.encode registryLockCodec lock + FromPath lock -> CJ.encode pathLockCodec lock + FromGit lock -> CJ.encode gitLockCodec lock + FromRegistry lock -> CJ.encode registryLockCodec lock decode json = - map FromPath (CA.decode pathLockCodec json) - <|> map FromGit (CA.decode gitLockCodec json) - <|> map FromRegistry (CA.decode registryLockCodec json) + map FromPath (Codec.decode pathLockCodec json) + <|> map FromGit (Codec.decode gitLockCodec json) + <|> map FromRegistry (Codec.decode registryLockCodec json) pathLockType :: String pathLockType = "local" @@ -111,12 +113,12 @@ type PathLock = , dependencies :: Array PackageName } -pathLockCodec :: JsonCodec PathLock -pathLockCodec = Profunctor.dimap toRep fromRep $ CA.object "PathLock" - $ CA.recordProp (Proxy :: _ "type") (constant pathLockType) - $ CA.recordProp (Proxy :: _ "path") CA.string - $ CA.recordProp (Proxy :: _ "dependencies") (CA.array PackageName.codec) - $ CA.record +pathLockCodec :: CJ.Codec PathLock +pathLockCodec = Profunctor.dimap toRep fromRep $ CJ.named "PathLock" $ CJ.object + $ CJ.recordProp (Proxy :: _ "type") (constant pathLockType) + $ CJ.recordProp (Proxy :: _ "path") CJ.string + $ CJ.recordProp (Proxy :: _ "dependencies") (CJ.array PackageName.codec) + $ CJ.record where toRep = Record.insert (Proxy :: _ "type") pathLockType fromRep = Record.delete (Proxy :: _ "type") @@ -128,14 +130,14 @@ type GitLock = , dependencies :: Array PackageName } -gitLockCodec :: JsonCodec GitLock -gitLockCodec = Profunctor.dimap toRep fromRep $ CA.object "GitLock" - $ CA.recordProp (Proxy :: _ "type") (constant gitLockType) - $ CA.recordProp (Proxy :: _ "url") CA.string - $ CA.recordProp (Proxy :: _ "rev") CA.string - $ CA.recordPropOptional (Proxy :: _ "subdir") CA.string - $ CA.recordProp (Proxy :: _ "dependencies") (CA.array PackageName.codec) - $ CA.record +gitLockCodec :: CJ.Codec GitLock +gitLockCodec = Profunctor.dimap toRep fromRep $ CJ.named "GitLock" $ CJ.object + $ CJ.recordProp (Proxy :: _ "type") (constant gitLockType) + $ CJ.recordProp (Proxy :: _ "url") CJ.string + $ CJ.recordProp (Proxy :: _ "rev") CJ.string + $ CJ.recordPropOptional (Proxy :: _ "subdir") CJ.string + $ CJ.recordProp (Proxy :: _ "dependencies") (CJ.array PackageName.codec) + $ CJ.record where toRep = Record.insert (Proxy :: _ "type") gitLockType fromRep = Record.delete (Proxy :: _ "type") @@ -146,21 +148,21 @@ type RegistryLock = , dependencies :: Array PackageName } -registryLockCodec :: JsonCodec RegistryLock -registryLockCodec = Profunctor.dimap toRep fromRep $ CA.object "RegistryLock" - $ CA.recordProp (Proxy :: _ "type") (constant registryLockType) - $ CA.recordProp (Proxy :: _ "version") Version.codec - $ CA.recordProp (Proxy :: _ "integrity") Sha256.codec - $ CA.recordProp (Proxy :: _ "dependencies") (CA.array PackageName.codec) - $ CA.record +registryLockCodec :: CJ.Codec RegistryLock +registryLockCodec = Profunctor.dimap toRep fromRep $ CJ.named "RegistryLock" $ CJ.object + $ CJ.recordProp (Proxy :: _ "type") (constant registryLockType) + $ CJ.recordProp (Proxy :: _ "version") Version.codec + $ CJ.recordProp (Proxy :: _ "integrity") Sha256.codec + $ CJ.recordProp (Proxy :: _ "dependencies") (CJ.array PackageName.codec) + $ CJ.record where toRep = Record.insert (Proxy :: _ "type") registryLockType fromRep = Record.delete (Proxy :: _ "type") -constant :: String → JsonCodec String -constant val = CA.codec' decode encode +constant :: String → CJ.Codec String +constant val = Codec.codec' decode encode where - encode = CA.encode CA.string - decode json = CA.decode CA.string json >>= case _ of + encode = CJ.encode CJ.string + decode json = except $ CJ.decode CJ.string json >>= case _ of decoded | decoded == val -> pure val - _ -> Left (CA.UnexpectedValue json) + res -> Left $ CJ.DecodeError.basic $ "Unexpected value: " <> res diff --git a/src/Spago/Prelude.purs b/src/Spago/Prelude.purs index ceeaadaa6..6f2bdee2e 100644 --- a/src/Spago/Prelude.purs +++ b/src/Spago/Prelude.purs @@ -20,7 +20,6 @@ module Spago.Prelude import Spago.Core.Prelude import Control.Parallel as Parallel -import Data.Argonaut.Core as Argonaut import Data.Array as Array import Data.Either as Either import Data.Foldable as Foldable @@ -32,6 +31,8 @@ import Data.String as String import Data.Traversable (class Traversable) import Effect.Aff as Aff import Effect.Now as Now +import JSON (JSON) +import JSON as JSON import Node.Buffer as Buffer import Node.Path as Path import Partial.Unsafe (unsafeCrashWith) @@ -82,7 +83,7 @@ partitionEithers = Array.foldMap case _ of -- | Unsafely stringify a value by coercing it to `Json` and stringifying it. unsafeStringify :: forall a. a -> String -unsafeStringify a = Argonaut.stringify (unsafeCoerce a :: Argonaut.Json) +unsafeStringify a = JSON.print (unsafeCoerce a :: JSON) parseLenientVersion :: String -> Either String Version.Version parseLenientVersion input = Version.parse do @@ -103,7 +104,7 @@ parseLenientVersion input = Version.parse do -- | Attempt an effectful computation with exponential backoff. withBackoff' :: forall a. Aff a -> Aff (Maybe.Maybe a) withBackoff' action = withBackoff - { delay: Aff.Milliseconds 5_000.0 + { delay: Aff.Milliseconds 2_000.0 , action , shouldCancel: \_ -> pure true , shouldRetry: \attempt -> if attempt > 3 then pure Maybe.Nothing else pure (Maybe.Just action) diff --git a/src/Spago/Psa.purs b/src/Spago/Psa.purs index 37c81d3fb..5ac0b5c18 100644 --- a/src/Spago/Psa.purs +++ b/src/Spago/Psa.purs @@ -8,11 +8,11 @@ module Spago.Psa where import Spago.Prelude +import Codec.JSON.DecodeError as CJ.DecodeError import Control.Alternative as Alternative -import Data.Argonaut.Parser (jsonParser) import Data.Array as Array import Data.Array.NonEmpty as NonEmptyArray -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.Map as Map import Data.Set as Set import Data.String as Str @@ -20,6 +20,7 @@ import Data.String as String import Data.Tuple as Tuple import Effect.Ref as Ref import Foreign.Object as FO +import JSON as JSON import Node.Encoding as Encoding import Node.FS.Aff as FSA import Node.Path as Path @@ -42,7 +43,7 @@ psaCompile globs pursArgs psaArgs = do result <- Purs.compile globs (Array.snoc pursArgs "--json-errors") let resultStdout = Cmd.getStdout result arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") resultStdout) \idx err -> - case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of + case JSON.parse err >>= CJ.decode psaResultCodec >>> lmap CJ.DecodeError.print of Left decodeErrMsg -> do logWarn $ Array.intercalate "\n" [ "Failed to decode PsaResult at index '" <> show idx <> "': " <> decodeErrMsg diff --git a/src/Spago/Psa/Printer.purs b/src/Spago/Psa/Printer.purs index 45b8740f2..10a70af6b 100644 --- a/src/Spago/Psa/Printer.purs +++ b/src/Spago/Psa/Printer.purs @@ -17,9 +17,8 @@ import Prelude import Ansi.Codes as Ansi import Control.Alternative as Alternative -import Data.Argonaut.Core (stringify) import Data.Array as Array -import Data.Codec.Argonaut as CA +import Data.Codec.JSON as CJ import Data.Foldable (fold, foldMap, maximum, maximumBy) import Data.FoldableWithIndex (forWithIndex_) import Data.Maybe (Maybe(..), fromMaybe, maybe) @@ -32,6 +31,7 @@ import Dodo.Ansi as DA import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO +import JSON as JSON import Spago.Core.Config as Core import Spago.Psa.Output (OutputStats, Output) import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaArgs, PsaPath(..), psaResultCodec) @@ -39,12 +39,12 @@ import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaArgs, PsaPath(..), printJsonOutputToOut :: Output -> Effect Unit printJsonOutputToOut output = do let - result = CA.encode psaResultCodec + result = CJ.encode psaResultCodec { warnings: _.error <$> output.warnings , errors: _.error <$> output.errors } - Console.log (stringify result) + Console.log (JSON.print result) -- | Prints output to the console. printDefaultOutputToErr :: PsaArgs -> Output -> Effect Unit diff --git a/src/Spago/Psa/Types.purs b/src/Spago/Psa/Types.purs index e09879310..3ee0b0ae3 100644 --- a/src/Spago/Psa/Types.purs +++ b/src/Spago/Psa/Types.purs @@ -27,9 +27,9 @@ module Spago.Psa.Types import Prelude -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Compat as CACompat -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON as CJ.Common +import Data.Codec.JSON.Record as CJ.Record import Data.Maybe (Maybe(..)) import Data.Tuple (Tuple(..)) import Spago.Core.Config as Core @@ -138,33 +138,33 @@ compareByLocation err1 err2 = (Tuple b.startLine b.startColumn) x -> x -psaResultCodec :: CA.JsonCodec PsaResult -psaResultCodec = CAR.object "PsaResult" - { warnings: CA.array psaErrorCodec - , errors: CA.array psaErrorCodec +psaResultCodec :: CJ.Codec PsaResult +psaResultCodec = CJ.named "PsaResult" $ CJ.Record.object + { warnings: CJ.array psaErrorCodec + , errors: CJ.array psaErrorCodec } -psaErrorCodec :: CA.JsonCodec PsaError -psaErrorCodec = CAR.object "PsaError" - { moduleName: CACompat.maybe CA.string - , errorCode: CA.string - , errorLink: CA.string - , message: CA.string - , filename: CACompat.maybe CA.string - , position: CACompat.maybe positionCodec - , suggestion: CACompat.maybe suggestionCodec +psaErrorCodec :: CJ.Codec PsaError +psaErrorCodec = CJ.named "PsaError" $ CJ.Record.object + { moduleName: CJ.Common.nullable CJ.string + , errorCode: CJ.string + , errorLink: CJ.string + , message: CJ.string + , filename: CJ.Common.nullable CJ.string + , position: CJ.Common.nullable positionCodec + , suggestion: CJ.Common.nullable suggestionCodec } -positionCodec :: CA.JsonCodec Position -positionCodec = CAR.object "Position" - { startLine: CA.int - , startColumn: CA.int - , endLine: CA.int - , endColumn: CA.int +positionCodec :: CJ.Codec Position +positionCodec = CJ.named "Position" $ CJ.Record.object + { startLine: CJ.int + , startColumn: CJ.int + , endLine: CJ.int + , endColumn: CJ.int } -suggestionCodec :: CA.JsonCodec Suggestion -suggestionCodec = CAR.object "Suggestion" - { replacement: CA.string - , replaceRange: CACompat.maybe positionCodec +suggestionCodec :: CJ.Codec Suggestion +suggestionCodec = CJ.named "Suggestion" $ CJ.Record.object + { replacement: CJ.string + , replaceRange: CJ.Common.nullable positionCodec } diff --git a/src/Spago/Purs.purs b/src/Spago/Purs.purs index c6efb4ae0..e28918fe6 100644 --- a/src/Spago/Purs.purs +++ b/src/Spago/Purs.purs @@ -3,8 +3,8 @@ module Spago.Purs where import Spago.Prelude import Data.Array as Array -import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Record as CJ.Record import Data.Profunctor as Profunctor import Data.Set as Set import Data.String as String @@ -106,21 +106,21 @@ newtype ModuleGraph = ModuleGraph (Map ModuleName ModuleGraphNode) derive instance Newtype ModuleGraph _ -moduleGraphCodec :: JsonCodec ModuleGraph -moduleGraphCodec = Profunctor.wrapIso ModuleGraph (Internal.Codec.strMap "ModuleGraph" Just identity moduleGraphNodeCodec) +moduleGraphCodec :: CJ.Codec ModuleGraph +moduleGraphCodec = Profunctor.wrapIso ModuleGraph (Internal.Codec.strMap "ModuleGraph" Right identity moduleGraphNodeCodec) type ModuleGraphNode = { path :: String , depends :: Array ModuleName } -moduleGraphNodeCodec :: JsonCodec ModuleGraphNode -moduleGraphNodeCodec = CAR.object "ModuleGraphNode" - { path: CA.string - , depends: CA.array CA.string +moduleGraphNodeCodec :: CJ.Codec ModuleGraphNode +moduleGraphNodeCodec = CJ.named "ModuleGraphNode" $ CJ.Record.object + { path: CJ.string + , depends: CJ.array CJ.string } -graph :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either JsonDecodeError ModuleGraph) +graph :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either CJ.DecodeError ModuleGraph) graph globs pursArgs = do { purs } <- ask let args = [ "graph" ] <> pursArgs <> Set.toUnfoldable globs diff --git a/src/Spago/Purs/Graph.purs b/src/Spago/Purs/Graph.purs index d506d7a3f..b580d65b7 100644 --- a/src/Spago/Purs/Graph.purs +++ b/src/Spago/Purs/Graph.purs @@ -16,9 +16,11 @@ module Spago.Purs.Graph import Spago.Prelude +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Array as Array -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR +import Data.Codec.JSON as CJ +import Data.Codec.JSON.Common as CJ.Common +import Data.Codec.JSON.Record as CJ.Record import Data.Map as Map import Data.Set as Set import Data.String as String @@ -49,7 +51,7 @@ type PreGraphEnv a = runGraph :: forall a. Set FilePath -> Array String -> Spago (PreGraphEnv a) (Either String Purs.ModuleGraph) runGraph globs pursArgs = map (lmap toErrorMessage) $ Purs.graph globs pursArgs where - toErrorMessage = append "Could not decode the output of `purs graph`, error: " <<< CA.printJsonDecodeError + toErrorMessage = append "Could not decode the output of `purs graph`, error: " <<< CJ.DecodeError.print -------------------------------------------------------------------------------- -- Graph enriched with the package names @@ -67,17 +69,17 @@ type ModuleGraphWithPackageNode = , package :: PackageName } -moduleGraphWithPackageNodeCodec :: JsonCodec ModuleGraphWithPackageNode -moduleGraphWithPackageNodeCodec = CAR.object "ModuleGraphNode" - { path: CA.string - , depends: CA.array CA.string +moduleGraphWithPackageNodeCodec :: CJ.Codec ModuleGraphWithPackageNode +moduleGraphWithPackageNodeCodec = CJ.named "ModuleGraphNode" $ CJ.Record.object + { path: CJ.string + , depends: CJ.array CJ.string , package: PackageName.codec } type ModuleGraphWithPackage = Map ModuleName ModuleGraphWithPackageNode -moduleGraphCodec :: JsonCodec ModuleGraphWithPackage -moduleGraphCodec = Internal.Codec.strMap "ModuleGraphWithPackage" Just identity moduleGraphWithPackageNodeCodec +moduleGraphCodec :: CJ.Codec ModuleGraphWithPackage +moduleGraphCodec = Internal.Codec.strMap "ModuleGraphWithPackage" Right identity moduleGraphWithPackageNodeCodec getModuleGraphWithPackage :: forall a. Purs.ModuleGraph -> Spago (PackageGraphEnv a) ModuleGraphWithPackage getModuleGraphWithPackage (ModuleGraph graph) = do @@ -126,8 +128,8 @@ compileGlob sourcePath = liftAff $ Glob.gitignoringGlob Paths.cwd [ withForwardS type PackageGraph = Map PackageName { depends :: Set PackageName } -packageGraphCodec :: JsonCodec PackageGraph -packageGraphCodec = Internal.Codec.packageMap (CAR.object "PackageGraphNode" { depends: CA.set PackageName.codec }) +packageGraphCodec :: CJ.Codec PackageGraph +packageGraphCodec = Internal.Codec.packageMap (CJ.named "PackageGraphNode" $ CJ.Record.object { depends: CJ.Common.set PackageName.codec }) getPackageGraph :: forall a. Purs.ModuleGraph -> Spago (PackageGraphEnv a) PackageGraph getPackageGraph graph = do diff --git a/test-fixtures/package-name-too-long-stderr.txt b/test-fixtures/package-name-too-long-stderr.txt new file mode 100644 index 000000000..a20e08c92 --- /dev/null +++ b/test-fixtures/package-name-too-long-stderr.txt @@ -0,0 +1,4 @@ +❌ Could not figure out a name for the new package. Error: + + + Package name cannot be longer than 150 characters diff --git a/test-fixtures/spago-yml-check-stderr.txt b/test-fixtures/spago-yml-check-stderr.txt index daf420453..a997c33e2 100644 --- a/test-fixtures/spago-yml-check-stderr.txt +++ b/test-fixtures/spago-yml-check-stderr.txt @@ -1,6 +1,10 @@ Reading Spago workspace configuration... ❌ Couldn't parse Spago config, error: - Did not find `spago.yaml`. Spago's configuration files must end with `.yaml`, not `.yml`. + + + Did not find `spago.yaml`. Spago's configuration files must end with `.yaml`, not `.yml`. Try renaming `spago.yml` to `spago.yaml` or run `spago init` to initialize a new project. + + The configuration file help can be found here https://github.com/purescript/spago#the-configuration-file diff --git a/test/Spago.purs b/test/Spago.purs index 6d0c2053e..ea5fc830f 100644 --- a/test/Spago.purs +++ b/test/Spago.purs @@ -8,10 +8,11 @@ import Data.Newtype (un) import Effect (Effect) import Effect.Aff (Milliseconds(..)) import Effect.Aff as Aff -import Test.Spago.Glob as Glob import Test.Spago.Build as Build import Test.Spago.Bundle as Bundle import Test.Spago.Docs as Docs +import Test.Spago.Errors as Errors +import Test.Spago.Glob as Glob import Test.Spago.Graph as Graph import Test.Spago.Init as Init import Test.Spago.Install as Install @@ -58,3 +59,4 @@ main = Aff.launchAff_ $ void $ un Identity $ Spec.Runner.runSpecT testConfig [ S Lock.spec Unit.spec Glob.spec + Errors.spec diff --git a/test/Spago/Errors.purs b/test/Spago/Errors.purs new file mode 100644 index 000000000..3224dacb3 --- /dev/null +++ b/test/Spago/Errors.purs @@ -0,0 +1,22 @@ +module Test.Spago.Errors where + +import Test.Prelude + +import Data.Array as Array +import Data.String as String +import Spago.FS as FS +import Test.Spec (Spec) +import Test.Spec as Spec + +spec :: Spec Unit +spec = Spec.around withTempDir do + Spec.describe "errors" do + + Spec.it "fails with a spago.yml" \{ spago, fixture } -> do + spago [ "init", "--name", "aaa" ] >>= shouldBeSuccess + FS.moveSync { src: "spago.yaml", dst: "spago.yml" } + spago [ "build" ] >>= shouldBeFailureErr (fixture "spago-yml-check-stderr.txt") + + Spec.it "fails for package names that are too long" \{ spago, fixture } -> do + let name = String.joinWith "" $ Array.replicate 256 "a" + spago [ "init", "--name", name ] >>= shouldBeFailureErr (fixture "package-name-too-long-stderr.txt") diff --git a/test/Spago/Lock.purs b/test/Spago/Lock.purs index 31cd15be3..c9d3f0abb 100644 --- a/test/Spago/Lock.purs +++ b/test/Spago/Lock.purs @@ -2,7 +2,7 @@ module Test.Spago.Lock where import Test.Prelude -import Data.Codec.Argonaut as CA +import Codec.JSON.DecodeError as CJ.DecodeError import Data.Map as Map import Data.Set as Set import Registry.Range as Range @@ -22,7 +22,7 @@ spec = do Spec.it "parses lockfile" do case parseYaml Lock.lockfileCodec validLockfileString of Left error -> - Assert.fail $ "Failed to parse: " <> CA.printJsonDecodeError error + Assert.fail $ "Failed to parse: " <> CJ.DecodeError.print error Right lock | lock /= validLockfile -> Assert.fail ("\n" <> printYaml Lock.lockfileCodec lock <> "\ndoes not equal\n\n" <> printYaml Lock.lockfileCodec validLockfile) Right _ -> diff --git a/test/Spago/Test.purs b/test/Spago/Test.purs index 9fcb69bbf..2bff0b29b 100644 --- a/test/Spago/Test.purs +++ b/test/Spago/Test.purs @@ -137,8 +137,3 @@ spec = Spec.around withTempDir do unless (String.contains (String.Pattern exp) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> exp <> "\n\nStderr was:\n" <> stdErr spago [ "test" ] >>= check { stdout: mempty, stderr: hasUnusedNameWarningError, result: isRight } - - Spec.it "check for spago.yml" \{ spago, fixture } -> do - spago [ "init", "--name", "aaa" ] >>= shouldBeSuccess - FS.moveSync {src: "spago.yaml", dst: "spago.yml"} - spago [ "build" ] >>= shouldBeFailureErr (fixture "spago-yml-check-stderr.txt")