From 74ca92bfa0d94c4a1aff85f7b79ee1be435ee59c Mon Sep 17 00:00:00 2001 From: Jared Jolton Date: Fri, 26 Jun 2026 11:32:16 -0600 Subject: [PATCH 1/2] fix(ga4, sap, mux): use sdk.cma instead of manual createClient app-sdk >=4.58.0 introduces a nested contentful-management@12 dep that conflicts with apps' own v11 direct dep when bundled by react-scripts, causing "createClient is not a function" at runtime. Replace createClient({ apiAdapter: sdk.cmaAdapter }, ...) with sdk.cma (the pre-configured plain CMA client the SDK already provides): - google-analytics-4: fetchAllContentTypes uses sdk.cma.contentType.getMany - sap-commerce-cloud: config useEffect uses sdk.cma.contentType/editorInterface.getMany - mux: class component stores sdk.cma directly instead of constructing a client Co-Authored-By: Claude Sonnet 4.6 --- .../AssignContentTypeSection.tsx | 8 ++------ apps/mux/frontend/src/index.tsx | 13 ++----------- .../frontend/src/components/AppConfig/AppConfig.tsx | 9 ++------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/apps/google-analytics-4/frontend/src/components/config-screen/assign-content-type/AssignContentTypeSection.tsx b/apps/google-analytics-4/frontend/src/components/config-screen/assign-content-type/AssignContentTypeSection.tsx index 11bc8c177b..874f96761b 100644 --- a/apps/google-analytics-4/frontend/src/components/config-screen/assign-content-type/AssignContentTypeSection.tsx +++ b/apps/google-analytics-4/frontend/src/components/config-screen/assign-content-type/AssignContentTypeSection.tsx @@ -11,7 +11,7 @@ import { Checkbox, } from '@contentful/f36-components'; import { ExternalLinkIcon } from '@contentful/f36-icons'; -import { ContentTypeProps, createClient } from 'contentful-management'; +import { ContentTypeProps } from 'contentful-management'; import { KnownAppSDK, EditorInterface } from '@contentful/app-sdk'; import { KeyValueMap } from '@contentful/app-sdk/dist/types/entities'; import { useSDK } from '@contentful/react-apps-toolkit'; @@ -163,17 +163,13 @@ const AssignContentTypeSection = (props: Props) => { }, [isContentTypeAssignmentValid, onIsValidContentTypeAssignment]); const fetchAllContentTypes = async (sdk: KnownAppSDK): Promise => { - const cma = createClient({ apiAdapter: sdk.cmaAdapter }); - const space = await cma.getSpace(sdk.ids.space); - const environment = await space.getEnvironment(sdk.ids.environment); - let allContentTypes: ContentTypeProps[] = []; let skip = 0; const limit = 100; let areMoreContentTypes = true; while (areMoreContentTypes) { - const response = await environment.getContentTypes({ skip, limit }); + const response = await sdk.cma.contentType.getMany({ query: { skip, limit } }); if (response.items) { allContentTypes = allContentTypes.concat(response.items as ContentTypeProps[]); areMoreContentTypes = response.items.length === limit; diff --git a/apps/mux/frontend/src/index.tsx b/apps/mux/frontend/src/index.tsx index 9876c1bfcc..63f0237e1d 100755 --- a/apps/mux/frontend/src/index.tsx +++ b/apps/mux/frontend/src/index.tsx @@ -45,7 +45,7 @@ import { } from './util/types'; import './index.css'; -import { createClient, PlainClientAPI } from 'contentful-management'; +import { PlainClientAPI } from 'contentful-management'; import { MuxApiService, MuxApiError, @@ -105,16 +105,7 @@ export class App extends React.Component { const { muxAccessTokenId, muxAccessTokenSecret } = this.props.sdk.parameters .installation as InstallationParams; - this.cmaClient = createClient( - { apiAdapter: this.props.sdk.cmaAdapter }, - { - type: 'plain', - defaults: { - environmentId: this.props.sdk.ids.environmentAlias ?? this.props.sdk.ids.environment, - spaceId: this.props.sdk.ids.space, - }, - } - ); + this.cmaClient = this.props.sdk.cma; const field = props.sdk.field.getValue(); diff --git a/apps/sap-commerce-cloud/frontend/src/components/AppConfig/AppConfig.tsx b/apps/sap-commerce-cloud/frontend/src/components/AppConfig/AppConfig.tsx index cf36856328..ccdfbf3df8 100644 --- a/apps/sap-commerce-cloud/frontend/src/components/AppConfig/AppConfig.tsx +++ b/apps/sap-commerce-cloud/frontend/src/components/AppConfig/AppConfig.tsx @@ -29,7 +29,6 @@ import { Config, ParameterDefinition, ValidateParametersFn } from '@interfaces'; import { styles } from '@components/AppConfig/AppConfig.styles'; import { useSDK } from '@contentful/react-apps-toolkit'; -import { createClient } from 'contentful-management'; interface Props { parameterDefinitions: ParameterDefinition[]; @@ -83,13 +82,9 @@ export default function AppConfig({ useEffect(() => { (async () => { - const cma = createClient({ apiAdapter: sdk.cmaAdapter }); - const space = await cma.getSpace(sdk.ids.space); - const environment = await space.getEnvironment(sdk.ids.environment); - const [contentTypesResponse, eisResponse, parameters] = await Promise.all([ - environment.getContentTypes(), - environment.getEditorInterfaces(), + sdk.cma.contentType.getMany({}), + sdk.cma.editorInterface.getMany({}), sdk.app.getParameters(), ]); From 46067789ff472749d3c04cde7efa95fbe19a0fbc Mon Sep 17 00:00:00 2001 From: Jared Jolton Date: Fri, 26 Jun 2026 13:37:10 -0600 Subject: [PATCH 2/2] fix(ga4): update mockSdk.cma to use plain client API Co-Authored-By: Claude Sonnet 4.6 --- .../frontend/test/mocks/mockSdk.ts | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/apps/google-analytics-4/frontend/test/mocks/mockSdk.ts b/apps/google-analytics-4/frontend/test/mocks/mockSdk.ts index 11d7a832fa..71de797b32 100644 --- a/apps/google-analytics-4/frontend/test/mocks/mockSdk.ts +++ b/apps/google-analytics-4/frontend/test/mocks/mockSdk.ts @@ -13,29 +13,9 @@ const mockSdk: any = { appSignedRequest: { create: () => ({}), }, - getSpace: () => ({ - getEnvironment: () => ({ - getContentTypes: () => ({ - description: - 'A series of lessons designed to teach sets of concepts that enable students to master Contentful.', - displayField: 'title', - name: 'Course', - fields: [ - { - course: { - disabled: false, - id: 'title', - localized: true, - name: 'Title', - omitted: false, - required: true, - type: 'Symbol', - }, - }, - ], - }), - }), - }), + contentType: { + getMany: vi.fn().mockResolvedValue({ items: [] }), + }, }, ids: { app: 'test-app',