Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion __test__/test-website/src/app/en/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,37 @@ import {
Row,
RowA,
} from '@/components/with-display-templates';
import {
ctArray,
ctBoolean,
ctContentReference,
ctInteger,
ctLink,
ctRich,
ctString,
ctWithCollision,
} from '@/components/with-repeated-properties';
import {
initContentTypeRegistry,
initDisplayTemplateRegistry,
} from '@optimizely/cms-sdk';
import { initReactComponentRegistry } from '@optimizely/cms-sdk/react/server';

initContentTypeRegistry([ct1, ct2, ct3, ct6, ct7]);
initContentTypeRegistry([
ct1,
ct2,
ct3,
ct6,
ct7,
ctString,
ctBoolean,
ctInteger,
ctRich,
ctContentReference,
ctArray,
ctWithCollision,
ctLink,
]);
initDisplayTemplateRegistry([dt1, dt2, dt3, dt4, dt5, dt6]);
initReactComponentRegistry({
resolver: {
Expand Down
3 changes: 3 additions & 0 deletions __test__/test-website/src/app/query/[...slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import RootLayout from '@/app/en/layout';

export default RootLayout;
39 changes: 39 additions & 0 deletions __test__/test-website/src/app/query/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { GraphClient, GraphErrors } from '@optimizely/cms-sdk';
import React from 'react';

type Props = {
params: Promise<{
slug: string[];
}>;
};

function handleGraphErrors(err: unknown): never {
if (err instanceof GraphErrors.GraphResponseError) {
console.log('Error message:', err.message);
console.log('Query:', err.request.query);
console.log('Variables:', err.request.variables);
}
if (err instanceof GraphErrors.GraphContentResponseError) {
console.log('Detailed errors: ', err.errors);
}

throw err;
}

export default async function Page({ params }: Props) {
const { slug } = await params;
const path = `/en/${slug.join('/')}/`;

const client = new GraphClient(process.env.OPTIMIZELY_GRAPH_SINGLE_KEY!, {
graphUrl: process.env.OPTIMIZELY_GRAPH_GATEWAY,
});

const items = await client.getContentByPath(path).catch(handleGraphErrors);

return (
<>
<h1>Query result</h1>
<pre>{JSON.stringify(items[0], null, 2)}</pre>
</>
);
}
70 changes: 70 additions & 0 deletions __test__/test-website/src/components/with-repeated-properties.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { contentType } from '@optimizely/cms-sdk';

export const ctString = contentType({
baseType: '_component',
key: 'ct_string',
properties: { p1: { type: 'string' } },
});
export const ctBoolean = contentType({
baseType: '_component',
key: 'ct_boolean',
properties: { p1: { type: 'boolean' } },
});
export const ctInteger = contentType({
baseType: '_component',
key: 'ct_integer',
properties: { p1: { type: 'integer' } },
});
export const ctRich = contentType({
baseType: '_component',
key: 'ct_rich',
properties: { p1: { type: 'richText' } },
});
export const ctLink = contentType({
baseType: '_component',
key: 'ct_link',
properties: { p1: { type: 'link' } },
});
export const ctContentReference = contentType({
baseType: '_component',
key: 'ct_contentreference',
properties: { p1: { type: 'contentReference' } },
});
export const ctArray = contentType({
baseType: '_component',
key: 'ct_array',
properties: { p1: { type: 'array', items: { type: 'string' } } },
});
export const ctWithCollision = contentType({
baseType: '_page',
key: 'ct_with_collision',
properties: {
collision: {
type: 'content',
allowedTypes: [
ctString,
ctBoolean,
ctInteger,
ctRich,
ctLink,
ctContentReference,
ctArray,
],
},
p2: {
type: 'array',
items: {
type: 'content',
allowedTypes: [
ctString,
ctBoolean,
ctInteger,
ctRich,
ctLink,
ctContentReference,
ctArray,
],
},
},
},
});
5 changes: 4 additions & 1 deletion __test__/test-website/with-display-templates.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { buildConfig } from '@optimizely/cms-sdk';

export default buildConfig({
components: ['./src/components/with-display-templates.tsx'],
components: [
'./src/components/with-display-templates.tsx',
'./src/components/with-repeated-properties.tsx',
],
});
44 changes: 22 additions & 22 deletions packages/optimizely-cms-sdk/src/graph/__test__/createQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('createFragment() simple cases', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment ct1 on ct1 { __typename str bin boo flo int dat ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__str:str ct1__bin:bin ct1__boo:boo ct1__flo:flo ct1__int:int ct1__dat:dat ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -56,7 +56,7 @@ describe('createFragment() simple cases', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment ct1 on ct1 { __typename str bin boo flo int dat ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__str:str ct1__bin:bin ct1__boo:boo ct1__flo:flo ct1__int:int ct1__dat:dat ..._IContent }",
]
`);
});
Expand All @@ -83,7 +83,7 @@ describe('createFragment() simple cases', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment ct1 on ct1 { __typename lin { text title target url { ...ContentUrl }} ric { html, json } lin2 { text title target url { ...ContentUrl }} ric2 { html, json } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__lin:lin { text title target url { ...ContentUrl }} ct1__ric:ric { html, json } ct1__lin2:lin2 { text title target url { ...ContentUrl }} ct1__ric2:ric2 { html, json } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('createFragment() with `content` properties. Explicit reference via `al
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -154,8 +154,8 @@ describe('createFragment() with `content` properties. Explicit reference via `al
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r2 on r2 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r2 } ..._IContent }",
"fragment r2 on r2 { __typename r2__p1:p1 { __typename ...r1 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r2 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -186,8 +186,8 @@ describe('createFragment() with `content` properties. Explicit reference via `al
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r2 on r2 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment ct2 on ct2 { __typename p1 { __typename ...r1 } pct1 { __typename ...r2 } ..._IContent }",
"fragment r2 on r2 { __typename r2__p1:p1 { __typename ...r1 } ..._IContent }",
"fragment ct2 on ct2 { __typename ct2__p1:p1 { __typename ...r1 } ct2__pct1:pct1 { __typename ...r2 } ..._IContent }",
]
`);
});
Expand All @@ -212,7 +212,7 @@ describe('createFragment() with `content` properties. Base types', () => {
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -240,8 +240,8 @@ describe('createFragment() with `content` properties. Base types', () => {
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r2 on r2 { __typename p1 { __typename ...r1 ...r2 } ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 ...r2 } ..._IContent }",
"fragment r2 on r2 { __typename r2__p1:p1 { __typename ...r1 ...r2 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 ...r2 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -274,7 +274,7 @@ describe('createFragment() with `content` properties. Base types', () => {
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r2 on r2 { __typename ..._IContent }",
"fragment r3 on r3 { __typename ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 ...r2 ...r3 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 ...r2 ...r3 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -305,8 +305,8 @@ describe('createFragment() with `content` properties. Base types', () => {
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r2 on r2 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment ct2 on ct2 { __typename p1 { __typename ...r1 } p2 { __typename ...r1 ...r2 } ..._IContent }",
"fragment r2 on r2 { __typename r2__p1:p1 { __typename ...r1 } ..._IContent }",
"fragment ct2 on ct2 { __typename ct2__p1:p1 { __typename ...r1 } ct2__p2:p2 { __typename ...r1 ...r2 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -340,7 +340,7 @@ describe('createFragment() with `content` properties. Allowed and restricted typ
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r3 on r3 { __typename ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 ...r3 ...ct1 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 ...r3 ...ct1 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -373,7 +373,7 @@ describe('createFragment() with `content` properties. Allowed and restricted typ
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename ..._IContent }",
"fragment r3 on r3 { __typename ..._IContent }",
"fragment ct1 on ct1 { __typename p1 { __typename ...r1 ...r3 } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename ...r1 ...r3 } ..._IContent }",
]
`);
});
Expand All @@ -397,7 +397,7 @@ describe('createFragment() with self references', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment r1 on r1 { __typename r1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand All @@ -419,7 +419,7 @@ describe('createFragment() with self references', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment r1 on r1 { __typename r1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand All @@ -441,7 +441,7 @@ describe('createFragment() with self references', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment r1 on r1 { __typename r1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -470,7 +470,7 @@ describe('createFragment() with self references', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment r1 on r1 { __typename p1 { __typename ...r1 } ..._IContent }",
"fragment r1 on r1 { __typename r1__p1:p1 { __typename ...r1 } ..._IContent }",
]
`);
});
Expand All @@ -497,7 +497,7 @@ describe('createFragment() empty objects', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment ct1 on ct1 { __typename p2 p3 ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p2:p2 ct1__p3:p3 ..._IContent }",
]
`);
});
Expand Down Expand Up @@ -548,7 +548,7 @@ describe('createFragment() empty objects', () => {
"fragment ContentUrl on ContentUrl { type default hierarchical internal graph base }",
"fragment IContentMetadata on IContentMetadata { key locale fallbackForLocale version displayName url {...ContentUrl} types published status created lastModified sortOrder variation ...MediaMetadata ...ItemMetadata ...InstanceMetadata }",
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment ct1 on ct1 { __typename p1 { __typename } ..._IContent }",
"fragment ct1 on ct1 { __typename ct1__p1:p1 { __typename } ..._IContent }",
]
`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ describe('createFragment()', () => {
"fragment _IContent on _IContent { _id _metadata {...IContentMetadata} }",
"fragment _IExperience on _IExperience { composition {...ICompositionNode }}",
"fragment ICompositionNode on ICompositionNode { __typename key type nodeType displayName displayTemplateKey displaySettings {key value} ...on CompositionStructureNode { nodes @recursive } ...on CompositionComponentNode { nodeType component { ..._IComponent } } }",
"fragment CallToAction on CallToAction { __typename label link ..._IContent }",
"fragment ExpSection on ExpSection { __typename heading ..._IContent }",
"fragment CallToAction on CallToAction { __typename CallToAction__label:label CallToAction__link:link ..._IContent }",
"fragment ExpSection on ExpSection { __typename ExpSection__heading:heading ..._IContent }",
"fragment _IComponent on _IComponent { __typename ...CallToAction ...ExpSection }",
"fragment MyExperience on MyExperience { __typename ..._IContent ..._IExperience }",
]
Expand Down
15 changes: 8 additions & 7 deletions packages/optimizely-cms-sdk/src/graph/createQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,13 @@ function convertPropertyField(
const fields: string[] = [];
const subfields: string[] = [];
const extraFragments: string[] = [];
const nameInFragment = `${rootName}__${name}:${name}`;

if (property.type === 'component') {
const key = property.contentType.key;
const fragmentName = `${key}Property`;
extraFragments.push(...createFragment(key, visited, 'Property', false));
fields.push(`${name} { ...${fragmentName} }`);
fields.push(`${nameInFragment} { ...${fragmentName} }`);
} else if (property.type === 'content') {
const allowed = resolveAllowedTypes(
property.allowedTypes,
Expand All @@ -132,24 +133,24 @@ function convertPropertyField(
}

const uniqueSubfields = ['__typename', ...new Set(subfields)].join(' '); // remove duplicates
fields.push(`${name} { ${uniqueSubfields} }`);
fields.push(`${nameInFragment} { ${uniqueSubfields} }`);
} else if (property.type === 'richText') {
fields.push(`${name} { html, json }`);
fields.push(`${nameInFragment} { html, json }`);
} else if (property.type === 'url') {
extraFragments.push(CONTENT_URL_FRAGMENT);
fields.push(`${name} { ...ContentUrl }`);
fields.push(`${nameInFragment} { ...ContentUrl }`);
} else if (property.type === 'link') {
extraFragments.push(CONTENT_URL_FRAGMENT);
fields.push(`${name} { text title target url { ...ContentUrl }}`);
fields.push(`${nameInFragment} { text title target url { ...ContentUrl }}`);
} else if (property.type === 'contentReference') {
extraFragments.push(CONTENT_URL_FRAGMENT);
fields.push(`${name} { key url { ...ContentUrl }}`);
fields.push(`${nameInFragment} { key url { ...ContentUrl }}`);
} else if (property.type === 'array') {
const f = convertProperty(name, property.items, rootName, visited);
fields.push(...f.fields);
extraFragments.push(...f.extraFragments);
} else {
fields.push(name);
fields.push(nameInFragment);
}

return {
Expand Down
Loading