@financial-times/dotcom-server-app-context 7.3.0 → 7.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/dist/node/AppContext.d.ts +11 -0
- package/dist/node/filterEmptyData.d.ts +5 -0
- package/dist/node/index.d.ts +2 -0
- package/dist/node/validate.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +2031 -0
- package/package.json +6 -4
- package/schema.md +0 -97
- package/scripts/schemaToMarkdown.js +0 -4
- package/src/AppContext.ts +0 -33
- package/src/filterEmptyData.ts +0 -19
- package/src/index.ts +0 -2
- package/src/schema.json +0 -88
- package/src/types.d.ts +0 -15
- package/src/validate.ts +0 -24
package/package.json
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
{
|
2
2
|
"name": "@financial-times/dotcom-server-app-context",
|
3
|
-
"version": "7.3.
|
3
|
+
"version": "7.3.1",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/node/index.js",
|
6
6
|
"types": "src/index.ts",
|
7
7
|
"scripts": {
|
8
8
|
"generate-schema": "node scripts/schemaToMarkdown.js > schema.md",
|
9
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
10
|
-
"tsc": "../../node_modules/.bin/tsc --incremental",
|
11
10
|
"clean": "npm run clean:dist && npm run clean:node_modules",
|
12
11
|
"clean:dist": "rm -rf dist",
|
13
12
|
"clean:node_modules": "rm -rf node_modules",
|
13
|
+
"build:node": "tsc",
|
14
14
|
"build": "npm run build:node",
|
15
|
-
"build:node": "npm run tsc -- --module commonjs --outDir ./dist/node",
|
16
15
|
"dev": "npm run build:node -- --watch",
|
17
16
|
"preinstall": "[ \"$INIT_CWD\" != \"$PWD\" ] || npm_config_yes=true npx check-engine"
|
18
17
|
},
|
@@ -30,6 +29,9 @@
|
|
30
29
|
"node": ">= 14.0.0",
|
31
30
|
"npm": "7.x || 8.x"
|
32
31
|
},
|
32
|
+
"files": [
|
33
|
+
"dist/"
|
34
|
+
],
|
33
35
|
"repository": {
|
34
36
|
"type": "git",
|
35
37
|
"repository": "https://github.com/Financial-Times/dotcom-page-kit.git",
|
@@ -39,4 +41,4 @@
|
|
39
41
|
"volta": {
|
40
42
|
"extends": "../../package.json"
|
41
43
|
}
|
42
|
-
}
|
44
|
+
}
|
package/schema.md
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
# FT App Context Schema
|
2
|
-
|
3
|
-
The schema defines the following properties:
|
4
|
-
|
5
|
-
## `abTestState` (string)
|
6
|
-
|
7
|
-
The A/B test flags data as a comma delimited string
|
8
|
-
|
9
|
-
Additional restrictions:
|
10
|
-
|
11
|
-
* Regex pattern: `^,*([0-9A-Za-z-_]+:[0-9A-Za-z-_]+,*)+$`
|
12
|
-
|
13
|
-
## `appName` (string)
|
14
|
-
|
15
|
-
The name of the application
|
16
|
-
|
17
|
-
Additional restrictions:
|
18
|
-
|
19
|
-
* Regex pattern: `^.+$`
|
20
|
-
|
21
|
-
## `appVersion` (string)
|
22
|
-
|
23
|
-
The running version of the app (usually a Git commit hash)
|
24
|
-
|
25
|
-
Additional restrictions:
|
26
|
-
|
27
|
-
* Regex pattern: `^.+$`
|
28
|
-
|
29
|
-
## `conceptId` (string)
|
30
|
-
|
31
|
-
The UUID of the concept on the current page
|
32
|
-
|
33
|
-
Additional restrictions:
|
34
|
-
|
35
|
-
* Regex pattern: `^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$`
|
36
|
-
|
37
|
-
## `conceptType` (string)
|
38
|
-
|
39
|
-
The type of concept on the current page
|
40
|
-
|
41
|
-
Additional restrictions:
|
42
|
-
|
43
|
-
* Regex pattern: `^http://www.ft.com/ontology/.+$`
|
44
|
-
|
45
|
-
## `contentId` (string)
|
46
|
-
|
47
|
-
The UUID of the content on the current page
|
48
|
-
|
49
|
-
Additional restrictions:
|
50
|
-
|
51
|
-
* Regex pattern: `^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$`
|
52
|
-
|
53
|
-
## `contentType` (string)
|
54
|
-
|
55
|
-
The type or sub-type of the content on the current page
|
56
|
-
|
57
|
-
Additional restrictions:
|
58
|
-
|
59
|
-
* Regex pattern: `^(article|video|audio|podcast|package|live-blog)$`
|
60
|
-
|
61
|
-
## `edition` (string)
|
62
|
-
|
63
|
-
The selected FT edition
|
64
|
-
|
65
|
-
Additional restrictions:
|
66
|
-
|
67
|
-
* Regex pattern: `^(uk|international)$`
|
68
|
-
|
69
|
-
## `isProduction` (boolean)
|
70
|
-
|
71
|
-
If the app is currently running in a production environment
|
72
|
-
|
73
|
-
Default: `false`
|
74
|
-
|
75
|
-
## `isUserLoggedIn` (boolean)
|
76
|
-
|
77
|
-
If the visitor is signed in to an FT account
|
78
|
-
|
79
|
-
Default: `false`
|
80
|
-
|
81
|
-
## `product` (string)
|
82
|
-
|
83
|
-
The product name
|
84
|
-
|
85
|
-
Default: `"next"`
|
86
|
-
|
87
|
-
Additional restrictions:
|
88
|
-
|
89
|
-
* Regex pattern: `^.+$`
|
90
|
-
|
91
|
-
## `publishReference` (string)
|
92
|
-
|
93
|
-
The publish reference of the content on the current page
|
94
|
-
|
95
|
-
Additional restrictions:
|
96
|
-
|
97
|
-
* Regex pattern: `^.+$`
|
package/src/AppContext.ts
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
import { TAppContext } from './types'
|
2
|
-
import validate from './validate'
|
3
|
-
import filterEmptyData from './filterEmptyData'
|
4
|
-
|
5
|
-
export type TAppContextOptions = {
|
6
|
-
appContext?: Partial<TAppContext>
|
7
|
-
}
|
8
|
-
|
9
|
-
export class AppContext {
|
10
|
-
private data: Partial<TAppContext> = {}
|
11
|
-
|
12
|
-
constructor(options: TAppContextOptions = {}) {
|
13
|
-
const data = filterEmptyData({ ...options.appContext })
|
14
|
-
|
15
|
-
for (const [property, value] of Object.entries(data)) {
|
16
|
-
this.set(property, value)
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
get(property: string) {
|
21
|
-
return this.data[property]
|
22
|
-
}
|
23
|
-
|
24
|
-
set(property: string, value: any) {
|
25
|
-
if (validate(property, value)) {
|
26
|
-
this.data[property] = value
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
getAll(): Partial<TAppContext> {
|
31
|
-
return Object.freeze({ ...this.data })
|
32
|
-
}
|
33
|
-
}
|
package/src/filterEmptyData.ts
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
const isEmptyString = (value) => typeof value === 'string' && value.trim().length === 0
|
2
|
-
|
3
|
-
const isDefined = (value) => value !== undefined && value !== null
|
4
|
-
|
5
|
-
type AnyObject = {
|
6
|
-
[key: string]: any
|
7
|
-
}
|
8
|
-
|
9
|
-
export default function filterEmptyProperties(properties: AnyObject): AnyObject {
|
10
|
-
const result = {}
|
11
|
-
|
12
|
-
for (const [key, value] of Object.entries(properties)) {
|
13
|
-
if (isDefined(value) && !isEmptyString(value)) {
|
14
|
-
result[key] = value
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
return result
|
19
|
-
}
|
package/src/index.ts
DELETED
package/src/schema.json
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
3
|
-
"type": "object",
|
4
|
-
"title": "FT App Context Schema",
|
5
|
-
"properties": {
|
6
|
-
"abTestState": {
|
7
|
-
"type": "string",
|
8
|
-
"description": "The A/B test flags data as a comma delimited string",
|
9
|
-
"examples": ["subscriberCohort:on,premiumCohort:on,nonUSACohort:on"],
|
10
|
-
"pattern": "^,*([0-9A-Za-z-_]+:[0-9A-Za-z-_]+,*)+$"
|
11
|
-
},
|
12
|
-
"appName": {
|
13
|
-
"type": "string",
|
14
|
-
"description": "The name of the application",
|
15
|
-
"examples": ["front-page", "stream-page", "article-page"],
|
16
|
-
"pattern": "^.+$"
|
17
|
-
},
|
18
|
-
"appVersion": {
|
19
|
-
"type": "string",
|
20
|
-
"description": "The running version of the app (usually a Git commit hash)",
|
21
|
-
"examples": ["882797258625531f20d604f6441ef8cfcb2d772b"],
|
22
|
-
"pattern": "^.+$"
|
23
|
-
},
|
24
|
-
"conceptId": {
|
25
|
-
"type": "string",
|
26
|
-
"description": "The UUID of the concept on the current page",
|
27
|
-
"examples": ["c5935758-7730-11e9-bbad-7c18c0ea0201"],
|
28
|
-
"pattern": "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$"
|
29
|
-
},
|
30
|
-
"conceptType": {
|
31
|
-
"type": "string",
|
32
|
-
"description": "The type of concept on the current page",
|
33
|
-
"examples": ["http://www.ft.com/ontology/product/Brand", "http://www.ft.com/ontology/Location"],
|
34
|
-
"pattern": "^http://www.ft.com/ontology/.+$"
|
35
|
-
},
|
36
|
-
"contentId": {
|
37
|
-
"type": "string",
|
38
|
-
"description": "The UUID of the content on the current page",
|
39
|
-
"examples": ["c5935758-7730-11e9-bbad-7c18c0ea0201"],
|
40
|
-
"pattern": "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$"
|
41
|
-
},
|
42
|
-
"contentType": {
|
43
|
-
"type": "string",
|
44
|
-
"description": "The type or sub-type of the content on the current page",
|
45
|
-
"examples": ["article", "video", "audio", "podcast", "package", "live-blog"],
|
46
|
-
"pattern": "^(article|video|audio|podcast|package|live-blog)$"
|
47
|
-
},
|
48
|
-
"edition": {
|
49
|
-
"type": "string",
|
50
|
-
"description": "The selected FT edition",
|
51
|
-
"examples": ["uk", "international"],
|
52
|
-
"pattern": "^(uk|international)$"
|
53
|
-
},
|
54
|
-
"isProduction": {
|
55
|
-
"type": "boolean",
|
56
|
-
"description": "If the app is currently running in a production environment",
|
57
|
-
"default": false
|
58
|
-
},
|
59
|
-
"isUserLoggedIn": {
|
60
|
-
"type": "boolean",
|
61
|
-
"description": "If the visitor is signed in to an FT account",
|
62
|
-
"default": false
|
63
|
-
},
|
64
|
-
"product": {
|
65
|
-
"type": "string",
|
66
|
-
"description": "The product name",
|
67
|
-
"default": "next",
|
68
|
-
"pattern": "^.+$"
|
69
|
-
},
|
70
|
-
"publishReference": {
|
71
|
-
"type": "string",
|
72
|
-
"description": "The publish reference of the content on the current page",
|
73
|
-
"examples": [
|
74
|
-
"tid_17wmwszvk3",
|
75
|
-
"SYNTHETIC-REQ-MONtid_UrnYVM6Waz_carousel_1534570047",
|
76
|
-
"republish_-453878e5-94e5-4e52-bfba-b16b024f31f8_carousel_1577700591"
|
77
|
-
],
|
78
|
-
"pattern": "^.+$"
|
79
|
-
},
|
80
|
-
"pageKitVersion": {
|
81
|
-
"type": "string",
|
82
|
-
"description": "The version of Page Kit powering the app",
|
83
|
-
"examples": ["1.0.0"],
|
84
|
-
"pattern": "^.+$"
|
85
|
-
}
|
86
|
-
},
|
87
|
-
"additionalProperties": false
|
88
|
-
}
|
package/src/types.d.ts
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
export interface TAppContext {
|
2
|
-
appName: string
|
3
|
-
appVersion: string
|
4
|
-
product: string
|
5
|
-
edition: string
|
6
|
-
abTestState: string
|
7
|
-
contentId?: string
|
8
|
-
contentType?: string
|
9
|
-
conceptId?: string
|
10
|
-
conceptType?: string
|
11
|
-
isProduction: boolean
|
12
|
-
isUserLoggedIn?: boolean
|
13
|
-
publishReference?: string
|
14
|
-
[key: string]: any
|
15
|
-
}
|
package/src/validate.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import Ajv from 'ajv'
|
2
|
-
import schema from './schema.json'
|
3
|
-
|
4
|
-
const ajv = new Ajv()
|
5
|
-
|
6
|
-
const isValid = ajv.compile(schema)
|
7
|
-
|
8
|
-
export default function validate(field: string, value): boolean {
|
9
|
-
const data = { [field]: value }
|
10
|
-
|
11
|
-
if (isValid(data)) {
|
12
|
-
return true
|
13
|
-
} else {
|
14
|
-
let errorMessage = `Validation error: ${ajv.errorsText(isValid.errors)}, received "${value}"`
|
15
|
-
const hasErrorsForAdditionProperties = isValid.errors.some(
|
16
|
-
(error) => error.keyword === 'additionalProperties'
|
17
|
-
)
|
18
|
-
if (hasErrorsForAdditionProperties) {
|
19
|
-
errorMessage +=
|
20
|
-
'\nIf you want to share application specific data with the client, consider using @financial-times/dotcom-ui-data-embed.'
|
21
|
-
}
|
22
|
-
throw Error(errorMessage)
|
23
|
-
}
|
24
|
-
}
|