@financial-times/cp-content-pipeline-schema 1.1.1 → 1.2.1
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.
- package/CHANGELOG.md +19 -0
- package/lib/generated/index.d.ts +2 -0
- package/lib/model/CapiResponse.d.ts +2 -0
- package/lib/model/CapiResponse.js +12 -0
- package/lib/model/CapiResponse.js.map +1 -1
- package/lib/model/Image.js +6 -3
- package/lib/model/Image.js.map +1 -1
- package/lib/model/Picture.d.ts +2 -1
- package/lib/model/Picture.js +4 -2
- package/lib/model/Picture.js.map +1 -1
- package/lib/model/Picture.test.js +5 -4
- package/lib/model/Picture.test.js.map +1 -1
- package/lib/model/Topper.test.js +6 -2
- package/lib/model/Topper.test.js.map +1 -1
- package/lib/model/schemas/capi/base-schema.d.ts +3 -0
- package/lib/model/schemas/capi/base-schema.js +1 -0
- package/lib/model/schemas/capi/base-schema.js.map +1 -1
- package/lib/model/schemas/capi/index.d.ts +1 -0
- package/lib/model/schemas/capi/live-blog-package.d.ts +3 -0
- package/lib/model/schemas/capi/live-blog-package.js +1 -0
- package/lib/model/schemas/capi/live-blog-package.js.map +1 -1
- package/lib/model/schemas/capi/video.d.ts +1 -0
- package/lib/resolvers/content-tree/references/ImageSet.js +2 -1
- package/lib/resolvers/content-tree/references/ImageSet.js.map +1 -1
- package/lib/resolvers/content-tree/references/LayoutImage.js +2 -1
- package/lib/resolvers/content-tree/references/LayoutImage.js.map +1 -1
- package/lib/resolvers/content-tree/references/ScrollyImage.js +2 -1
- package/lib/resolvers/content-tree/references/ScrollyImage.js.map +1 -1
- package/lib/resolvers/content.d.ts +1 -0
- package/lib/resolvers/content.js +1 -0
- package/lib/resolvers/content.js.map +1 -1
- package/lib/resolvers/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/generated/index.ts +2 -0
- package/src/model/CapiResponse.ts +17 -0
- package/src/model/Image.ts +6 -3
- package/src/model/Picture.test.ts +10 -4
- package/src/model/Picture.ts +9 -2
- package/src/model/Topper.test.ts +6 -2
- package/src/model/schemas/capi/base-schema.ts +1 -0
- package/src/model/schemas/capi/live-blog-package.ts +1 -0
- package/src/resolvers/content-tree/references/ImageSet.ts +3 -1
- package/src/resolvers/content-tree/references/LayoutImage.ts +3 -0
- package/src/resolvers/content-tree/references/ScrollyImage.ts +3 -1
- package/src/resolvers/content.ts +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/typedefs/content.graphql +1 -0
package/package.json
CHANGED
package/src/generated/index.ts
CHANGED
|
@@ -529,6 +529,7 @@ export type LiveBlogPackage = Content & {
|
|
|
529
529
|
readonly id: Scalars['String']['output'];
|
|
530
530
|
readonly liveBlogPosts?: Maybe<ReadonlyArray<Maybe<Content>>>;
|
|
531
531
|
readonly mainImage?: Maybe<Image>;
|
|
532
|
+
readonly pinnedPost?: Maybe<Content>;
|
|
532
533
|
readonly publishedDate: Scalars['String']['output'];
|
|
533
534
|
readonly realtime?: Maybe<Scalars['Boolean']['output']>;
|
|
534
535
|
readonly standfirst?: Maybe<Scalars['String']['output']>;
|
|
@@ -1569,6 +1570,7 @@ export type LiveBlogPackageResolvers<ContextType = QueryContext, ParentType exte
|
|
|
1569
1570
|
id?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
1570
1571
|
liveBlogPosts?: Resolver<Maybe<ReadonlyArray<Maybe<ResolversTypes['Content']>>>, ParentType, ContextType>;
|
|
1571
1572
|
mainImage?: Resolver<Maybe<ResolversTypes['Image']>, ParentType, ContextType>;
|
|
1573
|
+
pinnedPost?: Resolver<Maybe<ResolversTypes['Content']>, ParentType, ContextType>;
|
|
1572
1574
|
publishedDate?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
1573
1575
|
realtime?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
|
1574
1576
|
standfirst?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
@@ -537,6 +537,23 @@ export class CapiResponse {
|
|
|
537
537
|
return []
|
|
538
538
|
}
|
|
539
539
|
|
|
540
|
+
async pinnedPost(): Promise<CapiResponse | null> {
|
|
541
|
+
if ('pinnedPosts' in this.capiData) {
|
|
542
|
+
const pinnedPosts = this.capiData.pinnedPosts || []
|
|
543
|
+
const liveBlogPosts = await this.liveBlogPosts()
|
|
544
|
+
|
|
545
|
+
const pinnedPostId = pinnedPosts[0]
|
|
546
|
+
const pinnedPostIndex = liveBlogPosts.findIndex(
|
|
547
|
+
(post) => post.id() === pinnedPostId
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
if (pinnedPostIndex !== -1) {
|
|
551
|
+
return liveBlogPosts.splice(pinnedPostIndex, 1)[0]
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return null
|
|
555
|
+
}
|
|
556
|
+
|
|
540
557
|
isContainedInPackage(): boolean {
|
|
541
558
|
return 'containedIn' in this.capiData
|
|
542
559
|
? (this.capiData.containedIn?.length ?? 0) > 0
|
package/src/model/Image.ts
CHANGED
|
@@ -126,7 +126,7 @@ export class CAPIImage implements Image {
|
|
|
126
126
|
return resolutions.map((dpr) => ({
|
|
127
127
|
url: imageServiceUrl({
|
|
128
128
|
id,
|
|
129
|
-
url: this.
|
|
129
|
+
url: this.capiImage.binaryUrl,
|
|
130
130
|
systemCode: this.#systemCode,
|
|
131
131
|
width: maxAllowedWidth,
|
|
132
132
|
dpr,
|
|
@@ -137,7 +137,10 @@ export class CAPIImage implements Image {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
url() {
|
|
140
|
-
return
|
|
140
|
+
return imageServiceUrl({
|
|
141
|
+
url: this.capiImage.binaryUrl,
|
|
142
|
+
systemCode: this.#systemCode,
|
|
143
|
+
})
|
|
141
144
|
}
|
|
142
145
|
|
|
143
146
|
async dimensions() {
|
|
@@ -149,7 +152,7 @@ export class CAPIImage implements Image {
|
|
|
149
152
|
}
|
|
150
153
|
try {
|
|
151
154
|
const imageMetadata = await this.#dataSources.origami.getImageMetadata(
|
|
152
|
-
this.
|
|
155
|
+
this.capiImage.binaryUrl
|
|
153
156
|
)
|
|
154
157
|
return imageMetadata
|
|
155
158
|
} catch (error) {
|
|
@@ -2,6 +2,8 @@ import { QueryContext } from '..'
|
|
|
2
2
|
import { ImageSet } from '../types/internal-content'
|
|
3
3
|
import { Picture } from './Picture'
|
|
4
4
|
|
|
5
|
+
const isLiveBlog = false
|
|
6
|
+
|
|
5
7
|
describe('Picture model', () => {
|
|
6
8
|
const mockImageSet = {
|
|
7
9
|
apiUrl: 'https://api.ft.com/content/image-set',
|
|
@@ -35,9 +37,9 @@ describe('Picture model', () => {
|
|
|
35
37
|
|
|
36
38
|
describe('finding the standard image', () => {
|
|
37
39
|
it('uses the StandardInline image if it exists', () => {
|
|
38
|
-
const picture = new Picture(mockImageSet, mockContext)
|
|
40
|
+
const picture = new Picture(mockImageSet, isLiveBlog, mockContext)
|
|
39
41
|
expect(picture.standard().url()).toEqual(
|
|
40
|
-
'https://
|
|
42
|
+
'https://www.ft.com/__origami/service/image/v2/images/raw/https%3A%2F%2Fcloudfront.com%2Fstandard-inline.jpg?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
41
43
|
)
|
|
42
44
|
})
|
|
43
45
|
|
|
@@ -73,9 +75,13 @@ describe('Picture model', () => {
|
|
|
73
75
|
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
74
76
|
} as ImageSet
|
|
75
77
|
|
|
76
|
-
const picture = new Picture(
|
|
78
|
+
const picture = new Picture(
|
|
79
|
+
mockWithoutStandardInline,
|
|
80
|
+
isLiveBlog,
|
|
81
|
+
mockContext
|
|
82
|
+
)
|
|
77
83
|
expect(picture.standard().url()).toEqual(
|
|
78
|
-
'https://
|
|
84
|
+
'https://www.ft.com/__origami/service/image/v2/images/raw/https%3A%2F%2Fcloudfront.com%2Fdesktop.jpg?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
79
85
|
)
|
|
80
86
|
})
|
|
81
87
|
})
|
package/src/model/Picture.ts
CHANGED
|
@@ -14,7 +14,11 @@ function assertDefined<T>(
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export class Picture {
|
|
17
|
-
constructor(
|
|
17
|
+
constructor(
|
|
18
|
+
private imageSet: ImageSet,
|
|
19
|
+
private isLiveBlog: boolean,
|
|
20
|
+
private context: QueryContext
|
|
21
|
+
) {}
|
|
18
22
|
|
|
19
23
|
images(): Image[] {
|
|
20
24
|
return this.imageSet.members.map(
|
|
@@ -36,7 +40,10 @@ export class Picture {
|
|
|
36
40
|
|
|
37
41
|
async layoutWidth(): Promise<LayoutWidth> {
|
|
38
42
|
//TODO: actually work out the types
|
|
39
|
-
|
|
43
|
+
|
|
44
|
+
if (!this.isLiveBlog && this.imageSet.members.length === 3) {
|
|
45
|
+
return 'full-grid'
|
|
46
|
+
}
|
|
40
47
|
|
|
41
48
|
const dimensions = await this.standard().dimensions()
|
|
42
49
|
|
package/src/model/Topper.test.ts
CHANGED
|
@@ -7,6 +7,7 @@ import conceptIds from '@financial-times/n-concept-ids'
|
|
|
7
7
|
|
|
8
8
|
import type { QueryContext } from '..'
|
|
9
9
|
import type { Image as CAPIImage } from '../types/internal-content'
|
|
10
|
+
import imageServiceUrl from '../helpers/imageService'
|
|
10
11
|
|
|
11
12
|
const context = {} as unknown as QueryContext
|
|
12
13
|
describe('produces the correct types', () => {
|
|
@@ -325,7 +326,7 @@ describe('produces correct images', () => {
|
|
|
325
326
|
const topper = new Topper(capiResponse, context)
|
|
326
327
|
const fallback = topper.fallbackImage()
|
|
327
328
|
expect(fallback?.url()).toEqual(
|
|
328
|
-
'https://
|
|
329
|
+
'https://www.ft.com/__origami/service/image/v2/images/raw/https%3A%2F%2Fcloudfront.com%2Ftopper-standard.png?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
329
330
|
)
|
|
330
331
|
})
|
|
331
332
|
it('uses the main image as fallback if no lead images', () => {
|
|
@@ -334,7 +335,10 @@ describe('produces correct images', () => {
|
|
|
334
335
|
const topper = new Topper(capiResponse, context)
|
|
335
336
|
const fallback = topper.fallbackImage()
|
|
336
337
|
expect(fallback?.url()).toEqual(
|
|
337
|
-
(
|
|
338
|
+
imageServiceUrl({
|
|
339
|
+
url: (baseCapiObject.mainImage as CAPIImage).binaryUrl,
|
|
340
|
+
systemCode: 'cp-content-pipeline',
|
|
341
|
+
})
|
|
338
342
|
)
|
|
339
343
|
})
|
|
340
344
|
})
|
|
@@ -5,6 +5,8 @@ import { ImageSetResolvers } from '../../../generated'
|
|
|
5
5
|
|
|
6
6
|
export const ImageSet = {
|
|
7
7
|
picture(parent, _args, context) {
|
|
8
|
+
const isLiveBlog = parent.contentApiData?.type() === 'LiveBlogPost'
|
|
9
|
+
|
|
8
10
|
const imageSet = parent.contentApiData
|
|
9
11
|
?.embeds()
|
|
10
12
|
?.find(
|
|
@@ -12,6 +14,6 @@ export const ImageSet = {
|
|
|
12
14
|
uuidFromUrl(embed.id) === uuidFromUrl(parent.reference.id)
|
|
13
15
|
)
|
|
14
16
|
|
|
15
|
-
return imageSet ? new Picture(imageSet, context) : null
|
|
17
|
+
return imageSet ? new Picture(imageSet, isLiveBlog, context) : null
|
|
16
18
|
},
|
|
17
19
|
} satisfies ImageSetResolvers
|
|
@@ -3,6 +3,8 @@ import { LayoutImageResolvers } from '../../../generated'
|
|
|
3
3
|
|
|
4
4
|
export const LayoutImage = {
|
|
5
5
|
picture(parent, _args, context): Picture {
|
|
6
|
+
const isLiveBlog = parent.contentApiData?.type() === 'LiveBlogPost'
|
|
7
|
+
|
|
6
8
|
return new Picture(
|
|
7
9
|
{
|
|
8
10
|
id: 'layout-imageset',
|
|
@@ -21,6 +23,7 @@ export const LayoutImage = {
|
|
|
21
23
|
},
|
|
22
24
|
],
|
|
23
25
|
},
|
|
26
|
+
isLiveBlog,
|
|
24
27
|
context
|
|
25
28
|
)
|
|
26
29
|
},
|
|
@@ -5,6 +5,8 @@ import { ScrollyImageResolvers } from '../../../generated'
|
|
|
5
5
|
|
|
6
6
|
export const ScrollyImage = {
|
|
7
7
|
picture(parent, _args, context) {
|
|
8
|
+
const isLiveBlog = parent.contentApiData?.type() === 'LiveBlogPost'
|
|
9
|
+
|
|
8
10
|
const imageSet = parent.contentApiData
|
|
9
11
|
?.embeds()
|
|
10
12
|
?.find(
|
|
@@ -12,6 +14,6 @@ export const ScrollyImage = {
|
|
|
12
14
|
uuidFromUrl(embed.id) === uuidFromUrl(parent.reference.id)
|
|
13
15
|
)
|
|
14
16
|
|
|
15
|
-
return imageSet ? new Picture(imageSet, context) : null
|
|
17
|
+
return imageSet ? new Picture(imageSet, isLiveBlog, context) : null
|
|
16
18
|
},
|
|
17
19
|
} satisfies ScrollyImageResolvers
|