@financial-times/privacy-legislation-client 1.2.0 → 2.0.0

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/package.json CHANGED
@@ -1,21 +1,30 @@
1
1
  {
2
2
  "name": "@financial-times/privacy-legislation-client",
3
3
  "description": "",
4
- "version": "1.2.0",
5
- "main": "dist/cjs/main.js",
6
- "module": "dist/esm/main.js",
7
- "types": "dist/cjs/main.d.ts",
4
+ "version": "2.0.0",
8
5
  "private": false,
6
+ "type": "module",
7
+ "types": "./dist/main.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/main.js",
14
+ "require": "./dist/main.cjs"
15
+ }
16
+ },
9
17
  "devDependencies": {
10
18
  "jest-fetch-mock": "^3.0.3",
11
- "npm-run-all": "4.1.5"
19
+ "jsdom": "^22.1.0",
20
+ "msw": "^1.3.2",
21
+ "npm-run-all": "4.1.5",
22
+ "vite": "^4.5.0",
23
+ "vite-plugin-dts": "^3.6.0",
24
+ "vitest": "^0.34.6"
12
25
  },
13
26
  "scripts": {
14
- "test": "jest",
15
- "clean": "rm -rf ./dist",
16
- "build:browser": "npx tsc --module es2015 --outDir ./dist/esm",
17
- "build:node": "npx tsc --module commonjs --outDir ./dist/cjs",
18
- "prebuild": "npm run clean",
19
- "build": "run-p build:*"
27
+ "build": "vite build",
28
+ "test": "vitest"
20
29
  }
21
30
  }
