From edf037a79b41a908a16a90843c491d6d7011f601 Mon Sep 17 00:00:00 2001
From: Ben Price <ben@hackworthltd.com>
Date: Wed, 3 Aug 2022 13:54:22 +0100
Subject: [PATCH 1/2] ToSchema + deriving-aeson: it compiles, but is it
 right...:

- the manual instance (look for library?)
- my choices around what things are derived via and what are gnd and
  what are plain (should match ToJSON instances)

I would like to brush off the testing work and ensure that catches all
possible bugs here!
---
 primer-service/primer-service.cabal  |  1 +
 primer-service/src/Primer/OpenAPI.hs | 36 ++++++++++++++++++++++------
 primer/primer.cabal                  |  2 +-
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/primer-service/primer-service.cabal b/primer-service/primer-service.cabal
index d7a83a1f1..4877760d8 100644
--- a/primer-service/primer-service.cabal
+++ b/primer-service/primer-service.cabal
@@ -36,6 +36,7 @@ library
   build-depends:
     , aeson              >=2.0     && <=2.1
     , base               >=4.12    && <=4.17
+    , deriving-aeson     >=0.2     && <=0.3
     , exceptions         >=0.10.4  && <=0.11
     , http-media         >=0.8     && <=0.9
     , mtl                >=2.2.2   && <=2.3
diff --git a/primer-service/src/Primer/OpenAPI.hs b/primer-service/src/Primer/OpenAPI.hs
index 2998fa91c..a41d2e524 100644
--- a/primer-service/src/Primer/OpenAPI.hs
+++ b/primer-service/src/Primer/OpenAPI.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Primer.OpenAPI (
@@ -5,12 +6,14 @@ module Primer.OpenAPI (
   -- $orphanInstances
 ) where
 
-import Data.OpenApi (ToSchema)
-import Data.Text (Text)
-import Data.Typeable (Typeable)
+import Data.OpenApi (SchemaOptions, fromAesonOptions)
+import Data.OpenApi.Internal.Schema
+import Deriving.Aeson (AesonOptions (aesonOptions))
+import Foreword
 import Primer.API (Def, Module, NodeBody, NodeFlavor, Prog, Tree)
 import Primer.Core (GlobalName, ID (..), LVarName, ModuleName)
 import Primer.Database (Session, SessionName)
+import Primer.JSON (CustomJSON (..), PrimerJSON)
 import Primer.Name (Name)
 
 -- $orphanInstances
@@ -20,8 +23,24 @@ import Primer.Name (Name)
 -- build primer with ghcjs, because openapi3 transitively depends on network,
 -- which ghcjs currently cannot build.
 
-instance ToSchema SessionName
-instance ToSchema Session
+-- TODO: this compiles, but is it correct?
+
+-- Suitable for deriving via, when ToJSON is via the custom json
+-- instance (AesonOptions os, ToSchema a, Typeable os, Typeable ks) => ToSchema (CustomJSON (os :: ks) a) where
+--  declareNamedSchema = genericDeclareNamedSchemaNewtype opts (declareNamedSchema @a)
+instance
+  (Typeable a, Generic a, GToSchema (Rep a), Typeable os, Typeable ks, AesonOptions os) =>
+  ToSchema (CustomJSON (os :: ks) a)
+  where
+  declareNamedSchema _ = genericDeclareNamedSchema opts (Proxy @a)
+    where
+      opts :: SchemaOptions
+      opts = fromAesonOptions (aesonOptions @os)
+
+-- Technically should GND this, but cannot because of exports...
+-- instance ToSchema SessionName
+deriving via Text instance ToSchema SessionName -- see comments on instance ToSchema Name
+deriving via PrimerJSON Session instance ToSchema Session
 
 -- We need to GND the ID instance to match its To/FromJSON instances
 deriving newtype instance ToSchema ID
@@ -33,12 +52,15 @@ deriving via Text instance (ToSchema Name)
 
 -- For GlobalName and LVarName, we must derive ToSchema via Name,
 -- as that is how the To/FromJSON instances are derived
-deriving via Name instance Typeable k => ToSchema (GlobalName k)
+-- deriving via Name instance Typeable k => ToSchema (GlobalName k)
+instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here...
 deriving via Name instance (ToSchema LVarName)
+
+-- These are just plain ToJSON
 instance ToSchema Tree
 instance ToSchema NodeBody
 instance ToSchema NodeFlavor
 instance ToSchema Def
-instance ToSchema ModuleName
+deriving via NonEmpty Name instance ToSchema ModuleName
 instance ToSchema Module
 instance ToSchema Prog
diff --git a/primer/primer.cabal b/primer/primer.cabal
index 8fde82b4b..19db59619 100644
--- a/primer/primer.cabal
+++ b/primer/primer.cabal
@@ -29,6 +29,7 @@ library
     Primer.Eval
     Primer.EvalFull
     Primer.Examples
+    Primer.JSON
     Primer.Module
     Primer.Name
     Primer.Name.Fresh
@@ -45,7 +46,6 @@ library
   hs-source-dirs:     src
   other-modules:
     Control.Monad.NestedError
-    Primer.JSON
 
   default-language:   GHC2021
   default-extensions:

From 40ddb3b75537c3c5f82011bb52882cc8ef18b96e Mon Sep 17 00:00:00 2001
From: Ben Price <ben@hackworthltd.com>
Date: Wed, 3 Aug 2022 18:50:58 +0100
Subject: [PATCH 2/2] huh, ToSchema (GlobalName k) generates broken openapi!
 ...

TODO: check what difference this via-custom makes when have non Vanilla
(unsure if it currently is applied to any types where it is interesting)
TODO: check this via-custom is correct wrt the ToJSON encoding
---
 primer-service/src/Primer/OpenAPI.hs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/primer-service/src/Primer/OpenAPI.hs b/primer-service/src/Primer/OpenAPI.hs
index a41d2e524..0efbf74dd 100644
--- a/primer-service/src/Primer/OpenAPI.hs
+++ b/primer-service/src/Primer/OpenAPI.hs
@@ -52,8 +52,8 @@ deriving via Text instance (ToSchema Name)
 
 -- For GlobalName and LVarName, we must derive ToSchema via Name,
 -- as that is how the To/FromJSON instances are derived
--- deriving via Name instance Typeable k => ToSchema (GlobalName k)
-instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here...
+deriving via Name instance Typeable k => ToSchema (GlobalName k)
+--instance Typeable k => ToSchema (GlobalName k) -- actually, just plain ToJSON here..., but is invalid openapi!
 deriving via Name instance (ToSchema LVarName)
 
 -- These are just plain ToJSON