@financial-times/cp-content-pipeline-schema 1.0.0 → 1.1.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/lib/generated/index.d.ts +68 -5
  3. package/lib/model/CapiResponse.d.ts +4 -2
  4. package/lib/model/CapiResponse.js +23 -6
  5. package/lib/model/CapiResponse.js.map +1 -1
  6. package/lib/model/schemas/capi/article.d.ts +29 -26
  7. package/lib/model/schemas/capi/article.js +1 -0
  8. package/lib/model/schemas/capi/article.js.map +1 -1
  9. package/lib/model/schemas/capi/audio.d.ts +9 -6
  10. package/lib/model/schemas/capi/audio.js +1 -0
  11. package/lib/model/schemas/capi/audio.js.map +1 -1
  12. package/lib/model/schemas/capi/base-schema.d.ts +29 -26
  13. package/lib/model/schemas/capi/base-schema.js +14 -7
  14. package/lib/model/schemas/capi/base-schema.js.map +1 -1
  15. package/lib/model/schemas/capi/content-package.d.ts +29 -26
  16. package/lib/model/schemas/capi/content-package.js +1 -0
  17. package/lib/model/schemas/capi/content-package.js.map +1 -1
  18. package/lib/model/schemas/capi/index.js +3 -0
  19. package/lib/model/schemas/capi/index.js.map +1 -1
  20. package/lib/model/schemas/capi/live-blog-package.d.ts +29 -26
  21. package/lib/model/schemas/capi/live-blog-package.js +1 -0
  22. package/lib/model/schemas/capi/live-blog-package.js.map +1 -1
  23. package/lib/model/schemas/capi/placeholder.d.ts +1043 -0
  24. package/lib/model/schemas/capi/placeholder.js +37 -0
  25. package/lib/model/schemas/capi/placeholder.js.map +1 -0
  26. package/lib/resolvers/content.d.ts +7 -3
  27. package/lib/resolvers/content.js +6 -2
  28. package/lib/resolvers/content.js.map +1 -1
  29. package/lib/resolvers/index.d.ts +8 -4
  30. package/lib/resolvers/scalars.d.ts +2 -2
  31. package/lib/resolvers/scalars.js +1 -0
  32. package/lib/resolvers/scalars.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/generated/index.ts +75 -4
  35. package/src/model/CapiResponse.ts +46 -7
  36. package/src/model/schemas/capi/article.ts +1 -0
  37. package/src/model/schemas/capi/audio.ts +1 -0
  38. package/src/model/schemas/capi/base-schema.ts +22 -15
  39. package/src/model/schemas/capi/content-package.ts +1 -0
  40. package/src/model/schemas/capi/index.ts +3 -0
  41. package/src/model/schemas/capi/live-blog-package.ts +1 -0
  42. package/src/model/schemas/capi/placeholder.ts +41 -0
  43. package/src/resolvers/content.ts +10 -2
  44. package/src/resolvers/scalars.ts +2 -0
  45. package/src/types/internal-content.d.ts +8 -1
  46. package/tsconfig.tsbuildinfo +1 -1
  47. package/typedefs/content.graphql +27 -1
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.placeholderSchema = void 0;
4
+ const base_schema_1 = require("./base-schema");
5
+ const placeholderContentSchema = base_schema_1.baseContentSchema.pick({
6
+ title: true,
7
+ standfirst: true,
8
+ byline: true,
9
+ bodyXML: true,
10
+ alternativeTitles: true,
11
+ alternativeStandfirsts: true,
12
+ });
13
+ const placeholderMetadataSchema = base_schema_1.baseMetadataSchema.pick({
14
+ id: true,
15
+ annotations: true,
16
+ webUrl: true,
17
+ canonicalWebUrl: true,
18
+ type: true,
19
+ types: true,
20
+ standout: true,
21
+ publishedDate: true,
22
+ firstPublishedDate: true,
23
+ accessLevel: true,
24
+ canBeSyndicated: true,
25
+ topper: true,
26
+ comments: true,
27
+ containedIn: true,
28
+ });
29
+ const placeholderMediaSchema = base_schema_1.baseMediaSchema.pick({
30
+ mainImage: true,
31
+ leadImages: true,
32
+ embeds: true,
33
+ });
34
+ exports.placeholderSchema = placeholderContentSchema
35
+ .merge(placeholderMetadataSchema)
36
+ .merge(placeholderMediaSchema);
37
+ //# sourceMappingURL=placeholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../../../src/model/schemas/capi/placeholder.ts"],"names":[],"mappings":";;;AAAA,+CAIsB;AAEtB,MAAM,wBAAwB,GAAG,+BAAiB,CAAC,IAAI,CAAC;IACtD,KAAK,EAAE,IAAI;IACX,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,IAAI;IACb,iBAAiB,EAAE,IAAI;IACvB,sBAAsB,EAAE,IAAI;CAC7B,CAAC,CAAA;AAEF,MAAM,yBAAyB,GAAG,gCAAkB,CAAC,IAAI,CAAC;IACxD,EAAE,EAAE,IAAI;IACR,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,IAAI;IACZ,eAAe,EAAE,IAAI;IACrB,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,IAAI;IACnB,kBAAkB,EAAE,IAAI;IACxB,WAAW,EAAE,IAAI;IACjB,eAAe,EAAE,IAAI;IACrB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,IAAI;CAClB,CAAC,CAAA;AAEF,MAAM,sBAAsB,GAAG,6BAAe,CAAC,IAAI,CAAC;IAClD,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;CACb,CAAC,CAAA;AAEW,QAAA,iBAAiB,GAAG,wBAAwB;KACtD,KAAK,CAAC,yBAAyB,CAAC;KAChC,KAAK,CAAC,sBAAsB,CAAC,CAAA"}
@@ -2,7 +2,7 @@ import { Topper } from '../model/Topper';
2
2
  import { RichText } from '../model/RichText';