Binary file
@@ -1,28 +0,0 @@
1
- export declare const API_URL = "https://privacy.ft.com/api/v1";
2
- export declare const API_ENDPOINTS: {
3
- complianceRegion: string;
4
- };
5
- export type RegionalCompliance = {
6
- region: string;
7
- legislation: Set<string>;
8
- };
9
- type Props = {
10
- url: string;
11
- legislation: Set<string>;
12
- referrer?: string;
13
- };
14
- /**
15
- * Return a promise resolving to an object containing information about the
16
- * user's legal protections: *
17
- * - region: A string consisting of a country code or country-region ("GB", "US-CA")
18
- * - legislation: A Set of the applicable legislationIds
19
- */
20
- export declare function fetchLegislation(): Promise<RegionalCompliance>;
21
- /**
22
- * Embed legislationIds and referrer as params to `url`
23
- * Allows customisation (e.g. skinning, granularity of consent, etc) of the destination page
24
- *
25
- * This method provides a standardised way to interface with x-privacy-manager
26
- */
27
- export declare function buildConsentPageUrl({ url, legislation, referrer }: Props): string;
28
- export {};
package/dist/cjs/main.js DELETED
@@ -1,84 +0,0 @@
1
- "use strict";
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.buildConsentPageUrl = exports.fetchLegislation = exports.API_ENDPOINTS = exports.API_URL = void 0;
5
- exports.API_URL = "https://privacy.ft.com/api/v1";
6
- exports.API_ENDPOINTS = {
7
- complianceRegion: "/compliance-region.json",
8
- };
9
- function formatResponse(obj) {
10
- return {
11
- region: obj.region,
12
- legislation: new Set(obj.legislation.split(",")),
13
- };
14
- }
15
- function sessionStorageOk() {
16
- const test = "test";
17
- try {
18
- sessionStorage.setItem(test, test);
19
- sessionStorage.removeItem(test);
20
- return true;
21
- }
22
- catch (e) {
23
- return false;
24
- }
25
- }
26
- function getHostname(referrer) {
27
- if (referrer) {
28
- try {
29
- return new URL(referrer).hostname;
30
- }
31
- catch (err) {
32
- return referrer;
33
- }
34
- }
35
- return typeof window === "undefined" ? "" : window.location.hostname;
36
- }
37
- /**
38
- * Return a promise resolving to an object containing information about the
39
- * user's legal protections: *
40
- * - region: A string consisting of a country code or country-region ("GB", "US-CA")
41
- * - legislation: A Set of the applicable legislationIds
42
- */
43
- async function fetchLegislation() {
44
- // Look in session storage first
45
- const complianceStr = sessionStorageOk() && sessionStorage.getItem("user-compliance");
46
- const complianceObj = complianceStr && JSON.parse(complianceStr);
47
- if (complianceObj) {
48
- return Promise.resolve(formatResponse(complianceObj));
49
- }
50
- // Not found in session storage, fetch from API
51
- else {
52
- try {
53
- const url = `${exports.API_URL}${exports.API_ENDPOINTS.complianceRegion}`;
54
- const res = await fetch(url);
55
- const compliance = await (res.ok ? res.json() : Promise.reject(res));
56
- if (sessionStorageOk()) {
57
- sessionStorage.setItem("user-compliance", JSON.stringify(compliance));
58
- }
59
- return formatResponse(compliance);
60
- }
61
- catch (err) {
62
- throw new Error(err.status);
63
- }
64
- }
65
- }
66
- exports.fetchLegislation = fetchLegislation;
67
- /**
68
- * Embed legislationIds and referrer as params to `url`
69
- * Allows customisation (e.g. skinning, granularity of consent, etc) of the destination page
70
- *
71
- * This method provides a standardised way to interface with x-privacy-manager
72
- */
73
- function buildConsentPageUrl({ url, legislation, referrer }) {
74
- const decoratedUrl = new URL(url);
75
- const hostname = getHostname(referrer);
76
- for (const id of legislation) {
77
- decoratedUrl.searchParams.append("legislation", id);
78
- }
79
- if (hostname) {
80
- decoratedUrl.searchParams.set("referrer", hostname.toLowerCase());
81
- }
82
- return decoratedUrl.toString();
83
- }
84
- exports.buildConsentPageUrl = buildConsentPageUrl;
@@ -1,28 +0,0 @@
1
- export declare const API_URL = "https://privacy.ft.com/api/v1";
2
- export declare const API_ENDPOINTS: {
3
- complianceRegion: string;
4
- };
5
- export type RegionalCompliance = {
6
- region: string;
7
- legislation: Set<string>;
8
- };
9
- type Props = {
10
- url: string;
11
- legislation: Set<string>;
12
- referrer?: string;
13
- };
14
- /**
15
- * Return a promise resolving to an object containing information about the
16
- * user's legal protections: *
17
- * - region: A string consisting of a country code or country-region ("GB", "US-CA")
18
- * - legislation: A Set of the applicable legislationIds
19
- */
20
- export declare function fetchLegislation(): Promise<RegionalCompliance>;
21
- /**
22
- * Embed legislationIds and referrer as params to `url`
23
- * Allows customisation (e.g. skinning, granularity of consent, etc) of the destination page
24
- *
25
- * This method provides a standardised way to interface with x-privacy-manager
26
- */
27
- export declare function buildConsentPageUrl({ url, legislation, referrer }: Props): string;
28
- export {};
package/dist/esm/main.js DELETED
@@ -1,79 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- export const API_URL = "https://privacy.ft.com/api/v1";
3
- export const API_ENDPOINTS = {
4
- complianceRegion: "/compliance-region.json",
5
- };
6
- function formatResponse(obj) {
7
- return {
8
- region: obj.region,
9
- legislation: new Set(obj.legislation.split(",")),
10
- };
11
- }
12
- function sessionStorageOk() {
13
- const test = "test";
14
- try {
15
- sessionStorage.setItem(test, test);
16
- sessionStorage.removeItem(test);
17
- return true;
18
- }
19
- catch (e) {
20
- return false;
21
- }
22
- }
23
- function getHostname(referrer) {
24
- if (referrer) {
25
- try {
26
- return new URL(referrer).hostname;
27
- }
28
- catch (err) {
29
- return referrer;
30
- }
31
- }
32
- return typeof window === "undefined" ? "" : window.location.hostname;
33
- }
34
- /**
35
- * Return a promise resolving to an object containing information about the
36
- * user's legal protections: *
37
- * - region: A string consisting of a country code or country-region ("GB", "US-CA")
38
- * - legislation: A Set of the applicable legislationIds
39
- */
40
- export async function fetchLegislation() {
41
- // Look in session storage first
42
- const complianceStr = sessionStorageOk() && sessionStorage.getItem("user-compliance");
43
- const complianceObj = complianceStr && JSON.parse(complianceStr);
44
- if (complianceObj) {
45
- return Promise.resolve(formatResponse(complianceObj));
46
- }
47
- // Not found in session storage, fetch from API
48
- else {
49
- try {
50
- const url = `${API_URL}${API_ENDPOINTS.complianceRegion}`;
51
- const res = await fetch(url);
52
- const compliance = await (res.ok ? res.json() : Promise.reject(res));
53
- if (sessionStorageOk()) {
54
- sessionStorage.setItem("user-compliance", JSON.stringify(compliance));
55
- }
56
- return formatResponse(compliance);
57
- }
58
- catch (err) {
59
- throw new Error(err.status);
60
- }
61
- }
62
- }
63
- /**
64
- * Embed legislationIds and referrer as params to `url`
65
- * Allows customisation (e.g. skinning, granularity of consent, etc) of the destination page
66
- *
67
- * This method provides a standardised way to interface with x-privacy-manager
68
- */
69
- export function buildConsentPageUrl({ url, legislation, referrer }) {
70
- const decoratedUrl = new URL(url);
71
- const hostname = getHostname(referrer);
72
- for (const id of legislation) {
73
- decoratedUrl.searchParams.append("legislation", id);
74
- }
75
- if (hostname) {
76
- decoratedUrl.searchParams.set("referrer", hostname.toLowerCase());
77
- }
78
- return decoratedUrl.toString();
79
- }
package/src/main.ts DELETED
@@ -1,98 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
-
3
- export const API_URL = "https://privacy.ft.com/api/v1";
4
- export const API_ENDPOINTS = {
5
- complianceRegion: "/compliance-region.json",
6
- };
7
-
8
- export type RegionalCompliance = {
9
- region: string;
10
- legislation: Set<string>;
11
- };
12
-
13
- type Props = {
14
- url: string;
15
- legislation: Set<string>;
16
- referrer?: string;
17
- };
18
-
19
- function formatResponse(obj: { region: string; legislation: "string" }): RegionalCompliance {
20
- return {
21
- region: obj.region,
22
- legislation: new Set<string>(obj.legislation.split(",")),
23
- };
24
- }
25
-
26
- function sessionStorageOk(): boolean {
27
- const test = "test";
28
- try {
29
- sessionStorage.setItem(test, test);
30
- sessionStorage.removeItem(test);
31
- return true;
32
- } catch (e) {
33
- return false;
34
- }
35
- }
36
-
37
- function getHostname(referrer?: string): string {
38
- if (referrer) {
39
- try {
40
- return new URL(referrer).hostname;
41
- } catch (err) {
42
- return referrer;
43
- }
44
- }
45
-
46
- return typeof window === "undefined" ? "" : window.location.hostname;
47
- }
48
-
49
- /**
50
- * Return a promise resolving to an object containing information about the
51
- * user's legal protections: *
52
- * - region: A string consisting of a country code or country-region ("GB", "US-CA")
53
- * - legislation: A Set of the applicable legislationIds
54
- */
55
- export async function fetchLegislation(): Promise<RegionalCompliance> {
56
- // Look in session storage first
57
- const complianceStr = sessionStorageOk() && sessionStorage.getItem("user-compliance");
58
- const complianceObj = complianceStr && JSON.parse(complianceStr);
59
- if (complianceObj) {
60
- return Promise.resolve(formatResponse(complianceObj));
61
- }
62
- // Not found in session storage, fetch from API
63
- else {
64
- try {
65
- const url = `${API_URL}${API_ENDPOINTS.complianceRegion}`;
66
- const res = await fetch(url);
67
- const compliance = await (res.ok ? res.json() : Promise.reject(res));
68
- if (sessionStorageOk()) {
69
- sessionStorage.setItem("user-compliance", JSON.stringify(compliance));
70
- }
71
-
72
- return formatResponse(compliance);
73
- } catch (err: any) {
74
- throw new Error(err.status);
75
- }
76
- }
77
- }
78
-
79
- /**
80
- * Embed legislationIds and referrer as params to `url`
81
- * Allows customisation (e.g. skinning, granularity of consent, etc) of the destination page
82
- *
83
- * This method provides a standardised way to interface with x-privacy-manager
84
- */
85
- export function buildConsentPageUrl({ url, legislation, referrer }: Props): string {
86
- const decoratedUrl = new URL(url);
87
- const hostname = getHostname(referrer);
88
-
89
- for (const id of legislation) {
90
- decoratedUrl.searchParams.append("legislation", id);
91
- }
92
-
93
- if (hostname) {
94
- decoratedUrl.searchParams.set("referrer", hostname.toLowerCase());
95
- }
96
-
97
- return decoratedUrl.toString();
98
- }
@@ -1,131 +0,0 @@
1
- import fetch from "jest-fetch-mock";
2
-
3
- fetch.enableMocks();
4
-
5
- import { fetchLegislation, buildConsentPageUrl } from "../main";
6
-
7
- describe("fetchLegislation()", function () {
8
- const payload = {
9
- region: "US-CA",
10
- legislation: "ccpa,gdpr",
11
- };
12
-
13
- describe("no referrer", () => {
14
- beforeEach(() => {
15
- sessionStorage.clear();
16
- fetch.mockResponse(JSON.stringify(payload));
17
- });
18
-
19
- afterEach(() => {
20
- fetch.resetMocks();
21
- });
22
-
23
- it("returns a Set of legislation ids", async function () {
24
- const { region, legislation } = await fetchLegislation();
25
- const consentPageUrl = buildConsentPageUrl({
26
- url: "https://privacy.ft.com/consent",
27
- legislation,
28
- });
29
-
30
- expect(region).toEqual("US-CA");
31
- expect(legislation).toEqual(new Set(["ccpa", "gdpr"]));
32
- const matchRegex = /(https:\/\/privacy.ft.com\/consent\?legislation=ccpa&legislation=gdpr)&referrer=www.ft.com$/;
33
- expect(matchRegex.test(consentPageUrl)).toBeTruthy();
34
- });
35
- });
36
-
37
- describe("With referrer", () => {
38
- beforeEach(() => {
39
- sessionStorage.clear();
40
- fetch.mockResponse(
41
- JSON.stringify({
42
- region: "GB",
43
- legislation: "gdpr",
44
- })
45
- );
46
- });
47
-
48
- afterEach(() => {
49
- fetch.resetMocks();
50
- });
51
-
52
- it("Handles valid URL", async function () {
53
- const referrer =
54
- "https://www.thebanker.com/World/Middle-East/Saudi-Arabia/Will-the-pandemic-stymie-Saudi-Arabia-s-reform-agenda?ct=true";
55
-
56
- const { region, legislation } = await fetchLegislation();
57
- const consentPageUrl = buildConsentPageUrl({
58
- url: "https://privacy.ft.com/consent",
59
- legislation,
60
- referrer,
61
- });
62
-
63
- expect(region).toBe("GB");
64
- expect(legislation).toEqual(new Set(["gdpr"]));
65
- expect(consentPageUrl).toBe(
66
- "https://privacy.ft.com/consent?legislation=gdpr&referrer=www.thebanker.com"
67
- );
68
- });
69
-
70
- it("Handles invalid URLs", async function () {
71
- const { region, legislation } = await fetchLegislation();
72
- const consentPageUrl = buildConsentPageUrl({
73
- url: "https://privacy.ft.com/consent",
74
- legislation,
75
- referrer: "FT-App",
76
- });
77
-
78
- expect(region).toEqual("GB");
79
- expect(legislation).toEqual(new Set(["gdpr"]));
80
- expect(consentPageUrl).toBe(
81
- "https://privacy.ft.com/consent?legislation=gdpr&referrer=ft-app"
82
- );
83
- });
84
- });
85
-
86
- describe("sessionStorage available", () => {
87
- beforeEach(() => {
88
- sessionStorage.clear();
89
- fetch.mockResponse(
90
- JSON.stringify({
91
- region: "US-CA",
92
- legislation: "ccpa,gdpr",
93
- })
94
- );
95
- });
96
-
97
- afterEach(() => {
98
- fetch.resetMocks();
99
- });
100
-
101
- test("should fetch from sessionStorage if available", async () => {
102
- sessionStorage.setItem(
103
- "user-compliance",
104
- JSON.stringify({
105
- region: "US-CA",
106
- legislation: "ccpa,gdpr",
107
- })
108
- );
109
- const { region, legislation } = await fetchLegislation();
110
-
111
- expect(region).toBe("US-CA");
112
- expect(legislation).toEqual(new Set(["ccpa", "gdpr"]));
113
- expect(fetch.mock.calls.length).toEqual(0);
114
- });
115
-
116
- test("should set sessionStorage item after fetch", async () => {
117
- const { region, legislation } = await fetchLegislation();
118
-
119
- const ssItemStr = sessionStorage.getItem("user-compliance");
120
- const ssItemObj = ssItemStr && JSON.parse(ssItemStr);
121
-
122
- expect(region).toBe("US-CA");
123
- expect(legislation).toEqual(new Set(["ccpa", "gdpr"]));
124
- expect(fetch.mock.calls.length).toEqual(1);
125
- expect(ssItemObj).toEqual({
126
- region: "US-CA",
127
- legislation: "ccpa,gdpr",
128
- });
129
- });
130
- });
131
- });
package/tsconfig.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "./src/"
5
- }
6
- }