git.iko.soy/typeable/openapi3
on 23caa64 help sign in
typeable/openapi3/test/Data/Swagger/CommonTestTypes.hs
919 lines 21 kB history raw
1{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE QuasiQuotes #-}
3{-# LANGUAGE ScopedTypeVariables #-}
5module Data.Swagger.CommonTestTypes where
7import Prelude ()
8import Prelude.Compat
10import Data.Aeson (ToJSON (..), ToJSONKey (..), Value)
11import Data.Aeson.QQ.Simple
12import Data.Aeson.Types (toJSONKeyText)
13import Data.Char
14import Data.Map (Map)
15import Data.Proxy
16import Data.Set (Set)
17import qualified Data.Text as Text
18import Data.Word
19import GHC.Generics
21import Data.Swagger
23-- ========================================================================
24-- Unit type
25-- ========================================================================
27data Unit = Unit deriving (Generic)
28instance ToParamSchema Unit
29instance ToSchema Unit
31unitSchemaJSON :: Value
32unitSchemaJSON = [aesonQQ|
34 "type": "string",
35 "enum": ["Unit"]
37|]
39-- ========================================================================
40-- Color (enum)
41-- ========================================================================
42data Color
43 = Red
44 | Green
45 | Blue
46 deriving (Generic)
47instance ToParamSchema Color
48instance ToSchema Color
50colorSchemaJSON :: Value
51colorSchemaJSON = [aesonQQ|
53 "type": "string",
54 "enum": ["Red", "Green", "Blue"]
56|]
58-- ========================================================================
59-- Shade (paramSchemaToNamedSchema)
60-- ========================================================================
62data Shade = Dim | Bright deriving (Generic)
63instance ToParamSchema Shade
65instance ToSchema Shade where declareNamedSchema = pure . paramSchemaToNamedSchema defaultSchemaOptions
67shadeSchemaJSON :: Value
68shadeSchemaJSON = [aesonQQ|
70 "type": "string",
71 "enum": ["Dim", "Bright"]
73|]
75-- ========================================================================
76-- Paint (record with bounded enum property)
77-- ========================================================================
79newtype Paint = Paint { color :: Color }
80 deriving (Generic)
81instance ToSchema Paint
83paintSchemaJSON :: Value
84paintSchemaJSON = [aesonQQ|
86 "type": "object",
87 "properties":
88 {
89 "color":
90 {
91 "$ref": "#/components/schemas/Color"
92 }
93 },
94 "required": ["color"]
96|]
98paintInlinedSchemaJSON :: Value
99paintInlinedSchemaJSON = [aesonQQ|
101 "type": "object",
102 "properties":
103 {
104 "color":
105 {
106 "type": "string",
107 "enum": ["Red", "Green", "Blue"]
108 }
109 },
110 "required": ["color"]
112|]
114-- ========================================================================
115-- Status (constructorTagModifier)
116-- ========================================================================
118data Status
119 = StatusOk
120 | StatusError
121 deriving (Generic)
123instance ToParamSchema Status where
124 toParamSchema = genericToParamSchema defaultSchemaOptions
125 { constructorTagModifier = map toLower . drop (length "Status") }
126instance ToSchema Status where
127 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
128 { constructorTagModifier = map toLower . drop (length "Status") }
130statusSchemaJSON :: Value
131statusSchemaJSON = [aesonQQ|
133 "type": "string",
134 "enum": ["ok", "error"]
136|]
138-- ========================================================================
139-- Email (newtype with unwrapUnaryRecords set to True)
140-- ========================================================================
142newtype Email = Email { getEmail :: String }
143 deriving (Generic)
144instance ToParamSchema Email
145instance ToSchema Email where
146 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
147 { unwrapUnaryRecords = True }
149emailSchemaJSON :: Value
150emailSchemaJSON = [aesonQQ|
152 "type": "string"
154|]
156-- ========================================================================
157-- UserId (non-record newtype)
158-- ========================================================================
160newtype UserId = UserId Integer
161 deriving (Eq, Ord, Generic)
162instance ToParamSchema UserId
163instance ToSchema UserId
165userIdSchemaJSON :: Value
166userIdSchemaJSON = [aesonQQ|
168 "type": "integer"
170|]
172-- ========================================================================
173-- UserGroup (set newtype)
174-- ========================================================================
176newtype UserGroup = UserGroup (Set UserId)
177 deriving (Generic)
178instance ToSchema UserGroup
180userGroupSchemaJSON :: Value
181userGroupSchemaJSON = [aesonQQ|
183 "type": "array",
184 "items": { "$ref": "#/components/schemas/UserId" },
185 "uniqueItems": true
187|]
189-- ========================================================================
190-- Person (simple record with optional fields)
191-- ========================================================================
192data Person = Person
193 { name :: String
194 , phone :: Integer
195 , email :: Maybe String
196 } deriving (Generic)
198instance ToSchema Person
200personSchemaJSON :: Value
201personSchemaJSON = [aesonQQ|
203 "type": "object",
204 "properties":
205 {
206 "name": { "type": "string" },
207 "phone": { "type": "integer" },
208 "email": { "type": "string" }
209 },
210 "required": ["name", "phone"]
212|]
214-- ========================================================================
215-- Player (record newtype)
216-- ========================================================================
218newtype Player = Player
219 { position :: Point
220 } deriving (Generic)
221instance ToSchema Player
223playerSchemaJSON :: Value
224playerSchemaJSON = [aesonQQ|
226 "type": "object",
227 "properties":
228 {
229 "position":
230 {
231 "$ref": "#/components/schemas/Point"
232 }
233 },
234 "required": ["position"]
236|]
238newtype Players = Players [Inlined Player]
239 deriving (Generic)
240instance ToSchema Players
242playersSchemaJSON :: Value
243playersSchemaJSON = [aesonQQ|
245 "type": "array",
246 "items":
247 {
248 "type": "object",
249 "properties":
250 {
251 "position":
252 {
253 "$ref": "#/components/schemas/Point"
254 }
255 },
256 "required": ["position"]
257 }
259|]
261-- ========================================================================
262-- Character (sum type with ref and record in alternative)
263-- ========================================================================
265data Character
266 = PC Player
267 | NPC { npcName :: String, npcPosition :: Point }
268 deriving (Generic)
269instance ToSchema Character
271characterSchemaJSON :: Value
272characterSchemaJSON = [aesonQQ|
274 "oneOf": [
275 {
276 "required": [
277 "tag",
278 "contents"
279 ],
280 "type": "object",
281 "properties": {
282 "tag": {
283 "type": "string",
284 "enum": [
285 "PC"
286 ]
287 },
288 "contents": {
289 "$ref": "#/components/schemas/Player"
290 }
291 }
292 },
293 {
294 "required": [
295 "npcName",
296 "npcPosition",
297 "tag"
298 ],
299 "type": "object",
300 "properties": {
301 "tag": {
302 "type": "string",
303 "enum": [
304 "NPC"
305 ]
306 },
307 "npcPosition": {
308 "$ref": "#/components/schemas/Point"
309 },
310 "npcName": {
311 "type": "string"
312 }
313 }
314 }
315 ],
316 "type": "object"
319|]
321characterInlinedSchemaJSON :: Value
322characterInlinedSchemaJSON = [aesonQQ|
324 "oneOf": [
325 {
326 "required": [
327 "tag",
328 "contents"
329 ],
330 "type": "object",
331 "properties": {
332 "tag": {
333 "type": "string",
334 "enum": [
335 "PC"
336 ]
337 },
338 "contents": {
339 "required": [
340 "position"
341 ],
342 "type": "object",
343 "properties": {
344 "position": {
345 "required": [
346 "x",
347 "y"
348 ],
349 "type": "object",
350 "properties": {
351 "x": {
352 "format": "double",
353 "type": "number"
354 },
355 "y": {
356 "format": "double",
357 "type": "number"
358 }
359 }
360 }
361 }
362 }
363 }
364 },
365 {
366 "required": [
367 "npcName",
368 "npcPosition",
369 "tag"
370 ],
371 "type": "object",
372 "properties": {
373 "tag": {
374 "type": "string",
375 "enum": [
376 "NPC"
377 ]
378 },
379 "npcPosition": {
380 "required": [
381 "x",
382 "y"
383 ],
384 "type": "object",
385 "properties": {
386 "x": {
387 "format": "double",
388 "type": "number"
389 },
390 "y": {
391 "format": "double",
392 "type": "number"
393 }
394 }
395 },
396 "npcName": {
397 "type": "string"
398 }
399 }
400 }
401 ],
402 "type": "object"
404|]
406characterInlinedPlayerSchemaJSON :: Value
407characterInlinedPlayerSchemaJSON = [aesonQQ|
409 "oneOf": [
410 {
411 "required": [
412 "tag",
413 "contents"
414 ],
415 "type": "object",
416 "properties": {
417 "tag": {
418 "type": "string",
419 "enum": [
420 "PC"
421 ]
422 },
423 "contents": {
424 "required": [
425 "position"
426 ],
427 "type": "object",
428 "properties": {
429 "position": {
430 "$ref": "#/components/schemas/Point"
431 }
432 }
433 }
434 }
435 },
436 {
437 "required": [
438 "npcName",
439 "npcPosition",
440 "tag"
441 ],
442 "type": "object",
443 "properties": {
444 "tag": {
445 "type": "string",
446 "enum": [
447 "NPC"
448 ]
449 },
450 "npcPosition": {
451 "$ref": "#/components/schemas/Point"
452 },
453 "npcName": {
454 "type": "string"
455 }
456 }
457 }
458 ],
459 "type": "object"
461|]
463-- ========================================================================
464-- ISPair (non-record product data type)
465-- ========================================================================
466data ISPair = ISPair Integer String
467 deriving (Generic)
469instance ToSchema ISPair
471ispairSchemaJSON :: Value
472ispairSchemaJSON = [aesonQQ|
474 "type": "array",
475 "items":
476 [
477 { "type": "integer" },
478 { "type": "string" }
479 ],
480 "minItems": 2,
481 "maxItems": 2
483|]
485-- ========================================================================
486-- Point (record data type with custom fieldLabelModifier)
487-- ========================================================================
489data Point = Point
490 { pointX :: Double
491 , pointY :: Double
492 } deriving (Generic)
494instance ToSchema Point where
495 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
496 { fieldLabelModifier = map toLower . drop (length "point") }
498pointSchemaJSON :: Value
499pointSchemaJSON = [aesonQQ|
501 "type": "object",
502 "properties":
503 {
504 "x": { "type": "number", "format": "double" },
505 "y": { "type": "number", "format": "double" }
506 },
507 "required": ["x", "y"]
509|]
511-- ========================================================================
512-- Point (record data type with multiple fields)
513-- ========================================================================
515data Point5 = Point5
516 { point5X :: Double
517 , point5Y :: Double
518 , point5Z :: Double
519 , point5U :: Double
520 , point5V :: Double -- 5 dimensional!
521 } deriving (Generic)
523instance ToSchema Point5 where
524 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
525 { fieldLabelModifier = map toLower . drop (length "point5") }
527point5SchemaJSON :: Value
528point5SchemaJSON = [aesonQQ|
530 "type": "object",
531 "properties":
532 {
533 "x": { "type": "number", "format": "double" },
534 "y": { "type": "number", "format": "double" },
535 "z": { "type": "number", "format": "double" },
536 "u": { "type": "number", "format": "double" },
537 "v": { "type": "number", "format": "double" }
538 },
539 "required": ["x", "y", "z", "u", "v"]
541|]
543point5Properties :: [String]
544point5Properties = ["x", "y", "z", "u", "v"]
546-- ========================================================================
547-- MyRoseTree (custom datatypeNameModifier)
548-- ========================================================================
550data MyRoseTree = MyRoseTree
551 { root :: String
552 , trees :: [MyRoseTree]
553 } deriving (Generic)
555instance ToSchema MyRoseTree where
556 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
557 { datatypeNameModifier = drop (length "My") }
559myRoseTreeSchemaJSON :: Value
560myRoseTreeSchemaJSON = [aesonQQ|
562 "type": "object",
563 "properties":
564 {
565 "root": { "type": "string" },
566 "trees":
567 {
568 "type": "array",
569 "items":
570 {
571 "$ref": "#/components/schemas/RoseTree"
572 }
573 }
574 },
575 "required": ["root", "trees"]
577|]
579data MyRoseTree' = MyRoseTree'
580 { root' :: String
581 , trees' :: [MyRoseTree']
582 } deriving (Generic)
584instance ToSchema MyRoseTree' where
585 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
586 { datatypeNameModifier = map toLower }
588myRoseTreeSchemaJSON' :: Value
589myRoseTreeSchemaJSON' = [aesonQQ|
591 "type": "object",
592 "properties":
593 {
594 "root'": { "type": "string" },
595 "trees'":
596 {
597 "type": "array",
598 "items":
599 {
600 "$ref": "#/components/schemas/myrosetree'"
601 }
602 }
603 },
604 "required": ["root'", "trees'"]
606|]
608-- ========================================================================
609-- Inlined (newtype for inlining schemas)
610-- ========================================================================
612newtype Inlined a = Inlined { getInlined :: a }
614instance ToSchema a => ToSchema (Inlined a) where
615 declareNamedSchema _ = unname <$> declareNamedSchema (Proxy :: Proxy a)
616 where
617 unname (NamedSchema _ s) = NamedSchema Nothing s
619-- ========================================================================
620-- Light (sum type with unwrapUnaryRecords)
621-- ========================================================================
623data Light
624 = NoLight
625 | LightFreq Double
626 | LightColor Color
627 | LightWaveLength { waveLength :: Double }
628 deriving (Generic)
630instance ToSchema Light where
631 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
632 { unwrapUnaryRecords = True }
634lightSchemaJSON :: Value
635lightSchemaJSON = [aesonQQ|
637 "oneOf": [
638 {
639 "required": [
640 "tag"
641 ],
642 "type": "object",
643 "properties": {
644 "tag": {
645 "type": "string",
646 "enum": [
647 "NoLight"
648 ]
649 }
650 }
651 },
652 {
653 "required": [
654 "tag",
655 "contents"
656 ],
657 "type": "object",
658 "properties": {
659 "tag": {
660 "type": "string",
661 "enum": [
662 "LightFreq"
663 ]
664 },
665 "contents": {
666 "format": "double",
667 "type": "number"
668 }
669 }
670 },
671 {
672 "required": [
673 "tag",
674 "contents"
675 ],
676 "type": "object",
677 "properties": {
678 "tag": {
679 "type": "string",
680 "enum": [
681 "LightColor"
682 ]
683 },
684 "contents": {
685 "$ref": "#/components/schemas/Color"
686 }
687 }
688 },
689 {
690 "required": [
691 "waveLength",
692 "tag"
693 ],
694 "type": "object",
695 "properties": {
696 "tag": {
697 "type": "string",
698 "enum": [
699 "LightWaveLength"
700 ]
701 },
702 "waveLength": {
703 "format": "double",
704 "type": "number"
705 }
706 }
707 }
708 ],
709 "type": "object"
711|]
713lightInlinedSchemaJSON :: Value
714lightInlinedSchemaJSON = [aesonQQ|
716 "oneOf": [
717 {
718 "required": [
719 "tag"
720 ],
721 "type": "object",
722 "properties": {
723 "tag": {
724 "type": "string",
725 "enum": [
726 "NoLight"
727 ]
728 }
729 }
730 },
731 {
732 "required": [
733 "tag",
734 "contents"
735 ],
736 "type": "object",
737 "properties": {
738 "tag": {
739 "type": "string",
740 "enum": [
741 "LightFreq"
742 ]
743 },
744 "contents": {
745 "format": "double",
746 "type": "number"
747 }
748 }
749 },
750 {
751 "required": [
752 "tag",
753 "contents"
754 ],
755 "type": "object",
756 "properties": {
757 "tag": {
758 "type": "string",
759 "enum": [
760 "LightColor"
761 ]
762 },
763 "contents": {
764 "type": "string",
765 "enum": [
766 "Red",
767 "Green",
768 "Blue"
769 ]
770 }
771 }
772 },
773 {
774 "required": [
775 "waveLength",
776 "tag"
777 ],
778 "type": "object",
779 "properties": {
780 "tag": {
781 "type": "string",
782 "enum": [
783 "LightWaveLength"
784 ]
785 },
786 "waveLength": {
787 "format": "double",
788 "type": "number"
789 }
790 }
791 }
792 ],
793 "type": "object"
795|]
797-- ========================================================================
798-- ResourceId (series of newtypes)
799-- ========================================================================
801newtype Id = Id String deriving (Generic)
802instance ToSchema Id
804newtype ResourceId = ResourceId Id deriving (Generic)
805instance ToSchema ResourceId
807-- ========================================================================
808-- ButtonImages (bounded enum key mapping)
809-- ========================================================================
811data ButtonState = Neutral | Focus | Active | Hover | Disabled
812 deriving (Show, Bounded, Enum, Generic)
814instance ToJSON ButtonState
815instance ToSchema ButtonState
816instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (Text.pack . show)
818type ImageUrl = Text.Text
820newtype ButtonImages = ButtonImages { getButtonImages :: Map ButtonState ImageUrl }
821 deriving (Generic)
823instance ToJSON ButtonImages where
824 toJSON = toJSON . getButtonImages
826instance ToSchema ButtonImages where
827 declareNamedSchema = genericDeclareNamedSchemaNewtype defaultSchemaOptions
828 declareSchemaBoundedEnumKeyMapping
830buttonImagesSchemaJSON :: Value
831buttonImagesSchemaJSON = [aesonQQ|
833 "type": "object",
834 "properties":
835 {
836 "Neutral": { "type": "string" },
837 "Focus": { "type": "string" },
838 "Active": { "type": "string" },
839 "Hover": { "type": "string" },
840 "Disabled": { "type": "string" }
841 }
843|]
845-- ========================================================================
846-- SingleMaybeField (single field data with optional field)
847-- ========================================================================
849data SingleMaybeField = SingleMaybeField { singleMaybeField :: Maybe String }
850 deriving (Show, Generic)
852instance ToJSON SingleMaybeField
853instance ToSchema SingleMaybeField
855singleMaybeFieldSchemaJSON :: Value
856singleMaybeFieldSchemaJSON = [aesonQQ|
858 "type": "object",
859 "properties":
860 {
861 "singleMaybeField": { "type": "string" }
862 }
864|]
867-- ========================================================================
868-- TimeOfDay
869-- ========================================================================
870data TimeOfDay
871 = Int
872 | Pico
873 deriving (Generic)
874instance ToSchema TimeOfDay
875instance ToParamSchema TimeOfDay
878timeOfDaySchemaJSON :: Value
879timeOfDaySchemaJSON = [aesonQQ|
881 "example": "12:33:15",
882 "type": "string",
883 "format": "hh:MM:ss"
885|]
887timeOfDayParamSchemaJSON :: Value
888timeOfDayParamSchemaJSON = [aesonQQ|
890 "type": "string",
891 "format": "hh:MM:ss"
893|]
896-- ========================================================================
897-- UnsignedInts
898-- ========================================================================
899data UnsignedInts = UnsignedInts
900 { unsignedIntsUint32 :: Word32
901 , unsignedIntsUint64 :: Word64
902 } deriving (Generic)
904instance ToSchema UnsignedInts where
905 declareNamedSchema = genericDeclareNamedSchema defaultSchemaOptions
906 { fieldLabelModifier = map toLower . drop (length "unsignedInts") }
908unsignedIntsSchemaJSON :: Value
909unsignedIntsSchemaJSON = [aesonQQ|
911 "type": "object",
912 "properties":
913 {
914 "uint32": { "type": "integer", "format": "int32", "minimum": 0, "maximum": 4294967295 },
915 "uint64": { "type": "integer", "format": "int64", "minimum": 0, "maximum": 18446744073709551615 }
916 },
917 "required": ["uint32", "uint64"]
919|]