@tgwf/co2 0.9.0 → 0.10.2

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 (92) hide show
  1. package/.esbuild.browser.js +11 -0
  2. package/.esbuild.esm.js +25 -0
  3. package/.esbuild.node.js +16 -0
  4. package/.gitpod.yml +8 -0
  5. package/CHANGELOG.md +22 -1
  6. package/README.md +29 -66
  7. package/dist/cjs/1byte.js +52 -0
  8. package/dist/cjs/1byte.js.map +7 -0
  9. package/dist/cjs/1byte.test.js +27 -0
  10. package/dist/cjs/1byte.test.js.map +7 -0
  11. package/dist/cjs/co2.js +121 -0
  12. package/dist/cjs/co2.js.map +7 -0
  13. package/dist/cjs/co2.test.js +258 -0
  14. package/dist/cjs/co2.test.js.map +7 -0
  15. package/dist/cjs/constants/file-size.js +27 -0
  16. package/dist/cjs/constants/file-size.js.map +7 -0
  17. package/dist/cjs/constants/index.js +27 -0
  18. package/dist/cjs/constants/index.js.map +7 -0
  19. package/dist/cjs/helpers/index.js +24 -0
  20. package/dist/cjs/helpers/index.js.map +7 -0
  21. package/dist/cjs/hosting-api.js +64 -0
  22. package/dist/cjs/hosting-api.js.map +7 -0
  23. package/dist/cjs/hosting-api.test.js +47 -0
  24. package/dist/cjs/hosting-api.test.js.map +7 -0
  25. package/dist/cjs/hosting-database.node.test.js +36 -0
  26. package/dist/cjs/hosting-database.node.test.js.map +7 -0
  27. package/dist/cjs/hosting-json.node.js +73 -0
  28. package/dist/cjs/hosting-json.node.js.map +7 -0
  29. package/dist/cjs/hosting-json.node.test.js +43 -0
  30. package/dist/cjs/hosting-json.node.test.js.map +7 -0
  31. package/dist/cjs/hosting-node.js +78 -0
  32. package/dist/cjs/hosting-node.js.map +7 -0
  33. package/dist/cjs/hosting.js +36 -0
  34. package/dist/cjs/hosting.js.map +7 -0
  35. package/dist/cjs/hosting.test.js +74 -0
  36. package/dist/cjs/hosting.test.js.map +7 -0
  37. package/dist/cjs/index-node.js +29 -0
  38. package/dist/cjs/index-node.js.map +7 -0
  39. package/dist/cjs/index.js +31 -0
  40. package/dist/cjs/index.js.map +7 -0
  41. package/dist/cjs/package.json +3 -0
  42. package/dist/cjs/sustainable-web-design.js +134 -0
  43. package/dist/cjs/sustainable-web-design.js.map +7 -0
  44. package/dist/cjs/sustainable-web-design.test.js +79 -0
  45. package/dist/cjs/sustainable-web-design.test.js.map +7 -0
  46. package/dist/esm/1byte.js +32 -0
  47. package/dist/esm/1byte.test.js +11 -0
  48. package/dist/esm/co2.js +98 -0
  49. package/{src → dist/esm}/co2.test.js +47 -94
  50. package/dist/esm/constants/file-size.js +7 -0
  51. package/dist/esm/constants/index.js +4 -0
  52. package/dist/esm/helpers/index.js +4 -0
  53. package/dist/esm/hosting-api.js +41 -0
  54. package/dist/esm/hosting-api.test.js +31 -0
  55. package/{src/hosting-database.test.js → dist/esm/hosting-database.node.test.js} +7 -18
  56. package/{src/hosting-json.test.js → dist/esm/hosting-json.node.test.js} +4 -21
  57. package/dist/esm/hosting.js +13 -0
  58. package/{src → dist/esm}/hosting.test.js +10 -30
  59. package/dist/esm/index.js +8 -0
  60. package/dist/esm/package.json +3 -0
  61. package/dist/esm/sustainable-web-design.js +111 -0
  62. package/{src → dist/esm}/sustainable-web-design.test.js +19 -37
  63. package/dist/iife/index.js +2 -0
  64. package/dist/iife/index.js.map +7 -0
  65. package/fixup +19 -0
  66. package/package.json +38 -17
  67. package/public/index.html +58 -0
  68. package/public/index.js +2 -0
  69. package/src/1byte.js +2 -3
  70. package/src/co2.js +17 -18
  71. package/src/constants/file-size.js +2 -2
  72. package/src/constants/index.js +2 -2
  73. package/src/helpers/index.js +1 -3
  74. package/src/hosting-api.js +23 -43
  75. package/src/{hosting-json.js → hosting-json.node.js} +9 -11
  76. package/src/hosting-node.js +94 -0
  77. package/src/hosting.js +6 -28
  78. package/src/index-node.js +4 -0
  79. package/src/index.js +4 -6
  80. package/src/sustainable-web-design.js +37 -11
  81. package/.eslintrc.json +0 -21
  82. package/.github/workflows/unittests.yml +0 -26
  83. package/data/Lean-ICT-Materials-1byte-Model-2018.xlsx +0 -0
  84. package/data/Lean-ICT-Materials-Forecast-Model-2018.xlsx +0 -0
  85. package/data/fixtures/tgwf.har +0 -6107
  86. package/data/fixtures/url2green.test.db +0 -0
  87. package/data/fixtures/url2green.test.json +0 -1
  88. package/data/fixtures/url2green.test.json.gz +0 -0
  89. package/images/swd-energy-usage.png +0 -0
  90. package/src/1byte.test.js +0 -17
  91. package/src/green-byte.js +0 -26
  92. package/src/hosting-api.test.js +0 -37
