@@ -43,31 +43,32 @@ import Data.Array.NonEmpty as NonEmptyArray
4343import Data.Codec as Codec
4444import Data.Codec.JSON as CJ
4545import Data.Codec.JSON.Record as CJ.Record
46+ import Data.Codec.JSON.Strict as CJS
4647import Data.Codec.JSON.Sum as CJ.Sum
4748import Data.Either as Either
4849import Data.List as List
4950import Data.Map as Map
5051import Data.Profunctor as Profunctor
5152import Partial.Unsafe (unsafeCrashWith )
52- import Registry.Internal.Codec as Internal.Codec
53+ import Registry.Internal.Codec as Reg.Internal.Codec
54+ import Registry.Internal.Parsing as Reg.Internal.Parsing
5355import Registry.License as License
5456import Registry.Location as Location
5557import Registry.PackageName as PackageName
5658import Registry.Range as Range
5759import Registry.Sha256 as Sha256
5860import Registry.Version as Version
59- import Type.Proxy (Proxy (..))
6061
6162type Config =
6263 { package :: Maybe PackageConfig
6364 , workspace :: Maybe WorkspaceConfig
6465 }
6566
6667configCodec :: CJ.Codec Config
67- configCodec = CJ .object
68- $ CJ .recordPropOptional ( Proxy @" package" ) packageConfigCodec
69- $ CJ .recordPropOptional ( Proxy @" workspace" ) workspaceConfigCodec
70- $ CJ .record
68+ configCodec = CJS .objectStrict
69+ $ CJS .recordPropOptional @" package" packageConfigCodec
70+ $ CJS .recordPropOptional @" workspace" workspaceConfigCodec
71+ $ CJS .record
7172
7273type PackageConfig =
7374 { name :: PackageName
@@ -81,16 +82,16 @@ type PackageConfig =
8182 }
8283
8384packageConfigCodec :: CJ.Codec PackageConfig
84- packageConfigCodec = CJ .named " PackageConfig" $ CJ .object
85- $ CJ .recordProp ( Proxy @" name" ) PackageName .codec
86- $ CJ .recordPropOptional ( Proxy @" description" ) CJ .string
87- $ CJ .recordProp ( Proxy @" dependencies" ) dependenciesCodec
88- $ CJ .recordPropOptional ( Proxy @" build" ) packageBuildOptionsCodec
89- $ CJ .recordPropOptional ( Proxy @" bundle" ) bundleConfigCodec
90- $ CJ .recordPropOptional ( Proxy @" run" ) runConfigCodec
91- $ CJ .recordPropOptional ( Proxy @" test" ) testConfigCodec
92- $ CJ .recordPropOptional ( Proxy @" publish" ) publishConfigCodec
93- $ CJ .record
85+ packageConfigCodec = CJ .named " PackageConfig" $ CJS .objectStrict
86+ $ CJS .recordProp @" name" PackageName .codec
87+ $ CJS .recordPropOptional @" description" CJ .string
88+ $ CJS .recordProp @" dependencies" dependenciesCodec
89+ $ CJS .recordPropOptional @" build" packageBuildOptionsCodec
90+ $ CJS .recordPropOptional @" bundle" bundleConfigCodec
91+ $ CJS .recordPropOptional @" run" runConfigCodec
92+ $ CJS .recordPropOptional @" test" testConfigCodec
93+ $ CJS .recordPropOptional @" publish" publishConfigCodec
94+ $ CJS .record
9495
9596type PublishConfig =
9697 { version :: Version
@@ -101,24 +102,62 @@ type PublishConfig =
101102 }
102103
103104publishConfigCodec :: CJ.Codec PublishConfig
104- publishConfigCodec = CJ .named " PublishConfig" $ CJ .object
105- $ CJ .recordProp (Proxy @" version" ) Version .codec
106- $ CJ .recordProp (Proxy @" license" ) License .codec
107- $ CJ .recordPropOptional (Proxy @" location" ) Location .codec
108- $ CJ .recordPropOptional (Proxy @" include" ) (CJ .array CJ .string)
109- $ CJ .recordPropOptional (Proxy @" exclude" ) (CJ .array CJ .string)
110- $ CJ .record
105+ publishConfigCodec = CJ .named " PublishConfig" $ CJS .objectStrict
106+ $ CJS .recordProp @" version" Version .codec
107+ $ CJS .recordProp @" license" License .codec
108+ $ CJS .recordPropOptional @" location" publishLocationCodec
109+ $ CJS .recordPropOptional @" include" (CJ .array CJ .string)
110+ $ CJS .recordPropOptional @" exclude" (CJ .array CJ .string)
111+ $ CJS .record
112+
113+ -- This codec duplicates `Location.codec` from the Registry library, but with
114+ -- strict parsing of fields, so that we would error out on unknown fields, thus
115+ -- catching typos in field names. We do not want to modify the original codec in
116+ -- the Registry library, because it's used for network communication, not for
117+ -- reading user input, and therefore it's more important there to ignore unknown
118+ -- fields for backwards compatibiility.
119+ publishLocationCodec :: CJ.Codec Location
120+ publishLocationCodec = CJ .named " Publish Location" $ Codec .codec' decode encode
121+ where
122+ decode json =
123+ (Location.Git <$> Codec .decode gitCodec json)
124+ <|> (Location.GitHub <$> Codec .decode githubCodec json)
125+
126+ encode = case _ of
127+ Location.Git git -> CJ .encode gitCodec git
128+ Location.GitHub github -> CJ .encode githubCodec github
129+
130+ githubCodec :: CJ.Codec Location.GitHubData
131+ githubCodec = Profunctor .dimap toJsonRep fromJsonRep $ CJ .named " GitHub" $ CJ.Record .objectStrict
132+ { githubOwner: CJ .string
133+ , githubRepo: CJ .string
134+ , subdir: CJ.Record .optional CJ .string
135+ }
136+ where
137+ toJsonRep { owner, repo, subdir } = { githubOwner: owner, githubRepo: repo, subdir }
138+ fromJsonRep { githubOwner, githubRepo, subdir } = { owner: githubOwner, repo: githubRepo, subdir }
139+
140+ gitCodec :: CJ.Codec Location.GitData
141+ gitCodec = Profunctor .dimap toJsonRep fromJsonRep $ CJ .named " Git" $ CJ.Record .objectStrict
142+ { gitUrl: Reg.Internal.Codec .parsedString Reg.Internal.Parsing .gitUrl
143+ , subdir: CJ.Record .optional CJ .string
144+ }
145+ where
146+ -- The JSON representation of the GitHub type uses 'gitUrl', but in PureScript
147+ -- we use 'url' for convenience.
148+ toJsonRep { url, subdir } = { gitUrl: url, subdir }
149+ fromJsonRep { gitUrl, subdir } = { url: gitUrl, subdir }
111150
112151type RunConfig =
113152 { main :: Maybe String
114153 , execArgs :: Maybe (Array String )
115154 }
116155
117156runConfigCodec :: CJ.Codec RunConfig
118- runConfigCodec = CJ .named " RunConfig" $ CJ .object
119- $ CJ .recordPropOptional ( Proxy @" main" ) CJ .string
120- $ CJ .recordPropOptional ( Proxy @" execArgs" ) (CJ .array CJ .string)
121- $ CJ .record
157+ runConfigCodec = CJ .named " RunConfig" $ CJS .objectStrict
158+ $ CJS .recordPropOptional @" main" CJ .string
159+ $ CJS .recordPropOptional @" execArgs" (CJ .array CJ .string)
160+ $ CJS .record
122161
123162type TestConfig =
124163 { main :: String
@@ -130,25 +169,25 @@ type TestConfig =
130169 }
131170
132171testConfigCodec :: CJ.Codec TestConfig
133- testConfigCodec = CJ .named " TestConfig" $ CJ .object
134- $ CJ .recordProp ( Proxy @" main" ) CJ .string
135- $ CJ .recordPropOptional ( Proxy @" execArgs" ) (CJ .array CJ .string)
136- $ CJ .recordPropOptional ( Proxy @" censorTestWarnings" ) censorBuildWarningsCodec
137- $ CJ .recordPropOptional ( Proxy @" strict" ) CJ .boolean
138- $ CJ .recordPropOptional ( Proxy @" pedanticPackages" ) CJ .boolean
139- $ CJ .recordProp ( Proxy @" dependencies" ) dependenciesCodec
140- $ CJ .record
172+ testConfigCodec = CJ .named " TestConfig" $ CJS .objectStrict
173+ $ CJS .recordProp @" main" CJ .string
174+ $ CJS .recordPropOptional @" execArgs" (CJ .array CJ .string)
175+ $ CJS .recordPropOptional @" censorTestWarnings" censorBuildWarningsCodec
176+ $ CJS .recordPropOptional @" strict" CJ .boolean
177+ $ CJS .recordPropOptional @" pedanticPackages" CJ .boolean
178+ $ CJS .recordProp @" dependencies" dependenciesCodec
179+ $ CJS .record
141180
142181type BackendConfig =
143182 { cmd :: String
144183 , args :: Maybe (Array String )
145184 }
146185
147186backendConfigCodec :: CJ.Codec BackendConfig
148- backendConfigCodec = CJ .named " BackendConfig" $ CJ .object
149- $ CJ .recordProp ( Proxy @" cmd" ) CJ .string
150- $ CJ .recordPropOptional ( Proxy @" args" ) (CJ .array CJ .string)
151- $ CJ .record
187+ backendConfigCodec = CJ .named " BackendConfig" $ CJS .objectStrict
188+ $ CJS .recordProp @" cmd" CJ .string
189+ $ CJS .recordPropOptional @" args" (CJ .array CJ .string)
190+ $ CJS .record
152191
153192type PackageBuildOptionsInput =
154193 { censorProjectWarnings :: Maybe CensorBuildWarnings
@@ -157,11 +196,11 @@ type PackageBuildOptionsInput =
157196 }
158197
159198packageBuildOptionsCodec :: CJ.Codec PackageBuildOptionsInput
160- packageBuildOptionsCodec = CJ .named " PackageBuildOptionsInput" $ CJ .object
161- $ CJ .recordPropOptional ( Proxy @" censorProjectWarnings" ) censorBuildWarningsCodec
162- $ CJ .recordPropOptional ( Proxy @" strict" ) CJ .boolean
163- $ CJ .recordPropOptional ( Proxy @" pedanticPackages" ) CJ .boolean
164- $ CJ .record
199+ packageBuildOptionsCodec = CJ .named " PackageBuildOptionsInput" $ CJS .objectStrict
200+ $ CJS .recordPropOptional @" censorProjectWarnings" censorBuildWarningsCodec
201+ $ CJS .recordPropOptional @" strict" CJ .boolean
202+ $ CJS .recordPropOptional @" pedanticPackages" CJ .boolean
203+ $ CJS .record
165204
166205type BundleConfig =
167206 { minify :: Maybe Boolean
@@ -173,17 +212,19 @@ type BundleConfig =
173212 }
174213
175214bundleConfigCodec :: CJ.Codec BundleConfig
176- bundleConfigCodec = CJ .named " BundleConfig" $ CJ .object
177- $ CJ .recordPropOptional ( Proxy @" minify" ) CJ .boolean
178- $ CJ .recordPropOptional ( Proxy @" module" ) CJ .string
179- $ CJ .recordPropOptional ( Proxy @" outfile" ) CJ .string
180- $ CJ .recordPropOptional ( Proxy @" platform" ) bundlePlatformCodec
181- $ CJ .recordPropOptional ( Proxy @" type" ) bundleTypeCodec
182- $ CJ .recordPropOptional ( Proxy @" extraArgs" ) (CJ .array CJ .string)
183- $ CJ .record
215+ bundleConfigCodec = CJ .named " BundleConfig" $ CJS .objectStrict
216+ $ CJS .recordPropOptional @" minify" CJ .boolean
217+ $ CJS .recordPropOptional @" module" CJ .string
218+ $ CJS .recordPropOptional @" outfile" CJ .string
219+ $ CJS .recordPropOptional @" platform" bundlePlatformCodec
220+ $ CJS .recordPropOptional @" type" bundleTypeCodec
221+ $ CJS .recordPropOptional @" extraArgs" (CJ .array CJ .string)
222+ $ CJS .record
184223
185224data BundlePlatform = BundleNode | BundleBrowser
186225
226+ derive instance Eq BundlePlatform
227+
187228instance Show BundlePlatform where
188229 show = case _ of
189230 BundleNode -> " node"
@@ -202,6 +243,8 @@ bundlePlatformCodec = CJ.Sum.enumSum show (parsePlatform)
202243-- App bundles with a main fn, while Module does not include a main.
203244data BundleType = BundleApp | BundleModule
204245
246+ derive instance Eq BundleType
247+
205248instance Show BundleType where
206249 show = case _ of
207250 BundleApp -> " app"
@@ -238,7 +281,7 @@ instance Monoid Dependencies where
238281dependenciesCodec :: CJ.Codec Dependencies
239282dependenciesCodec = Profunctor .dimap to from $ CJ .array dependencyCodec
240283 where
241- packageSingletonCodec = Internal.Codec .packageMap spagoRangeCodec
284+ packageSingletonCodec = Reg. Internal.Codec .packageMap spagoRangeCodec
242285
243286 to :: Dependencies -> Array (Either PackageName (Map PackageName Range ))
244287 to (Dependencies deps) =
@@ -291,12 +334,12 @@ type WorkspaceConfig =
291334 }
292335
293336workspaceConfigCodec :: CJ.Codec WorkspaceConfig
294- workspaceConfigCodec = CJ .named " WorkspaceConfig" $ CJ .object
295- $ CJ .recordPropOptional ( Proxy @" packageSet" ) setAddressCodec
296- $ CJ .recordPropOptional ( Proxy @" backend" ) backendConfigCodec
297- $ CJ .recordPropOptional ( Proxy @" buildOpts" ) buildOptionsCodec
298- $ CJ .recordPropOptional ( Proxy @" extraPackages" ) ( Internal.Codec .packageMap extraPackageCodec)
299- $ CJ .record
337+ workspaceConfigCodec = CJ .named " WorkspaceConfig" $ CJS .objectStrict
338+ $ CJS .recordPropOptional @" packageSet" setAddressCodec
339+ $ CJS .recordPropOptional @" backend" backendConfigCodec
340+ $ CJS .recordPropOptional @" buildOpts" buildOptionsCodec
341+ $ CJS .recordPropOptional @" extraPackages" ( Reg. Internal.Codec .packageMap extraPackageCodec)
342+ $ CJS .record
300343
301344type WorkspaceBuildOptionsInput =
302345 { output :: Maybe FilePath
@@ -305,11 +348,11 @@ type WorkspaceBuildOptionsInput =
305348 }
306349
307350buildOptionsCodec :: CJ.Codec WorkspaceBuildOptionsInput
308- buildOptionsCodec = CJ .named " WorkspaceBuildOptionsInput" $ CJ .object
309- $ CJ .recordPropOptional ( Proxy @" output" ) CJ .string
310- $ CJ .recordPropOptional ( Proxy @" censorLibraryWarnings" ) censorBuildWarningsCodec
311- $ CJ .recordPropOptional ( Proxy @" statVerbosity" ) statVerbosityCodec
312- $ CJ .record
351+ buildOptionsCodec = CJ .named " WorkspaceBuildOptionsInput" $ CJS .objectStrict
352+ $ CJS .recordPropOptional @" output" CJ .string
353+ $ CJS .recordPropOptional @" censorLibraryWarnings" censorBuildWarningsCodec
354+ $ CJS .recordPropOptional @" statVerbosity" statVerbosityCodec
355+ $ CJS .record
313356
314357data CensorBuildWarnings
315358 = CensorAllWarnings
@@ -361,13 +404,15 @@ warningCensorTestCodec = Codec.codec' decode encode
361404 byCode = ByCode <$> Codec .decode CJ .string json
362405 byPrefix = (ByMessagePrefix <<< _.byPrefix) <$> Codec .decode byMessagePrefixCodec json
363406
364- byMessagePrefixCodec = CJ .named " ByMessagePrefix" $ CJ.Record .object { byPrefix: CJ .string }
407+ byMessagePrefixCodec = CJ .named " ByMessagePrefix" $ CJ.Record .objectStrict { byPrefix: CJ .string }
365408
366409data StatVerbosity
367410 = NoStats
368411 | CompactStats
369412 | VerboseStats
370413
414+ derive instance Eq StatVerbosity
415+
371416instance Show StatVerbosity where
372417 show = case _ of
373418 NoStats -> " NoStats"
@@ -397,9 +442,9 @@ derive instance Eq SetAddress
397442setAddressCodec :: CJ.Codec SetAddress
398443setAddressCodec = Codec .codec' decode encode
399444 where
400- setFromRegistryCodec = CJ .named " SetFromRegistry" $ CJ.Record .object { registry: Version .codec }
401- setFromUrlCodec = CJ .named " SetFromUrl" $ CJ.Record .object { url: CJ .string, hash: CJ.Record .optional Sha256 .codec }
402- setFromPathCodec = CJ .named " SetFromPath" $ CJ.Record .object { path: CJ .string }
445+ setFromRegistryCodec = CJ .named " SetFromRegistry" $ CJ.Record .objectStrict { registry: Version .codec }
446+ setFromUrlCodec = CJ .named " SetFromUrl" $ CJ.Record .objectStrict { url: CJ .string, hash: CJ.Record .optional Sha256 .codec }
447+ setFromPathCodec = CJ .named " SetFromPath" $ CJ.Record .objectStrict { path: CJ .string }
403448
404449 encode (SetFromRegistry r) = CJ .encode setFromRegistryCodec r
405450 encode (SetFromUrl u) = CJ .encode setFromUrlCodec u
@@ -427,7 +472,7 @@ extraPackageCodec = Codec.codec' decode encode
427472type LocalPackage = { path :: FilePath }
428473
429474localPackageCodec :: CJ.Codec LocalPackage
430- localPackageCodec = CJ .named " LocalPackage" $ CJ.Record .object { path: CJ .string }
475+ localPackageCodec = CJ .named " LocalPackage" $ CJ.Record .objectStrict { path: CJ .string }
431476
432477data RemotePackage
433478 = RemoteGitPackage GitPackage
@@ -455,12 +500,12 @@ type GitPackage =
455500 }
456501
457502gitPackageCodec :: CJ.Codec GitPackage
458- gitPackageCodec = CJ .named " GitPackage" $ CJ .object
459- $ CJ .recordProp ( Proxy @" git" ) CJ .string
460- $ CJ .recordProp ( Proxy @" ref" ) CJ .string
461- $ CJ .recordPropOptional ( Proxy @" subdir" ) CJ .string
462- $ CJ .recordPropOptional ( Proxy @" dependencies" ) dependenciesCodec
463- $ CJ .record
503+ gitPackageCodec = CJ .named " GitPackage" $ CJS .objectStrict
504+ $ CJS .recordProp @" git" CJ .string
505+ $ CJS .recordProp @" ref" CJ .string
506+ $ CJS .recordPropOptional @" subdir" CJ .string
507+ $ CJS .recordPropOptional @" dependencies" dependenciesCodec
508+ $ CJS .record
464509
465510-- | The format of a legacy packages.json package set entry for an individual
466511-- | package.
@@ -471,8 +516,8 @@ type LegacyPackageSetEntry =
471516 }
472517
473518legacyPackageSetEntryCodec :: CJ.Codec LegacyPackageSetEntry
474- legacyPackageSetEntryCodec = CJ .named " LegacyPackageSetEntry" $ CJ .object
475- $ CJ .recordProp ( Proxy @" repo" ) CJ .string
476- $ CJ .recordProp ( Proxy @" version" ) CJ .string
477- $ CJ .recordProp ( Proxy @" dependencies" ) (CJ .array PackageName .codec)
478- $ CJ .record
519+ legacyPackageSetEntryCodec = CJ .named " LegacyPackageSetEntry" $ CJS .objectStrict
520+ $ CJS .recordProp @" repo" CJ .string
521+ $ CJS .recordProp @" version" CJ .string
522+ $ CJS .recordProp @" dependencies" (CJ .array PackageName .codec)
523+ $ CJS .record
0 commit comments