mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 09:51:59 +03:00
84fd5910b0
This PR expands the OpenAPI specification generated for metadata to include separate definitions for `SourceMetadata` for each native database type, and for DataConnector. For the most part the changes add `HasCodec` implementations, and don't modify existing code otherwise. The generated OpenAPI spec can be used to generate TypeScript definitions that distinguish different source metadata types based on the value of the `kind` properly. There is a problem: because the specified `kind` value for a data connector source is any string, when TypeScript gets a source with a `kind` value of, say, `"postgres"`, it cannot unambiguously determine whether the source is postgres, or a data connector. For example, ```ts function consumeSourceMetadata(source: SourceMetadata) { if (source.kind === "postgres" || source.kind === "pg") { // At this point TypeScript infers that `source` is either an instance // of `PostgresSourceMetadata`, or `DataconnectorSourceMetadata`. It // can't narrow further. source } if (source.kind === "something else") { // TypeScript infers that this `source` must be an instance of // `DataconnectorSourceMetadata` because `source.kind` does not match // any of the other options. source } } ``` The simplest way I can think of to fix this would be to add a boolean property to the `SourceMetadata` type along the lines of `isNative` or `isDataConnector`. This could be a field that only exists in serialized data, like the metadata version field. The combination of one of the native database names for `kind`, and a true value for `isNative` would be enough for TypeScript to unambiguously distinguish the source kinds. But note that in the current state TypeScript is able to reference the short `"pg"` name correctly! ~~Tests are not passing yet due to some discrepancies in DTO serialization vs existing Metadata serialization. I'm working on that.~~ The placeholders that I used for table and function metadata are not compatible with the ordered JSON serialization in use. I think the best solution is to write compatible codecs for those types in another PR. For now I have disabled some DTO tests for this PR. Here are the generated [OpenAPI spec](https://github.com/hasura/graphql-engine-mono/files/9397333/openapi.tar.gz) based on these changes, and the generated [TypeScript client code](https://github.com/hasura/graphql-engine-mono/files/9397339/client-typescript.tar.gz) based on that spec. Ticket: [MM-66](https://hasurahq.atlassian.net/browse/MM-66) PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5582 GitOrigin-RevId: e1446191c6c832879db04f129daa397a3be03f62
58 lines
3.5 KiB
Haskell
58 lines
3.5 KiB
Haskell
module Hasura.Metadata.DTO.MetadataV3 (MetadataV3 (..)) where
|
|
|
|
import Autodocodec (Autodocodec (Autodocodec), HasCodec (codec), object, optionalField, requiredFieldWith, (.=))
|
|
import Autodocodec.OpenAPI ()
|
|
import Data.Aeson (FromJSON, ToJSON)
|
|
import Data.OpenApi qualified as OpenApi
|
|
import Hasura.Metadata.DTO.Placeholder (PlaceholderArray, PlaceholderObject)
|
|
import Hasura.Metadata.DTO.Utils (versionField)
|
|
import Hasura.Prelude
|
|
import Hasura.RQL.Types.Metadata.Common (Sources, sourcesCodec)
|
|
|
|
-- | Revision 3 of the Metadata export format. Note that values of the types,
|
|
-- 'PlaceholderArray' and 'PlaceholderObject' are placeholders that will
|
|
-- eventually be expanded to represent more detail.
|
|
data MetadataV3 = MetadataV3
|
|
{ metaV3Sources :: Sources,
|
|
metaV3RemoteSchemas :: Maybe PlaceholderArray,
|
|
metaV3QueryCollections :: Maybe PlaceholderArray,
|
|
metaV3Allowlist :: Maybe PlaceholderArray,
|
|
metaV3Actions :: Maybe PlaceholderArray,
|
|
metaV3CustomTypes :: Maybe PlaceholderObject,
|
|
metaV3CronTriggers :: Maybe PlaceholderArray,
|
|
metaV3RestEndpoints :: Maybe PlaceholderArray,
|
|
metaV3ApiLimits :: Maybe PlaceholderObject,
|
|
metaV3MetricsConfig :: Maybe PlaceholderObject,
|
|
metaV3InheritedRoles :: Maybe PlaceholderArray,
|
|
metaV3GraphqlSchemaIntrospection :: Maybe PlaceholderObject,
|
|
metaV3Network :: Maybe PlaceholderObject,
|
|
metaV3BackendConfigs :: Maybe PlaceholderObject
|
|
}
|
|
deriving stock (Show, Eq, Generic)
|
|
deriving (FromJSON, ToJSON, OpenApi.ToSchema) via (Autodocodec MetadataV3)
|
|
|
|
-- | Codecs simultaneously provide serialization logic for a type, and
|
|
-- documentation. A codec can be used to generate a specification in OpenAPI or
|
|
-- another format that matches the JSON serialization of the same type.
|
|
-- Documentation strings (the second argument to 'optionalField' and to
|
|
-- 'requiredField') appear in the generated specification for users' reference.
|
|
instance HasCodec MetadataV3 where
|
|
codec =
|
|
object "MetadataV3" $
|
|
MetadataV3
|
|
<$ versionField 3
|
|
<*> requiredFieldWith "sources" sourcesCodec "configured databases" .= metaV3Sources
|
|
<*> optionalField "remote_schemas" "merge remote GraphQL schemas and provide a unified GraphQL API" .= metaV3RemoteSchemas
|
|
<*> optionalField "query_collections" "group queries using query collections" .= metaV3QueryCollections
|
|
<*> optionalField "allowlist" "safe GraphQL operations - when allow lists are enabled only these operations are allowed" .= metaV3Allowlist
|
|
<*> optionalField "actions" "action definitions which extend Hasura's schema with custom business logic using custom queries and mutations" .= metaV3Actions
|
|
<*> optionalField "custom_types" "custom type definitions" .= metaV3CustomTypes
|
|
<*> optionalField "cron_triggers" "reliably trigger HTTP endpoints to run custom business logic periodically based on a cron schedule" .= metaV3CronTriggers
|
|
<*> optionalField "rest_endpoints" "REST interfaces to saved GraphQL queries and mutations" .= metaV3RestEndpoints
|
|
<*> optionalField "api_limits" "limts to depth and/or rate of API requests" .= metaV3ApiLimits
|
|
<*> optionalField "metrics_config" "TODO" .= metaV3MetricsConfig
|
|
<*> optionalField "inherited_roles" "an inherited role is a way to create a new role which inherits permissions from two or more roles" .= metaV3InheritedRoles
|
|
<*> optionalField "graphql_schema_introspection" "TODO" .= metaV3GraphqlSchemaIntrospection
|
|
<*> optionalField "network" "TODO" .= metaV3Network
|
|
<*> optionalField "backend_configs" "TODO" .= metaV3BackendConfigs
|