@financial-times/cp-content-pipeline-schema 1.3.0 → 1.3.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 +9 -0
- package/lib/generated/index.d.ts +12 -3
- package/lib/helpers/decorateHeadshotUrl.d.ts +3 -0
- package/lib/helpers/decorateHeadshotUrl.js +39 -0
- package/lib/helpers/decorateHeadshotUrl.js.map +1 -0
- package/lib/model/Concept.js +44 -14
- package/lib/model/Concept.js.map +1 -1
- package/lib/model/Concept.test.js +2 -2
- package/lib/model/Concept.test.js.map +1 -1
- package/lib/model/Picture.js +2 -0
- package/lib/model/Picture.js.map +1 -1
- package/lib/model/Topper.d.ts +1 -1
- package/lib/model/Topper.js +18 -11
- package/lib/model/Topper.js.map +1 -1
- package/lib/model/schemas/capi/article.d.ts +5 -0
- package/lib/model/schemas/capi/audio.d.ts +5 -0
- package/lib/model/schemas/capi/base-schema.d.ts +32 -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/content-package.d.ts +5 -0
- package/lib/model/schemas/capi/live-blog-package.d.ts +5 -0
- package/lib/model/schemas/capi/placeholder.d.ts +5 -0
- package/lib/resolvers/content-tree/references/ImageSet.js +1 -1
- package/lib/resolvers/content-tree/references/ImageSet.js.map +1 -1
- package/lib/resolvers/index.d.ts +3 -2
- package/lib/resolvers/topper.d.ts +3 -2
- package/lib/resolvers/topper.js +2 -3
- package/lib/resolvers/topper.js.map +1 -1
- package/package.json +1 -1
- package/src/generated/index.ts +9 -3
- package/src/helpers/decorateHeadshotUrl.ts +47 -0
- package/src/model/Concept.test.ts +2 -4
- package/src/model/Concept.ts +22 -17
- package/src/model/Picture.ts +3 -0
- package/src/model/Topper.ts +26 -12
- package/src/model/schemas/capi/base-schema.ts +1 -0
- package/src/resolvers/content-tree/references/ImageSet.ts +1 -1
- package/src/resolvers/topper.ts +2 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/typedefs/topper.graphql +3 -0
|
@@ -88,11 +88,9 @@ describe('Concept model', () => {
|
|
|
88
88
|
})
|
|
89
89
|
|
|
90
90
|
describe('headshot()', () => {
|
|
91
|
-
it('
|
|
91
|
+
it('returns null if the concept is not for an author', async () => {
|
|
92
92
|
const model = new Concept(topic, context)
|
|
93
|
-
await
|
|
94
|
-
'Cannot request headshot for a non-Author concept'
|
|
95
|
-
)
|
|
93
|
+
expect(await model.headshot()).toEqual(null)
|
|
96
94
|
})
|
|
97
95
|
|
|
98
96
|
it('returns the headshot for an author', async () => {
|
package/src/model/Concept.ts
CHANGED
|
@@ -5,6 +5,7 @@ import imageServiceUrl from '../helpers/imageService'
|
|
|
5
5
|
import isError from '../helpers/isError'
|
|
6
6
|
import { logRecoverableError } from '@dotcom-reliability-kit/log-error'
|
|
7
7
|
import conceptIds from '@financial-times/n-concept-ids'
|
|
8
|
+
import decorateHeadshotUrl, { UUID_REGEX } from '../helpers/decorateHeadshotUrl'
|
|
8
9
|
|
|
9
10
|
const CAPI_ID_PREFIX = /^https?:\/\/(?:www|api)\.ft\.com\/things?\//
|
|
10
11
|
const BASE_URL = 'https://www.ft.com/stream/'
|
|
@@ -165,26 +166,30 @@ export class Concept {
|
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
async headshot(args?: HeadshotArguments) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
const uuid = this.apiUrl().match(UUID_REGEX)?.[0]
|
|
170
|
+
|
|
171
|
+
if (!this.isAuthor() || !uuid) return null
|
|
171
172
|
|
|
172
173
|
try {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
174
|
+
const person = await this.context.dataSources.capi.getPerson(uuid)
|
|
175
|
+
const url = decorateHeadshotUrl(person)
|
|
176
|
+
|
|
177
|
+
return url
|
|
178
|
+
? imageServiceUrl({
|
|
179
|
+
url,
|
|
180
|
+
systemCode: this.#systemCode,
|
|
181
|
+
width: args?.width || 150,
|
|
182
|
+
dpr: args?.dpr ?? undefined,
|
|
183
|
+
})
|
|
184
|
+
: null
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (isError(error)) {
|
|
187
|
+
logRecoverableError({
|
|
188
|
+
logger: this.context.logger,
|
|
189
|
+
error,
|
|
190
|
+
})
|
|
191
|
+
}
|
|
186
192
|
return null
|
|
187
|
-
//TODO: log operational error here
|
|
188
193
|
}
|
|
189
194
|
}
|
|
190
195
|
}
|
package/src/model/Picture.ts
CHANGED
|
@@ -30,6 +30,9 @@ export class Picture {
|
|
|
30
30
|
const images = this.images()
|
|
31
31
|
const standard =
|
|
32
32
|
images.find((image) => image.format() === 'standard-inline') ?? images[0]
|
|
33
|
+
|
|
34
|
+
// this assert will never fail, as a Picture model won't be constructed if
|
|
35
|
+
// the imageset is empty. it's here for Typescript's benefit
|
|
33
36
|
assertDefined(
|
|
34
37
|
standard,
|
|
35
38
|
'Picture must contain at least one image to display'
|
package/src/model/Topper.ts
CHANGED
|
@@ -132,10 +132,6 @@ export class Topper {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
backgroundColour(): TopperBackgroundColourValues {
|
|
135
|
-
if (this.capiResponse.isAlphaville()) {
|
|
136
|
-
return 'matisse'
|
|
137
|
-
}
|
|
138
|
-
|
|
139
135
|
if (
|
|
140
136
|
this.capiResponse.type() === 'ContentPackage' &&
|
|
141
137
|
this.capiResponse.design()
|
|
@@ -158,6 +154,10 @@ export class Topper {
|
|
|
158
154
|
return this.capiResponse.isContainedInPackage() ? 'wheat' : 'sky'
|
|
159
155
|
}
|
|
160
156
|
|
|
157
|
+
if (this.capiResponse.isAlphaville()) {
|
|
158
|
+
return 'matisse'
|
|
159
|
+
}
|
|
160
|
+
|
|
161
161
|
if (type === 'PodcastTopper') {
|
|
162
162
|
return 'slate'
|
|
163
163
|
}
|
|
@@ -254,11 +254,11 @@ export class Topper {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
columnist() {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
const authors = this.capiResponse.getAuthors()
|
|
258
|
+
const isOpinionOrColumn =
|
|
259
|
+
this.type() === 'OpinionTopper' || this.capiResponse.isColumn()
|
|
260
260
|
|
|
261
|
-
return null
|
|
261
|
+
return isOpinionOrColumn && authors.length ? authors[0] : null
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
brandConcept() {
|
|
@@ -279,14 +279,28 @@ export class Topper {
|
|
|
279
279
|
return this.capiResponse.design()
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
headshot(args: HeadshotArguments) {
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
async headshot(args: HeadshotArguments) {
|
|
283
|
+
let headshotUrl: string | undefined
|
|
284
|
+
|
|
285
|
+
if (this.capiResponse.isPodcast()) {
|
|
286
|
+
headshotUrl = this.capiResponse.mainImage()?.url()
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (this.capiResponse.isOpinion()) {
|
|
290
|
+
const authors = this.capiResponse.getAuthors()
|
|
291
|
+
const headshotUrls: (string | null)[] = await Promise.all(
|
|
292
|
+
authors.map(async (author) => await author.headshot(args))
|
|
293
|
+
).then((res) => res.filter(Boolean))
|
|
294
|
+
|
|
295
|
+
headshotUrl = headshotUrls[0] ?? undefined
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (!headshotUrl) {
|
|
285
299
|
return null
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
return imageServiceUrl({
|
|
289
|
-
url:
|
|
303
|
+
url: headshotUrl,
|
|
290
304
|
systemCode: this.#systemCode,
|
|
291
305
|
width: args.width ?? undefined,
|
|
292
306
|
dpr: args.dpr ?? undefined,
|
|
@@ -14,7 +14,7 @@ export const ImageSet = {
|
|
|
14
14
|
uuidFromUrl(embed.id) === uuidFromUrl(parent.reference.id)
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
return imageSet && imageSet.members
|
|
17
|
+
return imageSet && imageSet.members && imageSet.members.length > 0
|
|
18
18
|
? new Picture(imageSet, isLiveBlog, context)
|
|
19
19
|
: null
|
|
20
20
|
},
|
package/src/resolvers/topper.ts
CHANGED
|
@@ -16,6 +16,7 @@ const resolvers = {
|
|
|
16
16
|
backgroundColour: (topper) => topper.backgroundColour(),
|
|
17
17
|
displayConcept: (topper) => topper.displayConcept(),
|
|
18
18
|
followButtonVariant: (topper) => topper.followButtonVariant(),
|
|
19
|
+
genreConcept: (topper) => topper.genreConcept(),
|
|
19
20
|
},
|
|
20
21
|
|
|
21
22
|
TopperWithImages: {
|
|
@@ -38,9 +39,7 @@ const resolvers = {
|
|
|
38
39
|
},
|
|
39
40
|
|
|
40
41
|
OpinionTopper: {
|
|
41
|
-
|
|
42
|
-
return topper.columnist()?.headshot(args) || null
|
|
43
|
-
},
|
|
42
|
+
headshot: (topper, args) => topper.headshot(args),
|
|
44
43
|
columnist: (topper) => topper.columnist(),
|
|
45
44
|
},
|
|
46
45
|
|