@financial-times/cp-content-pipeline-schema 0.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.
Files changed (100) hide show
  1. package/.toolkitrc.yml +12 -0
  2. package/CHANGELOG.md +72 -0
  3. package/jest.config.js +3 -0
  4. package/lib/concept.d.ts +7 -0
  5. package/lib/concept.js +39 -0
  6. package/lib/concept.js.map +1 -0
  7. package/lib/constants/contentTypes.d.ts +2 -0
  8. package/lib/constants/contentTypes.js +3 -0
  9. package/lib/constants/contentTypes.js.map +1 -0
  10. package/lib/content.d.ts +55 -0
  11. package/lib/content.js +133 -0
  12. package/lib/content.js.map +1 -0
  13. package/lib/content.test.d.ts +1 -0
  14. package/lib/content.test.js +149 -0
  15. package/lib/content.test.js.map +1 -0
  16. package/lib/datasources/capi.d.ts +10 -0
  17. package/lib/datasources/capi.js +28 -0
  18. package/lib/datasources/capi.js.map +1 -0
  19. package/lib/datasources/index.d.ts +9 -0
  20. package/lib/datasources/index.js +9 -0
  21. package/lib/datasources/index.js.map +1 -0
  22. package/lib/datasources/origami-image.d.ts +8 -0
  23. package/lib/datasources/origami-image.js +11 -0
  24. package/lib/datasources/origami-image.js.map +1 -0
  25. package/lib/datasources/url-management.d.ts +11 -0
  26. package/lib/datasources/url-management.js +40 -0
  27. package/lib/datasources/url-management.js.map +1 -0
  28. package/lib/datasources/url-management.test.d.ts +1 -0
  29. package/lib/datasources/url-management.test.js +69 -0
  30. package/lib/datasources/url-management.test.js.map +1 -0
  31. package/lib/helpers/byline.d.ts +1 -0
  32. package/lib/helpers/byline.js +5 -0
  33. package/lib/helpers/byline.js.map +1 -0
  34. package/lib/helpers/imageService.d.ts +8 -0
  35. package/lib/helpers/imageService.js +13 -0
  36. package/lib/helpers/imageService.js.map +1 -0
  37. package/lib/helpers/metadata.d.ts +12 -0
  38. package/lib/helpers/metadata.js +60 -0
  39. package/lib/helpers/metadata.js.map +1 -0
  40. package/lib/helpers/syntaxTree.d.ts +23 -0
  41. package/lib/helpers/syntaxTree.js +23 -0
  42. package/lib/helpers/syntaxTree.js.map +1 -0
  43. package/lib/image.d.ts +25 -0
  44. package/lib/image.js +123 -0
  45. package/lib/image.js.map +1 -0
  46. package/lib/image.test.d.ts +1 -0
  47. package/lib/image.test.js +235 -0
  48. package/lib/image.test.js.map +1 -0
  49. package/lib/index.d.ts +8 -0
  50. package/lib/index.js +69 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/picture.d.ts +22 -0
  53. package/lib/picture.js +80 -0
  54. package/lib/picture.js.map +1 -0
  55. package/lib/richText.d.ts +14 -0
  56. package/lib/richText.js +48 -0
  57. package/lib/richText.js.map +1 -0
  58. package/lib/tags.d.ts +13 -0
  59. package/lib/tags.js +178 -0
  60. package/lib/tags.js.map +1 -0
  61. package/lib/topper.d.ts +7 -0
  62. package/lib/topper.js +196 -0
  63. package/lib/topper.js.map +1 -0
  64. package/lib/unified-plugins/extract-references.d.ts +7 -0
  65. package/lib/unified-plugins/extract-references.js +36 -0
  66. package/lib/unified-plugins/extract-references.js.map +1 -0
  67. package/lib/unified-plugins/map-to-abstract-types.d.ts +4 -0
  68. package/lib/unified-plugins/map-to-abstract-types.js +17 -0
  69. package/lib/unified-plugins/map-to-abstract-types.js.map +1 -0
  70. package/package.json +43 -0
  71. package/src/__snapshots__/content.test.ts.snap +118 -0
  72. package/src/concept.ts +58 -0
  73. package/src/constants/contentTypes.ts +4 -0
  74. package/src/content.test.ts +163 -0
  75. package/src/content.ts +146 -0
  76. package/src/datasources/capi.ts +28 -0
  77. package/src/datasources/index.ts +11 -0
  78. package/src/datasources/origami-image.ts +10 -0
  79. package/src/datasources/url-management.test.ts +92 -0
  80. package/src/datasources/url-management.ts +65 -0
  81. package/src/helpers/byline.ts +4 -0
  82. package/src/helpers/imageService.ts +31 -0
  83. package/src/helpers/metadata.ts +88 -0
  84. package/src/helpers/syntaxTree.ts +26 -0
  85. package/src/image.test.ts +339 -0
  86. package/src/image.ts +154 -0
  87. package/src/index.ts +87 -0
  88. package/src/picture.ts +98 -0
  89. package/src/richText.ts +62 -0
  90. package/src/tags.ts +237 -0
  91. package/src/topper.ts +228 -0
  92. package/src/types/internal-content.d.ts +78 -0
  93. package/src/types/n-concept-ids.d.ts +16 -0
  94. package/src/types/n-display-metadata.d.ts +1 -0
  95. package/src/types/n-url-management-api-read-client.d.ts +11 -0
  96. package/src/types/next-metrics.d.ts +1 -0
  97. package/src/unified-plugins/extract-references.ts +50 -0
  98. package/src/unified-plugins/map-to-abstract-types.ts +21 -0
  99. package/tsconfig.json +10 -0
  100. package/tsconfig.tsbuildinfo +1 -0
