@financial-times/cp-content-pipeline-schema 3.4.0 → 3.5.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 +33 -0
- package/lib/datasources/capi.d.ts +0 -2
- package/lib/datasources/capi.js +10 -23
- package/lib/datasources/capi.js.map +1 -1
- package/lib/datasources/instrumented.js +4 -1
- package/lib/datasources/instrumented.js.map +1 -1
- package/lib/datasources/origami-image.d.ts +0 -2
- package/lib/datasources/origami-image.js +5 -19
- package/lib/datasources/origami-image.js.map +1 -1
- package/lib/datasources/twitter.d.ts +0 -2
- package/lib/datasources/twitter.js +2 -16
- package/lib/datasources/twitter.js.map +1 -1
- package/lib/datasources/url-management.js +5 -3
- package/lib/datasources/url-management.js.map +1 -1
- package/lib/fixtures/dummyContext.js +1 -1
- package/lib/generated/index.d.ts +73 -22
- package/lib/index.d.ts +1 -0
- package/lib/index.js.map +1 -1
- package/lib/model/Byline.js +11 -14
- package/lib/model/Byline.js.map +1 -1
- package/lib/model/CapiList.js +2 -0
- package/lib/model/CapiList.js.map +1 -1
- package/lib/model/CapiResponse.d.ts +7 -3
- package/lib/model/CapiResponse.js +125 -57
- package/lib/model/CapiResponse.js.map +1 -1
- package/lib/model/CapiResponse.test.js +92 -7
- package/lib/model/CapiResponse.test.js.map +1 -1
- package/lib/model/Clip.js +2 -0
- package/lib/model/Clip.js.map +1 -1
- package/lib/model/Concept.js +4 -10
- package/lib/model/Concept.js.map +1 -1
- package/lib/model/FlourishSource.d.ts +12 -5
- package/lib/model/FlourishSource.js +37 -38
- package/lib/model/FlourishSource.js.map +1 -1
- package/lib/model/FlourishSource.test.js +5 -5
- package/lib/model/FlourishSource.test.js.map +1 -1
- package/lib/model/Image.js +22 -20
- package/lib/model/Image.js.map +1 -1
- package/lib/model/LeadFlourish.d.ts +1 -1
- package/lib/model/LeadFlourish.js +8 -11
- package/lib/model/LeadFlourish.js.map +1 -1
- package/lib/model/LeadFlourish.test.js +5 -7
- package/lib/model/LeadFlourish.test.js.map +1 -1
- package/lib/model/Person.js +5 -16
- package/lib/model/Person.js.map +1 -1
- package/lib/model/Picture.js +3 -0
- package/lib/model/Picture.js.map +1 -1
- package/lib/model/RichText.js +3 -0
- package/lib/model/RichText.js.map +1 -1
- package/lib/model/Topper.js +5 -16
- package/lib/model/Topper.js.map +1 -1
- package/lib/model/schemas/capi/article.d.ts +3 -3
- package/lib/model/schemas/capi/audio.d.ts +5 -5
- package/lib/model/schemas/capi/base-schema.d.ts +5 -5
- package/lib/model/schemas/capi/base-schema.js +1 -1
- package/lib/model/schemas/capi/base-schema.js.map +1 -1
- package/lib/model/schemas/capi/content-package.d.ts +3 -3
- package/lib/model/schemas/capi/custom-code-component.d.ts +3 -3
- package/lib/model/schemas/capi/index.d.ts +20 -20
- package/lib/model/schemas/capi/internal-content.d.ts +1 -1
- package/lib/model/schemas/capi/live-blog-package.d.ts +3 -3
- package/lib/model/schemas/capi/placeholder.d.ts +3 -3
- package/lib/model/schemas/capi/video.d.ts +3 -3
- package/lib/resolvers/content-tree/references/Flourish.d.ts +9 -19
- package/lib/resolvers/content-tree/references/Flourish.js +10 -32
- package/lib/resolvers/content-tree/references/Flourish.js.map +1 -1
- package/lib/resolvers/content-tree/references/Flourish.test.js +3 -3
- package/lib/resolvers/content-tree/references/Flourish.test.js.map +1 -1
- package/lib/resolvers/content-tree/references/RawImage.js +2 -0
- package/lib/resolvers/content-tree/references/RawImage.js.map +1 -1
- package/lib/resolvers/content-tree/references/index.d.ts +2 -2
- package/lib/resolvers/content-tree/references/index.js +1 -1
- package/lib/resolvers/content-tree/references/index.js.map +1 -1
- package/lib/resolvers/content.d.ts +26 -1
- package/lib/resolvers/content.js +21 -1
- package/lib/resolvers/content.js.map +1 -1
- package/lib/resolvers/index.d.ts +27 -3
- package/lib/resolvers/leadFlourish.d.ts +1 -1
- package/lib/resolvers/literal-union.js +1 -0
- package/lib/resolvers/literal-union.js.map +1 -1
- package/lib/types/connection.d.ts +21 -0
- package/lib/types/connection.js +5 -0
- package/lib/types/connection.js.map +1 -0
- package/package.json +1 -1
- package/queries/article.graphql +8 -2
- package/src/datasources/capi.ts +1 -14
- package/src/datasources/origami-image.ts +1 -13
- package/src/datasources/twitter.ts +1 -14
- package/src/fixtures/dummyContext.ts +1 -1
- package/src/generated/index.ts +75 -24
- package/src/index.ts +1 -0
- package/src/model/CapiResponse.test.ts +137 -7
- package/src/model/CapiResponse.ts +129 -37
- package/src/model/FlourishSource.test.ts +5 -5
- package/src/model/FlourishSource.ts +57 -39
- package/src/model/Image.ts +16 -0
- package/src/model/LeadFlourish.test.ts +6 -9
- package/src/model/LeadFlourish.ts +5 -1
- package/src/model/schemas/capi/base-schema.ts +1 -1
- package/src/model/schemas/capi/internal-content.ts +1 -1
- package/src/resolvers/content-tree/references/Flourish.test.ts +4 -3
- package/src/resolvers/content-tree/references/Flourish.ts +16 -32
- package/src/resolvers/content-tree/references/index.ts +4 -4
- package/src/resolvers/content.ts +31 -1
- package/src/types/connection.ts +28 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/typedefs/content.graphql +40 -2
- package/typedefs/leadFlourish.graphql +1 -1
- package/typedefs/references/flourish.graphql +1 -11
- package/lib/helpers/timeout-error.d.ts +0 -6
- package/lib/helpers/timeout-error.js +0 -15
- package/lib/helpers/timeout-error.js.map +0 -1
- package/src/helpers/timeout-error.ts +0 -13
|
@@ -45,7 +45,7 @@ describe('FlourishSource', () => {
|
|
|
45
45
|
|
|
46
46
|
it('should return the correct flourishUrl', () => {
|
|
47
47
|
expect(flourishSource.flourishUrl()).toBe(
|
|
48
|
-
'https://public.flourish.studio/test-type/1234/thumbnail?cacheBuster=
|
|
48
|
+
'https://public.flourish.studio/test-type/1234/thumbnail?cacheBuster=952866'
|
|
49
49
|
)
|
|
50
50
|
})
|
|
51
51
|
|
|
@@ -70,9 +70,9 @@ describe('FlourishSource', () => {
|
|
|
70
70
|
expect(decodeURIComponent(url)).toMatch(flourishImageUrlRegex)
|
|
71
71
|
})
|
|
72
72
|
|
|
73
|
-
it('should bust the cache of the fallback image every
|
|
74
|
-
const oldCacheBuster = '
|
|
75
|
-
const newCacheBuster = '
|
|
73
|
+
it('should bust the cache of the fallback image every thirty minutes', async () => {
|
|
74
|
+
const oldCacheBuster = '952866'
|
|
75
|
+
const newCacheBuster = '952867'
|
|
76
76
|
|
|
77
77
|
expect(flourishSource.flourishUrl()).toBe(
|
|
78
78
|
`https://public.flourish.studio/test-type/1234/thumbnail?cacheBuster=${oldCacheBuster}`
|
|
@@ -85,7 +85,7 @@ describe('FlourishSource', () => {
|
|
|
85
85
|
)
|
|
86
86
|
|
|
87
87
|
newFlourishSource = new FlourishSource(mockFlourishData, context)
|
|
88
|
-
jest.spyOn(Date, 'now').mockImplementation(() =>
|
|
88
|
+
jest.spyOn(Date, 'now').mockImplementation(() => 1715160840000) // 8 May 2024 09:34:00
|
|
89
89
|
expect(newFlourishSource.flourishUrl()).toBe(
|
|
90
90
|
`https://public.flourish.studio/test-type/1234/thumbnail?cacheBuster=${newCacheBuster}`
|
|
91
91
|
)
|
|
@@ -8,19 +8,37 @@ type ImageMetadata = {
|
|
|
8
8
|
height: number
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
type FlourishData =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
type FlourishData = {
|
|
12
|
+
id: string
|
|
13
|
+
type?: string
|
|
14
|
+
description?: string
|
|
15
|
+
width?: number
|
|
16
|
+
height?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DEFAULT_WIDTH = 2626
|
|
20
|
+
const DEFAULT_HEIGHT = 1459
|
|
19
21
|
|
|
20
22
|
export class FlourishSource {
|
|
21
23
|
#systemCode: string
|
|
22
24
|
private imageMetadata?: ImageMetadata
|
|
23
25
|
|
|
26
|
+
static async createWithMetadata(data: FlourishData, context: QueryContext) {
|
|
27
|
+
const { width, height } = await FlourishSource.getImageMetadata(
|
|
28
|
+
data,
|
|
29
|
+
context
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return new FlourishSource(
|
|
33
|
+
{
|
|
34
|
+
...data,
|
|
35
|
+
width,
|
|
36
|
+
height,
|
|
37
|
+
},
|
|
38
|
+
context
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
constructor(
|
|
25
43
|
private flourishData: FlourishData,
|
|
26
44
|
private context: QueryContext
|
|
@@ -29,11 +47,11 @@ export class FlourishSource {
|
|
|
29
47
|
}
|
|
30
48
|
|
|
31
49
|
id() {
|
|
32
|
-
return this.flourishData
|
|
50
|
+
return this.flourishData.id
|
|
33
51
|
}
|
|
34
52
|
|
|
35
53
|
type() {
|
|
36
|
-
return this.flourishData
|
|
54
|
+
return this.flourishData.type ?? 'flourish'
|
|
37
55
|
}
|
|
38
56
|
|
|
39
57
|
format() {
|
|
@@ -41,63 +59,63 @@ export class FlourishSource {
|
|
|
41
59
|
}
|
|
42
60
|
|
|
43
61
|
flourishUrl() {
|
|
44
|
-
|
|
45
|
-
const cacheBusterTimestamp = Math.floor(Date.now() / (5 * 60 * 1000))
|
|
46
|
-
|
|
47
|
-
return `https://public.flourish.studio/${this.type()}/${this.id()}/thumbnail?cacheBuster=${cacheBusterTimestamp}`
|
|
62
|
+
return FlourishSource.fallbackUrl(this.flourishData)
|
|
48
63
|
}
|
|
49
64
|
|
|
50
|
-
private
|
|
51
|
-
|
|
52
|
-
const
|
|
65
|
+
private static fallbackUrl(data: FlourishData) {
|
|
66
|
+
// Timestamp rounded to the nearest 30 minutes to bust the cache every half an hour
|
|
67
|
+
const cacheBusterTimestamp = Math.floor(Date.now() / (30 * 60 * 1000))
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
69
|
+
return `https://public.flourish.studio/${data.type ?? 'flourish'}/${
|
|
70
|
+
data.id
|
|
71
|
+
}/thumbnail?cacheBuster=${cacheBusterTimestamp}`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static async getImageMetadata(
|
|
75
|
+
data: FlourishData,
|
|
76
|
+
context: QueryContext
|
|
77
|
+
) {
|
|
78
|
+
const url = FlourishSource.fallbackUrl(data)
|
|
57
79
|
|
|
58
80
|
try {
|
|
59
|
-
const metadata = await
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.imageMetadata = {
|
|
81
|
+
const metadata = await context.dataSources.origami.getImageMetadata(url)
|
|
82
|
+
|
|
83
|
+
return {
|
|
63
84
|
width: metadata?.width || DEFAULT_WIDTH,
|
|
64
85
|
height: metadata?.height || DEFAULT_HEIGHT,
|
|
65
86
|
}
|
|
66
87
|
} catch (error) {
|
|
67
88
|
if (isError(error)) {
|
|
68
|
-
|
|
89
|
+
context.logger.warn({
|
|
69
90
|
event: 'RECOVERABLE_ERROR',
|
|
70
91
|
error: new OperationalError({
|
|
71
92
|
code: 'FLOURISH_IMAGE_METADATA_ERROR',
|
|
72
|
-
message: `Error getting image dimensions for Flourish fallback image ${
|
|
93
|
+
message: `Error getting image dimensions for Flourish fallback image ${url}`,
|
|
73
94
|
cause: error,
|
|
74
95
|
}),
|
|
75
96
|
})
|
|
76
97
|
}
|
|
77
|
-
|
|
98
|
+
|
|
99
|
+
return {
|
|
78
100
|
width: DEFAULT_WIDTH,
|
|
79
101
|
height: DEFAULT_HEIGHT,
|
|
80
102
|
}
|
|
81
103
|
}
|
|
82
|
-
return this.imageMetadata
|
|
83
104
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return
|
|
105
|
+
|
|
106
|
+
width() {
|
|
107
|
+
return this.flourishData.width ?? DEFAULT_WIDTH
|
|
87
108
|
}
|
|
88
109
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return imageMetadata.height
|
|
110
|
+
height() {
|
|
111
|
+
return this.flourishData.height ?? DEFAULT_HEIGHT
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const imageServiceWrappedUrl = imageServiceUrl({
|
|
114
|
+
url() {
|
|
115
|
+
return imageServiceUrl({
|
|
97
116
|
url: this.flourishUrl(),
|
|
98
117
|
systemCode: 'cp-content-pipeline',
|
|
99
|
-
width,
|
|
118
|
+
width: this.width(),
|
|
100
119
|
})
|
|
101
|
-
return imageServiceWrappedUrl
|
|
102
120
|
}
|
|
103
121
|
}
|
package/src/model/Image.ts
CHANGED
|
@@ -157,6 +157,21 @@ export class CAPIImage implements Image {
|
|
|
157
157
|
height: this.capiImage.pixelHeight,
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
// HACK:KB:20241029 graphics don't publish pixelWidth/pixelHeight due to a
|
|
162
|
+
// known issue in Spark. we want to avoid calling Image Service to improve
|
|
163
|
+
// performance. skip calling Image Service for graphics for the time being
|
|
164
|
+
// https://financialtimes.slack.com/archives/C02NXHEEN7J/p1729770129991129
|
|
165
|
+
if(this.type() === 'graphic') {
|
|
166
|
+
this.context.logger.warn({
|
|
167
|
+
event: 'SKIPPING_GRAPHICS_DIMENSIONS',
|
|
168
|
+
message: 'Not calling Image Service to get graphics dimensions',
|
|
169
|
+
url: this.capiImage.binaryUrl
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
return null
|
|
173
|
+
}
|
|
174
|
+
|
|
160
175
|
try {
|
|
161
176
|
const imageMetadata = await this.#dataSources.origami.getImageMetadata(
|
|
162
177
|
this.capiImage.binaryUrl
|
|
@@ -174,6 +189,7 @@ export class CAPIImage implements Image {
|
|
|
174
189
|
}),
|
|
175
190
|
})
|
|
176
191
|
}
|
|
192
|
+
|
|
177
193
|
return null
|
|
178
194
|
}
|
|
179
195
|
}
|
|
@@ -7,18 +7,13 @@ import cloneDeep from 'clone-deep'
|
|
|
7
7
|
|
|
8
8
|
const context = {} as unknown as QueryContext
|
|
9
9
|
|
|
10
|
-
jest.mock('./FlourishSource', () => {
|
|
11
|
-
return {
|
|
12
|
-
FlourishSource: jest.fn().mockImplementation(() => ({})),
|
|
13
|
-
}
|
|
14
|
-
})
|
|
15
|
-
|
|
16
10
|
const leadFlourishData = {
|
|
17
11
|
id: 'test-id',
|
|
18
12
|
description: 'test-description',
|
|
19
13
|
type: 'test-type',
|
|
20
14
|
}
|
|
21
15
|
|
|
16
|
+
|
|
22
17
|
describe('LeadFlourish', () => {
|
|
23
18
|
let leadFlourish: LeadFlourish
|
|
24
19
|
|
|
@@ -30,15 +25,17 @@ describe('LeadFlourish', () => {
|
|
|
30
25
|
layoutWidth: 'full-width',
|
|
31
26
|
backgroundColour: 'paper',
|
|
32
27
|
}
|
|
28
|
+
jest.spyOn(FlourishSource, 'getImageMetadata').mockResolvedValue({
|
|
29
|
+
width: 800,
|
|
30
|
+
height: 600
|
|
31
|
+
})
|
|
33
32
|
const capiResponse = new CapiResponse(clonedBase, context)
|
|
34
33
|
leadFlourish = new LeadFlourish(capiResponse, context)
|
|
35
34
|
})
|
|
36
35
|
|
|
37
36
|
describe('fallbackImage', () => {
|
|
38
37
|
it('should instantiate a new FlourishSource', async () => {
|
|
39
|
-
await leadFlourish.fallbackImage()
|
|
40
|
-
|
|
41
|
-
expect(FlourishSource).toHaveBeenCalledWith(leadFlourishData, context)
|
|
38
|
+
await expect(leadFlourish.fallbackImage()).resolves.toBeInstanceOf(FlourishSource)
|
|
42
39
|
})
|
|
43
40
|
})
|
|
44
41
|
|
|
@@ -13,7 +13,11 @@ export class LeadFlourish {
|
|
|
13
13
|
|
|
14
14
|
async fallbackImage() {
|
|
15
15
|
const flourishData = this.capiResponse.leadFlourish()
|
|
16
|
-
|
|
16
|
+
if (!flourishData) {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return FlourishSource.createWithMetadata(flourishData, this.context)
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
id() {
|
|
@@ -23,7 +23,7 @@ import { contentPackageSchema } from './content-package'
|
|
|
23
23
|
|
|
24
24
|
export type Article = z.infer<typeof articleSchema>
|
|
25
25
|
type Placeholder = z.infer<typeof placeholderSchema>
|
|
26
|
-
type LiveBlogPackage = z.infer<typeof liveBlogPackageSchema>
|
|
26
|
+
export type LiveBlogPackage = z.infer<typeof liveBlogPackageSchema>
|
|
27
27
|
type ContentPackage = z.infer<typeof contentPackageSchema>
|
|
28
28
|
type Audio = z.infer<typeof audioSchema>
|
|
29
29
|
type Video = z.infer<typeof videoSchema>
|
|
@@ -30,6 +30,7 @@ describe('Flourish Model', () => {
|
|
|
30
30
|
timestamp: '2022-01-06T14:41:01.102Z',
|
|
31
31
|
description: 'Example description',
|
|
32
32
|
}
|
|
33
|
+
|
|
33
34
|
const fallbackResponse = await Flourish.fallbackImage(
|
|
34
35
|
{ reference },
|
|
35
36
|
{},
|
|
@@ -42,7 +43,7 @@ describe('Flourish Model', () => {
|
|
|
42
43
|
/https:\/\/public.flourish.studio\/.*\/.*\/thumbnail/
|
|
43
44
|
)
|
|
44
45
|
|
|
45
|
-
expect(decodeURIComponent(fallbackResponse
|
|
46
|
+
expect(decodeURIComponent(fallbackResponse?.url() as string)).toMatch(
|
|
46
47
|
flourishImageUrlRegex
|
|
47
48
|
)
|
|
48
49
|
})
|
|
@@ -66,7 +67,7 @@ describe('Flourish Model', () => {
|
|
|
66
67
|
/https:\/\/public.flourish.studio\/.*\/example-id/
|
|
67
68
|
)
|
|
68
69
|
|
|
69
|
-
expect(decodeURIComponent(fallbackResponse
|
|
70
|
+
expect(decodeURIComponent(fallbackResponse?.url() as string)).toMatch(
|
|
70
71
|
flourishImageUrlRegex
|
|
71
72
|
)
|
|
72
73
|
})
|
|
@@ -88,7 +89,7 @@ describe('Flourish Model', () => {
|
|
|
88
89
|
|
|
89
90
|
const flourishImageUrl = 'https://public.flourish.studio/example-type'
|
|
90
91
|
|
|
91
|
-
expect(fallbackResponse
|
|
92
|
+
expect(fallbackResponse?.url() ?? '').toContain(
|
|
92
93
|
encodeURIComponent(flourishImageUrl)
|
|
93
94
|
)
|
|
94
95
|
})
|
|
@@ -1,38 +1,25 @@
|
|
|
1
|
-
import imageServiceUrl from '../../../helpers/imageService'
|
|
2
1
|
import {
|
|
3
|
-
FlourishFallbackResolvers,
|
|
4
2
|
FlourishResolvers,
|
|
3
|
+
FlourishSourceResolvers,
|
|
5
4
|
} from '../../../generated'
|
|
6
|
-
import { FlourishSource } from '../../../model/FlourishSource'
|
|
5
|
+
import { FlourishSource as FlourishSourceModel } from '../../../model/FlourishSource'
|
|
7
6
|
|
|
8
7
|
export const Flourish = {
|
|
9
8
|
async fallbackImage(parent, _args, context) {
|
|
10
9
|
if (!parent.reference) {
|
|
11
|
-
return
|
|
10
|
+
return null
|
|
12
11
|
}
|
|
12
|
+
|
|
13
13
|
const flourishData = {
|
|
14
14
|
id: parent.reference.id,
|
|
15
15
|
type: parent.reference.flourishType,
|
|
16
16
|
description: parent.reference.description,
|
|
17
17
|
}
|
|
18
|
-
const flourishSource = new FlourishSource(flourishData, context)
|
|
19
|
-
const width = await flourishSource.width()
|
|
20
|
-
const height = await flourishSource.height()
|
|
21
|
-
|
|
22
|
-
const imageServiceWrappedUrl = imageServiceUrl({
|
|
23
|
-
url: flourishSource.flourishUrl(),
|
|
24
|
-
systemCode: context.systemCode ?? 'cp-content-pipeline',
|
|
25
|
-
width,
|
|
26
|
-
})
|
|
27
18
|
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
sourceSet: [],
|
|
33
|
-
width,
|
|
34
|
-
height,
|
|
35
|
-
}
|
|
19
|
+
return FlourishSourceModel.createWithMetadata(
|
|
20
|
+
flourishData,
|
|
21
|
+
context
|
|
22
|
+
)
|
|
36
23
|
},
|
|
37
24
|
|
|
38
25
|
type(parent) {
|
|
@@ -40,14 +27,11 @@ export const Flourish = {
|
|
|
40
27
|
},
|
|
41
28
|
} satisfies FlourishResolvers
|
|
42
29
|
|
|
43
|
-
export const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return parent.url ?? null
|
|
52
|
-
},
|
|
53
|
-
} satisfies FlourishFallbackResolvers
|
|
30
|
+
export const FlourishSource = {
|
|
31
|
+
id: (parent) => parent.id(),
|
|
32
|
+
url: (parent) => parent.flourishUrl(),
|
|
33
|
+
type: (parent) => parent.type(),
|
|
34
|
+
width: (parent) => parent.width(),
|
|
35
|
+
height: (parent) => parent.height(),
|
|
36
|
+
format: (parent) => parent.format(),
|
|
37
|
+
} satisfies FlourishSourceResolvers
|
|
@@ -8,7 +8,7 @@ import { ImageSet } from './ImageSet'
|
|
|
8
8
|
import { ClipSet, Accessibility, Caption } from './ClipSet'
|
|
9
9
|
import { CustomCodeComponent } from './CustomCodeComponent'
|
|
10
10
|
import { Video } from './Video'
|
|
11
|
-
import { Flourish,
|
|
11
|
+
import { Flourish, FlourishSource } from './Flourish'
|
|
12
12
|
import { Recommended } from './Recommended'
|
|
13
13
|
import { LayoutImage } from './LayoutImage'
|
|
14
14
|
import { RawImage } from './RawImage'
|
|
@@ -27,8 +27,8 @@ import {
|
|
|
27
27
|
VideoReferenceResolvers,
|
|
28
28
|
CaptionResolvers,
|
|
29
29
|
AccessibilityResolvers,
|
|
30
|
-
FlourishFallbackResolvers,
|
|
31
30
|
AuthorReferenceResolvers,
|
|
31
|
+
FlourishSourceResolvers,
|
|
32
32
|
} from '../../../generated'
|
|
33
33
|
import { AnyNode } from '../Workarounds'
|
|
34
34
|
import { Author } from './Author'
|
|
@@ -46,6 +46,7 @@ export const resolvers: {
|
|
|
46
46
|
CustomCodeComponent: CustomCodeComponentResolvers
|
|
47
47
|
VideoReference: VideoReferenceResolvers
|
|
48
48
|
Flourish: FlourishResolvers
|
|
49
|
+
FlourishSource: FlourishSourceResolvers
|
|
49
50
|
Recommended: RecommendedResolvers
|
|
50
51
|
LayoutImage: LayoutImageResolvers
|
|
51
52
|
RawImage: RawImageResolvers
|
|
@@ -53,7 +54,6 @@ export const resolvers: {
|
|
|
53
54
|
MainImage: ImageSetResolvers
|
|
54
55
|
Caption: CaptionResolvers
|
|
55
56
|
Accessibility: AccessibilityResolvers
|
|
56
|
-
FlourishFallback: FlourishFallbackResolvers
|
|
57
57
|
AuthorReference: AuthorReferenceResolvers
|
|
58
58
|
} = {
|
|
59
59
|
Reference,
|
|
@@ -63,6 +63,7 @@ export const resolvers: {
|
|
|
63
63
|
CustomCodeComponent,
|
|
64
64
|
VideoReference: Video,
|
|
65
65
|
Flourish,
|
|
66
|
+
FlourishSource,
|
|
66
67
|
Recommended,
|
|
67
68
|
LayoutImage,
|
|
68
69
|
RawImage,
|
|
@@ -70,7 +71,6 @@ export const resolvers: {
|
|
|
70
71
|
MainImage: ImageSet,
|
|
71
72
|
Caption,
|
|
72
73
|
Accessibility,
|
|
73
|
-
FlourishFallback,
|
|
74
74
|
AuthorReference: Author,
|
|
75
75
|
}
|
|
76
76
|
|
package/src/resolvers/content.ts
CHANGED
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
AudioResolvers,
|
|
6
6
|
ContentPackageResolvers,
|
|
7
7
|
ContentResolvers,
|
|
8
|
+
ContentConnectionResolvers,
|
|
9
|
+
ContentEdgeResolvers,
|
|
10
|
+
PageInfoResolvers,
|
|
8
11
|
LiveBlogPackageResolvers,
|
|
9
12
|
LiveBlogPostResolvers,
|
|
10
13
|
VideoResolvers,
|
|
@@ -70,6 +73,23 @@ const resolvers = {
|
|
|
70
73
|
...contentResolvers,
|
|
71
74
|
},
|
|
72
75
|
|
|
76
|
+
ContentConnection: {
|
|
77
|
+
edges: (parent) => parent.edges,
|
|
78
|
+
pageInfo: (parent) => parent.pageInfo,
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
ContentEdge: {
|
|
82
|
+
node: (parent) => parent.node,
|
|
83
|
+
cursor: (parent) => parent.cursor,
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
PageInfo: {
|
|
87
|
+
hasPreviousPage: (parent) => parent.hasPreviousPage,
|
|
88
|
+
hasNextPage: (parent) => parent.hasNextPage,
|
|
89
|
+
startCursor: (parent) => parent.startCursor ?? null,
|
|
90
|
+
endCursor: (parent) => parent.endCursor ?? null,
|
|
91
|
+
},
|
|
92
|
+
|
|
73
93
|
Article: {
|
|
74
94
|
...contentResolvers,
|
|
75
95
|
containedIn: (parent) => parent.containedIn(),
|
|
@@ -101,7 +121,14 @@ const resolvers = {
|
|
|
101
121
|
|
|
102
122
|
LiveBlogPackage: {
|
|
103
123
|
...contentResolvers,
|
|
104
|
-
liveBlogPosts: (parent) => parent.liveBlogPosts(),
|
|
124
|
+
liveBlogPosts: (parent, args) => parent.liveBlogPosts(args),
|
|
125
|
+
liveBlogPostsConnection: (parent, args) =>
|
|
126
|
+
parent.liveBlogPostsConnection({
|
|
127
|
+
first: args.first ?? undefined,
|
|
128
|
+
after: args.after ?? undefined,
|
|
129
|
+
last: args.last ?? undefined,
|
|
130
|
+
before: args.before ?? undefined,
|
|
131
|
+
}),
|
|
105
132
|
pinnedPost: (parent) => parent.pinnedPost(),
|
|
106
133
|
realtime: (parent) => parent.realtime(),
|
|
107
134
|
},
|
|
@@ -161,6 +188,9 @@ const resolvers = {
|
|
|
161
188
|
Placeholder: PlaceholderResolvers
|
|
162
189
|
LiveBlogPost: LiveBlogPostResolvers
|
|
163
190
|
Content: ContentResolvers
|
|
191
|
+
ContentConnection: ContentConnectionResolvers
|
|
192
|
+
ContentEdge: ContentEdgeResolvers
|
|
193
|
+
PageInfo: PageInfoResolvers
|
|
164
194
|
LiveBlogPackage: LiveBlogPackageResolvers
|
|
165
195
|
ContentPackage: ContentPackageResolvers
|
|
166
196
|
Audio: AudioResolvers
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Types to aid the implementation of a Connection type, as specified in
|
|
2
|
+
// https://relay.dev/graphql/connections.htm
|
|
3
|
+
|
|
4
|
+
export type ConnectionCursor = string
|
|
5
|
+
|
|
6
|
+
export interface ConnectionPageInfo {
|
|
7
|
+
hasPreviousPage: boolean
|
|
8
|
+
hasNextPage: boolean
|
|
9
|
+
startCursor?: ConnectionCursor
|
|
10
|
+
endCursor?: ConnectionCursor
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ConnectionEdge<T> {
|
|
14
|
+
node: T
|
|
15
|
+
cursor: ConnectionCursor
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Connection<T> {
|
|
19
|
+
edges: ConnectionEdge<T>[]
|
|
20
|
+
pageInfo: ConnectionPageInfo
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ConnectionArguments {
|
|
24
|
+
first?: number
|
|
25
|
+
after?: ConnectionCursor
|
|
26
|
+
last?: number
|
|
27
|
+
before?: ConnectionCursor
|
|
28
|
+
}
|