@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.
- package/.esbuild.browser.js +1 -1
- package/.gitpod.yml +8 -0
- package/CHANGELOG.md +15 -1
- package/README.md +36 -62
- package/dist/cjs/co2.js +13 -4
- package/dist/cjs/co2.js.map +2 -2
- package/dist/cjs/co2.test.js +33 -7
- package/dist/cjs/co2.test.js.map +2 -2
- package/dist/cjs/constants/file-size.js +1 -1
- package/dist/cjs/constants/file-size.js.map +2 -2
- package/dist/cjs/sustainable-web-design.js +23 -23
- package/dist/cjs/sustainable-web-design.js.map +2 -2
- package/dist/cjs/sustainable-web-design.test.js +13 -14
- package/dist/cjs/sustainable-web-design.test.js.map +2 -2
- package/dist/esm/co2.js +13 -4
- package/dist/esm/co2.test.js +34 -8
- package/dist/esm/constants/file-size.js +1 -1
- package/dist/esm/sustainable-web-design.js +23 -23
- package/dist/esm/sustainable-web-design.test.js +13 -14
- package/package.json +3 -2
- package/public/index.html +8 -5
- package/public/index.js +1 -1
- package/public/index.js.map +3 -3
- package/src/co2.js +24 -6
- package/src/constants/file-size.js +1 -1
- package/src/sustainable-web-design.js +48 -48
- package/.tool-versions +0 -1
|
@@ -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(
|
|
24
|
-
expect(groupedEnergy.networkEnergy).toBeCloseTo(
|
|
25
|
-
expect(groupedEnergy.
|
|
26
|
-
expect(groupedEnergy.
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;AAAA,oCAAiC;AAEjC,SAAS,gCAAgC,MAAM;AAC7C,QAAM,MAAM,IAAI,sCAAqB;AACrC,QAAM,wBAAwB;AAE9B,WAAS,4BAA4B,MAAM;AACzC,OAAG,iEAAiE,MAAM;
|
|
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.
|
|
6
|
-
|
|
7
|
-
|
|
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)) {
|
package/dist/esm/co2.test.js
CHANGED
|
@@ -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
|
|
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.
|
|
121
|
-
const MILLION_GREEN = 0.
|
|
122
|
-
const
|
|
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.
|
|
126
|
+
const TGWF_MIXED_VALUE = 0.22175;
|
|
125
127
|
beforeEach(() => {
|
|
126
|
-
co2 = new CO2(
|
|
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
|
});
|
|
@@ -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
|
|
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
|
|
77
|
-
let
|
|
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
|
-
|
|
96
|
+
firstVisits += val;
|
|
82
97
|
}
|
|
83
98
|
}
|
|
84
99
|
for (const [key, val] of energyBycomponent) {
|
|
85
100
|
if (key.indexOf("subsequent") > 0) {
|
|
86
|
-
|
|
101
|
+
subsequentVisits += val;
|
|
87
102
|
}
|
|
88
103
|
}
|
|
89
|
-
|
|
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(
|
|
9
|
-
expect(groupedEnergy.networkEnergy).toBeCloseTo(
|
|
10
|
-
expect(groupedEnergy.
|
|
11
|
-
expect(groupedEnergy.
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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({
|
|
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
|