@tgwf/co2 0.10.0 → 0.10.3

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.
@@ -20,16 +20,16 @@ describe("sustainable web design model", () => {
20
20
  describe("energyPerByteByComponent", () => {
21
21
  it("should return a object with numbers for each system component", () => {
22
22
  const groupedEnergy = swd.energyPerByteByComponent(averageWebsiteInBytes);
23
- expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(88564e-8, 8);
24
- expect(groupedEnergy.networkEnergy).toBeCloseTo(23844e-8, 8);
25
- expect(groupedEnergy.productionEnergy).toBeCloseTo(3236e-7, 8);
26
- expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(25547e-8, 8);
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
27
  });
28
28
  });
29
29
  describe("energyPerByte", () => {
30
30
  it("should return a number in kilowatt hours for the given data transfer in bytes", () => {
31
31
  const energyForTransfer = swd.energyPerByte(averageWebsiteInBytes);
32
- expect(energyForTransfer).toBeCloseTo(170316e-8, 7);
32
+ expect(energyForTransfer).toBeCloseTo(182874e-8, 7);
33
33
  });
34
34
  });
35
35
  describe("perByte", () => {
@@ -37,28 +37,27 @@ describe("sustainable web design model", () => {
37
37
  expect(typeof swd.perByte(22577152e-1)).toBe("number");
38
38
  });
39
39
  });
40
+ describe("perVisit", () => {
41
+ it("should return a single number for CO2 emissions", () => {
42
+ expect(typeof swd.perVisit(22577152e-1)).toBe("number");
43
+ });
44
+ });
40
45
  describe("energyPerVisit", () => {
41
46
  it("should return a number", () => {
42
47
  expect(typeof swd.energyPerVisit(averageWebsiteInBytes)).toBe("number");
43
48
  });
44
49
  it("should calculate the correct energy", () => {
45
- expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(0.001285882415771485);
46
- });
47
- it("should match the old calculations", () => {
48
- const v9currentEnergyCalc = swd.energyPerVisit(averageWebsiteInBytes);
49
- const v8VersionEnergyCalc = swd.energyPerVisitV8(averageWebsiteInBytes);
50
- expect(swd.emissionsPerVisitInGrams(v9currentEnergyCalc)).toEqual(0.57);
51
- expect(swd.emissionsPerVisitInGrams(v8VersionEnergyCalc)).toEqual(0.2);
50
+ expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(0.0013807057305600004);
52
51
  });
53
52
  });
54
53
  describe("emissionsPerVisitInGrams", () => {
55
54
  it("should calculate the correct co2 per visit", () => {
56
55
  const energy = swd.energyPerVisit(averageWebsiteInBytes);
57
- expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.57);
56
+ expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.61);
58
57
  });
59
58
  it("should accept a dynamic KwH value", () => {
60
59
  const energy = swd.energyPerVisit(averageWebsiteInBytes);
61
- expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.32);
60
+ expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.34);
62
61
  });
63
62
  });