package/.toolkitrc.yml ADDED
@@ -0,0 +1,12 @@
1
+ plugins:
2
+ - '@dotcom-tool-kit/npm'
3
+ - '../../tool-kit/placeholder-hook'
4
+
5
+ hooks:
6
+ publish:tag:
7
+ - NpmPublish
8
+
9
+ options:
10
+ '../../tool-kit/placeholder-hook':
11
+ hooks:
12
+ - publish:tag
package/CHANGELOG.md ADDED
@@ -0,0 +1,72 @@
1
+ # Changelog
2
+
3
+ ## [0.2.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.2.0...cp-content-pipeline-schema-v0.2.1) (2022-09-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * make an innocuous change to trigger a rerelease of these packages ([7ed623d](https://github.com/Financial-Times/cp-content-pipeline/commit/7ed623d126ddc00bc99ee050ddbba1cb18b01ee9))
9
+
10
+ ## [0.2.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.1.0...cp-content-pipeline-schema-v0.2.0) (2022-09-27)
11
+
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * rename "inline" image to "standard"
16
+
17
+ ### Features
18
+
19
+ * add a datasource for getting vanity URLs ([cb638a5](https://github.com/Financial-Times/cp-content-pipeline/commit/cb638a5b48bc7726008189376a27d245a7b642d0))
20
+ * add byline and authors to content schema ([37ea933](https://github.com/Financial-Times/cp-content-pipeline/commit/37ea93339f9e2c4a9ef4fed20bf4a8633762d594))
21
+ * add client package with typescript types generated from schema ([c00f07f](https://github.com/Financial-Times/cp-content-pipeline/commit/c00f07f9d9d10f74cdd834ad59efe189f151ede2))
22
+ * add Columnist tag to Opinion topper ([b50dc42](https://github.com/Financial-Times/cp-content-pipeline/commit/b50dc42113f3e477b5b30588d886e84fd800d718))
23
+ * add Headshot to topper ([a832390](https://github.com/Financial-Times/cp-content-pipeline/commit/a8323906e74d1fdd5d877e12efb9d2168ba20fef))
24
+ * add image caption and alt ([3dd2dd8](https://github.com/Financial-Times/cp-content-pipeline/commit/3dd2dd8cf88a33f8114470b57ea8cba4ea69e352))
25
+ * add image type, and fallback alt for graphics ([7589bea](https://github.com/Financial-Times/cp-content-pipeline/commit/7589beabe4a50d16cfff66c0c03536e75a5a2e22))
26
+ * add ImageSet type to graphQL api ([92534f0](https://github.com/Financial-Times/cp-content-pipeline/commit/92534f0f983d8e9c687b9f4c2474aa235c0f01bb))
27
+ * Add isColumn resolver to Content ([0a2af1a](https://github.com/Financial-Times/cp-content-pipeline/commit/0a2af1ae80d103e2d6d0c5a01338c8488b866e10))
28
+ * Add isEditorsChoice resolver to Content ([813e07b](https://github.com/Financial-Times/cp-content-pipeline/commit/813e07b2a70e0d642768d481e4fb38929da4caa2))
29
+ * Add isExclusive resolver to Content ([cef9675](https://github.com/Financial-Times/cp-content-pipeline/commit/cef9675c5c6d5f98c94c722f855671610ab69916))
30
+ * Add isPodcast resolver to Content ([d76eb78](https://github.com/Financial-Times/cp-content-pipeline/commit/d76eb78909accdec6aa8c654524d1ef89d4eaa56))
31
+ * Add isScoop resolver to Content ([0441fba](https://github.com/Financial-Times/cp-content-pipeline/commit/0441fba34374c69422a2d4a4fed82cd43d68c4e1))
32
+ * add metadata and BrandedTopper ([57fc4c5](https://github.com/Financial-Times/cp-content-pipeline/commit/57fc4c524b2b690ba993563d971ad10b14b85c10))
33
+ * Add opinion teasers ([fdbf3b2](https://github.com/Financial-Times/cp-content-pipeline/commit/fdbf3b2c61a9a6f2030bc23d4a0886f1f6a1ef25))
34
+ * add OpinionTopper type ([4fc3e38](https://github.com/Financial-Times/cp-content-pipeline/commit/4fc3e386b6cd45b8dc06bee51515f6a8889bd817))
35
+ * add PictureInline variant ([7d3f721](https://github.com/Financial-Times/cp-content-pipeline/commit/7d3f721fec6c9a79a21d076a5517955a15b7089d))
36
+ * add simple cache implementation for vanities ([3da9261](https://github.com/Financial-Times/cp-content-pipeline/commit/3da9261fbe0faf3ae748f78f03c7174b52ca93c6))
37
+ * add support for Methode layout components ([5013021](https://github.com/Financial-Times/cp-content-pipeline/commit/5013021a6ac0861c3cf191fff043291e747307d8))
38
+ * allow different image widths and breakpoints ([1210b62](https://github.com/Financial-Times/cp-content-pipeline/commit/1210b62e9f778ee09a9ecd1998bffbefb4234c2d))
39
+ * create byline component and add it to topper ([56d6ed1](https://github.com/Financial-Times/cp-content-pipeline/commit/56d6ed1af1dd31e2f51e95b5e538578d5802a726))
40
+ * default fullBleed and mobile images to use standard ([4c98bc6](https://github.com/Financial-Times/cp-content-pipeline/commit/4c98bc66c2adcab220098ad99340eb4cae810965))
41
+ * dont request wider image than the source image ([c4e0161](https://github.com/Financial-Times/cp-content-pipeline/commit/c4e0161fa5f0f7492e280a9bc81c4c75faa71b06))
42
+ * ensure content ID is valid before getting image sources ([a564118](https://github.com/Financial-Times/cp-content-pipeline/commit/a564118ff1eb0a580f719fd520789cadc340eede))
43
+ * handle vanity errors gracefully ([904c997](https://github.com/Financial-Times/cp-content-pipeline/commit/904c997dbdcf14564f624d66e7c10c09f0085c45))
44
+ * memoise vanity URL requests within same execution ([c9a26a7](https://github.com/Financial-Times/cp-content-pipeline/commit/c9a26a7d0ff48e5659da1397169a08ccb0cfb9dc))
45
+ * move schema into separate package ([0fe9f3e](https://github.com/Financial-Times/cp-content-pipeline/commit/0fe9f3e5afd2d31ce7fafd5dfb796c08eaf91c72))
46
+ * override cache TTLs for content API requests ([3a57d9a](https://github.com/Financial-Times/cp-content-pipeline/commit/3a57d9ae580b7899ffcce52d9801c5099d5f8497))
47
+ * provide all possible resolutions for image sources ([4d9d586](https://github.com/Financial-Times/cp-content-pipeline/commit/4d9d586ec4578bbd9d8d12e5333ad1f5f9f4e1ff))
48
+ * remove PictureResponsiveMobile, and rename PictureSingle ([b25b289](https://github.com/Financial-Times/cp-content-pipeline/commit/b25b289368c424c267ab65c9494a65cb437cf99b))
49
+ * render Layout components ([a134e30](https://github.com/Financial-Times/cp-content-pipeline/commit/a134e301f6eaddd6eb665489b76dfd36097a8903))
50
+ * separate types for SplitTextTopper and FullBleedTopper ([702503f](https://github.com/Financial-Times/cp-content-pipeline/commit/702503fcdb9b425108b4054dd1d0f0ded537ca17))
51
+ * support ftcms links for image services ([d19ac84](https://github.com/Financial-Times/cp-content-pipeline/commit/d19ac84e9aaf24b274129fef2b50366b0cf7fc35))
52
+ * use correct image data for different topper themes ([319abde](https://github.com/Financial-Times/cp-content-pipeline/commit/319abde3c62b57f97ea0ed109147517a47ac8848))
53
+ * use ImageSource type for image sources ([db767df](https://github.com/Financial-Times/cp-content-pipeline/commit/db767dfd6cd505b33981373d849d70ae0a343dae))
54
+
55
+
56
+ ### Bug Fixes
57
+
58
+ * correct author url for byline links ([cad3660](https://github.com/Financial-Times/cp-content-pipeline/commit/cad3660938ce5c9afbdcf1d7e135bb9d65b33bc7))
59
+ * correct entry point for schema package ([d19eddd](https://github.com/Financial-Times/cp-content-pipeline/commit/d19eddd8fe59b85521ec99c4821e0fe68b6f957a))
60
+ * correct import paths from tags ([46ad28c](https://github.com/Financial-Times/cp-content-pipeline/commit/46ad28c9362150437d99b47e8173c5427ab3eaa6))
61
+ * extract id correctly from image url ([041f310](https://github.com/Financial-Times/cp-content-pipeline/commit/041f3102e748bcdcbc77f39db7fa57ca7d9afa50))
62
+ * handle errors from image service metadata ([5f89ad4](https://github.com/Financial-Times/cp-content-pipeline/commit/5f89ad4116791577a77d8c9a62000f7699c60c23))
63
+ * handle old methode audio articles ([26b042b](https://github.com/Financial-Times/cp-content-pipeline/commit/26b042bd6441d2cd38c37ceccf709b613fe93a53))
64
+ * move schema compilation back to server and cast to fix types ([816eae7](https://github.com/Financial-Times/cp-content-pipeline/commit/816eae7e24718413737cbda092a95155d0926ef6))
65
+ * retrieve uuid from annotation id for stream page url ([96adabc](https://github.com/Financial-Times/cp-content-pipeline/commit/96adabcccebca6d0c4c4da3bc0d06adf6b5907d0))
66
+ * set imageService params rather than append ([da1f87e](https://github.com/Financial-Times/cp-content-pipeline/commit/da1f87e4abdc24bf0937772aed289e92881a2074))
67
+ * set schema package type to module ([a3460db](https://github.com/Financial-Times/cp-content-pipeline/commit/a3460dbfb34b4a97e9683701666c635b5eb5fc46))
68
+
69
+
70
+ ### Code Refactoring
71
+
72
+ * rename "inline" image to "standard" ([ca530b9](https://github.com/Financial-Times/cp-content-pipeline/commit/ca530b99f745e2a4f6a07249529601f0acdddd52))
package/jest.config.js ADDED
@@ -0,0 +1,3 @@
1
+ import base from '../../jest.config.base.mjs'
2
+
3
+ export default { ...base }
@@ -0,0 +1,7 @@
1
+ import { IResolvers } from '@graphql-tools/utils';
2
+ import { DataSources } from './index.js';
3
+ export declare const typeDef: import("graphql").DocumentNode;
4
+ export declare const resolvers: IResolvers<unknown, {
5
+ systemCode: string;
6
+ dataSources: DataSources;
7
+ }, never>;
package/lib/concept.js ADDED
@@ -0,0 +1,39 @@
1
+ import { gql } from 'graphql-tag';
2
+ const CAPI_ID_PREFIX = /^https?:\/\/(?:www|api)\.ft\.com\/things?\//;
3
+ const BASE_URL = 'https://www.ft.com/stream/';
4
+ const FT_URL = 'https://www.ft.com';
5
+ export const typeDef = gql `
6
+ type Concept {
7
+ apiUrl: String!
8
+ directType: String
9
+ id: String!
10
+ predicate: String!
11
+ prefLabel: String!
12
+ type: String!
13
+ types: [String!]!
14
+ url(vanity: Boolean, relative: Boolean): String!
15
+ }
16
+ `;
17
+ export const resolvers = {
18
+ Concept: {
19
+ async url(parent, args = { vanity: false, relative: false }, context) {
20
+ let url = parent.id.replace(CAPI_ID_PREFIX, BASE_URL);
21
+ if (args.vanity) {
22
+ try {
23
+ const vanity = await context.dataSources.vanityUrls.get(url);
24
+ if (vanity !== null) {
25
+ url = vanity;
26
+ }
27
+ }
28
+ catch (err) {
29
+ //TODO:AG:26-09-2022 log error here, but fail gracefully to use non-vanity
30
+ }
31
+ }
32
+ if (args.relative) {
33
+ url = url.replace(FT_URL, '');
34
+ }
35
+ return url;
36
+ },
37
+ },
38
+ };
39
+ //# sourceMappingURL=concept.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concept.js","sourceRoot":"","sources":["../src/concept.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,MAAM,cAAc,GAAG,6CAA6C,CAAA;AACpE,MAAM,QAAQ,GAAG,4BAA4B,CAAA;AAC7C,MAAM,MAAM,GAAG,oBAAoB,CAAA;AAOnC,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAA;;;;;;;;;;;CAWzB,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAIlB;IACF,OAAO,EAAE;QACP,KAAK,CAAC,GAAG,CACP,MAAsB,EACtB,OAAqB,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EACvD,OAAO;YAEP,IAAI,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;YAErD,IAAI,IAAI,CAAC,MAAM,EAAE;gBACf,IAAI;oBACF,MAAM,MAAM,GACV,MAAM,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;oBAC/C,IAAI,MAAM,KAAK,IAAI,EAAE;wBACnB,GAAG,GAAG,MAAM,CAAA;qBACb;iBACF;gBAAC,OAAO,GAAG,EAAE;oBACZ,0EAA0E;iBAC3E;aACF;YAED,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;aAC9B;YACD,OAAO,GAAG,CAAA;QACZ,CAAC;KACF;CACF,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const Article = "http://www.ft.com/ontology/content/Article";
2
+ export declare const LiveBlogPackage = "http://www.ft.com/ontology/content/LiveBlogPackage";
@@ -0,0 +1,3 @@
1
+ export const Article = 'http://www.ft.com/ontology/content/Article';
2
+ export const LiveBlogPackage = 'http://www.ft.com/ontology/content/LiveBlogPackage';
3
+ //# sourceMappingURL=contentTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentTypes.js","sourceRoot":"","sources":["../../src/constants/contentTypes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,4CAA4C,CAAA;AAEnE,MAAM,CAAC,MAAM,eAAe,GAC1B,oDAAoD,CAAA"}
@@ -0,0 +1,55 @@
1
+ import type { InternalContent } from './types/internal-content.js';
2
+ export declare const typeDef: import("graphql").DocumentNode[];
3
+ export declare const resolvers: {
4
+ Content: {
5
+ body(parent: InternalContent): {
6
+ source: string;
7
+ value: string;
8
+ contentApiData: InternalContent;
9
+ };
10
+ topper(parent: InternalContent): InternalContent;
11
+ byline(parent: InternalContent): {
12
+ tree: {
13
+ type: string;
14
+ children: ({
15
+ type: string;
16
+ tagName: string;
17
+ properties: {
18
+ href: string;
19
+ };
20
+ children: {
21
+ type: string;
22
+ value: string;
23
+ }[];
24
+ value?: undefined;
25
+ } | {
26
+ type: string;
27
+ value: string;
28
+ tagName?: undefined;
29
+ properties?: undefined;
30
+ children?: undefined;
31
+ })[];
32
+ };
33
+ };
34
+ metaLink(parent: InternalContent): any;
35
+ metaAltLink(parent: InternalContent): any;
36
+ metaPrefixText(parent: InternalContent): any;
37
+ metaSuffixText(parent: InternalContent): any;
38
+ url(parent: InternalContent, args: {
39
+ relative: boolean;
40
+ }): string;
41
+ type(parent: InternalContent): string;
42
+ mainImage(parent: InternalContent): import("./types/internal-content.js").Image | undefined;
43
+ altTitle(parent: InternalContent): string | undefined;
44
+ altStandfirst(parent: InternalContent): string | undefined;
45
+ indicators(parent: InternalContent): {
46
+ accessLevel: import("./types/internal-content.js").AccessLevel;
47
+ isOpinion: boolean;
48
+ isColumn: boolean;
49
+ isPodcast: boolean;
50
+ isEditorsChoice: boolean;
51
+ isExclusive: boolean;
52
+ isScoop: boolean;
53
+ };
54
+ };
55
+ };
package/lib/content.js ADDED
@@ -0,0 +1,133 @@
1
+ import { gql } from 'graphql-tag';
2
+ import metadata from '@financial-times/n-display-metadata';
3
+ import { getAuthorUrlMapping, isColumn, isEditorsChoice, isExclusive, isOpinion, isPodcast, isScoop, } from './helpers/metadata.js';
4
+ import { buildUrlTree } from './helpers/syntaxTree.js';
5
+ import { splitBylineByName } from './helpers/byline.js';
6
+ export const typeDef = [
7
+ gql `
8
+ type Content {
9
+ title: String!
10
+ id: String!
11
+ type: String!
12
+ standfirst: String
13
+ topper: Topper
14
+ body: RichText!
15
+ bodyXML: String!
16
+ url(relative: Boolean): String!
17
+ publishedDate: String!
18
+ firstPublishedDate: String!
19
+ metaLink: Concept
20
+ metaAltLink: Concept
21
+ metaPrefixText: String
22
+ metaSuffixText: String
23
+ mainImage: Image
24
+ indicators: Indicators!
25
+ altTitle: AltTitle
26
+ altStandfirst: AltStandfirst
27
+ byline: StructuredContent!
28
+ }
29
+ type Indicators {
30
+ accessLevel: AccessLevel
31
+ isOpinion: Boolean
32
+ isColumn: Boolean
33
+ isPodcast: Boolean
34
+ isEditorsChoice: Boolean
35
+ isExclusive: Boolean
36
+ isScoop: Boolean
37
+ }
38
+ enum AccessLevel {
39
+ premium
40
+ subscribed
41
+ registered
42
+ free
43
+ }
44
+ type AltTitle {
45
+ promotionalTitle: String
46
+ }
47
+ type AltStandfirst {
48
+ promotionalStandfirst: String
49
+ }
50
+ `,
51
+ ];
52
+ function getTeaserMetadata(annotations, field) {
53
+ const meta = metadata.teaser({
54
+ annotations,
55
+ });
56
+ return meta[field];
57
+ }
58
+ export const resolvers = {
59
+ Content: {
60
+ body(parent) {
61
+ return {
62
+ source: 'bodyXML',
63
+ value: parent.bodyXML,
64
+ contentApiData: parent,
65
+ };
66
+ },
67
+ topper(parent) {
68
+ return parent;
69
+ },
70
+ byline(parent) {
71
+ const { annotations } = parent;
72
+ const authorUrlMapping = getAuthorUrlMapping(annotations);
73
+ const split = splitBylineByName(parent.byline, [
74
+ ...authorUrlMapping.keys(),
75
+ ]);
76
+ return buildUrlTree(authorUrlMapping, split);
77
+ },
78
+ metaLink(parent) {
79
+ return getTeaserMetadata(parent.annotations, 'link');
80
+ },
81
+ metaAltLink(parent) {
82
+ return getTeaserMetadata(parent.annotations, 'altLink');
83
+ },
84
+ metaPrefixText(parent) {
85
+ return getTeaserMetadata(parent.annotations, 'prefixText');
86
+ },
87
+ metaSuffixText(parent) {
88
+ return getTeaserMetadata(parent.annotations, 'suffixText');
89
+ },
90
+ url(parent, args) {
91
+ const RELATIVE_URL_REGEX = /https?:\/\/www.ft.com/;
92
+ if (args.relative) {
93
+ return parent.webUrl.replace(RELATIVE_URL_REGEX, '');
94
+ }
95
+ else {
96
+ return parent.webUrl;
97
+ }
98
+ },
99
+ type(parent) {
100
+ const TYPE_REGEX = /https?:\/\/www.ft.com\/ontology\/content\//;
101
+ return parent.types[0].replace(TYPE_REGEX, '').toLowerCase();
102
+ },
103
+ mainImage(parent) {
104
+ var _a, _b;
105
+ if (((_a = parent.mainImage) === null || _a === void 0 ? void 0 : _a.type) === 'http://www.ft.com/ontology/content/Image') {
106
+ return parent.mainImage;
107
+ }
108
+ else if (((_b = parent.mainImage) === null || _b === void 0 ? void 0 : _b.type) === 'http://www.ft.com/ontology/content/ImageSet') {
109
+ return parent.mainImage.members[0];
110
+ }
111
+ },
112
+ altTitle(parent) {
113
+ var _a;
114
+ return (_a = parent.alternativeTitles) === null || _a === void 0 ? void 0 : _a.promotionalTitle;
115
+ },
116
+ altStandfirst(parent) {
117
+ var _a;
118
+ return (_a = parent.alternativeStandfirsts) === null || _a === void 0 ? void 0 : _a.promotionalStandfirst;
119
+ },
120
+ indicators(parent) {
121
+ return {
122
+ accessLevel: parent.accessLevel,
123
+ isOpinion: isOpinion(parent),
124
+ isColumn: isColumn(parent),
125
+ isPodcast: isPodcast(parent),
126
+ isEditorsChoice: isEditorsChoice(parent),
127
+ isExclusive: isExclusive(parent),
128
+ isScoop: isScoop(parent),
129
+ };
130
+ },
131
+ },
132
+ };
133
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,149 @@
1
+ import { jest } from '@jest/globals';
2
+ import { typeDefs, resolvers } from './index.js';
3
+ import { ApolloServer } from 'apollo-server';
4
+ import { CapiDataSource } from './datasources/capi.js';
5
+ const capiDataSource = new CapiDataSource();
6
+ jest.spyOn(capiDataSource, 'getContent').mockImplementation((uuid) => {
7
+ return Promise.resolve({
8
+ id: uuid,
9
+ byline: 'Chris Giles in London',
10
+ annotations: [
11
+ {
12
+ id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
13
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
14
+ prefLabel: 'Chris Giles',
15
+ },
16
+ ],
17
+ });
18
+ });
19
+ describe('byline transformation', () => {
20
+ let capiDataSource;
21
+ beforeEach(() => {
22
+ capiDataSource = new CapiDataSource();
23
+ });
24
+ const query = `
25
+ query TestQuery($uuid: String!) {
26
+ content(uuid: $uuid) {
27
+ byline {
28
+ tree
29
+ }
30
+ }
31
+ }
32
+ `;
33
+ const testServer = new ApolloServer({
34
+ typeDefs,
35
+ resolvers,
36
+ dataSources: () => {
37
+ return {
38
+ capi: capiDataSource,
39
+ };
40
+ },
41
+ });
42
+ test('adds a link around a single known author', async () => {
43
+ var _a;
44
+ jest
45
+ .spyOn(capiDataSource, 'getContent')
46
+ .mockImplementation((uuid) => {
47
+ return Promise.resolve({
48
+ id: uuid,
49
+ byline: 'Chris Giles in London',
50
+ annotations: [
51
+ {
52
+ id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
53
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
54
+ prefLabel: 'Chris Giles',
55
+ },
56
+ ],
57
+ });
58
+ });
59
+ const result = await testServer.executeOperation({
60
+ query,
61
+ variables: { uuid: '33d1ac64-88ce-4313-8763-da55200ccf43' },
62
+ });
63
+ const got = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.content.byline.tree;
64
+ expect(got).toMatchSnapshot();
65
+ });
66
+ test('adds links around multiple known authors', async () => {
67
+ var _a;
68
+ jest
69
+ .spyOn(capiDataSource, 'getContent')
70
+ .mockImplementation((uuid) => {
71
+ return Promise.resolve({
72
+ id: uuid,
73
+ byline: 'Chris Giles and Martin Wolf in London',
74
+ annotations: [
75
+ {
76
+ id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
77
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
78
+ prefLabel: 'Chris Giles',
79
+ },
80
+ {
81
+ id: 'http://api.ft.com/things/7c1e1e72-57ae-4461-862a-f8d24dd42e22',
82
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
83
+ prefLabel: 'Martin Wolf',
84
+ },
85
+ ],
86
+ });
87
+ });
88
+ const result = await testServer.executeOperation({
89
+ query,
90
+ variables: { uuid: '33d1ac64-88ce-4313-8763-da55200ccf43' },
91
+ });
92
+ const got = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.content.byline.tree;
93
+ expect(got).toMatchSnapshot();
94
+ });
95
+ test('ignores unknown authors in byline text', async () => {
96
+ var _a;
97
+ jest
98
+ .spyOn(capiDataSource, 'getContent')
99
+ .mockImplementation((uuid) => {
100
+ return Promise.resolve({
101
+ id: uuid,
102
+ byline: 'Chris Giles and Nick Ramsbottom in London',
103
+ annotations: [
104
+ {
105
+ id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
106
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
107
+ prefLabel: 'Chris Giles',
108
+ },
109
+ ],
110
+ });
111
+ });
112
+ const result = await testServer.executeOperation({
113
+ query,
114
+ variables: { uuid: '33d1ac64-88ce-4313-8763-da55200ccf43' },
115
+ });
116
+ const got = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.content.byline.tree;
117
+ expect(got).toMatchSnapshot();
118
+ });
119
+ test('ignores extra authors in annotations array', async () => {
120
+ var _a;
121
+ jest
122
+ .spyOn(capiDataSource, 'getContent')
123
+ .mockImplementation((uuid) => {
124
+ return Promise.resolve({
125
+ id: uuid,
126
+ byline: 'Martin Wolf in London',
127
+ annotations: [
128
+ {
129
+ id: 'http://api.ft.com/things/1d556016-ad16-4fe7-8724-42b3fb15ad28',
130
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
131
+ prefLabel: 'Chris Giles',
132
+ },
133
+ {
134
+ id: 'http://api.ft.com/things/7c1e1e72-57ae-4461-862a-f8d24dd42e22',
135
+ predicate: 'http://www.ft.com/ontology/annotation/hasAuthor',
136
+ prefLabel: 'Martin Wolf',
137
+ },
138
+ ],
139
+ });
140
+ });
141
+ const result = await testServer.executeOperation({
142
+ query,
143
+ variables: { uuid: '33d1ac64-88ce-4313-8763-da55200ccf43' },
144
+ });
145
+ const got = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.content.byline.tree;
146
+ expect(got).toMatchSnapshot();
147
+ });
148
+ });
149
+ //# sourceMappingURL=content.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.test.js","sourceRoot":"","sources":["../src/content.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { RESTDataSource, RequestOptions } from 'apollo-datasource-rest';
2
+ export declare class CapiDataSource extends RESTDataSource {
3
+ baseURL: string;
4
+ capiKey: string;
5
+ articleCacheTTL: number;
6
+ peopleCacheTTL: number;
7
+ willSendRequest(request: RequestOptions): void;
8
+ getContent(uuid: string): Promise<any>;
9
+ getPerson(uuid: string): Promise<any>;
10
+ }
@@ -0,0 +1,28 @@
1
+ import { RESTDataSource } from 'apollo-datasource-rest';
2
+ export class CapiDataSource extends RESTDataSource {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.baseURL = process.env.CAPI_URL || 'https://api-t.ft.com/';
6
+ this.capiKey = process.env.CAPI_API_KEY || '';
7
+ this.articleCacheTTL = process.env.ARTICLE_CACHE_TTL
8
+ ? parseInt(process.env.ARTICLE_CACHE_TTL)
9
+ : 60; // 60 seconds
10
+ this.peopleCacheTTL = process.env.PEOPLE_CACHE_TTL
11
+ ? parseInt(process.env.PEOPLE_CACHE_TTL)
12
+ : 600; // 10 minutes
13
+ }
14
+ willSendRequest(request) {
15
+ request.headers.set('x-api-key', this.capiKey);
16
+ }
17
+ async getContent(uuid) {
18
+ return this.get(`internalcontent/${uuid}`, undefined, {
19
+ cacheOptions: { ttl: this.articleCacheTTL },
20
+ });
21
+ }
22
+ async getPerson(uuid) {
23
+ return this.get(`people/${uuid}`, undefined, {
24
+ cacheOptions: { ttl: this.peopleCacheTTL },
25
+ });
26
+ }
27
+ }
28
+ //# sourceMappingURL=capi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAA;AAEvE,MAAM,OAAO,cAAe,SAAQ,cAAc;IAAlD;;QACE,YAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,uBAAuB,CAAA;QACzD,YAAO,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAA;QACxC,oBAAe,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YACzC,CAAC,CAAC,EAAE,CAAA,CAAC,aAAa;QACpB,mBAAc,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB;YAC3C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACxC,CAAC,CAAC,GAAG,CAAA,CAAC,aAAa;IAiBvB,CAAC;IAfC,eAAe,CAAC,OAAuB;QACrC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,EAAE,SAAS,EAAE;YACpD,YAAY,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE;SAC5C,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,SAAS,EAAE;YAC3C,YAAY,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE;SAC3C,CAAC,CAAA;IACJ,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ import { CapiDataSource } from './capi.js';
2
+ import { OrigamiImageDataSource } from './origami-image.js';
3
+ import { URLManagementDataSource } from './url-management.js';
4
+ export declare const dataSources: () => {
5
+ capi: CapiDataSource;
6
+ origami: OrigamiImageDataSource;
7
+ vanityUrls: URLManagementDataSource;
8
+ };
9
+ export declare type DataSources = ReturnType<typeof dataSources>;
@@ -0,0 +1,9 @@
1
+ import { CapiDataSource } from './capi.js';
2
+ import { OrigamiImageDataSource } from './origami-image.js';
3
+ import { URLManagementDataSource } from './url-management.js';
4
+ export const dataSources = () => ({
5
+ capi: new CapiDataSource(),
6
+ origami: new OrigamiImageDataSource(),
7
+ vanityUrls: new URLManagementDataSource(),
8
+ });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/datasources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CAAC;IAChC,IAAI,EAAE,IAAI,cAAc,EAAE;IAC1B,OAAO,EAAE,IAAI,sBAAsB,EAAE;IACrC,UAAU,EAAE,IAAI,uBAAuB,EAAE;CAC1C,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { RESTDataSource } from 'apollo-datasource-rest';
2
+ export declare class OrigamiImageDataSource extends RESTDataSource {
3
+ baseURL: string;
4
+ getImageMetadata(url: string): Promise<{
5
+ width: number;
6
+ height: number;
7
+ }>;
8
+ }
@@ -0,0 +1,11 @@
1
+ import { RESTDataSource } from 'apollo-datasource-rest';
2
+ export class OrigamiImageDataSource extends RESTDataSource {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.baseURL = 'https://www.ft.com/__origami/service/image/v2';
6
+ }
7
+ async getImageMetadata(url) {
8
+ return this.get(`/images/metadata/${encodeURIComponent(url)}?source=next`);
9
+ }
10
+ }
11
+ //# sourceMappingURL=origami-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origami-image.js","sourceRoot":"","sources":["../../src/datasources/origami-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEvD,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IAA1D;;QACE,YAAO,GAAG,+CAA+C,CAAA;IAM3D,CAAC;IALC,KAAK,CAAC,gBAAgB,CACpB,GAAW;QAEX,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAC5E,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import { DataSource, DataSourceConfig } from 'apollo-datasource';
2
+ import { KeyValueCache } from 'apollo-server-caching';
3
+ export declare class URLManagementDataSource extends DataSource {
4
+ context: unknown;
5
+ cache: KeyValueCache;
6
+ memoizedResults: Map<string, Promise<string>>;
7
+ static clientInitialised: boolean;
8
+ constructor();
9
+ initialize({ context, cache, }: DataSourceConfig<unknown>): void;
10
+ get(fromURL: string, ttl?: number): Promise<string>;
11
+ }