@financial-times/cp-content-pipeline-schema 2.5.2 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/lib/generated/index.d.ts +668 -907
  3. package/lib/model/CapiResponse.d.ts +14 -4
  4. package/lib/model/CapiResponse.js +19 -4
  5. package/lib/model/CapiResponse.js.map +1 -1
  6. package/lib/model/RichText.d.ts +1 -1
  7. package/lib/model/RichText.js.map +1 -1
  8. package/lib/model/Topper.d.ts +2 -2
  9. package/lib/model/Topper.js +2 -2
  10. package/lib/model/Topper.js.map +1 -1
  11. package/lib/model/schemas/capi/content-package.d.ts +18 -0
  12. package/lib/model/schemas/capi/content-package.js +1 -0
  13. package/lib/model/schemas/capi/content-package.js.map +1 -1
  14. package/lib/resolvers/clip.d.ts +10 -0
  15. package/lib/resolvers/clip.js +10 -0
  16. package/lib/resolvers/clip.js.map +1 -1
  17. package/lib/resolvers/content-tree/references/ClipSet.d.ts +13 -0
  18. package/lib/resolvers/content-tree/references/ClipSet.js +12 -1
  19. package/lib/resolvers/content-tree/references/ClipSet.js.map +1 -1
  20. package/lib/resolvers/content-tree/references/Flourish.d.ts +6 -0
  21. package/lib/resolvers/content-tree/references/Flourish.js +15 -1
  22. package/lib/resolvers/content-tree/references/Flourish.js.map +1 -1
  23. package/lib/resolvers/content-tree/references/ImageSet.d.ts +1 -0
  24. package/lib/resolvers/content-tree/references/ImageSet.js +3 -0
  25. package/lib/resolvers/content-tree/references/ImageSet.js.map +1 -1
  26. package/lib/resolvers/content-tree/references/LayoutImage.d.ts +1 -0
  27. package/lib/resolvers/content-tree/references/LayoutImage.js +3 -0
  28. package/lib/resolvers/content-tree/references/LayoutImage.js.map +1 -1
  29. package/lib/resolvers/content-tree/references/RawImage.d.ts +1 -0
  30. package/lib/resolvers/content-tree/references/RawImage.js +3 -0
  31. package/lib/resolvers/content-tree/references/RawImage.js.map +1 -1
  32. package/lib/resolvers/content-tree/references/Recommended.d.ts +1 -0
  33. package/lib/resolvers/content-tree/references/Recommended.js +3 -0
  34. package/lib/resolvers/content-tree/references/Recommended.js.map +1 -1
  35. package/lib/resolvers/content-tree/references/Reference.d.ts +1 -1
  36. package/lib/resolvers/content-tree/references/Reference.js +1 -3
  37. package/lib/resolvers/content-tree/references/Reference.js.map +1 -1
  38. package/lib/resolvers/content-tree/references/ScrollyImage.d.ts +1 -0
  39. package/lib/resolvers/content-tree/references/ScrollyImage.js +3 -0
  40. package/lib/resolvers/content-tree/references/ScrollyImage.js.map +1 -1
  41. package/lib/resolvers/content-tree/references/Tweet.d.ts +1 -0
  42. package/lib/resolvers/content-tree/references/Tweet.js +3 -0
  43. package/lib/resolvers/content-tree/references/Tweet.js.map +1 -1
  44. package/lib/resolvers/content-tree/references/Video.d.ts +2 -1
  45. package/lib/resolvers/content-tree/references/Video.js +4 -3
  46. package/lib/resolvers/content-tree/references/Video.js.map +1 -1
  47. package/lib/resolvers/content-tree/references/index.d.ts +5 -1
  48. package/lib/resolvers/content-tree/references/index.js +4 -0
  49. package/lib/resolvers/content-tree/references/index.js.map +1 -1
  50. package/lib/resolvers/content.d.ts +242 -33
  51. package/lib/resolvers/content.js +66 -31
  52. package/lib/resolvers/content.js.map +1 -1
  53. package/lib/resolvers/image.d.ts +142 -12
  54. package/lib/resolvers/image.js +45 -10
  55. package/lib/resolvers/image.js.map +1 -1
  56. package/lib/resolvers/index.d.ts +588 -60
  57. package/lib/resolvers/picture.d.ts +41 -8
  58. package/lib/resolvers/picture.js +19 -21
  59. package/lib/resolvers/picture.js.map +1 -1
  60. package/lib/resolvers/richText.d.ts +14 -2
  61. package/lib/resolvers/richText.js +8 -6
  62. package/lib/resolvers/richText.js.map +1 -1
  63. package/lib/resolvers/scalars.d.ts +2 -0
  64. package/lib/resolvers/scalars.js +2 -0
  65. package/lib/resolvers/scalars.js.map +1 -1
  66. package/lib/resolvers/teaser.d.ts +5 -0
  67. package/lib/resolvers/teaser.js +6 -1
  68. package/lib/resolvers/teaser.js.map +1 -1
  69. package/lib/resolvers/topper.d.ts +127 -7
  70. package/lib/resolvers/topper.js +64 -6
  71. package/lib/resolvers/topper.js.map +1 -1
  72. package/package.json +1 -1
  73. package/src/generated/index.ts +668 -668
  74. package/src/model/CapiResponse.ts +32 -7
  75. package/src/model/RichText.ts +1 -1
  76. package/src/model/Topper.ts +2 -2
  77. package/src/model/schemas/capi/content-package.ts +1 -0
  78. package/src/resolvers/clip.ts +13 -2
  79. package/src/resolvers/content-tree/references/ClipSet.ts +22 -2
  80. package/src/resolvers/content-tree/references/Flourish.ts +20 -1
  81. package/src/resolvers/content-tree/references/ImageSet.ts +4 -0
  82. package/src/resolvers/content-tree/references/LayoutImage.ts +4 -0
  83. package/src/resolvers/content-tree/references/RawImage.ts +4 -0
  84. package/src/resolvers/content-tree/references/Recommended.ts +4 -0
  85. package/src/resolvers/content-tree/references/Reference.ts +1 -3
  86. package/src/resolvers/content-tree/references/ScrollyImage.ts +4 -0
  87. package/src/resolvers/content-tree/references/Tweet.ts +4 -0
  88. package/src/resolvers/content-tree/references/Video.ts +5 -3
  89. package/src/resolvers/content-tree/references/index.ts +13 -2
  90. package/src/resolvers/content.ts +88 -38
  91. package/src/resolvers/image.ts +75 -5
  92. package/src/resolvers/picture.ts +35 -23
  93. package/src/resolvers/richText.ts +13 -8
  94. package/src/resolvers/scalars.ts +2 -0
  95. package/src/resolvers/teaser.ts +6 -2
  96. package/src/resolvers/topper.ts +86 -6
  97. package/tsconfig.tsbuildinfo +1 -1
