From 3fee8d1f58e22a7d2bd6314ea4818c8b8f7c2efa Mon Sep 17 00:00:00 2001 From: Jonas Natten Date: Tue, 24 Oct 2023 06:35:25 +0200 Subject: [PATCH 1/4] Handle multiple configuration types from learningpath-api backend --- src/api/learningpathApi.ts | 14 ++++++--- src/resolvers/learningpathResolvers.ts | 24 +++++++++++++--- src/schema.ts | 15 +++++++++- src/types/schema.d.ts | 40 ++++++++++++++++++++++++-- 4 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/api/learningpathApi.ts b/src/api/learningpathApi.ts index 2e4638be..56eb208b 100644 --- a/src/api/learningpathApi.ts +++ b/src/api/learningpathApi.ts @@ -78,13 +78,19 @@ export async function fetchLearningpath( }; } -export const fetchExamLockStatus = async ( +export const fetchConfig = async ( + configKey: string, context: Context, ): Promise => { const response = await fetch( - '/learningpath-api/v1/config/MY_NDLA_WRITE_RESTRICTED', + `/learningpath-api/v1/config/${configKey}`, context, ); - const examLockStatus: IConfigMetaRestricted = await resolveJson(response); - return examLockStatus; + const config: IConfigMetaRestricted = await resolveJson(response); + return config; }; + +export const fetchExamLockStatus = async ( + context: Context, +): Promise => + fetchConfig('MY_NDLA_WRITE_RESTRICTED', context); diff --git a/src/resolvers/learningpathResolvers.ts b/src/resolvers/learningpathResolvers.ts index 8d11369d..1894e819 100644 --- a/src/resolvers/learningpathResolvers.ts +++ b/src/resolvers/learningpathResolvers.ts @@ -6,10 +6,11 @@ * */ -import { IConfigMetaRestricted } from '@ndla/types-backend/learningpath-api'; import { fetchLearningpath, fetchNode, fetchOembed } from '../api'; -import { fetchExamLockStatus } from '../api/learningpathApi'; +import { fetchConfig, fetchExamLockStatus } from '../api/learningpathApi'; import { + GQLConfigMetaBoolean, + GQLConfigMetaStringList, GQLLearningpath, GQLLearningpathStep, GQLLearningpathStepOembed, @@ -31,8 +32,23 @@ export const Query = { _: any, __: any, context: ContextWithLoaders, - ): Promise { - return fetchExamLockStatus(context); + ): Promise { + const config = await fetchExamLockStatus(context); + if (typeof config.value !== 'boolean') { + throw new Error('Invalid exam lock status'); + } + + return { key: config.key, value: config.value }; + }, + async arenaEnabledOrgs( + _: any, + __: any, + context: ContextWithLoaders, + ): Promise { + const config = await fetchConfig('ARENA_ENABLED_ORGS', context); + if (typeof config.value === 'boolean') + throw new Error('Invalid arena enabled orgs'); + return { key: config.key, value: config.value }; }, }; diff --git a/src/schema.ts b/src/schema.ts index 73461f92..8805e15e 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1126,6 +1126,8 @@ export const typeDefs = gql` id: Int! favoriteSubjects: [String!]! role: String! + arenaEnabled: Boolean! + organization: String! } type ConfigMetaRestricted { @@ -1133,6 +1135,16 @@ export const typeDefs = gql` value: String! } + type ConfigMetaBoolean { + key: String! + value: Boolean! + } + + type ConfigMetaStringList { + key: String! + value: [String!]! + } + type ResourceMetaData { images: [ImageLicense!] audios: [AudioLicense!] @@ -1322,7 +1334,8 @@ export const typeDefs = gql` allFolderResources(size: Int): [FolderResource!]! personalData: MyNdlaPersonalData! image(id: String!): ImageMetaInformationV2 - examLockStatus: ConfigMetaRestricted! + examLockStatus: ConfigMetaBoolean! + arenaEnabledOrgs: ConfigMetaStringList resourceEmbed(id: String!, type: String!): ResourceEmbed! resourceEmbeds(resources: [ResourceEmbedInput!]!): ResourceEmbed! arenaCategories: [ArenaCategory!]! diff --git a/src/types/schema.d.ts b/src/types/schema.d.ts index 90bcb9c2..27e2ba08 100644 --- a/src/types/schema.d.ts +++ b/src/types/schema.d.ts @@ -369,12 +369,24 @@ export type GQLConceptResult = { totalCount: Scalars['Int']; }; +export type GQLConfigMetaBoolean = { + __typename?: 'ConfigMetaBoolean'; + key: Scalars['String']; + value: Scalars['Boolean']; +}; + export type GQLConfigMetaRestricted = { __typename?: 'ConfigMetaRestricted'; key: Scalars['String']; value: Scalars['String']; }; +export type GQLConfigMetaStringList = { + __typename?: 'ConfigMetaStringList'; + key: Scalars['String']; + value: Array; +}; + export type GQLContributor = { __typename?: 'Contributor'; name: Scalars['String']; @@ -949,8 +961,10 @@ export type GQLMutationUpdatePersonalDataArgs = { export type GQLMyNdlaPersonalData = { __typename?: 'MyNdlaPersonalData'; + arenaEnabled: Scalars['Boolean']; favoriteSubjects: Array; id: Scalars['Int']; + organization: Scalars['String']; role: Scalars['String']; }; @@ -1063,6 +1077,7 @@ export type GQLQuery = { allFolderResources: Array; arenaCategories: Array; arenaCategory?: Maybe; + arenaEnabledOrgs?: Maybe; arenaRecentTopics: Array; arenaTopic?: Maybe; arenaTopicsByUser: Array; @@ -1074,7 +1089,7 @@ export type GQLQuery = { conceptSearch?: Maybe; coreElement?: Maybe; coreElements?: Maybe>; - examLockStatus: GQLConfigMetaRestricted; + examLockStatus: GQLConfigMetaBoolean; filmfrontpage?: Maybe; folder: GQLFolder; folderResourceMeta?: Maybe; @@ -1869,7 +1884,9 @@ export type GQLResolversTypes = { ConceptFolderResourceMeta: ResolverTypeWrapper; ConceptLicense: ResolverTypeWrapper; ConceptResult: ResolverTypeWrapper; + ConfigMetaBoolean: ResolverTypeWrapper; ConfigMetaRestricted: ResolverTypeWrapper; + ConfigMetaStringList: ResolverTypeWrapper; Contributor: ResolverTypeWrapper; Copyright: ResolverTypeWrapper; CoreElement: ResolverTypeWrapper; @@ -2016,7 +2033,9 @@ export type GQLResolversParentTypes = { ConceptFolderResourceMeta: GQLConceptFolderResourceMeta; ConceptLicense: GQLConceptLicense; ConceptResult: GQLConceptResult; + ConfigMetaBoolean: GQLConfigMetaBoolean; ConfigMetaRestricted: GQLConfigMetaRestricted; + ConfigMetaStringList: GQLConfigMetaStringList; Contributor: GQLContributor; Copyright: GQLCopyright; CoreElement: GQLCoreElement; @@ -2477,12 +2496,24 @@ export type GQLConceptResultResolvers; }; +export type GQLConfigMetaBooleanResolvers = { + key?: Resolver; + value?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type GQLConfigMetaRestrictedResolvers = { key?: Resolver; value?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; +export type GQLConfigMetaStringListResolvers = { + key?: Resolver; + value?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type GQLContributorResolvers = { name?: Resolver; type?: Resolver; @@ -2969,8 +3000,10 @@ export type GQLMutationResolvers = { + arenaEnabled?: Resolver; favoriteSubjects?: Resolver, ParentType, ContextType>; id?: Resolver; + organization?: Resolver; role?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -3084,6 +3117,7 @@ export type GQLQueryResolvers, ParentType, ContextType, Partial>; arenaCategories?: Resolver, ParentType, ContextType>; arenaCategory?: Resolver, ParentType, ContextType, RequireFields>; + arenaEnabledOrgs?: Resolver, ParentType, ContextType>; arenaRecentTopics?: Resolver, ParentType, ContextType>; arenaUser?: Resolver, ParentType, ContextType, RequireFields>; arenaTopic?: Resolver, ParentType, ContextType, RequireFields>; @@ -3096,7 +3130,7 @@ export type GQLQueryResolvers, ParentType, ContextType, Partial>; coreElement?: Resolver, ParentType, ContextType, RequireFields>; coreElements?: Resolver>, ParentType, ContextType, Partial>; - examLockStatus?: Resolver; + examLockStatus?: Resolver; filmfrontpage?: Resolver, ParentType, ContextType>; folder?: Resolver>; folderResourceMeta?: Resolver, ParentType, ContextType, RequireFields>; @@ -3531,7 +3565,9 @@ export type GQLResolvers = { ConceptFolderResourceMeta?: GQLConceptFolderResourceMetaResolvers; ConceptLicense?: GQLConceptLicenseResolvers; ConceptResult?: GQLConceptResultResolvers; + ConfigMetaBoolean?: GQLConfigMetaBooleanResolvers; ConfigMetaRestricted?: GQLConfigMetaRestrictedResolvers; + ConfigMetaStringList?: GQLConfigMetaStringListResolvers; Contributor?: GQLContributorResolvers; Copyright?: GQLCopyrightResolvers; CoreElement?: GQLCoreElementResolvers; From 11d32b6f6cc8dda842b1c1c9432e709785e93adc Mon Sep 17 00:00:00 2001 From: Jonas Natten Date: Wed, 8 Nov 2023 11:39:30 +0100 Subject: [PATCH 2/4] Bump `@ndla/types-backend` --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8c92be44..d2ae55da 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@graphql-codegen/typescript-operations": "^2.5.6", "@graphql-codegen/typescript-resolvers": "^2.7.6", "@graphql-eslint/eslint-plugin": "^3.12.0", - "@ndla/types-backend": "^0.2.23", + "@ndla/types-backend": "^0.2.26", "@ndla/types-embed": "^4.0.0", "@ndla/types-taxonomy": "^1.0.19", "@types/bunyan": "^1.8.5", diff --git a/yarn.lock b/yarn.lock index 3afa5a47..417492b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1506,10 +1506,10 @@ resolved "https://registry.yarnpkg.com/@ndla/licenses/-/licenses-7.1.3.tgz#3a826083fdf29cafe66b6197087c455d80a7a0ec" integrity sha512-3GNJxmAlFHnc4Q77sJL+RapEUcxxyBe9jDaFZ9f4miVpu3cIiZUhSXdqWR6E4C9EOKk86tuGftbr9BXIqREa+Q== -"@ndla/types-backend@^0.2.23": - version "0.2.23" - resolved "https://registry.yarnpkg.com/@ndla/types-backend/-/types-backend-0.2.23.tgz#dbd64746100e9ba4fc89332987ba3d89ed9fd503" - integrity sha512-jPU9uj/ItVyNnBCuPIqbSnOhfhVqC1nmEQzbV9cLCF0ijp7KmHpQ7UzfbG3zOg8/3GfuKVZT1Tk3vpVzlS4waQ== +"@ndla/types-backend@^0.2.26": + version "0.2.26" + resolved "https://registry.npmjs.org/@ndla/types-backend/-/types-backend-0.2.26.tgz#cf0e5ff76ce2893d7b54a475df4fa4865bf7a0a7" + integrity sha512-xSl2C20vXo1VvcOH7qWfsgg+T9sSmxInuPTcWgZPChKSX+Mo8nIZlz1Arz2gw9pg9YYDrMnMwKVD8B7i9xOihQ== "@ndla/types-embed@^4.0.0": version "4.0.0" From 663192567791c968fb4025526da39f8233802cba Mon Sep 17 00:00:00 2001 From: Jonas Natten Date: Wed, 8 Nov 2023 11:55:26 +0100 Subject: [PATCH 3/4] Remove `ConfigMetaRestricted` from schema --- src/schema.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/schema.ts b/src/schema.ts index 8805e15e..31485b15 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1130,11 +1130,6 @@ export const typeDefs = gql` organization: String! } - type ConfigMetaRestricted { - key: String! - value: String! - } - type ConfigMetaBoolean { key: String! value: Boolean! From 9cb067cef0942f68f3b7e6d28a2a504c096698ee Mon Sep 17 00:00:00 2001 From: Jonas Natten Date: Wed, 8 Nov 2023 11:55:43 +0100 Subject: [PATCH 4/4] Generate schema types --- src/types/schema.d.ts | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/types/schema.d.ts b/src/types/schema.d.ts index 27e2ba08..db5eb33d 100644 --- a/src/types/schema.d.ts +++ b/src/types/schema.d.ts @@ -69,10 +69,10 @@ export type GQLArenaTopic = { export type GQLArenaUser = { __typename?: 'ArenaUser'; displayName: Scalars['String']; - username: Scalars['String']; id: Scalars['Int']; profilePicture?: Maybe; slug: Scalars['String']; + username: Scalars['String']; }; export type GQLArticle = { @@ -375,12 +375,6 @@ export type GQLConfigMetaBoolean = { value: Scalars['Boolean']; }; -export type GQLConfigMetaRestricted = { - __typename?: 'ConfigMetaRestricted'; - key: Scalars['String']; - value: Scalars['String']; -}; - export type GQLConfigMetaStringList = { __typename?: 'ConfigMetaStringList'; key: Scalars['String']; @@ -1081,6 +1075,7 @@ export type GQLQuery = { arenaRecentTopics: Array; arenaTopic?: Maybe; arenaTopicsByUser: Array; + arenaUser?: Maybe; article?: Maybe; audio?: Maybe; competenceGoal?: Maybe; @@ -1126,14 +1121,12 @@ export type GQLQueryAllFolderResourcesArgs = { size?: InputMaybe; }; + export type GQLQueryArenaCategoryArgs = { categoryId: Scalars['Int']; page: Scalars['Int']; }; -export type GQLQueryArenaUserArgs = { - username: Scalars['String']; -}; export type GQLQueryArenaTopicArgs = { page: Scalars['Int']; @@ -1146,6 +1139,11 @@ export type GQLQueryArenaTopicsByUserArgs = { }; +export type GQLQueryArenaUserArgs = { + username: Scalars['String']; +}; + + export type GQLQueryArticleArgs = { absoluteUrl?: InputMaybe; convertEmbeds?: InputMaybe; @@ -1885,7 +1883,6 @@ export type GQLResolversTypes = { ConceptLicense: ResolverTypeWrapper; ConceptResult: ResolverTypeWrapper; ConfigMetaBoolean: ResolverTypeWrapper; - ConfigMetaRestricted: ResolverTypeWrapper; ConfigMetaStringList: ResolverTypeWrapper; Contributor: ResolverTypeWrapper; Copyright: ResolverTypeWrapper; @@ -2034,7 +2031,6 @@ export type GQLResolversParentTypes = { ConceptLicense: GQLConceptLicense; ConceptResult: GQLConceptResult; ConfigMetaBoolean: GQLConfigMetaBoolean; - ConfigMetaRestricted: GQLConfigMetaRestricted; ConfigMetaStringList: GQLConfigMetaStringList; Contributor: GQLContributor; Copyright: GQLCopyright; @@ -2204,6 +2200,7 @@ export type GQLArenaUserResolvers; profilePicture?: Resolver, ParentType, ContextType>; slug?: Resolver; + username?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -2502,12 +2499,6 @@ export type GQLConfigMetaBooleanResolvers; }; -export type GQLConfigMetaRestrictedResolvers = { - key?: Resolver; - value?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type GQLConfigMetaStringListResolvers = { key?: Resolver; value?: Resolver, ParentType, ContextType>; @@ -3119,9 +3110,9 @@ export type GQLQueryResolvers, ParentType, ContextType, RequireFields>; arenaEnabledOrgs?: Resolver, ParentType, ContextType>; arenaRecentTopics?: Resolver, ParentType, ContextType>; - arenaUser?: Resolver, ParentType, ContextType, RequireFields>; arenaTopic?: Resolver, ParentType, ContextType, RequireFields>; arenaTopicsByUser?: Resolver, ParentType, ContextType, RequireFields>; + arenaUser?: Resolver, ParentType, ContextType, RequireFields>; article?: Resolver, ParentType, ContextType, RequireFields>; audio?: Resolver, ParentType, ContextType, RequireFields>; competenceGoal?: Resolver, ParentType, ContextType, RequireFields>; @@ -3566,7 +3557,6 @@ export type GQLResolvers = { ConceptLicense?: GQLConceptLicenseResolvers; ConceptResult?: GQLConceptResultResolvers; ConfigMetaBoolean?: GQLConfigMetaBooleanResolvers; - ConfigMetaRestricted?: GQLConfigMetaRestrictedResolvers; ConfigMetaStringList?: GQLConfigMetaStringListResolvers; Contributor?: GQLContributorResolvers; Copyright?: GQLCopyrightResolvers;