64
63
  describe("annualEnergyInKwh", () => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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 const groupedEnergy = swd.energyPerByteByComponent(averageWebsiteInBytes);\n\n expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(0.00088564, 8);\n expect(groupedEnergy.networkEnergy).toBeCloseTo(0.00023844, 8);\n expect(groupedEnergy.productionEnergy).toBeCloseTo(0.0003236, 8);\n expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(0.00025547, 8);\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.00170316, 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.001285882415771485\n );\n });\n\n it(\"should match the old calculations\", () => {\n // Test the v0.9.0 updates to the SWD method to identify differences\n const v9currentEnergyCalc = swd.energyPerVisit(averageWebsiteInBytes);\n const v8VersionEnergyCalc = swd.energyPerVisitV8(averageWebsiteInBytes);\n\n // expect(currentEnergyCalc).toBe(0.0004513362121582032);\n // expect(oldVersionEnergyCalc).toBe(0.0012858824157714846);\n\n // with the constants switched around so the first view is 0.75, now 0.25\n // we should we the page come back at 0.57g not 0.2\n expect(swd.emissionsPerVisitInGrams(v9currentEnergyCalc)).toEqual(0.57);\n expect(swd.emissionsPerVisitInGrams(v8VersionEnergyCalc)).toEqual(0.2);\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.57);\n });\n\n it(\"should accept a dynamic KwH value\", () => {\n const energy = swd.energyPerVisit(averageWebsiteInBytes);\n expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.32);\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;AACxE,YAAM,gBAAgB,IAAI,yBAAyB,qBAAqB;AAExE,aAAO,cAAc,oBAAoB,EAAE,YAAY,UAAY,CAAC;AACpE,aAAO,cAAc,aAAa,EAAE,YAAY,UAAY,CAAC;AAC7D,aAAO,cAAc,gBAAgB,EAAE,YAAY,SAAW,CAAC;AAC/D,aAAO,cAAc,gBAAgB,EAAE,YAAY,UAAY,CAAC;AAAA,IAClE,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,oBACF;AAAA,IACF,CAAC;AAED,OAAG,qCAAqC,MAAM;AAE5C,YAAM,sBAAsB,IAAI,eAAe,qBAAqB;AACpE,YAAM,sBAAsB,IAAI,iBAAiB,qBAAqB;AAOtE,aAAO,IAAI,yBAAyB,mBAAmB,CAAC,EAAE,QAAQ,IAAI;AACtE,aAAO,IAAI,yBAAyB,mBAAmB,CAAC,EAAE,QAAQ,GAAG;AAAA,IACvE,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;",
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(\"perVisit\", () => {\n it(\"should return a single number for CO2 emissions\", () => {\n expect(typeof swd.perVisit(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,YAAY,MAAM;AACzB,OAAG,mDAAmD,MAAM;AAC1D,aAAO,OAAO,IAAI,SAAS,WAAS,CAAC,EAAE,KAAK,QAAQ;AAAA,IACtD,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
6
  "names": []
7
7
  }
package/dist/esm/co2.js CHANGED
@@ -1,16 +1,25 @@
1
1
  "use strict";
2
2
  import OneByte from "./1byte.js";
3
+ import SustainableWebDesign from "./sustainable-web-design.js";
3
4
  class CO2 {
4
5
  constructor(options) {
5
- this.options = options;
6
- this.model = new OneByte();
7
- if (options) {
8
- this.model = new options.model();
6
+ this.model = new SustainableWebDesign();
7
+ if ((options == null ? void 0 : options.model) === "1byte") {
8
+ this.model = new OneByte();
9
9
  }
10
10
  }
11
11
  perByte(bytes, green) {
12
12
  return this.model.perByte(bytes, green);
13
13
  }
14
+ perVisit(bytes, green) {
15
+ var _a;
16
+ if ((_a = this.model) == null ? void 0 : _a.perVisit) {
17
+ return this.model.perVisit(bytes, green);
18
+ } else {
19
+ console.warn("The model you have selected does not support perVisit. Using perByte instead.");
20
+ return this.model.perByte(bytes, green);
21
+ }
22
+ }
14
23
  perDomain(pageXray, greenDomains) {
15
24
  const co2PerDomain = [];
16
25
  for (let domain of Object.keys(pageXray.domains)) {
@@ -3,7 +3,7 @@ import fs from "fs";
3
3
  import path from "path";
4
4
  import pagexray from "pagexray";
5
5
  import CO2 from "./co2.js";
6
- import swd from "./sustainable-web-design.js";
6
+ import SustainableWebDesign from "./sustainable-web-design.js";
7
7
  describe("co2", () => {
8
8
  let har, co2;
9
9
  describe("1 byte model", () => {
@@ -14,7 +14,7 @@ describe("co2", () => {
14
14
  const MILLION_GREY = 0.29081;
15
15
  const MILLION_GREEN = 0.23196;
16
16
  beforeEach(() => {
17
- co2 = new CO2();
17
+ co2 = new CO2({ model: "1byte" });
18
18
  har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
19
19
  });
20
20
  describe("perByte", () => {
@@ -115,15 +115,17 @@ describe("co2", () => {
115
115
  });
116
116
  });
117
117
  });
118
- describe("Sustainable Web Design model", () => {
118
+ describe("Sustainable Web Design model as simple option", () => {
119
119
  const MILLION = 1e6;
120
- const MILLION_GREY = 0.33343;
121
- const MILLION_GREEN = 0.28908;
122
- const TGWF_GREY_VALUE = 0.23501;
120
+ const MILLION_GREY = 0.35802;
121
+ const MILLION_GREEN = 0.31039;
122
+ const MILLION_PERVISIT_GREY = 0.27031;
123
+ const MILLION_PERVISIT_GREEN = 0.23434;
124
+ const TGWF_GREY_VALUE = 0.25234;
123
125
  const TGWF_GREEN_VALUE = 0.54704;
124
- const TGWF_MIXED_VALUE = 0.20652;
126
+ const TGWF_MIXED_VALUE = 0.22175;
125
127
  beforeEach(() => {
126
- co2 = new CO2({ model: swd });
128
+ co2 = new CO2();
127
129
  har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
128
130
  });
129
131
  describe("perByte", () => {
@@ -136,6 +138,16 @@ describe("co2", () => {
136
138
  expect(co2.perByte(MILLION, true).toPrecision(5)).toBe(MILLION_GREEN.toPrecision(5));
137
139
  });
138
140
  });
141
+ describe("perVisit", () => {
142
+ it("returns a CO2 number for data transfer per visit with caching assumptions from the Sustainable Web Design model", () => {
143
+ co2.perVisit(MILLION);
144
+ expect(co2.perVisit(MILLION).toPrecision(5)).toBe(MILLION_PERVISIT_GREY.toPrecision(5));
145
+ });
146
+ it("returns a lower CO2 number for data transfer from domains using entirely 'green' power", () => {
147
+ expect(co2.perVisit(MILLION, false).toPrecision(5)).toBe(MILLION_PERVISIT_GREY.toPrecision(5));
148
+ expect(co2.perVisit(MILLION, true).toPrecision(5)).toBe(MILLION_PERVISIT_GREEN.toPrecision(5));
149
+ });
150
+ });
139
151
  describe("perPage", () => {
140
152
  it("returns CO2 for total transfer for page", () => {
141
153
  const pages = pagexray.convert(har);
@@ -225,4 +237,18 @@ describe("co2", () => {
225
237
  });
226
238
  });
227
239
  });
240
+ describe("New model that implements the same API", () => {
241
+ const MILLION = 1e6;
242
+ const MILLION_GREY = 0.35802;
243
+ beforeEach(() => {
244
+ co2 = new CO2({ model: SustainableWebDesign });
245
+ har = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../data/fixtures/tgwf.har"), "utf8"));
246
+ });
247
+ describe("perByte", () => {
248
+ it("returns a CO2 number for data transfer", () => {
249
+ co2.perByte(MILLION);
250
+ expect(co2.perByte(MILLION).toPrecision(5)).toBe(MILLION_GREY.toPrecision(5));
251
+ });
252
+ });
253
+ });
228
254
  });
@@ -1,4 +1,4 @@
1
- const GIGABYTE = 1024 * 1024 * 1024;
1
+ const GIGABYTE = 1e3 * 1e3 * 1e3;
2
2
  var file_size_default = {
3
3
  GIGABYTE
4
4
  };
@@ -30,8 +30,10 @@ class SustainableWebDesign {
30
30
  co2byComponent(energyBycomponent, carbonIntensity = GLOBAL_INTENSITY) {
31
31
  const returnCO2ByComponent = {};
32
32
  for (const [key, value] of Object.entries(energyBycomponent)) {
33
- if (key === "dataCenterEnergy") {
33
+ if (key.startsWith("dataCenterEnergy")) {
34
+ console.log(key);
34
35
  returnCO2ByComponent[key] = value * carbonIntensity;
36
+ console.log(returnCO2ByComponent[key]);
35
37
  } else {
36
38
  returnCO2ByComponent[key] = value * GLOBAL_INTENSITY;
37
39
  }
@@ -53,6 +55,21 @@ class SustainableWebDesign {
53
55
  const co2Values = Object.values(co2ValuesbyComponent);
54
56
  return co2Values.reduce((prevValue, currentValue) => prevValue + currentValue);
55
57
  }
58
+ perVisit(bytes, carbonIntensity = GLOBAL_INTENSITY) {
59
+ const energyBycomponent = this.energyPerVisitByComponent(bytes);
60
+ if (Boolean(carbonIntensity) === false) {
61
+ carbonIntensity = GLOBAL_INTENSITY;
62
+ }
63
+ if (carbonIntensity === true) {
64
+ carbonIntensity = RENEWABLES_INTENSITY;
65
+ }
66
+ if (typeof carbonIntensity !== "number") {
67
+ throw new Error(`perVisit expects a numeric value or boolean for the carbon intensity value. Received: ${carbonIntensity}`);
68
+ }
69
+ const co2ValuesbyComponent = this.co2byComponent(energyBycomponent, carbonIntensity);
70
+ const co2Values = Object.values(co2ValuesbyComponent);
71
+ return co2Values.reduce((prevValue, currentValue) => prevValue + currentValue);
72
+ }
56
73
  energyPerByte(bytes) {
57
74
  const energyByComponent = this.energyPerByteByComponent(bytes);
58
75
  const energyValues = Object.values(energyByComponent);
@@ -63,8 +80,6 @@ class SustainableWebDesign {
63
80
  const cacheAdjustedSegmentEnergy = {};
64
81
  log({ energyBycomponent });
65
82
  const energyValues = Object.values(energyBycomponent);
66
- const v9recombinedNoCaching = energyValues.reduce((prevValue, currentValue) => prevValue + currentValue);
67
- log({ v9recombinedNoCaching });
68
83
  for (const [key, value] of Object.entries(energyBycomponent)) {
69
84
  cacheAdjustedSegmentEnergy[`${key} - first`] = value * firstView;
70
85
  cacheAdjustedSegmentEnergy[`${key} - subsequent`] = value * returnView * dataReloadRatio;
@@ -73,35 +88,20 @@ class SustainableWebDesign {
73
88
  return cacheAdjustedSegmentEnergy;
74
89
  }
75
90
  energyPerVisit(bytes) {
76
- let v9firstVisits = 0;
77
- let v9subsequentVisits = 0;
91
+ let firstVisits = 0;
92
+ let subsequentVisits = 0;
78
93
  const energyBycomponent = Object.entries(this.energyPerVisitByComponent(bytes));
79
94
  for (const [key, val] of energyBycomponent) {
80
95
  if (key.indexOf("first") > 0) {
81
- v9firstVisits += val;
96
+ firstVisits += val;
82
97
  }
83
98
  }
84
99
  for (const [key, val] of energyBycomponent) {
85
100
  if (key.indexOf("subsequent") > 0) {
86
- v9subsequentVisits += val;
101
+ subsequentVisits += val;
87
102
  }
88
103
  }
89
- log({ v9firstVisits });
90
- log({ v9subsequentVisits });
91
- return v9firstVisits + v9subsequentVisits;
92
- }
93
- energyPerVisitV8(bytes) {
94
- log({ bytes });
95
- const transferedBytesToGb = bytes / fileSize.GIGABYTE;
96
- const v8visitWithNoCaching = transferedBytesToGb * KWH_PER_GB;
97
- const v8firstVisit = transferedBytesToGb * KWH_PER_GB * RETURNING_VISITOR_PERCENTAGE;
98
- const v8subsequentVisits = transferedBytesToGb * KWH_PER_GB * FIRST_TIME_VIEWING_PERCENTAGE * PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD;
99
- const v8firstAndSubsequentVisits = v8firstVisit + v8subsequentVisits;
100
- log({ v8visitWithNoCaching });
101
- log({ v8firstVisit });
102
- log({ v8subsequentVisits });
103
- log({ v8firstAndSubsequentVisits });
104
- return v8firstVisit + v8subsequentVisits;
104
+ return firstVisits + subsequentVisits;
105
105
  }
106
106
  emissionsPerVisitInGrams(energyPerVisit, carbonintensity = GLOBAL_INTENSITY) {
107
107
  return formatNumber(energyPerVisit * carbonintensity);
@@ -5,16 +5,16 @@ describe("sustainable web design model", () => {
5
5
  describe("energyPerByteByComponent", () => {
6
6
  it("should return a object with numbers for each system component", () => {
7
7
  const groupedEnergy = swd.energyPerByteByComponent(averageWebsiteInBytes);
8
- expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(88564e-8, 8);
9
- expect(groupedEnergy.networkEnergy).toBeCloseTo(23844e-8, 8);
10
- expect(groupedEnergy.productionEnergy).toBeCloseTo(3236e-7, 8);
11
- expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(25547e-8, 8);
8
+ expect(groupedEnergy.consumerDeviceEnergy).toBeCloseTo(95095e-8, 8);
9
+ expect(groupedEnergy.networkEnergy).toBeCloseTo(25602e-8, 7);
10
+ expect(groupedEnergy.dataCenterEnergy).toBeCloseTo(27431e-8, 8);
11
+ expect(groupedEnergy.productionEnergy).toBeCloseTo(3475e-7, 7);
12
12
  });
13
13
  });
14
14
  describe("energyPerByte", () => {
15
15
  it("should return a number in kilowatt hours for the given data transfer in bytes", () => {
16
16
  const energyForTransfer = swd.energyPerByte(averageWebsiteInBytes);
17
- expect(energyForTransfer).toBeCloseTo(170316e-8, 7);
17
+ expect(energyForTransfer).toBeCloseTo(182874e-8, 7);
18
18
  });
19
19
  });
20
20
  describe("perByte", () => {
@@ -22,28 +22,27 @@ describe("sustainable web design model", () => {
22
22
  expect(typeof swd.perByte(22577152e-1)).toBe("number");
23
23
  });
24
24
  });
25
+ describe("perVisit", () => {
26
+ it("should return a single number for CO2 emissions", () => {
27
+ expect(typeof swd.perVisit(22577152e-1)).toBe("number");
28
+ });
29
+ });
25
30
  describe("energyPerVisit", () => {
26
31
  it("should return a number", () => {
27
32
  expect(typeof swd.energyPerVisit(averageWebsiteInBytes)).toBe("number");
28
33
  });
29
34
  it("should calculate the correct energy", () => {
30
- expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(0.001285882415771485);
31
- });
32
- it("should match the old calculations", () => {
33
- const v9currentEnergyCalc = swd.energyPerVisit(averageWebsiteInBytes);
34
- const v8VersionEnergyCalc = swd.energyPerVisitV8(averageWebsiteInBytes);
35
- expect(swd.emissionsPerVisitInGrams(v9currentEnergyCalc)).toEqual(0.57);
36
- expect(swd.emissionsPerVisitInGrams(v8VersionEnergyCalc)).toEqual(0.2);
35
+ expect(swd.energyPerVisit(averageWebsiteInBytes)).toBe(0.0013807057305600004);
37
36
  });
38
37
  });
39
38
  describe("emissionsPerVisitInGrams", () => {
40
39
  it("should calculate the correct co2 per visit", () => {
41
40
  const energy = swd.energyPerVisit(averageWebsiteInBytes);
42
- expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.57);
41
+ expect(swd.emissionsPerVisitInGrams(energy)).toEqual(0.61);
43
42
  });
44
43
  it("should accept a dynamic KwH value", () => {
45
44
  const energy = swd.energyPerVisit(averageWebsiteInBytes);
46
- expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.32);
45
+ expect(swd.emissionsPerVisitInGrams(energy, 245)).toEqual(0.34);
47
46
  });
48
47
  });
49
48
  describe("annualEnergyInKwh", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tgwf/co2",
3
- "version": "0.10.0",
3
+ "version": "0.10.3",
4
4
  "description": "Work out the co2 of your digital services",
5
5
  "main": "dist/cjs/index-node.js",
6
6
  "module": "dist/esm/index.js",
@@ -19,7 +19,8 @@
19
19
  "build": "npm run build:esm && npm run build:browser && npm run build:node",
20
20
  "build:esm": "node .esbuild.esm.js && ./fixup",
21
21
  "build:browser": "node .esbuild.browser.js",
22
- "build:node": "node .esbuild.node.js && ./fixup"
22
+ "build:node": "node .esbuild.node.js && ./fixup",
23
+ "gitpod": "npm run build && cp ./dist/iife/index.js ./public && npm run serve"
23
24
  },
24
25
  "keywords": [
25
26
  "sustainability",
package/public/index.html CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <body class="">
9
9
 
10
- <h1>This is a minimal demo</h1>
10
+ <h1>This is a minimal demo using the IIFE version of CO2.js.</h1>
11
11
 
12
12
  <p>Add a number in bytes, and we convert it to carbon, using the SWD model</p>
13
13
 
@@ -26,8 +26,9 @@
26
26
 
27
27
  <script src="./index.js"></script>
28
28
  <script>
29
-
30
- let emissions = new co2.co2();
29
+ let emissions = new co2.co2({
30
+ model: 'swd'
31
+ });
31
32
 
32
33
  async function main() {
33
34
 
@@ -36,7 +37,9 @@
36
37
  // is the result green?
37
38
  const result = await hosting.check("google.com")
38
39
  // should return true or false
39
- console.log({result})
40
+ console.log({
41
+ result
42
+ })
40
43
 
41
44
  document.querySelector('form').addEventListener('submit', function (event) {
42
45
  event.preventDefault();
@@ -54,4 +57,4 @@
54
57
  </script>
55
58
  </body>
56
59
 
57
- </html>
60
+ </html>
package/public/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var co2=(()=>{var V=Object.create;var b=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var v=(r,t)=>()=>(t||r((t={exports:{}}).exports,t),t.exports),re=(r,t)=>{for(var e in t)b(r,e,{get:t[e],enumerable:!0})},z=(r,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of X(t))!te.call(r,n)&&n!==e&&b(r,n,{get:()=>t[n],enumerable:!(o=Q(t,n))||o.enumerable});return r};var D=(r,t,e)=>(e=r!=null?V(ee(r)):{},z(t||!r||!r.__esModule?b(e,"default",{value:r,enumerable:!0}):e,r)),ne=r=>z(b({},"__esModule",{value:!0}),r);var G=v((ve,H)=>{var m=1e3,g=m*60,y=g*60,p=y*24,oe=p*7,se=p*365.25;H.exports=function(r,t){t=t||{};var e=typeof r;if(e==="string"&&r.length>0)return ie(r);if(e==="number"&&isFinite(r))return t.long?ae(r):ce(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function ie(r){if(r=String(r),!(r.length>100)){var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(!!t){var e=parseFloat(t[1]),o=(t[2]||"ms").toLowerCase();switch(o){case"years":case"year":case"yrs":case"yr":case"y":return e*se;case"weeks":case"week":case"w":return e*oe;case"days":case"day":case"d":return e*p;case"hours":case"hour":case"hrs":case"hr":case"h":return e*y;case"minutes":case"minute":case"mins":case"min":case"m":return e*g;case"seconds":case"second":case"secs":case"sec":case"s":return e*m;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return e;default:return}}}}function ce(r){var t=Math.abs(r);return t>=p?Math.round(r/p)+"d":t>=y?Math.round(r/y)+"h":t>=g?Math.round(r/g)+"m":t>=m?Math.round(r/m)+"s":r+"ms"}function ae(r){var t=Math.abs(r);return t>=p?R(r,t,p,"day"):t>=y?R(r,t,y,"hour"):t>=g?R(r,t,g,"minute"):t>=m?R(r,t,m,"second"):r+" ms"}function R(r,t,e,o){var n=t>=e*1.5;return Math.round(r/e)+" "+o+(n?"s":"")}});var Y=v((Pe,M)=>{function ue(r){e.debug=e,e.default=e,e.coerce=x,e.disable=i,e.enable=n,e.enabled=u,e.humanize=G(),e.destroy=F,Object.keys(r).forEach(s=>{e[s]=r[s]}),e.names=[],e.skips=[],e.formatters={};function t(s){let c=0;for(let a=0;a<s.length;a++)c=(c<<5)-c+s.charCodeAt(a),c|=0;return e.colors[Math.abs(c)%e.colors.length]}e.selectColor=t;function e(s){let c,a=null,_,T;function C(...l){if(!C.enabled)return;let h=C,E=Number(new Date),q=E-(c||E);h.diff=q,h.prev=c,h.curr=E,c=E,l[0]=e.coerce(l[0]),typeof l[0]!="string"&&l.unshift("%O");let w=0;l[0]=l[0].replace(/%([a-zA-Z%])/g,(I,J)=>{if(I==="%%")return"%";w++;let B=e.formatters[J];if(typeof B=="function"){let Z=l[w];I=B.call(h,Z),l.splice(w,1),w--}return I}),e.formatArgs.call(h,l),(h.log||e.log).apply(h,l)}return C.namespace=s,C.useColors=e.useColors(),C.color=e.selectColor(s),C.extend=o,C.destroy=e.destroy,Object.defineProperty(C,"enabled",{enumerable:!0,configurable:!1,get:()=>a!==null?a:(_!==e.namespaces&&(_=e.namespaces,T=e.enabled(s)),T),set:l=>{a=l}}),typeof e.init=="function"&&e.init(C),C}function o(s,c){let a=e(this.namespace+(typeof c>"u"?":":c)+s);return a.log=this.log,a}function n(s){e.save(s),e.namespaces=s,e.names=[],e.skips=[];let c,a=(typeof s=="string"?s:"").split(/[\s,]+/),_=a.length;for(c=0;c<_;c++)!a[c]||(s=a[c].replace(/\*/g,".*?"),s[0]==="-"?e.skips.push(new RegExp("^"+s.slice(1)+"$")):e.names.push(new RegExp("^"+s+"$")))}function i(){let s=[...e.names.map(d),...e.skips.map(d).map(c=>"-"+c)].join(",");return e.enable(""),s}function u(s){if(s[s.length-1]==="*")return!0;let c,a;for(c=0,a=e.skips.length;c<a;c++)if(e.skips[c].test(s))return!1;for(c=0,a=e.names.length;c<a;c++)if(e.names[c].test(s))return!0;return!1}function d(s){return s.toString().substring(2,s.toString().length-2).replace(/\.\*\?$/,"*")}function x(s){return s instanceof Error?s.stack||s.message:s}function F(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return e.enable(e.load()),e}M.exports=ue});var N=v((f,O)=>{f.formatArgs=le;f.save=Ce;f.load=de;f.useColors=fe;f.storage=he();f.destroy=(()=>{let r=!1;return()=>{r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();f.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function fe(){return typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs)?!0:typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function le(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+O.exports.humanize(this.diff),!this.useColors)return;let t="color: "+this.color;r.splice(1,0,t,"color: inherit");let e=0,o=0;r[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(e++,n==="%c"&&(o=e))}),r.splice(o,0,t)}f.log=console.debug||console.log||(()=>{});function Ce(r){try{r?f.storage.setItem("debug",r):f.storage.removeItem("debug")}catch{}}function de(){let r;try{r=f.storage.getItem("debug")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function he(){try{return localStorage}catch{}}O.exports=Y()(f);var{formatters:pe}=O.exports;pe.j=function(r){try{return JSON.stringify(r)}catch(t){return"[UnexpectedJSONParseError]: "+t.message}}});var we={};re(we,{co2:()=>W,default:()=>Ee,hosting:()=>K});var P=4883333333333333e-25;var k=class{constructor(t){this.options=t,this.KWH_PER_BYTE_FOR_NETWORK=P}perByte(t,e){if(t<1)return 0;if(e){let n=t*72e-12*0,i=t*P*475;return n+i}let o=72e-12+P;return t*o*519}};var j=k;var S=class{constructor(t){this.options=t,this.model=new j,t&&(this.model=new t.model)}perByte(t,e){return this.model.perByte(t,e)}perDomain(t,e){let o=[];for(let n of Object.keys(t.domains)){let i;e&&e.indexOf(n)>-1?i=this.perByte(t.domains[n].transferSize,!0):i=this.perByte(t.domains[n].transferSize),o.push({domain:n,co2:i,transferSize:t.domains[n].transferSize})}return o.sort((n,i)=>i.co2-n.co2),o}perPage(t,e){let o=this.perDomain(t,e),n=0;for(let i of o)n+=i.co2;return n}perContentType(t,e){let o={};for(let i of t.assets){let u=new URL(i.url).domain,d=i.transferSize,x=this.perByte(d,e&&e.indexOf(u)>-1),F=i.type;o[F]||(o[F]={co2:0,transferSize:0}),o[F].co2+=x,o[F].transferSize+=d}let n=[];for(let i of Object.keys(o))n.push({type:i,co2:o[i].co2,transferSize:o[i].transferSize});return n.sort((i,u)=>u.co2-i.co2),n}dirtiestResources(t,e){let o=[];for(let n of t.assets){let i=new URL(n.url).domain,u=n.transferSize,d=this.perByte(u,e&&e.indexOf(i)>-1);o.push({url:n.url,co2:d,transferSize:u})}return o.sort((n,i)=>i.co2-n.co2),o.slice(0,o.length>10?10:o.length)}perParty(t,e){let o=0,n=0,i=t.firstPartyRegEx;for(let u of Object.keys(t.domains))u.match(i)?o+=this.perByte(t.domains[u].transferSize,e&&e.indexOf(u)>-1):n+=this.perByte(t.domains[u].transferSize,e&&e.indexOf(u)>-1);return{firstParty:o,thirdParty:n}}};var W=S;var U=D(N());var $=D(N()),A=(0,$.default)("tgwf:hostingAPI");function Fe(r){return typeof r=="string"?me(r):ge(r)}async function me(r){return(await(await fetch(`https://api.thegreenwebfoundation.org/greencheck/${r}`)).json()).green}async function ge(r){try{let t="https://api.thegreenwebfoundation.org/v2/greencheckmulti",e=JSON.stringify(r),o=await fetch(`${t}/${e}`);A(`${t}/${e}`),A({req:o});let n=await o.text();A({textResult:n});let i=await o.json();return ye(i)}catch{return[]}}function ye(r){return Object.entries(r).filter(([o,n])=>n.green).map(([o,n])=>n.url)}var L={check:Fe};var Se=(0,U.default)("tgwf:hosting");function _e(r,t){return L.check(r)}var K={check:_e};var Ee={co2:W,hosting:K};return ne(we);})();
1
+ var co2=(()=>{var ue=Object.create;var B=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,Ce=Object.prototype.hasOwnProperty;var T=(r,t)=>()=>(t||r((t={exports:{}}).exports,t),t.exports),pe=(r,t)=>{for(var e in t)B(r,e,{get:t[e],enumerable:!0})},Y=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of fe(t))!Ce.call(r,o)&&o!==e&&B(r,o,{get:()=>t[o],enumerable:!(n=le(t,o))||n.enumerable});return r};var I=(r,t,e)=>(e=r!=null?ue(de(r)):{},Y(t||!r||!r.__esModule?B(e,"default",{value:r,enumerable:!0}):e,r)),me=r=>Y(B({},"__esModule",{value:!0}),r);var $=T((ze,L)=>{var E=1e3,F=E*60,_=F*60,y=_*24,ye=y*7,ge=y*365.25;L.exports=function(r,t){t=t||{};var e=typeof r;if(e==="string"&&r.length>0)return he(r);if(e==="number"&&isFinite(r))return t.long?Fe(r):Ee(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function he(r){if(r=String(r),!(r.length>100)){var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(!!t){var e=parseFloat(t[1]),n=(t[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"yrs":case"yr":case"y":return e*ge;case"weeks":case"week":case"w":return e*ye;case"days":case"day":case"d":return e*y;case"hours":case"hour":case"hrs":case"hr":case"h":return e*_;case"minutes":case"minute":case"mins":case"min":case"m":return e*F;case"seconds":case"second":case"secs":case"sec":case"s":return e*E;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return e;default:return}}}}function Ee(r){var t=Math.abs(r);return t>=y?Math.round(r/y)+"d":t>=_?Math.round(r/_)+"h":t>=F?Math.round(r/F)+"m":t>=E?Math.round(r/E)+"s":r+"ms"}function Fe(r){var t=Math.abs(r);return t>=y?v(r,t,y,"day"):t>=_?v(r,t,_,"hour"):t>=F?v(r,t,F,"minute"):t>=E?v(r,t,E,"second"):r+" ms"}function v(r,t,e,n){var o=t>=e*1.5;return Math.round(r/e)+" "+n+(o?"s":"")}});var M=T((Ye,U)=>{function _e(r){e.debug=e,e.default=e,e.coerce=h,e.disable=s,e.enable=o,e.enabled=a,e.humanize=$(),e.destroy=p,Object.keys(r).forEach(i=>{e[i]=r[i]}),e.names=[],e.skips=[],e.formatters={};function t(i){let c=0;for(let u=0;u<i.length;u++)c=(c<<5)-c+i.charCodeAt(u),c|=0;return e.colors[Math.abs(c)%e.colors.length]}e.selectColor=t;function e(i){let c,u=null,b,j;function C(...d){if(!C.enabled)return;let m=C,R=Number(new Date),ie=R-(c||R);m.diff=ie,m.prev=c,m.curr=R,c=R,d[0]=e.coerce(d[0]),typeof d[0]!="string"&&d.unshift("%O");let O=0;d[0]=d[0].replace(/%([a-zA-Z%])/g,(P,ce)=>{if(P==="%%")return"%";O++;let z=e.formatters[ce];if(typeof z=="function"){let ae=d[O];P=z.call(m,ae),d.splice(O,1),O--}return P}),e.formatArgs.call(m,d),(m.log||e.log).apply(m,d)}return C.namespace=i,C.useColors=e.useColors(),C.color=e.selectColor(i),C.extend=n,C.destroy=e.destroy,Object.defineProperty(C,"enabled",{enumerable:!0,configurable:!1,get:()=>u!==null?u:(b!==e.namespaces&&(b=e.namespaces,j=e.enabled(i)),j),set:d=>{u=d}}),typeof e.init=="function"&&e.init(C),C}function n(i,c){let u=e(this.namespace+(typeof c>"u"?":":c)+i);return u.log=this.log,u}function o(i){e.save(i),e.namespaces=i,e.names=[],e.skips=[];let c,u=(typeof i=="string"?i:"").split(/[\s,]+/),b=u.length;for(c=0;c<b;c++)!u[c]||(i=u[c].replace(/\*/g,".*?"),i[0]==="-"?e.skips.push(new RegExp("^"+i.slice(1)+"$")):e.names.push(new RegExp("^"+i+"$")))}function s(){let i=[...e.names.map(f),...e.skips.map(f).map(c=>"-"+c)].join(",");return e.enable(""),i}function a(i){if(i[i.length-1]==="*")return!0;let c,u;for(c=0,u=e.skips.length;c<u;c++)if(e.skips[c].test(i))return!1;for(c=0,u=e.names.length;c<u;c++)if(e.names[c].test(i))return!0;return!1}function f(i){return i.toString().substring(2,i.toString().length-2).replace(/\.\*\?$/,"*")}function h(i){return i instanceof Error?i.stack||i.message:i}function p(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return e.enable(e.load()),e}U.exports=_e});var x=T((l,N)=>{l.formatArgs=be;l.save=Re;l.load=Oe;l.useColors=we;l.storage=Be();l.destroy=(()=>{let r=!1;return()=>{r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();l.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function we(){return typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs)?!0:typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function be(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+N.exports.humanize(this.diff),!this.useColors)return;let t="color: "+this.color;r.splice(1,0,t,"color: inherit");let e=0,n=0;r[0].replace(/%[a-zA-Z%]/g,o=>{o!=="%%"&&(e++,o==="%c"&&(n=e))}),r.splice(n,0,t)}l.log=console.debug||console.log||(()=>{});function Re(r){try{r?l.storage.setItem("debug",r):l.storage.removeItem("debug")}catch{}}function Oe(){let r;try{r=l.storage.getItem("debug")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function Be(){try{return localStorage}catch{}}N.exports=M()(l);var{formatters:ve}=N.exports;ve.j=function(r){try{return JSON.stringify(r)}catch(t){return"[UnexpectedJSONParseError]: "+t.message}}});var De={};pe(De,{co2:()=>D,default:()=>We,hosting:()=>K});var A=4883333333333333e-25;var S=class{constructor(t){this.options=t,this.KWH_PER_BYTE_FOR_NETWORK=A}perByte(t,e){if(t<1)return 0;if(e){let o=t*72e-12*0,s=t*A*475;return o+s}let n=72e-12+A;return t*n*519}};var H=S;var te=I(x());var k={GIGABYTE:1e9};var w=r=>parseFloat(r.toFixed(2));var q=(0,te.default)("tgwf:sustainable-web-design"),Ne=.81,J=.52,Z=.14,Q=.15,X=.19,g=442,ee=50,xe=.75,Pe=.25,Te=.02,G=class{constructor(t){this.options=t}energyPerByteByComponent(t){let n=t/k.GIGABYTE*Ne;return{consumerDeviceEnergy:n*J,networkEnergy:n*Z,productionEnergy:n*X,dataCenterEnergy:n*Q}}co2byComponent(t,e=g){let n={};for(let[o,s]of Object.entries(t))o.startsWith("dataCenterEnergy")?(console.log(o),n[o]=s*e,console.log(n[o])):n[o]=s*g;return n}perByte(t,e=g){let n=this.energyPerByteByComponent(t);if(Boolean(e)===!1&&(e=g),e===!0&&(e=ee),typeof e!="number")throw new Error(`perByte expects a numeric value or boolean for the carbon intensity value. Received: ${e}`);let o=this.co2byComponent(n,e);return Object.values(o).reduce((a,f)=>a+f)}perVisit(t,e=g){let n=this.energyPerVisitByComponent(t);if(Boolean(e)===!1&&(e=g),e===!0&&(e=ee),typeof e!="number")throw new Error(`perVisit expects a numeric value or boolean for the carbon intensity value. Received: ${e}`);let o=this.co2byComponent(n,e);return Object.values(o).reduce((a,f)=>a+f)}energyPerByte(t){let e=this.energyPerByteByComponent(t);return Object.values(e).reduce((o,s)=>o+s)}energyPerVisitByComponent(t,e=xe,n=Pe,o=Te){let s=this.energyPerByteByComponent(t),a={};q({energyBycomponent:s});let f=Object.values(s);for(let[h,p]of Object.entries(s))a[`${h} - first`]=p*e,a[`${h} - subsequent`]=p*n*o;return q({cacheAdjustedSegmentEnergy:a}),a}energyPerVisit(t){let e=0,n=0,o=Object.entries(this.energyPerVisitByComponent(t));for(let[s,a]of o)s.indexOf("first")>0&&(e+=a);for(let[s,a]of o)s.indexOf("subsequent")>0&&(n+=a);return e+n}emissionsPerVisitInGrams(t,e=g){return w(t*e)}annualEnergyInKwh(t,e=1e3){return t*e*12}annualEmissionsInGrams(t,e=1e3){return t*e*12}annualSegmentEnergy(t){return{consumerDeviceEnergy:w(t*J),networkEnergy:w(t*Z),dataCenterEnergy:w(t*Q),productionEnergy:w(t*X)}}};var re=G;var W=class{constructor(t){this.model=new re,t?.model==="1byte"&&(this.model=new H)}perByte(t,e){return this.model.perByte(t,e)}perVisit(t,e){return this.model?.perVisit?this.model.perVisit(t,e):(console.warn("The model you have selected does not support perVisit. Using perByte instead."),this.model.perByte(t,e))}perDomain(t,e){let n=[];for(let o of Object.keys(t.domains)){let s;e&&e.indexOf(o)>-1?s=this.perByte(t.domains[o].transferSize,!0):s=this.perByte(t.domains[o].transferSize),n.push({domain:o,co2:s,transferSize:t.domains[o].transferSize})}return n.sort((o,s)=>s.co2-o.co2),n}perPage(t,e){let n=this.perDomain(t,e),o=0;for(let s of n)o+=s.co2;return o}perContentType(t,e){let n={};for(let s of t.assets){let a=new URL(s.url).domain,f=s.transferSize,h=this.perByte(f,e&&e.indexOf(a)>-1),p=s.type;n[p]||(n[p]={co2:0,transferSize:0}),n[p].co2+=h,n[p].transferSize+=f}let o=[];for(let s of Object.keys(n))o.push({type:s,co2:n[s].co2,transferSize:n[s].transferSize});return o.sort((s,a)=>a.co2-s.co2),o}dirtiestResources(t,e){let n=[];for(let o of t.assets){let s=new URL(o.url).domain,a=o.transferSize,f=this.perByte(a,e&&e.indexOf(s)>-1);n.push({url:o.url,co2:f,transferSize:a})}return n.sort((o,s)=>s.co2-o.co2),n.slice(0,n.length>10?10:n.length)}perParty(t,e){let n=0,o=0,s=t.firstPartyRegEx;for(let a of Object.keys(t.domains))a.match(s)?n+=this.perByte(t.domains[a].transferSize,e&&e.indexOf(a)>-1):o+=this.perByte(t.domains[a].transferSize,e&&e.indexOf(a)>-1);return{firstParty:n,thirdParty:o}}};var D=W;var se=I(x());var ne=I(x()),V=(0,ne.default)("tgwf:hostingAPI");function Ie(r){return typeof r=="string"?Ae(r):Se(r)}async function Ae(r){return(await(await fetch(`https://api.thegreenwebfoundation.org/greencheck/${r}`)).json()).green}async function Se(r){try{let t="https://api.thegreenwebfoundation.org/v2/greencheckmulti",e=JSON.stringify(r),n=await fetch(`${t}/${e}`);V(`${t}/${e}`),V({req:n});let o=await n.text();V({textResult:o});let s=await n.json();return ke(s)}catch{return[]}}function ke(r){return Object.entries(r).filter(([n,o])=>o.green).map(([n,o])=>o.url)}var oe={check:Ie};var tt=(0,se.default)("tgwf:hosting");function Ge(r,t){return oe.check(r)}var K={check:Ge};var We={co2:D,hosting:K};return me(De);})();
2
2
  //# sourceMappingURL=index.js.map