3
3
  declare const resolvers: {
4
4
  Content: {
5
- __resolveType: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage";
5
+ __resolveType: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Placeholder" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage";
6
6
  body(parent: import("../model/CapiResponse").CapiResponse): RichText;
7
7
  topper: (parent: import("../model/CapiResponse").CapiResponse, _: {}, context: import("..").QueryContext) => Topper;
8
8
  byline(parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentBylineArgs>, context: import("..").QueryContext): Promise<{
@@ -13,7 +13,7 @@ declare const resolvers: {
13
13
  references: never[];
14
14
  }> | null;
15
15
  url: (parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentUrlArgs>) => Promise<string>;
16
- type: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage" | "Content" | "MediaResource";
16
+ type: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Placeholder" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage" | "Content" | "MediaResource";
17
17
  mainImage: (parent: import("../model/CapiResponse").CapiResponse) => import("../model/Image").CAPIImage | null;
18
18
  altTitle: (parent: import("../model/CapiResponse").CapiResponse) => {
19
19
  promotionalTitle: string;
@@ -34,12 +34,16 @@ declare const resolvers: {
34
34
  Article: {
35
35
  containedIn: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse | null>;
36
36
  };
37
+ Placeholder: {
38
+ containedIn: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse | null>;
39
+ };
37
40
  LiveBlogPackage: {
38
41
  liveBlogPosts: (parent: import("../model/CapiResponse").CapiResponse) => Promise<[] | import("../model/CapiResponse").CapiResponse[]>;
39
42
  realtime: (parent: import("../model/CapiResponse").CapiResponse) => boolean | null;
40
43
  };
41
44
  ContentPackage: {
42
- contains: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse[] | null>;
45
+ contains: (parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentPackageContainsArgs>) => Promise<import("../model/CapiResponse").CapiResponse[] | null>;
46
+ containsLength: (parent: import("../model/CapiResponse").CapiResponse) => number | null;
43
47
  };
44
48
  Audio: {
45
49
  media: (parent: import("../model/CapiResponse").CapiResponse) => import("../generated").Media[] | null;
@@ -8,7 +8,7 @@ const resolvers = {
8
8
  __resolveType: (parent) => {
9
9
  const type = parent.type();
10
10
  if (type === 'Content') {
11
- return 'Article';
11
+ return parent.isPlaceholder() ? 'Placeholder' : 'Article';
12
12
  }
13
13
  if (type === 'MediaResource') {
14
14
  return 'Video';
@@ -44,12 +44,16 @@ const resolvers = {
44
44
  Article: {
45
45
  containedIn: (parent) => parent.containedIn(),
46
46
  },
47
+ Placeholder: {
48
+ containedIn: (parent) => parent.containedIn(),
49
+ },
47
50
  LiveBlogPackage: {
48
51
  liveBlogPosts: (parent) => parent.liveBlogPosts(),
49
52
  realtime: (parent) => parent.realtime(),
50
53
  },
51
54
  ContentPackage: {
52
- contains: (parent) => parent.contains(),
55
+ contains: (parent, args) => parent.contains(args),
56
+ containsLength: (parent) => parent.containsLength(),
53
57
  },
54
58
  Audio: {
55
59
  media: (parent) =>
@@ -1 +1 @@
1
- {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/resolvers/content.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/resolvers/content.ts"],"names":[],"mappings":"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"}
@@ -65,7 +65,7 @@ declare const resolvers: {
65
65
  CanBeSyndicated: import("./literal-union").LiteralUnionScalar<["yes", "no", "verify", "withContributorPayment", "unknown"]>;
66
66
  ImageType: import("./literal-union").LiteralUnionScalar<["image", "graphic"]>;
67
67
  RichTextSource: import("./literal-union").LiteralUnionScalar<["standfirst", "summary", "bodyXML"]>;
68
- ContentType: import("./literal-union").LiteralUnionScalar<["Article", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
68
+ ContentType: import("./literal-union").LiteralUnionScalar<["Article", "Placeholder", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
69
69
  RichText: {
70
70
  raw(parent: import("../model/RichText").RichText): string | null;
71
71
  structured(parent: import("../model/RichText").RichText, args: {}, context: import("..").QueryContext): Promise<{
@@ -106,7 +106,7 @@ declare const resolvers: {
106
106
  invalidateRedisCache: (_: {}, args: import("../generated").RequireFields<import("../generated").MutationInvalidateRedisCacheArgs, "uuid">, context: import("..").QueryContext) => Promise<string>;
107
107
  };
108
108
  Content: {
109
- __resolveType: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage";
109
+ __resolveType: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Placeholder" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage";
110
110
  body(parent: import("../model/CapiResponse").CapiResponse): import("../model/RichText").RichText;
111
111
  topper: (parent: import("../model/CapiResponse").CapiResponse, _: {}, context: import("..").QueryContext) => import("../model/Topper").Topper;
112
112
  byline(parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentBylineArgs>, context: import("..").QueryContext): Promise<{
@@ -117,7 +117,7 @@ declare const resolvers: {
117
117
  references: never[];
118
118
  }> | null;
119
119
  url: (parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentUrlArgs>) => Promise<string>;
120
- type: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage" | "Content" | "MediaResource";
120
+ type: (parent: import("../model/CapiResponse").CapiResponse) => "Article" | "Placeholder" | "Video" | "Audio" | "LiveBlogPackage" | "LiveBlogPost" | "ContentPackage" | "Content" | "MediaResource";
121
121
  mainImage: (parent: import("../model/CapiResponse").CapiResponse) => import("../model/Image").CAPIImage | null;
122
122
  altTitle: (parent: import("../model/CapiResponse").CapiResponse) => {
123
123
  promotionalTitle: string;
@@ -138,12 +138,16 @@ declare const resolvers: {
138
138
  Article: {
139
139
  containedIn: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse | null>;
140
140
  };
141
+ Placeholder: {
142
+ containedIn: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse | null>;
143
+ };
141
144
  LiveBlogPackage: {
142
145
  liveBlogPosts: (parent: import("../model/CapiResponse").CapiResponse) => Promise<[] | import("../model/CapiResponse").CapiResponse[]>;
143
146
  realtime: (parent: import("../model/CapiResponse").CapiResponse) => boolean | null;
144
147
  };
145
148
  ContentPackage: {
146
- contains: (parent: import("../model/CapiResponse").CapiResponse) => Promise<import("../model/CapiResponse").CapiResponse[] | null>;
149
+ contains: (parent: import("../model/CapiResponse").CapiResponse, args: Partial<import("../generated").ContentPackageContainsArgs>) => Promise<import("../model/CapiResponse").CapiResponse[] | null>;
150
+ containsLength: (parent: import("../model/CapiResponse").CapiResponse) => number | null;
147
151
  };
148
152
  Audio: {
149
153
  media: (parent: import("../model/CapiResponse").CapiResponse) => import("../generated").Media[] | null;
@@ -7,7 +7,7 @@ export declare const AccessLevel: LiteralUnionScalar<["premium", "subscribed", "
7
7
  export declare const CanBeSyndicated: LiteralUnionScalar<["yes", "no", "verify", "withContributorPayment", "unknown"]>;
8
8
  export declare const ImageType: LiteralUnionScalar<["image", "graphic"]>;
9
9
  export declare const RichTextSource: LiteralUnionScalar<["standfirst", "summary", "bodyXML"]>;
10
- export declare const ContentType: LiteralUnionScalar<["Article", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
10
+ export declare const ContentType: LiteralUnionScalar<["Article", "Placeholder", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
11
11
  declare const resolvers: {
12
12
  ImageFormat: LiteralUnionScalar<["standard", "standard-inline", "desktop", "mobile", "wide", "square", "square-ftedit", "portrait", "landscape"]>;
13
13
  PackageDesign: LiteralUnionScalar<["special-report", "extra", "basic"]>;
@@ -17,6 +17,6 @@ declare const resolvers: {
17
17
  CanBeSyndicated: LiteralUnionScalar<["yes", "no", "verify", "withContributorPayment", "unknown"]>;
18
18
  ImageType: LiteralUnionScalar<["image", "graphic"]>;
19
19
  RichTextSource: LiteralUnionScalar<["standfirst", "summary", "bodyXML"]>;
20
- ContentType: LiteralUnionScalar<["Article", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
20
+ ContentType: LiteralUnionScalar<["Article", "Placeholder", "Video", "Audio", "LiveBlogPackage", "LiveBlogPost", "ContentPackage", "Content", "MediaResource"]>;
21
21
  };
22
22
  export default resolvers;
@@ -63,6 +63,7 @@ exports.ContentType = new literal_union_1.LiteralUnionScalar({
63
63
  name: 'ContentType',
64
64
  values: [
65
65
  'Article',
66
+ 'Placeholder',
66
67
  'Video',
67
68
  'Audio',
68
69
  'LiveBlogPackage',
@@ -1 +1 @@
1
- {"version":3,"file":"scalars.js","sourceRoot":"","sources":["../../src/resolvers/scalars.ts"],"names":[],"mappings":";;;AAAA,mDAAoD;AAEvC,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAY/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE;QACN,UAAU;QACV,iBAAiB;QACjB,SAAS;QACT,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,eAAe;QACf,UAAU;QACV,WAAW;KACZ;CACF,CAAC,CAAA;AAEW,QAAA,aAAa,GAAG,IAAI,kCAAkB,CAEjD,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;AAE7D,QAAA,sBAAsB,GAAG,IAAI,kCAAkB,CAa1D;IACA,IAAI,EAAE,wBAAwB;IAC9B,MAAM,EAAE;QACN,OAAO;QACP,OAAO;QACP,OAAO;QACP,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,SAAS;QACT,KAAK;QACL,SAAS;KACV;CACF,CAAC,CAAA;AAEW,QAAA,mBAAmB,GAAG,IAAI,kCAAkB,CASvD;IACA,IAAI,EAAE,qBAAqB;IAC3B,MAAM,EAAE;QACN,UAAU;QACV,SAAS;QACT,SAAS;QACT,YAAY;QACZ,YAAY;QACZ,oBAAoB;KACrB;CACF,CAAC,CAAA;AAEW,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAE/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC;CACxD,CAAC,CAAA;AAEW,QAAA,eAAe,GAAG,IAAI,kCAAkB,CAEnD;IACA,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,wBAAwB,EAAE,SAAS,CAAC;CACrE,CAAC,CAAA;AAEW,QAAA,SAAS,GAAG,IAAI,kCAAkB,CAAuB;IACpE,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;CAC7B,CAAC,CAAA;AAEW,QAAA,cAAc,GAAG,IAAI,kCAAkB,CAElD;IACA,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC;CAC7C,CAAC,CAAA;AAEW,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAW/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE;QACN,SAAS;QACT,OAAO;QACP,OAAO;QACP,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,SAAS;QACT,eAAe;KAChB;CACF,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG;IAChB,WAAW,EAAX,mBAAW;IACX,aAAa,EAAb,qBAAa;IACb,sBAAsB,EAAtB,8BAAsB;IACtB,mBAAmB,EAAnB,2BAAmB;IACnB,WAAW,EAAX,mBAAW;IACX,eAAe,EAAf,uBAAe;IACf,SAAS,EAAT,iBAAS;IACT,cAAc,EAAd,sBAAc;IACd,WAAW,EAAX,mBAAW;CACZ,CAAA;AAED,kBAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"scalars.js","sourceRoot":"","sources":["../../src/resolvers/scalars.ts"],"names":[],"mappings":";;;AAAA,mDAAoD;AAEvC,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAY/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE;QACN,UAAU;QACV,iBAAiB;QACjB,SAAS;QACT,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,eAAe;QACf,UAAU;QACV,WAAW;KACZ;CACF,CAAC,CAAA;AAEW,QAAA,aAAa,GAAG,IAAI,kCAAkB,CAEjD,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;AAE7D,QAAA,sBAAsB,GAAG,IAAI,kCAAkB,CAa1D;IACA,IAAI,EAAE,wBAAwB;IAC9B,MAAM,EAAE;QACN,OAAO;QACP,OAAO;QACP,OAAO;QACP,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,SAAS;QACT,KAAK;QACL,SAAS;KACV;CACF,CAAC,CAAA;AAEW,QAAA,mBAAmB,GAAG,IAAI,kCAAkB,CASvD;IACA,IAAI,EAAE,qBAAqB;IAC3B,MAAM,EAAE;QACN,UAAU;QACV,SAAS;QACT,SAAS;QACT,YAAY;QACZ,YAAY;QACZ,oBAAoB;KACrB;CACF,CAAC,CAAA;AAEW,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAE/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC;CACxD,CAAC,CAAA;AAEW,QAAA,eAAe,GAAG,IAAI,kCAAkB,CAEnD;IACA,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,wBAAwB,EAAE,SAAS,CAAC;CACrE,CAAC,CAAA;AAEW,QAAA,SAAS,GAAG,IAAI,kCAAkB,CAAuB;IACpE,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;CAC7B,CAAC,CAAA;AAEW,QAAA,cAAc,GAAG,IAAI,kCAAkB,CAElD;IACA,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC;CAC7C,CAAC,CAAA;AAEW,QAAA,WAAW,GAAG,IAAI,kCAAkB,CAY/C;IACA,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE;QACN,SAAS;QACT,aAAa;QACb,OAAO;QACP,OAAO;QACP,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,SAAS;QACT,eAAe;KAChB;CACF,CAAC,CAAA;AAEF,MAAM,SAAS,GAAG;IAChB,WAAW,EAAX,mBAAW;IACX,aAAa,EAAb,qBAAa;IACb,sBAAsB,EAAtB,8BAAsB;IACtB,mBAAmB,EAAnB,2BAAmB;IACnB,WAAW,EAAX,mBAAW;IACX,eAAe,EAAf,uBAAe;IACf,SAAS,EAAT,iBAAS;IACT,cAAc,EAAd,sBAAc;IACd,WAAW,EAAX,mBAAW;CACZ,CAAA;AAED,kBAAe,SAAS,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cp-content-pipeline-schema",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -27,7 +27,7 @@ export type Scalars = {
27
27
  Float: { input: number; output: number; }
28
28
  AccessLevel: { input: 'premium' | 'subscribed' | 'registered' | 'free'; output: 'premium' | 'subscribed' | 'registered' | 'free'; }
29
29
  CanBeSyndicated: { input: 'yes' | 'no' | 'verify' | 'withContributorPayment' | 'unknown'; output: 'yes' | 'no' | 'verify' | 'withContributorPayment' | 'unknown'; }
30
- ContentType: { input: 'Article' | 'Video' | 'Audio' | 'LiveBlogPackage' | 'LiveBlogPost' | 'ContentPackage' | 'Content' | 'MediaResource'; output: 'Article' | 'Video' | 'Audio' | 'LiveBlogPackage' | 'LiveBlogPost' | 'ContentPackage' | 'Content' | 'MediaResource'; }
30
+ ContentType: { input: 'Article' | 'Placeholder' | 'Video' | 'Audio' | 'LiveBlogPackage' | 'LiveBlogPost' | 'ContentPackage' | 'Content' | 'MediaResource'; output: 'Article' | 'Placeholder' | 'Video' | 'Audio' | 'LiveBlogPackage' | 'LiveBlogPost' | 'ContentPackage' | 'Content' | 'MediaResource'; }
31
31
  FollowButtonVariant: { input: 'standard' | 'inverse' | 'opinion' | 'alphaville' | 'monochrome' | 'inverse-monochrome'; output: 'standard' | 'inverse' | 'opinion' | 'alphaville' | 'monochrome' | 'inverse-monochrome'; }
32
32
  ImageFormat: { input: 'standard' | 'standard-inline' | 'desktop' | 'mobile' | 'wide' | 'square' | 'square-ftedit' | 'portrait' | 'landscape'; output: 'standard' | 'standard-inline' | 'desktop' | 'mobile' | 'wide' | 'square' | 'square-ftedit' | 'portrait' | 'landscape'; }
33
33
  ImageType: { input: 'image' | 'graphic'; output: 'image' | 'graphic'; }
@@ -202,6 +202,7 @@ export type ContentPackage = Content & {
202
202
  readonly canBeSyndicated?: Maybe<Scalars['CanBeSyndicated']['output']>;
203
203
  readonly commentsEnabled?: Maybe<Scalars['Boolean']['output']>;
204
204
  readonly contains?: Maybe<ReadonlyArray<Maybe<Teaser>>>;
205
+ readonly containsLength?: Maybe<Scalars['Int']['output']>;
205
206
  readonly design?: Maybe<Design>;
206
207
  readonly firstPublishedDate: Scalars['String']['output'];
207
208
  readonly id: Scalars['String']['output'];
@@ -222,6 +223,12 @@ export type ContentPackageBylineArgs = {
222
223
  };
223
224
 
224
225
 
226
+ export type ContentPackageContainsArgs = {
227
+ fromId?: InputMaybe<Scalars['String']['input']>;
228
+ surroundingArticles?: InputMaybe<Scalars['Int']['input']>;
229
+ };
230
+
231
+
225
232
  export type ContentPackageUrlArgs = {
226
233
  relative?: InputMaybe<Scalars['Boolean']['input']>;
227
234
  vanity?: InputMaybe<Scalars['Boolean']['input']>;
@@ -658,6 +665,41 @@ export type PictureStandard = Picture & {
658
665
  readonly layoutWidth?: Maybe<Scalars['String']['output']>;
659
666
  };
660
667
 
668
+ export type Placeholder = Content & {
669
+ readonly accessLevel?: Maybe<Scalars['AccessLevel']['output']>;
670
+ readonly altStandfirst?: Maybe<AltStandfirst>;
671
+ readonly altTitle?: Maybe<AltTitle>;
672
+ readonly annotations?: Maybe<ReadonlyArray<Maybe<Concept>>>;
673
+ readonly body?: Maybe<RichText>;
674
+ readonly bodyXML?: Maybe<Scalars['String']['output']>;
675
+ readonly byline?: Maybe<StructuredContent>;
676
+ readonly canBeSyndicated?: Maybe<Scalars['CanBeSyndicated']['output']>;
677
+ readonly commentsEnabled?: Maybe<Scalars['Boolean']['output']>;
678
+ readonly containedIn?: Maybe<Content>;
679
+ readonly design?: Maybe<Design>;
680
+ readonly firstPublishedDate: Scalars['String']['output'];
681
+ readonly id: Scalars['String']['output'];
682
+ readonly mainImage?: Maybe<Image>;
683
+ readonly publishedDate: Scalars['String']['output'];
684
+ readonly standfirst?: Maybe<Scalars['String']['output']>;
685
+ readonly teaser?: Maybe<Teaser>;
686
+ readonly title: Scalars['String']['output'];
687
+ readonly topper?: Maybe<Topper>;
688
+ readonly type: Scalars['ContentType']['output'];
689
+ readonly url: Scalars['String']['output'];
690
+ };
691
+
692
+
693
+ export type PlaceholderBylineArgs = {
694
+ vanity?: InputMaybe<Scalars['Boolean']['input']>;
695
+ };
696
+
697
+
698
+ export type PlaceholderUrlArgs = {
699
+ relative?: InputMaybe<Scalars['Boolean']['input']>;
700
+ vanity?: InputMaybe<Scalars['Boolean']['input']>;
701
+ };
702
+
661
703
  export type PodcastTopper = Topper & TopperWithBrand & TopperWithHeadshot & TopperWithTheme & {
662
704
  readonly backgroundBox?: Maybe<Scalars['Boolean']['output']>;
663
705
  readonly backgroundColour?: Maybe<Scalars['TopperBackgroundColour']['output']>;
@@ -926,7 +968,7 @@ export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs
926
968
 
927
969
  /** Mapping of interface types */
928
970
  export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = ResolversObject<{
929
- Content: ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse );
971
+ Content: ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse ) | ( CapiResponse );
930
972
  Image: ( ImageDesktop ) | ( ImageLandscape ) | ( ImageMobile ) | ( ImagePortrait ) | ( ImageSquare ) | ( ImageSquareFtEdit ) | ( ImageStandard ) | ( ImageStandardInline ) | ( ImageWide );
931
973
  Picture: ( Omit<PictureFullBleed, 'fallbackImage' | 'images'> & { fallbackImage: RefType['Image'], images: ReadonlyArray<RefType['Image']> } ) | ( Omit<PictureInline, 'fallbackImage' | 'images'> & { fallbackImage: RefType['Image'], images: ReadonlyArray<RefType['Image']> } ) | ( Omit<PictureStandard, 'fallbackImage' | 'images'> & { fallbackImage: RefType['Image'], images: ReadonlyArray<RefType['Image']> } );
932
974
  Reference: ( ReferenceWithCAPIData<ContentTree.Flourish> ) | ( ReferenceWithCAPIData<ContentTree.ImageSet> ) | ( ReferenceWithCAPIData<ContentTree.LayoutImage> ) | ( ReferenceWithCAPIData<ContentTree.ImageSet> ) | ( ReferenceWithCAPIData<RawImageNode> ) | ( ReferenceWithCAPIData<ContentTree.Recommended> ) | ( ReferenceWithCAPIData<ContentTree.ScrollyImage> ) | ( ReferenceWithCAPIData<ContentTree.Tweet> ) | ( ReferenceWithCAPIData<VideoNode> );
@@ -990,6 +1032,7 @@ export type ResolversTypes = ResolversObject<{
990
1032
  PictureFullBleed: ResolverTypeWrapper<Omit<PictureFullBleed, 'fallbackImage' | 'images'> & { fallbackImage: ResolversTypes['Image'], images: ReadonlyArray<ResolversTypes['Image']> }>;
991
1033
  PictureInline: ResolverTypeWrapper<Omit<PictureInline, 'fallbackImage' | 'images'> & { fallbackImage: ResolversTypes['Image'], images: ReadonlyArray<ResolversTypes['Image']> }>;
992
1034
  PictureStandard: ResolverTypeWrapper<Omit<PictureStandard, 'fallbackImage' | 'images'> & { fallbackImage: ResolversTypes['Image'], images: ReadonlyArray<ResolversTypes['Image']> }>;
1035
+ Placeholder: ResolverTypeWrapper<CapiResponse>;
993
1036
  PodcastTopper: ResolverTypeWrapper<TopperModel>;
994
1037
  Query: ResolverTypeWrapper<{}>;
995
1038
  RawImage: ResolverTypeWrapper<ReferenceWithCAPIData<RawImageNode>>;
@@ -1067,6 +1110,7 @@ export type ResolversParentTypes = ResolversObject<{
1067
1110
  PictureFullBleed: Omit<PictureFullBleed, 'fallbackImage' | 'images'> & { fallbackImage: ResolversParentTypes['Image'], images: ReadonlyArray<ResolversParentTypes['Image']> };
1068
1111
  PictureInline: Omit<PictureInline, 'fallbackImage' | 'images'> & { fallbackImage: ResolversParentTypes['Image'], images: ReadonlyArray<ResolversParentTypes['Image']> };
1069
1112
  PictureStandard: Omit<PictureStandard, 'fallbackImage' | 'images'> & { fallbackImage: ResolversParentTypes['Image'], images: ReadonlyArray<ResolversParentTypes['Image']> };
1113
+ Placeholder: CapiResponse;
1070
1114
  PodcastTopper: TopperModel;
1071
1115
  Query: {};
1072
1116
  RawImage: ReferenceWithCAPIData<RawImageNode>;
@@ -1200,7 +1244,7 @@ export type ConceptResolvers<ContextType = QueryContext, ParentType extends Reso
1200
1244
  }>;
1201
1245
 
1202
1246
  export type ContentResolvers<ContextType = QueryContext, ParentType extends ResolversParentTypes['Content'] = ResolversParentTypes['Content']> = ResolversObject<{
1203
- __resolveType?: TypeResolveFn<'Article' | 'Audio' | 'ContentPackage' | 'LiveBlogPackage' | 'LiveBlogPost' | 'Video', ParentType, ContextType>;
1247
+ __resolveType?: TypeResolveFn<'Article' | 'Audio' | 'ContentPackage' | 'LiveBlogPackage' | 'LiveBlogPost' | 'Placeholder' | 'Video', ParentType, ContextType>;
1204
1248
  accessLevel?: Resolver<Maybe<ResolversTypes['AccessLevel']>, ParentType, ContextType>;
1205
1249
  altStandfirst?: Resolver<Maybe<ResolversTypes['AltStandfirst']>, ParentType, ContextType>;
1206
1250
  altTitle?: Resolver<Maybe<ResolversTypes['AltTitle']>, ParentType, ContextType>;
@@ -1233,7 +1277,8 @@ export type ContentPackageResolvers<ContextType = QueryContext, ParentType exten
1233
1277
  byline?: Resolver<Maybe<ResolversTypes['StructuredContent']>, ParentType, ContextType, Partial<ContentPackageBylineArgs>>;
1234
1278
  canBeSyndicated?: Resolver<Maybe<ResolversTypes['CanBeSyndicated']>, ParentType, ContextType>;
1235
1279
  commentsEnabled?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
1236
- contains?: Resolver<Maybe<ReadonlyArray<Maybe<ResolversTypes['Teaser']>>>, ParentType, ContextType>;
1280
+ contains?: Resolver<Maybe<ReadonlyArray<Maybe<ResolversTypes['Teaser']>>>, ParentType, ContextType, Partial<ContentPackageContainsArgs>>;
1281
+ containsLength?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
1237
1282
  design?: Resolver<Maybe<ResolversTypes['Design']>, ParentType, ContextType>;
1238
1283
  firstPublishedDate?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1239
1284
  id?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -1640,6 +1685,31 @@ export type PictureStandardResolvers<ContextType = QueryContext, ParentType exte
1640
1685
  __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
1641
1686
  }>;
1642
1687
 
1688
+ export type PlaceholderResolvers<ContextType = QueryContext, ParentType extends ResolversParentTypes['Placeholder'] = ResolversParentTypes['Placeholder']> = ResolversObject<{
1689
+ accessLevel?: Resolver<Maybe<ResolversTypes['AccessLevel']>, ParentType, ContextType>;
1690
+ altStandfirst?: Resolver<Maybe<ResolversTypes['AltStandfirst']>, ParentType, ContextType>;
1691
+ altTitle?: Resolver<Maybe<ResolversTypes['AltTitle']>, ParentType, ContextType>;
1692
+ annotations?: Resolver<Maybe<ReadonlyArray<Maybe<ResolversTypes['Concept']>>>, ParentType, ContextType>;
1693
+ body?: Resolver<Maybe<ResolversTypes['RichText']>, ParentType, ContextType>;
1694
+ bodyXML?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
1695
+ byline?: Resolver<Maybe<ResolversTypes['StructuredContent']>, ParentType, ContextType, Partial<PlaceholderBylineArgs>>;
1696
+ canBeSyndicated?: Resolver<Maybe<ResolversTypes['CanBeSyndicated']>, ParentType, ContextType>;
1697
+ commentsEnabled?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
1698
+ containedIn?: Resolver<Maybe<ResolversTypes['Content']>, ParentType, ContextType>;
1699
+ design?: Resolver<Maybe<ResolversTypes['Design']>, ParentType, ContextType>;
1700
+ firstPublishedDate?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1701
+ id?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1702
+ mainImage?: Resolver<Maybe<ResolversTypes['Image']>, ParentType, ContextType>;
1703
+ publishedDate?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1704
+ standfirst?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
1705
+ teaser?: Resolver<Maybe<ResolversTypes['Teaser']>, ParentType, ContextType>;
1706
+ title?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1707
+ topper?: Resolver<Maybe<ResolversTypes['Topper']>, ParentType, ContextType>;
1708
+ type?: Resolver<ResolversTypes['ContentType'], ParentType, ContextType>;
1709
+ url?: Resolver<ResolversTypes['String'], ParentType, ContextType, Partial<PlaceholderUrlArgs>>;
1710
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
1711
+ }>;
1712
+
1643
1713
  export type PodcastTopperResolvers<ContextType = QueryContext, ParentType extends ResolversParentTypes['PodcastTopper'] = ResolversParentTypes['PodcastTopper']> = ResolversObject<{
1644
1714
  backgroundBox?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
1645
1715
  backgroundColour?: Resolver<Maybe<ResolversTypes['TopperBackgroundColour']>, ParentType, ContextType>;
@@ -1874,6 +1944,7 @@ export type Resolvers<ContextType = QueryContext> = ResolversObject<{
1874
1944
  PictureFullBleed?: PictureFullBleedResolvers<ContextType>;
1875
1945
  PictureInline?: PictureInlineResolvers<ContextType>;
1876
1946
  PictureStandard?: PictureStandardResolvers<ContextType>;
1947
+ Placeholder?: PlaceholderResolvers<ContextType>;
1877
1948
  PodcastTopper?: PodcastTopperResolvers<ContextType>;
1878
1949
  Query?: QueryResolvers<ContextType>;
1879
1950
  RawImage?: RawImageResolvers<ContextType>;
@@ -29,7 +29,7 @@ import {
29
29
  validLiteralUnionValue,
30
30
  } from '../resolvers/literal-union'
31
31
 
32
- import { Media } from '../generated'
32
+ import { ContentPackageContainsArgs, Media } from '../generated'
33
33
 
34
34
  type Design = {
35
35
  theme: LiteralUnionScalarValues<typeof PackageDesign>
@@ -203,7 +203,11 @@ export class CapiResponse {
203
203
  return this.capiData.types
204
204
  }
205
205
  async url(vanity?: boolean | null) {
206
- const url = this.capiData.webUrl
206
+ const url =
207
+ this.capiData.webUrl ??
208
+ this.capiData.canonicalWebUrl ??
209
+ `https://www.ft.com/content/${this.id()}`
210
+
207
211
  if (vanity) {
208
212
  try {
209
213
  const vanityUrl = await this.context.dataSources.vanityUrls.get(url)
@@ -231,7 +235,7 @@ export class CapiResponse {
231
235
  return null
232
236
  }
233
237
  accessLevel(): LiteralUnionScalarValues<typeof AccessLevel> {
234
- return this.capiData.accessLevel
238
+ return this.capiData.accessLevel ?? 'subscribed'
235
239
  }
236
240
  canBeSyndicated(): LiteralUnionScalarValues<typeof CanBeSyndicated> {
237
241
  return this.capiData.canBeSyndicated
@@ -257,7 +261,7 @@ export class CapiResponse {
257
261
  return this.capiData.publishedDate
258
262
  }
259
263
  firstPublishedDate() {
260
- return this.capiData.firstPublishedDate
264
+ return this.capiData.firstPublishedDate || this.capiData.publishedDate
261
265
  }
262
266
  alternativeTitle() {
263
267
  return this.capiData.alternativeTitles ?? null
@@ -461,16 +465,42 @@ export class CapiResponse {
461
465
  return this.getBrandConcept()?.uuid() === conceptIds.brand.alphaville
462
466
  }
463
467
 
468
+ isPlaceholder() {
469
+ const isArticle = this.capiData.types.includes(
470
+ 'http://www.ft.com/ontology/content/Article'
471
+ )
472
+ const isContent = this.capiData.types.includes(
473
+ 'http://www.ft.com/ontology/content/Content'
474
+ )
475
+
476
+ return !isArticle && isContent
477
+ }
478
+
464
479
  isPodcast() {
465
480
  return this.capiData.types.includes(
466
481
  'http://www.ft.com/ontology/content/Audio'
467
482
  )
468
483
  }
469
484
 
470
- async contains(): Promise<CapiResponse[] | null> {
485
+ async contains({
486
+ surroundingArticles,
487
+ fromId,
488
+ }: Partial<ContentPackageContainsArgs> = {}): Promise<CapiResponse[] | null> {
471
489
  if ('contains' in this.capiData) {
490
+ const fromIndex = this.capiData.contains.findIndex(
491
+ (contains) => contains.id === `http://api.ft.com/things/${fromId}`
492
+ )
493
+
494
+ const contains =
495
+ fromId && surroundingArticles
496
+ ? this.capiData.contains.slice(
497
+ Math.max(0, fromIndex - surroundingArticles),
498
+ fromIndex + surroundingArticles
499
+ )
500
+ : this.capiData.contains
501
+
472
502
  return Promise.all(
473
- this.capiData.contains.map(({ id }) =>
503
+ contains.map(({ id }) =>
474
504
  this.context.dataSources.capi.getContent(uuidFromUrl(id), this)
475
505
  )
476
506
  )
@@ -479,6 +509,14 @@ export class CapiResponse {
479
509
  return null
480
510
  }
481
511
 
512
+ containsLength() {
513
+ if ('contains' in this.capiData) {
514
+ return this.capiData.contains.length
515
+ }
516
+
517
+ return null
518
+ }
519
+
482
520
  async tableOfContents() {
483
521
  return 'tableOfContents' in this.capiData
484
522
  ? this.capiData.tableOfContents
@@ -517,8 +555,9 @@ export class CapiResponse {
517
555
 
518
556
  commentsEnabled(): boolean {
519
557
  if ('comments' in this.capiData) {
520
- return this.capiData.comments.enabled
558
+ return this.capiData.comments?.enabled ?? false
521
559
  }
560
+
522
561
  return false
523
562
  }
524
563
 
@@ -17,6 +17,7 @@ const articleMetadataSchema = baseMetadataSchema.pick({
17
17
  id: true,
18
18
  annotations: true,
19
19
  webUrl: true,
20
+ canonicalWebUrl: true,
20
21
  type: true,
21
22
  types: true,
22
23
  standout: true,
@@ -14,6 +14,7 @@ const audioMetadataSchema = baseMetadataSchema.pick({
14
14
  id: true,
15
15
  annotations: true,
16
16
  webUrl: true,
17
+ canonicalWebUrl: true,
17
18
  types: true,
18
19
  publishedDate: true,
19
20
  firstPublishedDate: true,
@@ -120,23 +120,28 @@ export const CapiPerson = z.object({
120
120
  export const baseMetadataSchema = z.object({
121
121
  id: z.string(),
122
122
  annotations: Annotation.array(),
123
- webUrl: z.string(),
123
+ webUrl: z.string().optional(),
124
+ canonicalWebUrl: z.string().optional(),
124
125
  type: z.string(),
125
126
  types: z.string().array(),
126
- standout: z.object({
127
- editorsChoice: z.boolean(),
128
- exclusive: z.boolean(),
129
- scoop: z.boolean(),
130
- }),
127
+ standout: z
128
+ .object({
129
+ editorsChoice: z.boolean(),
130
+ exclusive: z.boolean(),
131
+ scoop: z.boolean(),
132
+ })
133
+ .optional(),
131
134
  publishedDate: z.string(),
132
135
  firstPublishedDate: z.string(),
133
136
  realtime: z.boolean(),
134
- accessLevel: z.union([
135
- z.literal('premium'),
136
- z.literal('subscribed'),
137
- z.literal('registered'),
138
- z.literal('free'),
139
- ]),
137
+ accessLevel: z
138
+ .union([
139
+ z.literal('premium'),
140
+ z.literal('subscribed'),
141
+ z.literal('registered'),
142
+ z.literal('free'),
143
+ ])
144
+ .optional(),
140
145
  canBeSyndicated: z.union([
141
146
  z.literal('yes'),
142
147
  z.literal('no'),
@@ -145,9 +150,11 @@ export const baseMetadataSchema = z.object({
145
150
  z.literal('unknown'),
146
151
  ]),
147
152
  topper: Topper.optional(),
148
- comments: z.object({
149
- enabled: z.boolean(),
150
- }),
153
+ comments: z
154
+ .object({
155
+ enabled: z.boolean(),
156
+ })
157
+ .optional(),
151
158
  containedIn: z
152
159
  .object({ apiUrl: z.string(), id: z.string() })
153
160
  .array()
@@ -26,6 +26,7 @@ const contentPackageMetadataSchema = baseMetadataSchema.pick({
26
26
  id: true,
27
27
  annotations: true,
28
28
  webUrl: true,
29
+ canonicalWebUrl: true,
29
30
  type: true,
30
31
  types: true,
31
32
  standout: true,
@@ -1,4 +1,5 @@
1
1
  import { articleSchema } from './article'
2
+ import { placeholderSchema } from './placeholder'
2
3
  import { liveBlogPackageSchema } from './live-blog-package'
3
4
  import { contentPackageSchema } from './content-package'
4
5
  import { audioSchema } from './audio'
@@ -10,6 +11,8 @@ export const schemas = (
10
11
  contentType: LiteralUnionScalarValues<typeof ContentType>
11
12
  ) => {
12
13
  switch (contentType) {
14
+ case 'Placeholder':
15
+ return placeholderSchema
13
16
  case 'Article':
14
17
  return articleSchema
15
18
  case 'LiveBlogPackage':
@@ -17,6 +17,7 @@ const liveBlogPackageMetadataSchema = baseMetadataSchema.pick({
17
17
  id: true,
18
18
  annotations: true,
19
19
  webUrl: true,
20
+ canonicalWebUrl: true,
20
21
  type: true,
21
22
  types: true,
22
23
  standout: true,
@@ -0,0 +1,41 @@
1
+ import {
2
+ baseContentSchema,
3
+ baseMetadataSchema,
4
+ baseMediaSchema,
5
+ } from './base-schema'
6
+
7
+ const placeholderContentSchema = baseContentSchema.pick({
8
+ title: true,
9
+ standfirst: true,
10
+ byline: true,
11
+ bodyXML: true,
12
+ alternativeTitles: true,
13
+ alternativeStandfirsts: true,
14
+ })
15
+
16
+ const placeholderMetadataSchema = baseMetadataSchema.pick({
17
+ id: true,
18
+ annotations: true,
19
+ webUrl: true,
20
+ canonicalWebUrl: true,
21
+ type: true,
22
+ types: true,
23
+ standout: true,
24
+ publishedDate: true,
25
+ firstPublishedDate: true,
26
+ accessLevel: true,
27
+ canBeSyndicated: true,
28
+ topper: true,
29
+ comments: true,
30
+ containedIn: true,
31
+ })
32
+
33
+ const placeholderMediaSchema = baseMediaSchema.pick({
34
+ mainImage: true,
35
+ leadImages: true,
36
+ embeds: true,
37
+ })
38
+
39
+ export const placeholderSchema = placeholderContentSchema
40
+ .merge(placeholderMetadataSchema)
41
+ .merge(placeholderMediaSchema)