@@ -28,9 +28,16 @@ import {
28
28
  validLiteralUnionValue,
29
29
  } from '../resolvers/literal-union'
30
30
 
31
- import { ContentPackageContainsArgs, Media } from '../generated'
31
+ import {
32
+ ContentPackageContainsArgs,
33
+ ContentUrlArgs,
34
+ Media,
35
+ TableOfContents,
36
+ } from '../generated'
32
37
  import { Topper } from './Topper'
33
38
  import { z } from 'zod'
39
+ import { Byline } from './Byline'
40
+ import { RichText } from './RichText'
34
41
 
35
42
  function isPlainObject(object: unknown): object is Record<string, unknown> {
36
43
  if (object && typeof object === 'object') {
@@ -214,7 +221,9 @@ export class CapiResponse {
214
221
  packageContainer
215
222
  )
216
223
  }
217
-
224
+ body() {
225
+ return new RichText('bodyXML', this.bodyXML(), this)
226
+ }
218
227
  bodyXML(): string | null {
219
228
  if ('bodyXML' in this.capiData) {
220
229
  return this.capiData.bodyXML
@@ -226,7 +235,20 @@ export class CapiResponse {
226
235
  return this.capiData.embeds
227
236
  return []
228
237
  }
229
- byline(): string | null {
238
+ byline({ vanity }: Partial<ContentUrlArgs>) {
239
+ const bylineText = this.rawByline()
240
+
241
+ if (!bylineText) return null
242
+ const authorUrlMapping = this.getAuthorUrlMapping()
243
+
244
+ return new Byline(
245
+ bylineText,
246
+ Boolean(vanity),
247
+ authorUrlMapping,
248
+ this.context
249
+ ).buildBylineTree()
250
+ }
251
+ rawByline(): string | null {
230
252
  if ('byline' in this.capiData && this.capiData.byline) {
231
253
  return this.capiData.byline
232
254
  }
@@ -245,7 +267,10 @@ export class CapiResponse {
245
267
  types() {
246
268
  return this.capiData.types
247
269
  }
248
- async url(vanity?: boolean | null) {
270
+ url({ relative, vanity }: Partial<ContentUrlArgs>) {
271
+ return relative ? this.relativeUrl(vanity) : this.absoluteUrl(vanity)
272
+ }
273
+ async absoluteUrl(vanity?: boolean | null) {
249
274
  const url =
250
275
  this.capiData.webUrl ??
251
276
  this.capiData.canonicalWebUrl ??
@@ -449,7 +474,7 @@ export class CapiResponse {
449
474
 
450
475
  async relativeUrl(vanity?: boolean | null) {
451
476
  const RELATIVE_URL_REGEX = /https?:\/\/www.ft.com/
452
- const url = await this.url(vanity)
477
+ const url = await this.absoluteUrl(vanity)
453
478
  return url.replace(RELATIVE_URL_REGEX, '')
454
479
  }
455
480
 
@@ -635,9 +660,9 @@ export class CapiResponse {
635
660
  return null
636
661
  }
637
662
 
638
- async tableOfContents() {
663
+ async tableOfContents(): Promise<TableOfContents | null> {
639
664
  return 'tableOfContents' in this.capiData
640
- ? this.capiData.tableOfContents
665
+ ? this.capiData.tableOfContents ?? null
641
666
  : null
642
667
  }
643
668
 
@@ -14,7 +14,7 @@ import { QueryContext } from '..'
14
14
 
15
15
  export class RichText {
16
16
  constructor(
17
- private source: LiteralUnionScalarValues<typeof RichTextSource>,
17
+ public source: LiteralUnionScalarValues<typeof RichTextSource>,
18
18
  private value: string | null,
19
19
  private contentApiData?: CapiResponse
20
20
  ) {}
@@ -203,11 +203,11 @@ export class Topper {
203
203
  }
204
204
 
205
205
  backgroundBox() {
206
- return this.capiResponse.topper()?.backgroundBox
206
+ return this.capiResponse.topper()?.backgroundBox ?? null
207
207
  }
208
208
 
209
209
  textShadow() {
210
- return this.capiResponse.topper()?.textShadow
210
+ return this.capiResponse.topper()?.textShadow ?? null
211
211
  }
212
212
 
213
213
  displayConcept() {
@@ -38,6 +38,7 @@ const contentPackageMetadataSchema = baseMetadataSchema.pick({
38
38
  canBeDistributed: true,
39
39
  topper: true,
40
40
  comments: true,
41
+ tableOfContents: true,
41
42
  })
42
43
 
43
44
  const contentPackageMediaSchema = baseMediaSchema.pick({
@@ -1,4 +1,4 @@
1
- import { ClipResolvers } from '../generated'
1
+ import { ClipResolvers, ClipSourceResolvers } from '../generated'
2
2
 
3
3
  const resolvers = {
4
4
  Clip: {
@@ -7,7 +7,18 @@ const resolvers = {
7
7
  type: (clip) => clip.type(),
8
8
  format: (clip) => clip.format(),
9
9
  poster: (clip) => clip.poster(),
10
+ id: (clip) => clip.id(),
10
11
  },
11
- } satisfies { Clip: ClipResolvers }
12
+
13
+ ClipSource: {
14
+ audioCodec: (parent) => parent.audioCodec ?? null,
15
+ binaryUrl: (parent) => parent.binaryUrl,
16
+ duration: (parent) => parent.duration ?? null,
17
+ mediaType: (parent) => parent.mediaType,
18
+ pixelWidth: (parent) => parent.pixelWidth ?? null,
19
+ pixelHeight: (parent) => parent.pixelHeight ?? null,
20
+ videoCodec: (parent) => parent.videoCodec ?? null,
21
+ },
22
+ } satisfies { Clip: ClipResolvers; ClipSource: ClipSourceResolvers }
12
23
 
13
24
  export default resolvers
@@ -6,7 +6,11 @@ import type {
6
6
  import { uuidFromUrl } from '../../../helpers/metadata'
7
7
  import { Clip } from '../../../model/Clip'
8
8
  import { RichText } from '../../../model/RichText'
9
- import { ClipSetResolvers } from '../../../generated'
9
+ import {
10
+ AccessibilityResolvers,
11
+ CaptionResolvers,
12
+ ClipSetResolvers,
13
+ } from '../../../generated'
10
14
  import { ReferenceWithCAPIData } from '.'
11
15
 
12
16
  function getClipSet(
@@ -73,7 +77,23 @@ export const ClipSet = {
73
77
  const clipSet = getClipSet(parent)
74
78
 
75
79
  return clipSet && clipSet.members && clipSet.members.length > 0
76
- ? clipSet.members.map((clip) => new Clip(clip, parent.reference.dataLayout))
80
+ ? clipSet.members.map(
81
+ (clip) => new Clip(clip, parent.reference.dataLayout)
82
+ )
77
83
  : null
78
84
  },
85
+
86
+ type() {
87
+ return 'clip-set'
88
+ },
79
89
  } satisfies ClipSetResolvers
90
+
91
+ export const Accessibility = {
92
+ captions: (parent) => parent.captions ?? null,
93
+ transcript: (parent) => parent.transcript,
94
+ } satisfies AccessibilityResolvers
95
+
96
+ export const Caption = {
97
+ mediaType: (parent) => parent.mediaType ?? null,
98
+ url: (parent) => parent.url ?? null,
99
+ } satisfies CaptionResolvers
@@ -1,5 +1,8 @@
1
1
  import imageServiceUrl from '../../../helpers/imageService'
2
- import { FlourishResolvers } from '../../../generated'
2
+ import {
3
+ FlourishFallbackResolvers,
4
+ FlourishResolvers,
5
+ } from '../../../generated'
3
6
  import { QueryContext } from '../../..'
4
7
  import isError from '../../../helpers/isError'
5
8
 
@@ -35,8 +38,24 @@ export const Flourish = {
35
38
  height,
36
39
  }
37
40
  },
41
+
42
+ type(parent) {
43
+ return parent.reference.type
44
+ },
38
45
  } satisfies FlourishResolvers
39
46
 
47
+ export const FlourishFallback = {
48
+ async height(parent) {
49
+ return parent.height ?? null
50
+ },
51
+ async width(parent) {
52
+ return parent.width ?? null
53
+ },
54
+ async url(parent) {
55
+ return parent.url ?? null
56
+ },
57
+ } satisfies FlourishFallbackResolvers
58
+
40
59
  type ImageMetadata = {
41
60
  width: number
42
61
  height: number
@@ -22,4 +22,8 @@ export const ImageSet = {
22
22
  ? new Picture(imageSet, isLiveBlog, context)
23
23
  : null
24
24
  },
25
+
26
+ type(parent) {
27
+ return parent.reference.type
28
+ },
25
29
  } satisfies ImageSetResolvers
@@ -27,4 +27,8 @@ export const LayoutImage = {
27
27
  context
28
28
  )
29
29
  },
30
+
31
+ type(parent) {
32
+ return parent.reference.type
33
+ },
30
34
  } satisfies LayoutImageResolvers
@@ -96,4 +96,8 @@ export const RawImage = {
96
96
  image(parent, _args, context): Image {
97
97
  return new RawImageModel(parent.reference, context)
98
98
  },
99
+
100
+ type(parent) {
101
+ return parent.reference.type
102
+ },
99
103
  } satisfies RawImageResolvers
@@ -28,4 +28,8 @@ export const Recommended = {
28
28
  return null
29
29
  }
30
30
  },
31
+
32
+ type(parent) {
33
+ return parent.reference.type
34
+ },
31
35
  } satisfies RecommendedResolvers
@@ -18,7 +18,5 @@ export const Reference = {
18
18
  validNodes: Object.keys(mapNodeToReference),
19
19
  })
20
20
  },
21
- type(parent) {
22
- return parent.reference.type
23
- },
21
+ type: (parent) => parent.reference.type,
24
22
  } satisfies ReferenceResolvers
@@ -20,4 +20,8 @@ export const ScrollyImage = {
20
20
 
21
21
  return imageSet ? new Picture(imageSet, isLiveBlog, context) : null
22
22
  },
23
+
24
+ type(parent) {
25
+ return parent.reference.type
26
+ },
23
27
  } satisfies ScrollyImageResolvers
@@ -18,4 +18,8 @@ export const Tweet = {
18
18
  return null
19
19
  }
20
20
  },
21
+
22
+ type(parent) {
23
+ return parent.reference.type
24
+ },
21
25
  } satisfies TweetResolvers
@@ -3,9 +3,7 @@ import { VideoReferenceResolvers } from '../../../generated'
3
3
 
4
4
  export const Video = {
5
5
  // This will override the original id from the parent that is a URL.
6
- id(parent) {
7
- return uuidFromUrl(parent.reference.id)
8
- },
6
+ id: (parent) => uuidFromUrl(parent.reference.id),
9
7
 
10
8
  async title(parent, _args, context) {
11
9
  const capiResponse = await context.dataSources.capi.getContent(
@@ -13,4 +11,8 @@ export const Video = {
13
11
  )
14
12
  return capiResponse.title()
15
13
  },
14
+
15
+ type(parent) {
16
+ return parent.reference.type
17
+ },
16
18
  } satisfies VideoReferenceResolvers
@@ -5,9 +5,9 @@ import { Reference } from './Reference'
5
5
 
6
6
  import { Tweet } from './Tweet'
7
7
  import { ImageSet } from './ImageSet'
8
- import { ClipSet } from './ClipSet'
8
+ import { ClipSet, Accessibility, Caption } from './ClipSet'
9
9
  import { Video } from './Video'
10
- import { Flourish } from './Flourish'
10
+ import { Flourish, FlourishFallback } from './Flourish'
11
11
  import { Recommended } from './Recommended'
12
12
  import { LayoutImage } from './LayoutImage'
13
13
  import { RawImage } from './RawImage'
@@ -23,6 +23,9 @@ import {
23
23
  ScrollyImageResolvers,
24
24
  TweetResolvers,
25
25
  VideoReferenceResolvers,
26
+ CaptionResolvers,
27
+ AccessibilityResolvers,
28
+ FlourishFallbackResolvers,
26
29
  } from '../../../generated'
27
30
  import { AnyNode } from '../Workarounds'
28
31
 
@@ -42,6 +45,10 @@ export const resolvers: {
42
45
  LayoutImage: LayoutImageResolvers
43
46
  RawImage: RawImageResolvers
44
47
  ScrollyImage: ScrollyImageResolvers
48
+ MainImage: ImageSetResolvers
49
+ Caption: CaptionResolvers
50
+ Accessibility: AccessibilityResolvers
51
+ FlourishFallback: FlourishFallbackResolvers
45
52
  } = {
46
53
  Reference,
47
54
  Tweet,
@@ -53,6 +60,10 @@ export const resolvers: {
53
60
  LayoutImage,
54
61
  RawImage,
55
62
  ScrollyImage,
63
+ MainImage: ImageSet,
64
+ Caption,
65
+ Accessibility,
66
+ FlourishFallback,
56
67
  }
57
68
 
58
69
  export const mapNodeToReference = {
@@ -1,5 +1,4 @@
1
1
  import { Topper } from '../model/Topper'
2
- import { Byline } from '../model/Byline'
3
2
  import {
4
3
  ArticleResolvers,
5
4
  PlaceholderResolvers,
@@ -8,8 +7,40 @@ import {
8
7
  ContentResolvers,
9
8
  LiveBlogPackageResolvers,
10
9
  LiveBlogPostResolvers,
10
+ VideoResolvers,
11
+ TableOfContentsResolvers,
12
+ AltStandfirstResolvers,
13
+ AltTitleResolvers,
14
+ DesignResolvers,
15
+ IndicatorsResolvers,
16
+ MediaResolvers,
11
17
  } from '../generated'
12
- import { RichText } from '../model/RichText'
18
+
19
+ const contentResolvers: ContentResolvers = {
20
+ accessLevel: (parent) => parent.accessLevel(),
21
+ altStandfirst: (parent) => parent.alternativeStandfirst(),
22
+ altTitle: (parent) => parent.alternativeTitle(),
23
+ annotations: (parent) => parent.annotations(),
24
+ body: (parent) => parent.body(),
25
+ bodyXML: (parent) => parent.bodyXML(),
26
+ byline: (parent, args) => parent.byline(args),
27
+ canBeSyndicated: (parent) => parent.canBeSyndicated(),
28
+ commentsEnabled: (parent) => parent.commentsEnabled(),
29
+ design: (parent) => parent.design(),
30
+ editorialDesk: (parent) => parent.editorialDesk(),
31
+ firstPublishedDate: (parent) => parent.firstPublishedDate(),
32
+ id: (parent) => parent.id(),
33
+ instantAlertConcept: (parent) => parent.instantAlertConcept(),
34
+ mainImage: (parent) => parent.mainImage(),
35
+ originatingParty: (parent) => parent.originatingParty(),
36
+ publishedDate: (parent) => parent.publishedDate(),
37
+ standfirst: (parent) => parent.standfirst(),
38
+ teaser: (parent) => parent.teaser(),
39
+ title: (parent) => parent.title(),
40
+ topper: (parent, _, context) => new Topper(parent, context),
41
+ type: (parent) => parent.type(),
42
+ url: (parent, args) => parent.url(args),
43
+ }
13
44
 
14
45
  const resolvers = {
15
46
  Content: {
@@ -26,78 +57,90 @@ const resolvers = {
26
57
 
27
58
  return type
28
59
  },
29
- body(parent) {
30
- return new RichText('bodyXML', parent.bodyXML(), parent)
31
- },
32
- topper: (parent, _, context) => new Topper(parent, context),
33
- byline(parent, args, context) {
34
- const vanity = Boolean(args.vanity)
35
- const bylineText = parent.byline()
36
-
37
- if (!bylineText) return null
38
- const authorUrlMapping = parent.getAuthorUrlMapping()
39
-
40
- return new Byline(
41
- bylineText,
42
- vanity,
43
- authorUrlMapping,
44
- context
45
- ).buildBylineTree()
46
- },
47
- url: (parent, args) =>
48
- args.relative
49
- ? parent.relativeUrl(args?.vanity)
50
- : parent.url(args?.vanity),
51
- type: (parent) => parent.type(),
52
- mainImage: (parent) => parent.mainImage(),
53
- altTitle: (parent) => parent.alternativeTitle(),
54
- altStandfirst: (parent) => parent.alternativeStandfirst(),
55
- publishedDate: (parent) => parent.publishedDate(),
56
- annotations: (parent) => parent.annotations(),
57
- accessLevel: (parent) => parent.accessLevel(),
58
- editorialDesk: (parent) => parent.editorialDesk(),
59
- canBeSyndicated: (parent) => parent.canBeSyndicated(),
60
- instantAlertConcept: (parent) => parent.instantAlertConcept(),
61
- originatingParty: (parent) => parent.originatingParty(),
62
- commentsEnabled: (parent) => parent.commentsEnabled(),
63
- design: (parent) => parent.design(),
60
+ ...contentResolvers,
64
61
  },
65
62
 
66
63
  Article: {
64
+ ...contentResolvers,
67
65
  containedIn: (parent) => parent.containedIn(),
68
66
  },
69
67
 
70
68
  Placeholder: {
69
+ ...contentResolvers,
71
70
  containedIn: (parent) => parent.containedIn(),
72
71
  },
73
72
 
74
73
  LiveBlogPost: {
74
+ ...contentResolvers,
75
75
  containedIn: (parent) => parent.containedIn(),
76
- isPinned: (parent) => parent.isPinned(),
77
76
  indicators(parent) {
78
77
  return {
79
78
  isOpinion: parent.isOpinion(),
80
79
  }
81
80
  },
81
+ isPinned: (parent) => parent.isPinned(),
82
82
  },
83
83
 
84
84
  LiveBlogPackage: {
85
+ ...contentResolvers,
85
86
  liveBlogPosts: (parent) => parent.liveBlogPosts(),
86
87
  pinnedPost: (parent) => parent.pinnedPost(),
87
88
  realtime: (parent) => parent.realtime(),
88
89
  },
89
90
 
90
91
  ContentPackage: {
92
+ ...contentResolvers,
91
93
  contains: (parent, args) => parent.contains(args),
94
+ tableOfContents: (parent) => parent.tableOfContents(),
92
95
  containsLength: (parent) => parent.containsLength(),
93
96
  },
94
97
 
95
98
  Audio: {
99
+ ...contentResolvers,
96
100
  media: (parent) =>
97
101
  // TODO:20230712:IM should probably return captions too
98
102
  parent.media()?.filter(({ mediaType }) => mediaType === 'audio/mpeg') ??
99
103
  null,
100
104
  },
105
+
106
+ Video: {
107
+ ...contentResolvers,
108
+ },
109
+
110
+ AltStandfirst: {
111
+ promotionalStandfirst: (parent) => parent.promotionalStandfirst ?? null,
112
+ },
113
+
114
+ AltTitle: {
115
+ promotionalTitle: (parent) => parent.promotionalTitle ?? null,
116
+ },
117
+
118
+ Design: {
119
+ layout: (parent) => parent.layout ?? null,
120
+ theme: (parent) => parent.theme ?? null,
121
+ },
122
+
123
+ Indicators: {
124
+ accessLevel: (parent) => parent.accessLevel ?? null,
125
+ isOpinion: (parent) => parent.isOpinion ?? null,
126
+ isColumn: (parent) => parent.isColumn ?? null,
127
+ isPodcast: (parent) => parent.isPodcast ?? null,
128
+ isEditorsChoice: (parent) => parent.isEditorsChoice ?? null,
129
+ isExclusive: (parent) => parent.isExclusive ?? null,
130
+ isScoop: (parent) => parent.isScoop ?? null,
131
+ },
132
+
133
+ Media: {
134
+ url: (parent) => parent.url ?? null,
135
+ duration: (parent) => parent.duration ?? null,
136
+ filesize: (parent) => parent.filesize ?? null,
137
+ mediaType: (parent) => parent.mediaType ?? null,
138
+ },
139
+
140
+ TableOfContents: {
141
+ labelType: (parent) => parent.labelType ?? null,
142
+ sequence: (parent) => parent.sequence ?? null,
143
+ },
101
144
  } satisfies {
102
145
  Article: ArticleResolvers
103
146
  Placeholder: PlaceholderResolvers
@@ -106,6 +149,13 @@ const resolvers = {
106
149
  LiveBlogPackage: LiveBlogPackageResolvers
107
150
  ContentPackage: ContentPackageResolvers
108
151
  Audio: AudioResolvers
152
+ Video: VideoResolvers
153
+ AltStandfirst: AltStandfirstResolvers
154
+ AltTitle: AltTitleResolvers
155
+ Design: DesignResolvers
156
+ Indicators: IndicatorsResolvers
157
+ TableOfContents: TableOfContentsResolvers
158
+ Media: MediaResolvers
109
159
  }
110
160
 
111
161
  export default resolvers
@@ -1,4 +1,16 @@
1
- import { ImageResolvers } from '../generated'
1
+ import {
2
+ ImageDesktopResolvers,
3
+ ImageLandscapeResolvers,
4
+ ImageMobileResolvers,
5
+ ImagePortraitResolvers,
6
+ ImageResolvers,
7
+ ImageSourceResolvers,
8
+ ImageSquareFtEditResolvers,
9
+ ImageSquareResolvers,
10
+ ImageStandardInlineResolvers,
11
+ ImageStandardResolvers,
12
+ ImageWideResolvers,
13
+ } from '../generated'
2
14
  import { LiteralUnionScalarValues } from './literal-union'
3
15
  import { ImageFormat } from './scalars'
4
16
 
@@ -47,9 +59,7 @@ const resolveImageTypeFromTree = (
47
59
  return 'ImageStandard'
48
60
  }
49
61
 
50
- const resolvers = {
51
- Image: {
52
- __resolveType: (image) => resolveImageTypeFromTree(image.format()),
62
+ const imageResolvers: ImageResolvers = {
53
63
  type: (image) => image.type(),
54
64
  format: (image) => image.format(),
55
65
  caption: (image) => image.caption(),
@@ -60,7 +70,67 @@ const resolvers = {
60
70
  height: async (image) => (await image.dimensions())?.height ?? null,
61
71
  sourceSet: (image, args) => image.sourceSet(args),
62
72
  altText: (image) => image.alt(),
73
+ }
74
+
75
+ const resolvers = {
76
+ Image: {
77
+ __resolveType: (image) => resolveImageTypeFromTree(image.format()),
78
+ ...imageResolvers,
63
79
  },
64
- } satisfies { Image: ImageResolvers }
80
+
81
+ ImageDesktop: {
82
+ ...imageResolvers,
83
+ },
84
+
85
+ ImageMobile: {
86
+ ...imageResolvers,
87
+ },
88
+
89
+ ImagePortrait: {
90
+ ...imageResolvers,
91
+ },
92
+
93
+ ImageLandscape: {
94
+ ...imageResolvers,
95
+ },
96
+
97
+ ImageSquare: {
98
+ ...imageResolvers,
99
+ },
100
+
101
+ ImageSquareFTEdit: {
102
+ ...imageResolvers,
103
+ },
104
+
105
+ ImageStandard: {
106
+ ...imageResolvers,
107
+ },
108
+
109
+ ImageStandardInline: {
110
+ ...imageResolvers,
111
+ },
112
+
113
+ ImageWide: {
114
+ ...imageResolvers,
115
+ },
116
+
117
+ ImageSource: {
118
+ url: (image) => image.url,
119
+ width: (image) => image.width ?? null,
120
+ dpr: (image) => image.dpr ?? null,
121
+ },
122
+ } satisfies {
123
+ Image: ImageResolvers
124
+ ImageDesktop: ImageDesktopResolvers
125
+ ImageMobile: ImageMobileResolvers
126
+ ImagePortrait: ImagePortraitResolvers
127
+ ImageLandscape: ImageLandscapeResolvers
128
+ ImageSquare: ImageSquareResolvers
129
+ ImageSquareFTEdit: ImageSquareFtEditResolvers
130
+ ImageStandard: ImageStandardResolvers
131
+ ImageStandardInline: ImageStandardInlineResolvers
132
+ ImageWide: ImageWideResolvers
133
+ ImageSource: ImageSourceResolvers
134
+ }
65
135
 
66
136
  export default resolvers