Skip to content

Commit 1080571

Browse files
committed
JS SDK - Add type Infer for displaySettings
Feature: CMS-47083
1 parent 129f5fc commit 1080571

File tree

5 files changed

+69
-25
lines changed

5 files changed

+69
-25
lines changed

packages/optimizely-cms-sdk/src/infer.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
SectionContentType,
2929
} from './model/contentTypes.js';
3030
import { Node } from './components/richText/renderer.js';
31+
import { DisplayTemplate } from './model/displayTemplates.js';
3132

3233
/** Forces Intellisense to resolve types */
3334
export type Prettify<T> = {
@@ -184,9 +185,21 @@ type InferFromContentType<T extends AnyContentType> = Prettify<
184185
InferredBase & InferProps<T> & InferExperience<T> & InferSection<T>
185186
>;
186187

188+
/** Infers the TypeScript type for a display setting */
189+
type InferFromDisplayTemplate<T extends DisplayTemplate> =
190+
T extends { settings: infer S }
191+
? {
192+
[K in keyof S]:
193+
S[K] extends { choices: Record<string, any> }
194+
? keyof S[K]['choices']
195+
: never;
196+
}
197+
: {};
198+
187199
/** Infers the Graph response types of `T`. `T` can be a content type or a property */
188200
// prettier-ignore
189201
export type Infer<T> =
190-
T extends AnyContentType ? InferFromContentType<T>
191-
: T extends AnyProperty ? InferFromProperty<T>
192-
: unknown;
202+
T extends DisplayTemplate ? InferFromDisplayTemplate<T>
203+
: T extends AnyContentType ? InferFromContentType<T>
204+
: T extends AnyProperty ? InferFromProperty<T>
205+
: unknown;

packages/optimizely-cms-sdk/src/model/__test__/parseDisplaySettings.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ describe('parseDisplaySettings', () => {
2525
it('should return an empty object for null input', () => {
2626
const input = null;
2727
const result = parseDisplaySettings(input ?? undefined);
28-
expect(result).toEqual(undefined);
28+
expect(result).toEqual({});
2929
});
3030

3131
it('should return an empty object for undefined input', () => {
3232
const input = undefined;
3333
const result = parseDisplaySettings(input);
34-
expect(result).toEqual(undefined);
34+
expect(result).toEqual({});
3535
});
3636
});

packages/optimizely-cms-sdk/src/model/displayTemplates.ts

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DisplaySettingsType } from '../infer.js';
1+
import { DisplaySettingsType, Infer } from '../infer.js';
22
import { BaseTypes } from './contentTypes.js';
33

44
// section node types
@@ -62,20 +62,30 @@ export type DisplayTemplate<T = DisplayTemplateVariant> = T & {
6262
__type: 'displayTemplate';
6363
};
6464

65-
export function parseDisplaySettings(
66-
displaySettings?: DisplaySettingsType[] | null
67-
): Record<string, string> | undefined {
68-
if (!displaySettings) {
69-
return undefined; // Return undefined if displaySettings is not provided
70-
}
71-
72-
const result: Record<string, string> = {}; // Initialize an empty object
73-
74-
// Iterate over the input array
75-
for (const item of displaySettings) {
76-
// Assign the value to the key in the result object
77-
result[item.key] = item.value;
78-
}
79-
65+
// export function parseDisplaySettings(
66+
// displaySettings?: DisplaySettingsType[] | null
67+
// ): Record<string, string> | undefined {
68+
// if (!displaySettings) {
69+
// return undefined; // Return undefined if displaySettings is not provided
70+
// }
71+
72+
// const result: Record<string, string> = {}; // Initialize an empty object
73+
74+
// // Iterate over the input array
75+
// for (const item of displaySettings) {
76+
// // Assign the value to the key in the result object
77+
// result[item.key] = item.value;
78+
// }
79+
80+
// return result;
81+
// }
82+
83+
export const parseDisplaySettings = <T extends DisplayTemplate>(
84+
settings: DisplaySettingsType[] | null | undefined
85+
): Infer<DisplayTemplate> => {
86+
const result = {} as Infer<T>;
87+
settings?.forEach(s => {
88+
result[s.key as keyof Infer<T>] = s.value as Infer<T>[keyof Infer<T>];
89+
});
8090
return result;
81-
}
91+
};

packages/optimizely-cms-sdk/src/model/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function contentType<T extends AnyContentType>(
1212
/** Defines a Optimizely CMS display template */
1313
export function displayTemplate<T extends DisplayTemplateVariant>(
1414
options: T
15-
): T & { __type: 'displayTemplate' } {
15+
): DisplayTemplate<T> {
1616
return { ...options, __type: 'displayTemplate' };
1717
}
1818

samples/nextjs-template/src/components/Article.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { contentType, Infer } from '@optimizely/cms-sdk';
1+
import { contentType, displayTemplate, Infer } from '@optimizely/cms-sdk';
22
import { getPreviewUtils } from '@optimizely/cms-sdk/react/server';
33

44
export const ArticleContentType = contentType({
@@ -21,21 +21,42 @@ export const ArticleContentType = contentType({
2121
},
2222
});
2323

24+
export const TeaserDisplayTemplate = displayTemplate({
25+
key: 'TeaserDisplayTemplate',
26+
displayName: 'TeaserDisplayTemplate',
27+
isDefault: false,
28+
baseType: '_component',
29+
settings: {
30+
orientation: {
31+
editor: 'select',
32+
displayName: 'Teaser Orientation',
33+
sortOrder: 0,
34+
choices: {
35+
vertical: { displayName: 'Vertical', sortOrder: 1 },
36+
horizontal: { displayName: 'Horizontal', sortOrder: 2 },
37+
},
38+
},
39+
},
40+
});
41+
2442
type Props = {
2543
opti: Infer<typeof ArticleContentType>;
44+
displaySettings?: Infer<typeof TeaserDisplayTemplate>;
2645
};
2746

28-
export default function Article({ opti }: Props) {
47+
export default function Article({ opti, displaySettings }: Props) {
2948
const { pa } = getPreviewUtils(opti);
3049

3150
return (
3251
<main>
3352
<h1 {...pa('heading')}>{opti.heading}</h1>
3453
<p {...pa('subtitle')}>{opti.subtitle}</p>
54+
<p>{displaySettings?.orientation}</p>
3555
<div
3656
{...pa('body')}
3757
dangerouslySetInnerHTML={{ __html: opti.body?.html ?? '' }}
3858
/>
3959
</main>
4060
);
4161
}
62+

0 commit comments

Comments
 (0)