@financial-times/cp-content-pipeline-schema 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +57 -0
- package/lib/concept.d.ts +3 -5
- package/lib/concept.js +8 -21
- package/lib/concept.js.map +1 -1
- package/lib/content.d.ts +3 -54
- package/lib/content.js +18 -95
- package/lib/content.js.map +1 -1
- package/lib/datasources/capi.d.ts +7 -4
- package/lib/datasources/capi.js +5 -3
- package/lib/datasources/capi.js.map +1 -1
- package/lib/datasources/instrumented.d.ts +7 -0
- package/lib/datasources/instrumented.js +18 -0
- package/lib/datasources/instrumented.js.map +1 -0
- package/lib/datasources/origami-image.d.ts +2 -2
- package/lib/datasources/origami-image.js +2 -2
- package/lib/datasources/origami-image.js.map +1 -1
- package/lib/datasources/url-management.d.ts +3 -3
- package/lib/datasources/url-management.js +4 -5
- package/lib/datasources/url-management.js.map +1 -1
- package/lib/datasources/url-management.test.js +12 -5
- package/lib/datasources/url-management.test.js.map +1 -1
- package/lib/fixtures/capiObject.d.ts +2 -0
- package/lib/fixtures/capiObject.js +60 -0
- package/lib/fixtures/capiObject.js.map +1 -0
- package/lib/fixtures/capiPerson.d.ts +2 -0
- package/lib/fixtures/capiPerson.js +54 -0
- package/lib/fixtures/capiPerson.js.map +1 -0
- package/lib/helpers/metadata.d.ts +0 -11
- package/lib/helpers/metadata.js +0 -52
- package/lib/helpers/metadata.js.map +1 -1
- package/lib/image.d.ts +2 -23
- package/lib/image.js +10 -82
- package/lib/image.js.map +1 -1
- package/lib/index.d.ts +7 -3
- package/lib/index.js +5 -12
- package/lib/index.js.map +1 -1
- package/lib/model/Byline.d.ts +29 -0
- package/lib/model/Byline.js +45 -0
- package/lib/model/Byline.js.map +1 -0
- package/lib/{content.test.d.ts → model/Byline.test.d.ts} +0 -0
- package/lib/model/Byline.test.js +60 -0
- package/lib/model/Byline.test.js.map +1 -0
- package/lib/model/CapiResponse.d.ts +48 -0
- package/lib/model/CapiResponse.js +159 -0
- package/lib/model/CapiResponse.js.map +1 -0
- package/lib/model/Concept.d.ts +36 -0
- package/lib/model/Concept.js +109 -0
- package/lib/model/Concept.js.map +1 -0
- package/lib/{image.test.d.ts → model/Concept.test.d.ts} +0 -0
- package/lib/model/Concept.test.js +96 -0
- package/lib/model/Concept.test.js.map +1 -0
- package/lib/model/Image.d.ts +34 -0
- package/lib/model/Image.js +101 -0
- package/lib/model/Image.js.map +1 -0
- package/lib/model/Image.test.d.ts +1 -0
- package/lib/{image.test.js → model/Image.test.js} +71 -74
- package/lib/model/Image.test.js.map +1 -0
- package/lib/model/Topper.d.ts +26 -0
- package/lib/model/Topper.js +93 -0
- package/lib/model/Topper.js.map +1 -0
- package/lib/model/Topper.test.d.ts +1 -0
- package/lib/model/Topper.test.js +283 -0
- package/lib/model/Topper.test.js.map +1 -0
- package/lib/picture.d.ts +7 -8
- package/lib/picture.js +15 -8
- package/lib/picture.js.map +1 -1
- package/lib/richText.d.ts +2 -2
- package/lib/richText.js.map +1 -1
- package/lib/tags/ImageSet.d.ts +2 -0
- package/lib/tags/ImageSet.js +24 -0
- package/lib/tags/ImageSet.js.map +1 -0
- package/lib/tags/LayoutImage.d.ts +2 -0
- package/lib/tags/LayoutImage.js +42 -0
- package/lib/tags/LayoutImage.js.map +1 -0
- package/lib/tags/Link.d.ts +2 -0
- package/lib/tags/Link.js +21 -0
- package/lib/tags/Link.js.map +1 -0
- package/lib/tags/PullQuote.d.ts +2 -0
- package/lib/tags/PullQuote.js +25 -0
- package/lib/tags/PullQuote.js.map +1 -0
- package/lib/tags/Recommended.d.ts +2 -0
- package/lib/tags/Recommended.js +39 -0
- package/lib/tags/Recommended.js.map +1 -0
- package/lib/{tags.d.ts → tags/index.d.ts} +5 -5
- package/lib/tags/index.js +33 -0
- package/lib/tags/index.js.map +1 -0
- package/lib/teaser.d.ts +4 -0
- package/lib/teaser.js +56 -0
- package/lib/teaser.js.map +1 -0
- package/lib/topper.d.ts +2 -5
- package/lib/topper.js +27 -101
- package/lib/topper.js.map +1 -1
- package/lib/unified-plugins/extract-references.d.ts +2 -2
- package/lib/unified-plugins/extract-references.js +1 -1
- package/lib/unified-plugins/extract-references.js.map +1 -1
- package/lib/unified-plugins/map-to-abstract-types.js +3 -2
- package/lib/unified-plugins/map-to-abstract-types.js.map +1 -1
- package/package.json +5 -2
- package/src/concept.ts +12 -39
- package/src/content.ts +25 -109
- package/src/datasources/capi.ts +8 -4
- package/src/datasources/instrumented.ts +39 -0
- package/src/datasources/origami-image.ts +2 -2
- package/src/datasources/url-management.test.ts +14 -5
- package/src/datasources/url-management.ts +7 -10
- package/src/fixtures/capiObject.ts +61 -0
- package/src/fixtures/capiPerson.ts +59 -0
- package/src/helpers/metadata.ts +0 -79
- package/src/image.ts +15 -112
- package/src/index.ts +20 -14
- package/src/model/Byline.test.ts +67 -0
- package/src/model/Byline.ts +39 -0
- package/src/model/CapiResponse.ts +182 -0
- package/src/model/Concept.test.ts +124 -0
- package/src/model/Concept.ts +143 -0
- package/src/{image.test.ts → model/Image.test.ts} +84 -134
- package/src/model/Image.ts +116 -0
- package/src/model/Topper.test.ts +354 -0
- package/src/model/Topper.ts +120 -0
- package/src/model/__snapshots__/Byline.test.ts.snap +126 -0
- package/src/picture.ts +16 -15
- package/src/richText.ts +3 -3
- package/src/tags/ImageSet.ts +35 -0
- package/src/tags/LayoutImage.ts +51 -0
- package/src/tags/Link.ts +23 -0
- package/src/tags/PullQuote.ts +32 -0
- package/src/tags/Recommended.ts +49 -0
- package/src/tags/index.ts +65 -0
- package/src/teaser.ts +63 -0
- package/src/topper.ts +30 -124
- package/src/types/internal-content.d.ts +29 -4
- package/src/unified-plugins/extract-references.ts +6 -5
- package/src/unified-plugins/map-to-abstract-types.ts +5 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/content.test.js +0 -149
- package/lib/content.test.js.map +0 -1
- package/lib/helpers/byline.d.ts +0 -1
- package/lib/helpers/byline.js +0 -5
- package/lib/helpers/byline.js.map +0 -1
- package/lib/helpers/syntaxTree.d.ts +0 -23
- package/lib/helpers/syntaxTree.js +0 -23
- package/lib/helpers/syntaxTree.js.map +0 -1
- package/lib/image.test.js.map +0 -1
- package/lib/tags.js +0 -178
- package/lib/tags.js.map +0 -1
- package/src/__snapshots__/content.test.ts.snap +0 -118
- package/src/content.test.ts +0 -163
- package/src/helpers/byline.ts +0 -4
- package/src/helpers/syntaxTree.ts +0 -26
- package/src/tags.ts +0 -237
- package/src/types/next-metrics.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.3.0...cp-content-pipeline-schema-v0.3.1) (2022-10-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* instrument REST datasources ([ce509a2](https://github.com/Financial-Times/cp-content-pipeline/commit/ce509a2f4bc91e6e9593ef21f7341a5e504727b4))
|
|
9
|
+
* split restdatasource metrics by response status ([3c2356c](https://github.com/Financial-Times/cp-content-pipeline/commit/3c2356c12001bb6af30c5820111d21a6c7766588))
|
|
10
|
+
|
|
11
|
+
## [0.3.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v0.2.1...cp-content-pipeline-schema-v0.3.0) (2022-10-11)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### ⚠ BREAKING CHANGES
|
|
15
|
+
|
|
16
|
+
* render byline as part of a new ArticleInfo component
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add pull-quotes ([b4cd5d6](https://github.com/Financial-Times/cp-content-pipeline/commit/b4cd5d65b8ae50c64e774ae55049e1d43c7b1c7e))
|
|
21
|
+
* render byline as part of a new ArticleInfo component ([de58076](https://github.com/Financial-Times/cp-content-pipeline/commit/de580765ec5094252b23132b6b457003ca66c4fb))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* implement min/max width resolvers ([8140aa2](https://github.com/Financial-Times/cp-content-pipeline/commit/8140aa27b39dbe89970a5f52a5c500546ec6d587))
|
|
27
|
+
* show brand as displayConcept for opinion articles ([c86060e](https://github.com/Financial-Times/cp-content-pipeline/commit/c86060eea95d8ef632105e9a10deff16aab9ee0f))
|
|
28
|
+
* show brand tags on fancy toppers with brands ([b3d4748](https://github.com/Financial-Times/cp-content-pipeline/commit/b3d4748c518e96200369abf5a8e9068e68580fc0))
|
|
29
|
+
* support articles without bylines ([0996c75](https://github.com/Financial-Times/cp-content-pipeline/commit/0996c75f0452aa2fec8b4b1e5617f3246e16c915))
|
|
30
|
+
* use image model for teaser image ([0eae6f8](https://github.com/Financial-Times/cp-content-pipeline/commit/0eae6f82f508369dd4384d24b2fc25cbd417af0e))
|
|
31
|
+
* use wheat as 'auto' colour for fancy toppers ([dfb1eac](https://github.com/Financial-Times/cp-content-pipeline/commit/dfb1eac6b0948199d0cb41d71a05b857a4456dec))
|
|
32
|
+
|
|
3
33
|
## [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
34
|
|
|
5
35
|
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Schema
|
|
2
|
+
|
|
3
|
+
## What is this?
|
|
4
|
+
|
|
5
|
+
The GraphQL schema, data sources, and business logic for the content pipeline API. It is consumed by the
|
|
6
|
+
[api package](../api) and not intended for use outside this project.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { ApolloServer } from 'apollo-server'
|
|
12
|
+
import {
|
|
13
|
+
resolvers,
|
|
14
|
+
typeDefs,
|
|
15
|
+
dataSources,
|
|
16
|
+
} from '@financial-times/cp-content-pipeline-schema'
|
|
17
|
+
|
|
18
|
+
const server = new ApolloServer({
|
|
19
|
+
typeDefs,
|
|
20
|
+
resolvers,
|
|
21
|
+
dataSources,
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
See the [api package entry point](../api/src/index.ts) for a more complex example.
|
|
26
|
+
|
|
27
|
+
## How does it work?
|
|
28
|
+
|
|
29
|
+
This package's exports are shown below. They are consumed by a GraphQL server framework:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
resolvers,
|
|
34
|
+
typeDefs,
|
|
35
|
+
dataSources,
|
|
36
|
+
DataSources,
|
|
37
|
+
QueryContext,
|
|
38
|
+
} from '@financial-times/cp-content-pipeline-schema'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The schema is a collection of type definitions that is exported as `typeDefs`. It defines the 'shape' of queries that
|
|
42
|
+
are executed against our data.
|
|
43
|
+
|
|
44
|
+
The schema is split into files at the root of the `src` directory and brought together in `src/index.ts` for export.
|
|
45
|
+
|
|
46
|
+
Resolvers define the technique for fetching the types defined in the schema. The resolvers for each part of the schema
|
|
47
|
+
are defined in the
|
|
48
|
+
same file the schema definition is in. They are exported as `resolvers`.
|
|
49
|
+
|
|
50
|
+
Data sources are used to fetch data from external sources, such as the content API. These are defined in the
|
|
51
|
+
[data sources directory](src/datasources). Its type is exported as `DataSources`, its factory function is exported as
|
|
52
|
+
`dataSources`.
|
|
53
|
+
|
|
54
|
+
The `QueryContext` type defines the context object sent to each resolver function.
|
|
55
|
+
|
|
56
|
+
The model contains the business logic gluing the data sources and resolvers together. It is defined in the
|
|
57
|
+
[model](src/model) directory and consumed by the resolvers.
|
package/lib/concept.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { IResolvers } from '@graphql-tools/utils';
|
|
2
|
-
import {
|
|
2
|
+
import type { QueryContext } from './index.js';
|
|
3
|
+
import { Concept } from './model/Concept.js';
|
|
3
4
|
export declare const typeDef: import("graphql").DocumentNode;
|
|
4
|
-
export declare const resolvers: IResolvers<
|
|
5
|
-
systemCode: string;
|
|
6
|
-
dataSources: DataSources;
|
|
7
|
-
}, never>;
|
|
5
|
+
export declare const resolvers: IResolvers<Concept, QueryContext, never>;
|
package/lib/concept.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
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
2
|
export const typeDef = gql `
|
|
6
3
|
type Concept {
|
|
7
4
|
apiUrl: String!
|
|
@@ -16,24 +13,14 @@ export const typeDef = gql `
|
|
|
16
13
|
`;
|
|
17
14
|
export const resolvers = {
|
|
18
15
|
Concept: {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
},
|
|
16
|
+
apiUrl: (parent) => parent.apiUrl(),
|
|
17
|
+
directType: (parent) => parent.directType(),
|
|
18
|
+
id: (parent) => parent.id(),
|
|
19
|
+
predicate: (parent) => parent.predicate(),
|
|
20
|
+
prefLabel: (parent) => parent.prefLabel(),
|
|
21
|
+
type: (parent) => parent.type(),
|
|
22
|
+
types: (parent) => parent.types(),
|
|
23
|
+
url: async (parent, args, context) => parent.url(args),
|
|
37
24
|
},
|
|
38
25
|
};
|
|
39
26
|
//# sourceMappingURL=concept.js.map
|
package/lib/concept.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concept.js","sourceRoot":"","sources":["../src/concept.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"concept.js","sourceRoot":"","sources":["../src/concept.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAIjC,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAA;;;;;;;;;;;CAWzB,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6C;IACjE,OAAO,EAAE;QACP,MAAM,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE;QAC5C,UAAU,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE;QACpD,EAAE,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;QACpC,SAAS,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QAClD,SAAS,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QAClD,IAAI,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;QACxC,KAAK,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;QAC1C,GAAG,EAAE,KAAK,EAAE,MAAe,EAAE,IAAkB,EAAE,OAAO,EAAE,EAAE,CAC1D,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACnB;CACF,CAAA"}
|
package/lib/content.d.ts
CHANGED
|
@@ -1,55 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IResolvers } from '@graphql-tools/utils';
|
|
2
|
+
import type { QueryContext } from './index.js';
|
|
2
3
|
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
|
-
};
|
|
4
|
+
export declare const resolvers: IResolvers<unknown, QueryContext, never>;
|
package/lib/content.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { gql } from 'graphql-tag';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { buildUrlTree } from './helpers/syntaxTree.js';
|
|
5
|
-
import { splitBylineByName } from './helpers/byline.js';
|
|
2
|
+
import { Topper } from './model/Topper.js';
|
|
3
|
+
import { Byline } from './model/Byline.js';
|
|
6
4
|
export const typeDef = [
|
|
7
5
|
gql `
|
|
8
6
|
type Content {
|
|
@@ -16,30 +14,11 @@ export const typeDef = [
|
|
|
16
14
|
url(relative: Boolean): String!
|
|
17
15
|
publishedDate: String!
|
|
18
16
|
firstPublishedDate: String!
|
|
19
|
-
metaLink: Concept
|
|
20
|
-
metaAltLink: Concept
|
|
21
|
-
metaPrefixText: String
|
|
22
|
-
metaSuffixText: String
|
|
23
17
|
mainImage: Image
|
|
24
|
-
indicators: Indicators!
|
|
25
18
|
altTitle: AltTitle
|
|
26
19
|
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
|
|
20
|
+
byline: StructuredContent
|
|
21
|
+
teaser: Teaser
|
|
43
22
|
}
|
|
44
23
|
type AltTitle {
|
|
45
24
|
promotionalTitle: String
|
|
@@ -49,85 +28,29 @@ export const typeDef = [
|
|
|
49
28
|
}
|
|
50
29
|
`,
|
|
51
30
|
];
|
|
52
|
-
function getTeaserMetadata(annotations, field) {
|
|
53
|
-
const meta = metadata.teaser({
|
|
54
|
-
annotations,
|
|
55
|
-
});
|
|
56
|
-
return meta[field];
|
|
57
|
-
}
|
|
58
31
|
export const resolvers = {
|
|
59
32
|
Content: {
|
|
60
33
|
body(parent) {
|
|
61
34
|
return {
|
|
62
35
|
source: 'bodyXML',
|
|
63
|
-
value: parent.bodyXML,
|
|
36
|
+
value: parent.bodyXML(),
|
|
64
37
|
contentApiData: parent,
|
|
65
38
|
};
|
|
66
39
|
},
|
|
67
|
-
topper(parent)
|
|
68
|
-
return parent;
|
|
69
|
-
},
|
|
40
|
+
topper: (parent, args, context) => new Topper(parent, context),
|
|
70
41
|
byline(parent) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
},
|
|
42
|
+
const bylineText = parent.byline();
|
|
43
|
+
if (!bylineText)
|
|
44
|
+
return null;
|
|
45
|
+
const authorUrlMapping = parent.getAuthorUrlMapping();
|
|
46
|
+
return new Byline(bylineText, authorUrlMapping).buildBylineTree();
|
|
47
|
+
},
|
|
48
|
+
url: (parent, args) => args.relative ? parent.relativeUrl() : parent.url(),
|
|
49
|
+
type: (parent) => parent.type(),
|
|
50
|
+
mainImage: (parent) => parent.mainImage(),
|
|
51
|
+
altTitle: (parent) => parent.alternativeTitle(),
|
|
52
|
+
altStandfirst: (parent) => parent.alternativeStandfirst(),
|
|
53
|
+
publishedDate: (parent) => parent.publishedDate(),
|
|
131
54
|
},
|
|
132
55
|
};
|
|
133
56
|
//# sourceMappingURL=content.js.map
|
package/lib/content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAIjC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6C;IACjE,OAAO,EAAE;QACP,IAAI,CAAC,MAAoB;YACvB,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;gBACvB,cAAc,EAAE,MAAM;aACvB,CAAA;QACH,CAAC;QACD,MAAM,EAAE,CAAC,MAAoB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAC9C,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAC7B,MAAM,CAAC,MAAoB;YACzB,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;YAClC,IAAI,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAA;YAC5B,MAAM,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,EAAE,CAAA;YACrD,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,eAAe,EAAE,CAAA;QACnE,CAAC;QACD,GAAG,EAAE,CAAC,MAAoB,EAAE,IAA2B,EAAE,EAAE,CACzD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;QACrD,IAAI,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;QAC7C,SAAS,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE;QACvD,QAAQ,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC7D,aAAa,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,qBAAqB,EAAE;QACvE,aAAa,EAAE,CAAC,MAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE;KAChE;CACF,CAAA"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { RequestOptions } from 'apollo-datasource-rest';
|
|
2
|
+
import { CapiResponse } from '../model/CapiResponse.js';
|
|
3
|
+
import { InstrumentedRESTDataSource } from './instrumented.js';
|
|
4
|
+
import { CapiPerson } from '../types/internal-content.js';
|
|
5
|
+
export declare class CapiDataSource extends InstrumentedRESTDataSource {
|
|
3
6
|
baseURL: string;
|
|
4
7
|
capiKey: string;
|
|
5
8
|
articleCacheTTL: number;
|
|
6
9
|
peopleCacheTTL: number;
|
|
7
10
|
willSendRequest(request: RequestOptions): void;
|
|
8
|
-
getContent(uuid: string): Promise<
|
|
9
|
-
getPerson(uuid: string): Promise<
|
|
11
|
+
getContent(uuid: string): Promise<CapiResponse>;
|
|
12
|
+
getPerson(uuid: string): Promise<CapiPerson>;
|
|
10
13
|
}
|
package/lib/datasources/capi.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { CapiResponse } from '../model/CapiResponse.js';
|
|
2
|
+
import { InstrumentedRESTDataSource } from './instrumented.js';
|
|
3
|
+
export class CapiDataSource extends InstrumentedRESTDataSource {
|
|
3
4
|
constructor() {
|
|
4
5
|
super(...arguments);
|
|
5
6
|
this.baseURL = process.env.CAPI_URL || 'https://api-t.ft.com/';
|
|
@@ -12,12 +13,13 @@ export class CapiDataSource extends RESTDataSource {
|
|
|
12
13
|
: 600; // 10 minutes
|
|
13
14
|
}
|
|
14
15
|
willSendRequest(request) {
|
|
16
|
+
super.willSendRequest(request);
|
|
15
17
|
request.headers.set('x-api-key', this.capiKey);
|
|
16
18
|
}
|
|
17
19
|
async getContent(uuid) {
|
|
18
20
|
return this.get(`internalcontent/${uuid}`, undefined, {
|
|
19
21
|
cacheOptions: { ttl: this.articleCacheTTL },
|
|
20
|
-
});
|
|
22
|
+
}).then((response) => new CapiResponse(response, this.context));
|
|
21
23
|
}
|
|
22
24
|
async getPerson(uuid) {
|
|
23
25
|
return this.get(`people/${uuid}`, undefined, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAG9D,MAAM,OAAO,cAAe,SAAQ,0BAA0B;IAA9D;;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;IAkBvB,CAAC;IAhBC,eAAe,CAAC,OAAuB;QACrC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;QAC9B,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,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IACjE,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,7 @@
|
|
|
1
|
+
import { Request, RequestOptions, Response, RESTDataSource } from 'apollo-datasource-rest';
|
|
2
|
+
import { QueryContext } from '../index.js';
|
|
3
|
+
export declare class InstrumentedRESTDataSource extends RESTDataSource<QueryContext> {
|
|
4
|
+
startTime?: bigint;
|
|
5
|
+
willSendRequest(request: RequestOptions): void;
|
|
6
|
+
didReceiveResponse<TResult>(response: Response, request: Request): Promise<TResult>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RESTDataSource, } from 'apollo-datasource-rest';
|
|
2
|
+
export class InstrumentedRESTDataSource extends RESTDataSource {
|
|
3
|
+
willSendRequest(request) {
|
|
4
|
+
var _a;
|
|
5
|
+
this.startTime = process.hrtime.bigint();
|
|
6
|
+
(_a = this.context.metrics) === null || _a === void 0 ? void 0 : _a.count(`graphql.datasource.${this.constructor.name}.request.count`, 1);
|
|
7
|
+
}
|
|
8
|
+
async didReceiveResponse(response, request) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
// this.startTime will definitely have been set by willSendRequest, but no way of encoding that in types
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
12
|
+
const duration = (process.hrtime.bigint() - this.startTime) / BigInt(1e6);
|
|
13
|
+
(_a = this.context.metrics) === null || _a === void 0 ? void 0 : _a.count(`graphql.datasource.${this.constructor.name}.response.${response.status}.count`, 1);
|
|
14
|
+
(_b = this.context.metrics) === null || _b === void 0 ? void 0 : _b.count(`graphql.datasource.${this.constructor.name}.response.${response.status}.time`, Number(duration));
|
|
15
|
+
return super.didReceiveResponse(response, request);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=instrumented.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumented.js","sourceRoot":"","sources":["../../src/datasources/instrumented.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,cAAc,GACf,MAAM,wBAAwB,CAAA;AAG/B,MAAM,OAAO,0BAA2B,SAAQ,cAA4B;IAG1E,eAAe,CAAC,OAAuB;;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;QACxC,MAAA,IAAI,CAAC,OAAO,CAAC,OAAO,0CAAE,KAAK,CACzB,sBAAsB,IAAI,CAAC,WAAW,CAAC,IAAI,gBAAgB,EAC3D,CAAC,CACF,CAAA;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,QAAkB,EAClB,OAAgB;;QAEhB,wGAAwG;QACxG,oEAAoE;QACpE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAU,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QAE1E,MAAA,IAAI,CAAC,OAAO,CAAC,OAAO,0CAAE,KAAK,CACzB,sBAAsB,IAAI,CAAC,WAAW,CAAC,IAAI,aAAa,QAAQ,CAAC,MAAM,QAAQ,EAC/E,CAAC,CACF,CAAA;QACD,MAAA,IAAI,CAAC,OAAO,CAAC,OAAO,0CAAE,KAAK,CACzB,sBAAsB,IAAI,CAAC,WAAW,CAAC,IAAI,aAAa,QAAQ,CAAC,MAAM,OAAO,EAC9E,MAAM,CAAC,QAAQ,CAAC,CACjB,CAAA;QAED,OAAO,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACpD,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class OrigamiImageDataSource extends
|
|
1
|
+
import { InstrumentedRESTDataSource } from './instrumented.js';
|
|
2
|
+
export declare class OrigamiImageDataSource extends InstrumentedRESTDataSource {
|
|
3
3
|
baseURL: string;
|
|
4
4
|
getImageMetadata(url: string): Promise<{
|
|
5
5
|
width: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export class OrigamiImageDataSource extends
|
|
1
|
+
import { InstrumentedRESTDataSource } from './instrumented.js';
|
|
2
|
+
export class OrigamiImageDataSource extends InstrumentedRESTDataSource {
|
|
3
3
|
constructor() {
|
|
4
4
|
super(...arguments);
|
|
5
5
|
this.baseURL = 'https://www.ft.com/__origami/service/image/v2';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origami-image.js","sourceRoot":"","sources":["../../src/datasources/origami-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"origami-image.js","sourceRoot":"","sources":["../../src/datasources/origami-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAE9D,MAAM,OAAO,sBAAuB,SAAQ,0BAA0B;IAAtE;;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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DataSource, DataSourceConfig } from 'apollo-datasource';
|
|
2
2
|
import { KeyValueCache } from 'apollo-server-caching';
|
|
3
|
+
import { QueryContext } from '../index.js';
|
|
3
4
|
export declare class URLManagementDataSource extends DataSource {
|
|
4
|
-
context:
|
|
5
|
+
context: QueryContext;
|
|
5
6
|
cache: KeyValueCache;
|
|
6
7
|
memoizedResults: Map<string, Promise<string>>;
|
|
7
8
|
static clientInitialised: boolean;
|
|
8
|
-
|
|
9
|
-
initialize({ context, cache, }: DataSourceConfig<unknown>): void;
|
|
9
|
+
initialize({ context, cache, }: DataSourceConfig<QueryContext>): void;
|
|
10
10
|
get(fromURL: string, ttl?: number): Promise<string>;
|
|
11
11
|
}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { DataSource } from 'apollo-datasource';
|
|
2
2
|
import { InMemoryLRUCache, PrefixingKeyValueCache, } from 'apollo-server-caching';
|
|
3
3
|
import * as nUrlManagementApiReadClient from '@financial-times/n-url-management-api-read-client';
|
|
4
|
-
import metrics from 'next-metrics';
|
|
5
4
|
const CACHE_PREFIX = 'nurlmgmtapi';
|
|
6
5
|
const DEFAULT_TTL_IN_SECONDS = 60 * 60; // one hour
|
|
7
6
|
export class URLManagementDataSource extends DataSource {
|
|
8
7
|
constructor() {
|
|
9
|
-
super();
|
|
8
|
+
super(...arguments);
|
|
10
9
|
this.memoizedResults = new Map();
|
|
10
|
+
}
|
|
11
|
+
initialize({ context, cache = new InMemoryLRUCache(), }) {
|
|
11
12
|
if (!URLManagementDataSource.clientInitialised) {
|
|
12
|
-
nUrlManagementApiReadClient.init({ metrics });
|
|
13
|
+
nUrlManagementApiReadClient.init({ metrics: context.metrics });
|
|
13
14
|
URLManagementDataSource.clientInitialised = true;
|
|
14
15
|
}
|
|
15
|
-
}
|
|
16
|
-
initialize({ context, cache = new InMemoryLRUCache(), }) {
|
|
17
16
|
this.context = context;
|
|
18
17
|
this.cache = new PrefixingKeyValueCache(cache, CACHE_PREFIX);
|
|
19
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-management.js","sourceRoot":"","sources":["../../src/datasources/url-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAEL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,2BAA2B,MAAM,mDAAmD,CAAA;
|
|
1
|
+
{"version":3,"file":"url-management.js","sourceRoot":"","sources":["../../src/datasources/url-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAEL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,2BAA2B,MAAM,mDAAmD,CAAA;AAIhG,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,sBAAsB,GAAG,EAAE,GAAG,EAAE,CAAA,CAAC,WAAW;AAElD,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IAAvD;;QAGE,oBAAe,GAAG,IAAI,GAAG,EAA2B,CAAA;IA4CtD,CAAC;IAxCU,UAAU,CAAC,EAClB,OAAO,EACP,KAAK,GAAG,IAAI,gBAAgB,EAAE,GACC;QAC/B,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,EAAE;YAC9C,2BAA2B,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;YAC9D,uBAAuB,CAAC,iBAAiB,GAAG,IAAI,CAAA;SACjD;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAsB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAC9D,CAAC;IAED,KAAK,CAAC,GAAG,CACP,OAAe,EACf,MAAc,sBAAsB;QAEpC,MAAM,SAAS,GAAG,KAAK,IAAqB,EAAE;YAC5C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC/C,IAAI,SAAS,EAAE;gBACb,OAAO,SAAS,CAAA;aACjB;YAED,MAAM,YAAY,GAChB,MAAM,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAChD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1D,OAAO,YAAY,CAAC,KAAK,CAAA;QAC3B,CAAC,CAAA;QAED,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAE/C,IAAI,OAAO,EAAE;YACX,OAAO,OAAO,CAAA;SACf;QAED,OAAO,GAAG,SAAS,EAAE,CAAA;QACrB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAE1C,OAAO,OAAO,CAAA;IAChB,CAAC;;AAzCM,yCAAiB,GAAG,KAAK,CAAA"}
|
|
@@ -10,14 +10,21 @@ const nUrlManagementApiReadClient = await import('@financial-times/n-url-managem
|
|
|
10
10
|
import { InMemoryLRUCache } from 'apollo-server-caching';
|
|
11
11
|
import { jest } from '@jest/globals';
|
|
12
12
|
const getMock = nUrlManagementApiReadClient.get;
|
|
13
|
+
const context = {};
|
|
13
14
|
describe('URL management data source', () => {
|
|
14
15
|
beforeEach(() => {
|
|
15
16
|
jest.resetAllMocks();
|
|
16
17
|
});
|
|
17
18
|
it('only initialises the client library once', async () => {
|
|
18
|
-
new URLManagementDataSource()
|
|
19
|
+
new URLManagementDataSource().initialize({
|
|
20
|
+
context,
|
|
21
|
+
cache: new InMemoryLRUCache(),
|
|
22
|
+
});
|
|
19
23
|
expect(nUrlManagementApiReadClient.init).toHaveBeenCalledTimes(1);
|
|
20
|
-
new URLManagementDataSource()
|
|
24
|
+
new URLManagementDataSource().initialize({
|
|
25
|
+
context,
|
|
26
|
+
cache: new InMemoryLRUCache(),
|
|
27
|
+
});
|
|
21
28
|
expect(nUrlManagementApiReadClient.init).toHaveBeenCalledTimes(1);
|
|
22
29
|
});
|
|
23
30
|
it('gets a vanity URL from the dynamodb database', async () => {
|
|
@@ -25,7 +32,7 @@ describe('URL management data source', () => {
|
|
|
25
32
|
toURL: 'vanity.url',
|
|
26
33
|
});
|
|
27
34
|
const dataSource = new URLManagementDataSource();
|
|
28
|
-
dataSource.initialize({ context
|
|
35
|
+
dataSource.initialize({ context, cache: new InMemoryLRUCache() });
|
|
29
36
|
const vanity = await dataSource.get('original.url');
|
|
30
37
|
expect(vanity).toEqual('vanity.url');
|
|
31
38
|
expect(nUrlManagementApiReadClient.get).toHaveBeenCalled();
|
|
@@ -34,7 +41,7 @@ describe('URL management data source', () => {
|
|
|
34
41
|
getMock.mockImplementation((fromUrl) => Promise.resolve({ toURL: `${fromUrl}.vanity` }));
|
|
35
42
|
const dataSource = new URLManagementDataSource();
|
|
36
43
|
const cache = new InMemoryLRUCache();
|
|
37
|
-
dataSource.initialize({ context
|
|
44
|
+
dataSource.initialize({ context, cache });
|
|
38
45
|
const firstRequest = await dataSource.get('original.url');
|
|
39
46
|
expect(firstRequest).toEqual('original.url.vanity');
|
|
40
47
|
expect(await cache.getTotalSize()).toEqual(19); // string length of original.url.vanity
|
|
@@ -51,7 +58,7 @@ describe('URL management data source', () => {
|
|
|
51
58
|
getMock.mockImplementation((fromUrl) => Promise.resolve({ toURL: `${fromUrl}.vanity` }));
|
|
52
59
|
const dataSource = new URLManagementDataSource();
|
|
53
60
|
const cache = new InMemoryLRUCache();
|
|
54
|
-
dataSource.initialize({ context
|
|
61
|
+
dataSource.initialize({ context, cache });
|
|
55
62
|
const firstRequest = dataSource.get('original.url');
|
|
56
63
|
const secondRequest = dataSource.get('original.url');
|
|
57
64
|
const differentRequest = dataSource.get('different.url');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-management.test.js","sourceRoot":"","sources":["../../src/datasources/url-management.test.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,oDAAoD;AAEpD,IAAI,CAAC,mBAAmB,CACtB,mDAAmD,EACnD,GAAG,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE;IACd,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;CAChB,CAAC,CACH,CAAA;AAED,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAEzD,MAAM,uBAAuB,GAAG,aAAa,CAAC,uBAAuB,CAAA;AACrE,MAAM,2BAA2B,GAAG,MAAM,MAAM,CAC9C,mDAAmD,CACpD,CAAA;
|
|
1
|
+
{"version":3,"file":"url-management.test.js","sourceRoot":"","sources":["../../src/datasources/url-management.test.ts"],"names":[],"mappings":"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"}
|