@@ -0,0 +1,79 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __copyProps = (to, from, except, desc) => {
8
+ if (from && typeof from === "object" || typeof from === "function") {
9
+ for (let key of __getOwnPropNames(from))
10
+ if (!__hasOwnProp.call(to, key) && key !== except)
11
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
12
+ }
13
+ return to;
14
+ };
15
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
16
+ var import_sustainable_web_design = __toESM(require("./sustainable-web-design.js"));
17
+ describe("sustainable web design model", () => {
18
+ const swd = new import_sustainable_web_design.default();
19
+ const averageWebsiteInBytes = 22577152e-1;
20
+ describe("energyPerByteByComponent", () => {
21
+ it("should return a object with numbers for each system component", () => {
22
+ const groupedEnergy = swd.energyPerByteByComponent(averageWebsiteInBytes);
23
+ expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(95095e-8, 8);
24
+ expect(groupedEnergy.networkEnergy).toBeCloseTo(25602e-8, 7);
25
+ expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(27431e-8, 8);
26
+ expect(groupedEnergy.productionEnergy).toBeCloseTo(3475e-7, 7);
27
+ });
28
+ });
29
+ describe("energyPerByte", () => {
30
+ it("should return a number in kilowatt hours for the given data transfer in bytes", () => {
31
+ const energyForTransfer = swd.energyPerByte(averageWebsiteInBytes);
32
+ expect(energyForTransfer).toBeCloseTo(182874e-8, 7);
33
+ });
34
+ });
35
+ describe("perByte", () => {
36
+ it("should return a single number for CO2 emissions", () => {
37
+ expect(typeof swd.perByte(22577152e-1)).toBe("number");
38
+ });
39
+ });
40
+ describe("energyPerVisit", () => {
41
+ it("should return a number", () => {
42
+ expect(typeof swd.energyPerVisit(averageWebsiteInBytes)).toBe("number");
43
+ });
44
+ it("should calculate the correct energy", () => {
45
+ expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(0.0013807057305600004);
46
+ });
47
+ });
48
+ describe("emissionsPerVisitInGrams", () => {
49
+ it("should calculate the correct co2 per visit", () => {
50
+ const energy = swd.energyPerVisit(averageWebsiteInBytes);
51
+ expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.61);
52
+ });
53
+ it("should accept a dynamic KwH value", () => {
54
+ const energy = swd.energyPerVisit(averageWebsiteInBytes);
55
+ expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.34);
56
+ });
57
+ });
58
+ describe("annualEnergyInKwh", () => {
59
+ it("should calculate the correct energy in kWh", () => {
60
+ expect(swd.annualEnergyInKwh(averageWebsiteInBytes)).toBe(27092582400);
61
+ });
62
+ });
63
+ describe("annualEmissionsInGrams", () => {
64
+ it("should calculate the corrent energy in grams", () => {
65
+ expect(swd.annualEmissionsInGrams(averageWebsiteInBytes)).toBe(27092582400);
66
+ });
67
+ });
68
+ describe("annualSegmentEnergy", () => {
69
+ it("should return the correct values", () => {
70
+ expect(swd.annualSegmentEnergy(averageWebsiteInBytes)).toEqual({
71
+ consumerDeviceEnergy: 11740119e-1,
72
+ dataCenterEnergy: 338657.28,
73
+ networkEnergy: 316080.13,
74
+ productionEnergy: 428965.89
75
+ });
76
+ });
77
+ });
78
+ });
79
+ //# sourceMappingURL=sustainable-web-design.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sustainable-web-design.test.js"],
4
+ "sourcesContent": ["import SustainableWebDesign from \"./sustainable-web-design.js\";\n\ndescribe(\"sustainable web design model\", () => {\n const swd = new SustainableWebDesign();\n const averageWebsiteInBytes = 2257715.2;\n\n describe(\"energyPerByteByComponent\", () => {\n it(\"should return a object with numbers for each system component\", () => {\n // Compare these with the carbon intensity tab C7-C10.\n // https://docs.google.com/spreadsheets/d/1eFlHhSBus_HqmoXqX237eAYr0PREUhTr6YBxznQC4jI/edit#gid=0\n\n // These numbers should match the spreadsheet\n const groupedEnergy = swd.energyPerByteByComponent(averageWebsiteInBytes);\n expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(0.00095095, 8);\n expect(groupedEnergy.networkEnergy).toBeCloseTo(0.00025602, 7);\n expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(0.00027431, 8);\n expect(groupedEnergy.productionEnergy).toBeCloseTo(0.0003475, 7);\n });\n });\n\n describe(\"energyPerByte\", () => {\n it(\"should return a number in kilowatt hours for the given data transfer in bytes\", () => {\n const energyForTransfer = swd.energyPerByte(averageWebsiteInBytes);\n expect(energyForTransfer).toBeCloseTo(0.00182874, 7);\n });\n });\n\n describe(\"perByte\", () => {\n it(\"should return a single number for CO2 emissions\", () => {\n expect(typeof swd.perByte(2257715.2)).toBe(\"number\");\n });\n });\n\n describe(\"energyPerVisit\", () => {\n it(\"should return a number\", () => {\n expect(typeof swd.energyPerVisit(averageWebsiteInBytes)).toBe(\"number\");\n });\n\n it(\"should calculate the correct energy\", () => {\n expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(\n 0.0013807057305600004\n );\n });\n });\n\n describe(\"emissionsPerVisitInGrams\", () => {\n it(\"should calculate the correct co2 per visit\", () => {\n const energy = swd.energyPerVisit(averageWebsiteInBytes);\n expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.61);\n });\n\n it(\"should accept a dynamic KwH value\", () => {\n const energy = swd.energyPerVisit(averageWebsiteInBytes);\n expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.34);\n });\n });\n\n describe(\"annualEnergyInKwh\", () => {\n it(\"should calculate the correct energy in kWh\", () => {\n expect(swd.annualEnergyInKwh(averageWebsiteInBytes)).toBe(27092582400);\n });\n });\n\n describe(\"annualEmissionsInGrams\", () => {\n it(\"should calculate the corrent energy in grams\", () => {\n expect(swd.annualEmissionsInGrams(averageWebsiteInBytes)).toBe(\n 27092582400\n );\n });\n });\n\n describe(\"annualSegmentEnergy\", () => {\n it(\"should return the correct values\", () => {\n expect(swd.annualSegmentEnergy(averageWebsiteInBytes)).toEqual({\n consumerDeviceEnergy: 1174011.9,\n dataCenterEnergy: 338657.28,\n networkEnergy: 316080.13,\n productionEnergy: 428965.89,\n });\n });\n });\n});\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;AAAA,oCAAiC;AAEjC,SAAS,gCAAgC,MAAM;AAC7C,QAAM,MAAM,IAAI,sCAAqB;AACrC,QAAM,wBAAwB;AAE9B,WAAS,4BAA4B,MAAM;AACzC,OAAG,iEAAiE,MAAM;AAKxE,YAAM,gBAAgB,IAAI,yBAAyB,qBAAqB;AACxE,aAAO,cAAc,oBAAoB,EAAE,YAAY,UAAY,CAAC;AACpE,aAAO,cAAc,aAAa,EAAE,YAAY,UAAY,CAAC;AAC7D,aAAO,cAAc,gBAAgB,EAAE,YAAY,UAAY,CAAC;AAChE,aAAO,cAAc,gBAAgB,EAAE,YAAY,SAAW,CAAC;AAAA,IACjE,CAAC;AAAA,EACH,CAAC;AAED,WAAS,iBAAiB,MAAM;AAC9B,OAAG,iFAAiF,MAAM;AACxF,YAAM,oBAAoB,IAAI,cAAc,qBAAqB;AACjE,aAAO,iBAAiB,EAAE,YAAY,WAAY,CAAC;AAAA,IACrD,CAAC;AAAA,EACH,CAAC;AAED,WAAS,WAAW,MAAM;AACxB,OAAG,mDAAmD,MAAM;AAC1D,aAAO,OAAO,IAAI,QAAQ,WAAS,CAAC,EAAE,KAAK,QAAQ;AAAA,IACrD,CAAC;AAAA,EACH,CAAC;AAED,WAAS,kBAAkB,MAAM;AAC/B,OAAG,0BAA0B,MAAM;AACjC,aAAO,OAAO,IAAI,eAAe,qBAAqB,CAAC,EAAE,KAAK,QAAQ;AAAA,IACxE,CAAC;AAED,OAAG,uCAAuC,MAAM;AAC9C,aAAO,IAAI,eAAe,qBAAqB,CAAC,EAAE,KAChD,qBACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,WAAS,4BAA4B,MAAM;AACzC,OAAG,8CAA8C,MAAM;AACrD,YAAM,SAAS,IAAI,eAAe,qBAAqB;AACvD,aAAO,IAAI,yBAAyB,MAAM,CAAC,EAAE,QAAQ,IAAI;AAAA,IAC3D,CAAC;AAED,OAAG,qCAAqC,MAAM;AAC5C,YAAM,SAAS,IAAI,eAAe,qBAAqB;AACvD,aAAO,IAAI,yBAAyB,QAAQ,GAAG,CAAC,EAAE,QAAQ,IAAI;AAAA,IAChE,CAAC;AAAA,EACH,CAAC;AAED,WAAS,qBAAqB,MAAM;AAClC,OAAG,8CAA8C,MAAM;AACrD,aAAO,IAAI,kBAAkB,qBAAqB,CAAC,EAAE,KAAK,WAAW;AAAA,IACvE,CAAC;AAAA,EACH,CAAC;AAED,WAAS,0BAA0B,MAAM;AACvC,OAAG,gDAAgD,MAAM;AACvD,aAAO,IAAI,uBAAuB,qBAAqB,CAAC,EAAE,KACxD,WACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,WAAS,uBAAuB,MAAM;AACpC,OAAG,oCAAoC,MAAM;AAC3C,aAAO,IAAI,oBAAoB,qBAAqB,CAAC,EAAE,QAAQ;AAAA,QAC7D,sBAAsB;AAAA,QACtB,kBAAkB;AAAA,QAClB,eAAe;AAAA,QACf,kBAAkB;AAAA,MACpB,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH,CAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ const CO2_PER_KWH_IN_DC_GREY = 519;
2
+ const CO2_PER_KWH_NETWORK_GREY = 475;
3
+ const CO2_PER_KWH_IN_DC_GREEN = 0;
4
+ const KWH_PER_BYTE_IN_DC = 72e-12;
5
+ const FIXED_NETWORK_WIRED = 429e-12;
6
+ const FIXED_NETWORK_WIFI = 152e-12;
7
+ const FOUR_G_MOBILE = 884e-12;
8
+ const KWH_PER_BYTE_FOR_NETWORK = (FIXED_NETWORK_WIRED + FIXED_NETWORK_WIFI + FOUR_G_MOBILE) / 3;
9
+ const KWH_PER_BYTE_FOR_DEVICES = 13e-11;
10
+ class OneByte {
11
+ constructor(options) {
12
+ this.options = options;
13
+ this.KWH_PER_BYTE_FOR_NETWORK = KWH_PER_BYTE_FOR_NETWORK;
14
+ }
15
+ perByte(bytes, green) {
16
+ if (bytes < 1) {
17
+ return 0;
18
+ }
19
+ if (green) {
20
+ const Co2ForDC = bytes * KWH_PER_BYTE_IN_DC * CO2_PER_KWH_IN_DC_GREEN;
21
+ const Co2forNetwork = bytes * KWH_PER_BYTE_FOR_NETWORK * CO2_PER_KWH_NETWORK_GREY;
22
+ return Co2ForDC + Co2forNetwork;
23
+ }
24
+ const KwHPerByte = KWH_PER_BYTE_IN_DC + KWH_PER_BYTE_FOR_NETWORK;
25
+ return bytes * KwHPerByte * CO2_PER_KWH_IN_DC_GREY;
26
+ }
27
+ }
28
+ var byte_default = OneByte;
29
+ export {
30
+ OneByte,
31
+ byte_default as default
32
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ import OneByte from "./1byte.js";
3
+ describe("onebyte", () => {
4
+ describe("perByte", () => {
5
+ it("returns a simple average of the different networks", () => {
6
+ const expected_val = 488e-12 .toFixed(12);
7
+ const instance = new OneByte();
8
+ expect(instance.KWH_PER_BYTE_FOR_NETWORK.toFixed(12)).toBe(expected_val);
9
+ });
10
+ });
11
+ });
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ import OneByte from "./1byte.js";
3
+ import SustainableWebDesign from "./sustainable-web-design.js";
4
+ class CO2 {
5
+ constructor(options) {
6
+ this.options = options;
7
+ this.model = new OneByte();
8
+ if (options) {
9
+ if (options.model === "swd") {
10
+ this.model = new SustainableWebDesign();
11
+ } else {
12
+ this.model = new options.model();
13
+ }
14
+ }
15
+ }
16
+ perByte(bytes, green) {
17
+ return this.model.perByte(bytes, green);
18
+ }
19
+ perDomain(pageXray, greenDomains) {
20
+ const co2PerDomain = [];
21
+ for (let domain of Object.keys(pageXray.domains)) {
22
+ let co2;
23
+ if (greenDomains && greenDomains.indexOf(domain) > -1) {
24
+ co2 = this.perByte(pageXray.domains[domain].transferSize, true);
25
+ } else {
26
+ co2 = this.perByte(pageXray.domains[domain].transferSize);
27
+ }
28
+ co2PerDomain.push({
29
+ domain,
30
+ co2,
31
+ transferSize: pageXray.domains[domain].transferSize
32
+ });
33
+ }
34
+ co2PerDomain.sort((a, b) => b.co2 - a.co2);
35
+ return co2PerDomain;
36
+ }
37
+ perPage(pageXray, green) {
38
+ const domainCO2 = this.perDomain(pageXray, green);
39
+ let totalCO2 = 0;
40
+ for (let domain of domainCO2) {
41
+ totalCO2 += domain.co2;
42
+ }
43
+ return totalCO2;
44
+ }
45
+ perContentType(pageXray, greenDomains) {
46
+ const co2PerContentType = {};
47
+ for (let asset of pageXray.assets) {
48
+ const domain = new URL(asset.url).domain;
49
+ const transferSize = asset.transferSize;
50
+ const co2ForTransfer = this.perByte(transferSize, greenDomains && greenDomains.indexOf(domain) > -1);
51
+ const contentType = asset.type;
52
+ if (!co2PerContentType[contentType]) {
53
+ co2PerContentType[contentType] = { co2: 0, transferSize: 0 };
54
+ }
55
+ co2PerContentType[contentType].co2 += co2ForTransfer;
56
+ co2PerContentType[contentType].transferSize += transferSize;
57
+ }
58
+ const all = [];
59
+ for (let type of Object.keys(co2PerContentType)) {
60
+ all.push({
61
+ type,
62
+ co2: co2PerContentType[type].co2,
63
+ transferSize: co2PerContentType[type].transferSize
64
+ });
65
+ }
66
+ all.sort((a, b) => b.co2 - a.co2);
67
+ return all;
68
+ }
69
+ dirtiestResources(pageXray, greenDomains) {
70
+ const allAssets = [];
71
+ for (let asset of pageXray.assets) {
72
+ const domain = new URL(asset.url).domain;
73
+ const transferSize = asset.transferSize;
74
+ const co2ForTransfer = this.perByte(transferSize, greenDomains && greenDomains.indexOf(domain) > -1);
75
+ allAssets.push({ url: asset.url, co2: co2ForTransfer, transferSize });
76
+ }
77
+ allAssets.sort((a, b) => b.co2 - a.co2);
78
+ return allAssets.slice(0, allAssets.length > 10 ? 10 : allAssets.length);
79
+ }
80
+ perParty(pageXray, greenDomains) {
81
+ let firstParty = 0;
82
+ let thirdParty = 0;
83
+ const firstPartyRegEx = pageXray.firstPartyRegEx;
84
+ for (let d of Object.keys(pageXray.domains)) {
85
+ if (!d.match(firstPartyRegEx)) {
86
+ thirdParty += this.perByte(pageXray.domains[d].transferSize, greenDomains && greenDomains.indexOf(d) > -1);
87
+ } else {
88
+ firstParty += this.perByte(pageXray.domains[d].transferSize, greenDomains && greenDomains.indexOf(d) > -1);
89
+ }
90
+ }
91
+ return { firstParty, thirdParty };
92
+ }
93
+ }
94
+ var co2_default = CO2;
95
+ export {
96
+ CO2,
97
+ co2_default as default
98
+ };
@@ -1,59 +1,36 @@
1
1
  "use strict";
2
-
3
- const fs = require("fs");
4
- const path = require("path");
5
-
6
- const CO2 = require("./co2");
7
- const swd = require("./sustainable-web-design");
8
- const pagexray = require("pagexray");
9
-
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import pagexray from "pagexray";
5
+ import CO2 from "./co2.js";
6
+ import SustainableWebDesign from "./sustainable-web-design.js";
10
7
  describe("co2", () => {
11
8
  let har, co2;
12
-
13
9
  describe("1 byte model", () => {
14
10
  const TGWF_GREY_VALUE = 0.20497;
15
11
  const TGWF_GREEN_VALUE = 0.54704;
16
12
  const TGWF_MIXED_VALUE = 0.16718;
17
-
18
- const MILLION = 1000000;
13
+ const MILLION = 1e6;
19
14
  const MILLION_GREY = 0.29081;
20
15
  const MILLION_GREEN = 0.23196;
21
-
22
16
  beforeEach(() => {
23
17
  co2 = new CO2();
24
- har = JSON.parse(
25
- fs.readFileSync(
26
- path.resolve(__dirname, "../data/fixtures/tgwf.har"),
27
- "utf8"
28
- )
29
- );
18
+ har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
30
19
  });
31
-
32
20
  describe("perByte", () => {
33
21
  it("returns a CO2 number for data transfer using 'grey' power", () => {
34
- expect(co2.perByte(MILLION).toPrecision(5)).toBe(
35
- MILLION_GREY.toPrecision(5)
36
- );
22
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
37
23
  });
38
-
39
24
  it("returns a lower CO2 number for data transfer from domains using entirely 'green' power", () => {
40
- expect(co2.perByte(MILLION).toPrecision(5)).toBe(
41
- MILLION_GREY.toPrecision(5)
42
- );
43
- expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(
44
- MILLION_GREEN.toPrecision(5)
45
- );
25
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
26
+ expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(MILLION_GREEN.toPrecision(5));
46
27
  });
47
28
  });
48
-
49
29
  describe("perPage", () => {
50
30
  it("returns CO2 for total transfer for page", () => {
51
31
  const pages = pagexray.convert(har);
52
32
  const pageXrayRun = pages[0];
53
-
54
- expect(co2.perPage(pageXrayRun).toPrecision(5)).toBe(
55
- TGWF_GREY_VALUE.toPrecision(5)
56
- );
33
+ expect(co2.perPage(pageXrayRun).toPrecision(5)).toBe(TGWF_GREY_VALUE.toPrecision(5));
57
34
  });
58
35
  it("returns lower CO2 for page served from green site", () => {
59
36
  const pages = pagexray.convert(har);
@@ -67,14 +44,13 @@ describe("co2", () => {
67
44
  "graphite.thegreenwebfoundation.org",
68
45
  "analytics.thegreenwebfoundation.org",
69
46
  "fonts.gstatic.com",
70
- "api.thegreenwebfoundation.org",
47
+ "api.thegreenwebfoundation.org"
71
48
  ];
72
49
  expect(co2.perPage(pageXrayRun, green)).toBeLessThan(TGWF_GREY_VALUE);
73
50
  });
74
51
  it("returns a lower CO2 number where *some* domains use green power", () => {
75
52
  const pages = pagexray.convert(har);
76
53
  const pageXrayRun = pages[0];
77
- // green can be true, or a array containing entries
78
54
  let green = [
79
55
  "www.thegreenwebfoundation.org",
80
56
  "fonts.googleapis.com",
@@ -84,11 +60,9 @@ describe("co2", () => {
84
60
  "graphite.thegreenwebfoundation.org",
85
61
  "analytics.thegreenwebfoundation.org",
86
62
  "fonts.gstatic.com",
87
- "api.thegreenwebfoundation.org",
63
+ "api.thegreenwebfoundation.org"
88
64
  ];
89
- expect(co2.perPage(pageXrayRun, green).toPrecision(5)).toBe(
90
- TGWF_MIXED_VALUE.toPrecision(5)
91
- );
65
+ expect(co2.perPage(pageXrayRun, green).toPrecision(5)).toBe(TGWF_MIXED_VALUE.toPrecision(5));
92
66
  });
93
67
  });
94
68
  describe("perDomain", () => {
@@ -96,7 +70,6 @@ describe("co2", () => {
96
70
  const pages = pagexray.convert(har);
97
71
  const pageXrayRun = pages[0];
98
72
  const res = co2.perDomain(pageXrayRun);
99
-
100
73
  const domains = [
101
74
  "thegreenwebfoundation.org",
102
75
  "www.thegreenwebfoundation.org",
@@ -108,9 +81,8 @@ describe("co2", () => {
108
81
  "graphite.thegreenwebfoundation.org",
109
82
  "analytics.thegreenwebfoundation.org",
110
83
  "fonts.gstatic.com",
111
- "api.thegreenwebfoundation.org",
84
+ "api.thegreenwebfoundation.org"
112
85
  ];
113
-
114
86
  for (let obj of res) {
115
87
  expect(domains.indexOf(obj.domain)).toBeGreaterThan(-1);
116
88
  expect(typeof obj.co2).toBe("number");
@@ -119,7 +91,6 @@ describe("co2", () => {
119
91
  it("shows lower Co2 for green domains", () => {
120
92
  const pages = pagexray.convert(har);
121
93
  const pageXrayRun = pages[0];
122
-
123
94
  const greenDomains = [
124
95
  "www.thegreenwebfoundation.org",
125
96
  "fonts.googleapis.com",
@@ -129,11 +100,10 @@ describe("co2", () => {
129
100
  "graphite.thegreenwebfoundation.org",
130
101
  "analytics.thegreenwebfoundation.org",
131
102
  "fonts.gstatic.com",
132
- "api.thegreenwebfoundation.org",
103
+ "api.thegreenwebfoundation.org"
133
104
  ];
134
105
  const res = co2.perDomain(pageXrayRun);
135
106
  const resWithGreen = co2.perDomain(pageXrayRun, greenDomains);
136
-
137
107
  for (let obj of res) {
138
108
  expect(typeof obj.co2).toBe("number");
139
109
  }
@@ -145,56 +115,32 @@ describe("co2", () => {
145
115
  });
146
116
  });
147
117
  });
148
-
149
- describe("Sustainable Web Design model", () => {
150
- // the SWD model should have slightly higher values as
151
- // we include more of the system in calculations for the
152
- // same levels of data transfer
153
- const MILLION = 1000000;
154
- const MILLION_GREY = 0.33343;
155
- const MILLION_GREEN = 0.28908;
156
-
157
- const TGWF_GREY_VALUE = 0.23501;
118
+ describe("Sustainable Web Design model as simple option", () => {
119
+ const MILLION = 1e6;
120
+ const MILLION_GREY = 0.35802;
121
+ const MILLION_GREEN = 0.31039;
122
+ const TGWF_GREY_VALUE = 0.25234;
158
123
  const TGWF_GREEN_VALUE = 0.54704;
159
- const TGWF_MIXED_VALUE = 0.20652;
160
-
124
+ const TGWF_MIXED_VALUE = 0.22175;
161
125
  beforeEach(() => {
162
- co2 = new CO2({ model: swd });
163
- har = JSON.parse(
164
- fs.readFileSync(
165
- path.resolve(__dirname, "../data/fixtures/tgwf.har"),
166
- "utf8"
167
- )
168
- );
126
+ co2 = new CO2({ model: "swd" });
127
+ har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
169
128
  });
170
-
171
129
  describe("perByte", () => {
172
130
  it("returns a CO2 number for data transfer", () => {
173
131
  co2.perByte(MILLION);
174
- expect(co2.perByte(MILLION).toPrecision(5)).toBe(
175
- MILLION_GREY.toPrecision(5)
176
- );
132
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
177
133
  });
178
-
179
134
  it("returns a lower CO2 number for data transfer from domains using entirely 'green' power", () => {
180
- expect(co2.perByte(MILLION, false).toPrecision(5)).toBe(
181
- MILLION_GREY.toPrecision(5)
182
- );
183
-
184
- expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(
185
- MILLION_GREEN.toPrecision(5)
186
- );
135
+ expect(co2.perByte(MILLION, false).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
136
+ expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(MILLION_GREEN.toPrecision(5));
187
137
  });
188
138
  });
189
-
190
139
  describe("perPage", () => {
191
140
  it("returns CO2 for total transfer for page", () => {
192
141
  const pages = pagexray.convert(har);
193
142
  const pageXrayRun = pages[0];
194
-
195
- expect(co2.perPage(pageXrayRun).toPrecision(5)).toBe(
196
- TGWF_GREY_VALUE.toPrecision(5)
197
- );
143
+ expect(co2.perPage(pageXrayRun).toPrecision(5)).toBe(TGWF_GREY_VALUE.toPrecision(5));
198
144
  });
199
145
  it("returns lower CO2 for page served from green site", () => {
200
146
  const pages = pagexray.convert(har);
@@ -208,14 +154,13 @@ describe("co2", () => {
208
154
  "graphite.thegreenwebfoundation.org",
209
155
  "analytics.thegreenwebfoundation.org",
210
156
  "fonts.gstatic.com",
211
- "api.thegreenwebfoundation.org",
157
+ "api.thegreenwebfoundation.org"
212
158
  ];
213
159
  expect(co2.perPage(pageXrayRun, green)).toBeLessThan(TGWF_GREY_VALUE);
214
160
  });
215
161
  it("returns a lower CO2 number where *some* domains use green power", () => {
216
162
  const pages = pagexray.convert(har);
217
163
  const pageXrayRun = pages[0];
218
- // green can be true, or a array containing entries
219
164
  let green = [
220
165
  "www.thegreenwebfoundation.org",
221
166
  "fonts.googleapis.com",
@@ -225,11 +170,9 @@ describe("co2", () => {
225
170
  "graphite.thegreenwebfoundation.org",
226
171
  "analytics.thegreenwebfoundation.org",
227
172
  "fonts.gstatic.com",
228
- "api.thegreenwebfoundation.org",
173
+ "api.thegreenwebfoundation.org"
229
174
  ];
230
- expect(co2.perPage(pageXrayRun, green).toPrecision(5)).toBe(
231
- TGWF_MIXED_VALUE.toPrecision(5)
232
- );
175
+ expect(co2.perPage(pageXrayRun, green).toPrecision(5)).toBe(TGWF_MIXED_VALUE.toPrecision(5));
233
176
  });
234
177
  });
235
178
  describe("perDomain", () => {
@@ -237,7 +180,6 @@ describe("co2", () => {
237
180
  const pages = pagexray.convert(har);
238
181
  const pageXrayRun = pages[0];
239
182
  const res = co2.perDomain(pageXrayRun);
240
-
241
183
  const domains = [
242
184
  "thegreenwebfoundation.org",
243
185
  "www.thegreenwebfoundation.org",
@@ -249,9 +191,8 @@ describe("co2", () => {
249
191
  "graphite.thegreenwebfoundation.org",
250
192
  "analytics.thegreenwebfoundation.org",
251
193
  "fonts.gstatic.com",
252
- "api.thegreenwebfoundation.org",
194
+ "api.thegreenwebfoundation.org"
253
195
  ];
254
-
255
196
  for (let obj of res) {
256
197
  expect(domains.indexOf(obj.domain)).toBeGreaterThan(-1);
257
198
  expect(typeof obj.co2).toBe("number");
@@ -260,7 +201,6 @@ describe("co2", () => {
260
201
  it("shows lower Co2 for green domains", () => {
261
202
  const pages = pagexray.convert(har);
262
203
  const pageXrayRun = pages[0];
263
-
264
204
  const greenDomains = [
265
205
  "www.thegreenwebfoundation.org",
266
206
  "fonts.googleapis.com",
@@ -270,11 +210,10 @@ describe("co2", () => {
270
210
  "graphite.thegreenwebfoundation.org",
271
211
  "analytics.thegreenwebfoundation.org",
272
212
  "fonts.gstatic.com",
273
- "api.thegreenwebfoundation.org",
213
+ "api.thegreenwebfoundation.org"
274
214
  ];
275
215
  const res = co2.perDomain(pageXrayRun);
276
216
  const resWithGreen = co2.perDomain(pageXrayRun, greenDomains);
277
-
278
217
  for (let obj of res) {
279
218
  expect(typeof obj.co2).toBe("number");
280
219
  }
@@ -286,4 +225,18 @@ describe("co2", () => {
286
225
  });
287
226
  });
288
227
  });
228
+ describe("New model that implements the same API", () => {
229
+ const MILLION = 1e6;
230
+ const MILLION_GREY = 0.35802;
231
+ beforeEach(() => {
232
+ co2 = new CO2({ model: SustainableWebDesign });
233
+ har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
234
+ });
235
+ describe("perByte", () => {
236
+ it("returns a CO2 number for data transfer", () => {
237
+ co2.perByte(MILLION);
238
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
239
+ });
240
+ });
241
+ });
289
242
  });
@@ -0,0 +1,7 @@
1
+ const GIGABYTE = 1e3 * 1e3 * 1e3;
2
+ var file_size_default = {
3
+ GIGABYTE
4
+ };
5
+ export {
6
+ file_size_default as default
7
+ };
@@ -0,0 +1,4 @@
1
+ import fileSize from "./file-size.js";
2
+ export {
3
+ fileSize
4
+ };
@@ -0,0 +1,4 @@
1
+ const formatNumber = (num) => parseFloat(num.toFixed(2));
2
+ export {
3
+ formatNumber
4
+ };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ import debugFactory from "debug";
3
+ const log = debugFactory("tgwf:hostingAPI");
4
+ function check(domain) {
5
+ if (typeof domain === "string") {
6
+ return checkAgainstAPI(domain);
7
+ } else {
8
+ return checkDomainsAgainstAPI(domain);
9
+ }
10
+ }
11
+ async function checkAgainstAPI(domain) {
12
+ const req = await fetch(`https://api.thegreenwebfoundation.org/greencheck/${domain}`);
13
+ const res = await req.json();
14
+ return res.green;
15
+ }
16
+ async function checkDomainsAgainstAPI(domains) {
17
+ try {
18
+ const apiPath = "https://api.thegreenwebfoundation.org/v2/greencheckmulti";
19
+ const domainsString = JSON.stringify(domains);
20
+ const req = await fetch(`${apiPath}/${domainsString}`);
21
+ log(`${apiPath}/${domainsString}`);
22
+ log({ req });
23
+ const textResult = await req.text();
24
+ log({ textResult });
25
+ const allGreenCheckResults = await req.json();
26
+ return greenDomainsFromResults(allGreenCheckResults);
27
+ } catch (e) {
28
+ return [];
29
+ }
30
+ }
31
+ function greenDomainsFromResults(greenResults) {
32
+ const entries = Object.entries(greenResults);
33
+ const greenEntries = entries.filter(([key, val]) => val.green);
34
+ return greenEntries.map(([key, val]) => val.url);
35
+ }
36
+ var hosting_api_default = {
37
+ check
38
+ };
39
+ export {
40
+ hosting_api_default as default
41
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ import hosting from "./hosting-node.js";
3
+ import nock from "nock";
4
+ describe("hostingAPI", () => {
5
+ describe("checking a single domain with #check", () => {
6
+ it.skip("using the API", async () => {
7
+ const scope = nock("https://api.thegreenwebfoundation.org/").get("/greencheck/google.com").reply(200, {
8
+ url: "google.com",
9
+ green: true
10
+ });
11
+ const res = await hosting.check("google.com");
12
+ expect(res).toEqual(true);
13
+ });
14
+ });
15
+ describe("implicitly checking multiple domains with #check", () => {
16
+ it.skip("using the API", async () => {
17
+ const scope = nock("https://api.thegreenwebfoundation.org/").get("/v2/greencheckmulti/[%22google.com%22,%22kochindustries.com%22]").reply(200, {
18
+ "google.com": {
19
+ url: "google.com",
20
+ green: true
21
+ },
22
+ "kochindustries.com": {
23
+ url: "kochindustries.com",
24
+ green: null
25
+ }
26
+ });
27
+ const res = await hosting.check(["google.com", "kochindustries.com"]);
28
+ expect(res).toContain("google.com");
29
+ });
30
+ });
31
+ });
@@ -1,30 +1,19 @@
1
1
  "use strict";
2
-
3
- const log = require("debug")("tgwf:url2green:test");
4
- const { hosting } = require("@tgwf/url2green");
5
- const path = require("path");
6
-
7
- const dbPath = path.resolve(
8
- __dirname,
9
- "..",
10
- "data",
11
- "fixtures",
12
- "url2green.test.db"
13
- );
14
-
2
+ import path from "path";
3
+ import debugFactory from "debug";
4
+ const log = debugFactory("tgwf:url2green:test");
5
+ import { hosting } from "@tgwf/url2green";
6
+ const dbPath = path.resolve(__dirname, "..", "data", "fixtures", "url2green.test.db");
15
7
  describe("hostingDatabase", () => {
16
8
  describe("checking a single domain with #check", () => {
17
- test("tries to use a local database if available ", async () => {
9
+ test("tries to use a local database if available", async () => {
18
10
  const res = await hosting.check("google.com", dbPath);
19
11
  expect(res).toEqual(true);
20
12
  });
21
13
  });
22
14
  describe("implicitly checking multiple domains with #check", () => {
23
15
  test("tries to use a local database if available", async () => {
24
- const res = await hosting.check(
25
- ["google.com", "kochindustries.com"],
26
- dbPath
27
- );
16
+ const res = await hosting.check(["google.com", "kochindustries.com"], dbPath);
28
17
  expect(res).toContain("google.com");
29
18
  });
30
19
  });