@tgwf/co2 0.13.2 → 0.13.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/README.md CHANGED
@@ -96,6 +96,17 @@ We use [`np`](https://www.npmjs.com/package/np) to publish new versions of this
96
96
  3. `np` will run several automated steps to publish the new package to NPM.
97
97
  4. If everything runs successfully, you can then add release notes to GitHub for the newly published package.
98
98
 
99
+ ## Release communication
100
+
101
+ CO2.js releases will be communicated through the following channels:
102
+
103
+ | Channel | Minor Release (0.xx) | Patch Release (0.xx.x) |
104
+ |----------|----------------------|----------------------|
105
+ | [Github](https://github.com/thegreenwebfoundation/co2.js/releases) | ✅ | ✅ |
106
+ | [Green Web Foundation website](https://www.thegreenwebfoundation.org/co2-js/#releases) | ✅ | ❌ |
107
+ | W3C Slack Sustainability Channel | ✅ | ❌ |
108
+ | ClimateAction.Tech Slack | ✅ | ❌ |
109
+ | [Green Web Foundation LinkedIn Account](https://www.linkedin.com/company/green-web-foundation/) | ✅ | ❌ |
99
110
 
100
111
  ## Licenses
101
112
 
@@ -34,12 +34,13 @@ __export(constants_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(constants_exports);
36
36
  var import_file_size = __toESM(require("./file-size.js"));
37
+ var import__ = require("../index.js");
37
38
  const KWH_PER_GB = 0.81;
38
39
  const END_USER_DEVICE_ENERGY = 0.52;
39
40
  const NETWORK_ENERGY = 0.14;
40
41
  const DATACENTER_ENERGY = 0.15;
41
42
  const PRODUCTION_ENERGY = 0.19;
42
- const GLOBAL_GRID_INTENSITY = 442;
43
+ const GLOBAL_GRID_INTENSITY = import__.averageIntensity.data["WORLD"];
43
44
  const RENEWABLES_GRID_INTENSITY = 50;
44
45
  const FIRST_TIME_VIEWING_PERCENTAGE = 0.75;
45
46
  const RETURNING_VISITOR_PERCENTAGE = 0.25;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/constants/index.js"],
4
- "sourcesContent": ["import fileSize from \"./file-size.js\";\n\n// SUSTAINABLE WEB DESIGN CONSTANTS\n// this refers to the estimated total energy use for the internet around 2000 TWh,\n// divided by the total transfer it enables around 2500 exabytes\nconst KWH_PER_GB = 0.81;\n\n// these constants outline how the energy is attributed to\n// different parts of the system in the SWD model\nconst END_USER_DEVICE_ENERGY = 0.52;\nconst NETWORK_ENERGY = 0.14;\nconst DATACENTER_ENERGY = 0.15;\nconst PRODUCTION_ENERGY = 0.19;\n\n// These carbon intensity figures https://ember-climate.org/data/data-explorer\n// - Global carbon intensity for 2021\nconst GLOBAL_GRID_INTENSITY = 442;\nconst RENEWABLES_GRID_INTENSITY = 50;\n\n// Taken from: https://gitlab.com/wholegrain/carbon-api-2-0/-/blob/master/includes/carbonapi.php\n\nconst FIRST_TIME_VIEWING_PERCENTAGE = 0.75;\nconst RETURNING_VISITOR_PERCENTAGE = 0.25;\nconst PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD = 0.02;\n\nexport {\n fileSize,\n KWH_PER_GB,\n END_USER_DEVICE_ENERGY,\n NETWORK_ENERGY,\n DATACENTER_ENERGY,\n PRODUCTION_ENERGY,\n GLOBAL_GRID_INTENSITY,\n RENEWABLES_GRID_INTENSITY,\n FIRST_TIME_VIEWING_PERCENTAGE,\n RETURNING_VISITOR_PERCENTAGE,\n PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD,\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAqB;AAKrB,MAAM,aAAa;AAInB,MAAM,yBAAyB;AAC/B,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAI1B,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAIlC,MAAM,gCAAgC;AACtC,MAAM,+BAA+B;AACrC,MAAM,+CAA+C;",
4
+ "sourcesContent": ["import fileSize from \"./file-size.js\";\nimport { averageIntensity } from \"../index.js\";\n\n// SUSTAINABLE WEB DESIGN CONSTANTS\n// this refers to the estimated total energy use for the internet around 2000 TWh,\n// divided by the total transfer it enables around 2500 exabytes\nconst KWH_PER_GB = 0.81;\n\n// these constants outline how the energy is attributed to\n// different parts of the system in the SWD model\nconst END_USER_DEVICE_ENERGY = 0.52;\nconst NETWORK_ENERGY = 0.14;\nconst DATACENTER_ENERGY = 0.15;\nconst PRODUCTION_ENERGY = 0.19;\n\n// These carbon intensity figures https://ember-climate.org/data/data-explorer\n// - Global carbon intensity for 2022\nconst GLOBAL_GRID_INTENSITY = averageIntensity.data[\"WORLD\"];\nconst RENEWABLES_GRID_INTENSITY = 50;\n\n// Taken from: https://gitlab.com/wholegrain/carbon-api-2-0/-/blob/master/includes/carbonapi.php\n\nconst FIRST_TIME_VIEWING_PERCENTAGE = 0.75;\nconst RETURNING_VISITOR_PERCENTAGE = 0.25;\nconst PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD = 0.02;\n\nexport {\n fileSize,\n KWH_PER_GB,\n END_USER_DEVICE_ENERGY,\n NETWORK_ENERGY,\n DATACENTER_ENERGY,\n PRODUCTION_ENERGY,\n GLOBAL_GRID_INTENSITY,\n RENEWABLES_GRID_INTENSITY,\n FIRST_TIME_VIEWING_PERCENTAGE,\n RETURNING_VISITOR_PERCENTAGE,\n PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAqB;AACrB,eAAiC;AAKjC,MAAM,aAAa;AAInB,MAAM,yBAAyB;AAC/B,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAI1B,MAAM,wBAAwB,0BAAiB,KAAK;AACpD,MAAM,4BAA4B;AAIlC,MAAM,gCAAgC;AACtC,MAAM,+BAA+B;AACrC,MAAM,+CAA+C;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,15 +15,12 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- 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));
21
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
19
  var hosting_api_exports = {};
23
20
  __export(hosting_api_exports, {
24
21
  default: () => hosting_api_default
25
22
  });
26
23
  module.exports = __toCommonJS(hosting_api_exports);
27
- var import_debug = __toESM(require("debug"));
28
- const log = (0, import_debug.default)("tgwf:hostingAPI");
29
24
  function check(domain) {
30
25
  if (typeof domain === "string") {
31
26
  return checkAgainstAPI(domain);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hosting-api.js"],
4
- "sourcesContent": ["\"use strict\";\n\nimport debugFactory from \"debug\";\nconst log = debugFactory(\"tgwf:hostingAPI\");\n\nfunction check(domain) {\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkAgainstAPI(domain);\n } else {\n return checkDomainsAgainstAPI(domain);\n }\n}\n\nasync function checkAgainstAPI(domain) {\n const req = await fetch(\n `https://api.thegreenwebfoundation.org/greencheck/${domain}`\n );\n const res = await req.json();\n return res.green;\n}\n\nasync function checkDomainsAgainstAPI(domains) {\n try {\n const apiPath = \"https://api.thegreenwebfoundation.org/v2/greencheckmulti\";\n const domainsString = JSON.stringify(domains);\n\n const req = await fetch(`${apiPath}/${domainsString}`);\n\n // sanity check API result. Is this the library or\n // the actual API request that's the problem?\n // Is nock mocking node-native fetch API calls properly?\n // Commented out the logs for now, as they cause an error to be thrown when using the library.\n // log(`${apiPath}/${domainsString}`);\n // log({ req });\n // const textResult = await req.text();\n // log({ textResult });\n\n const allGreenCheckResults = await req.json();\n\n return greenDomainsFromResults(allGreenCheckResults);\n } catch (e) {\n return [];\n }\n}\n\nfunction greenDomainsFromResults(greenResults) {\n const entries = Object.entries(greenResults);\n const greenEntries = entries.filter(([key, val]) => val.green);\n return greenEntries.map(([key, val]) => val.url);\n}\n\nexport default {\n check,\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAyB;AACzB,MAAM,MAAM,0BAAa,iBAAiB;AAE1C,eAAe,QAAQ;AAErB,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,gBAAgB,MAAM;AAAA,EAC/B,OAAO;AACL,WAAO,uBAAuB,MAAM;AAAA,EACtC;AACF;AAEA,+BAA+B,QAAQ;AACrC,QAAM,MAAM,MAAM,MAChB,oDAAoD,QACtD;AACA,QAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,SAAO,IAAI;AACb;AAEA,sCAAsC,SAAS;AAC7C,MAAI;AACF,UAAM,UAAU;AAChB,UAAM,gBAAgB,KAAK,UAAU,OAAO;AAE5C,UAAM,MAAM,MAAM,MAAM,GAAG,WAAW,eAAe;AAWrD,UAAM,uBAAuB,MAAM,IAAI,KAAK;AAE5C,WAAO,wBAAwB,oBAAoB;AAAA,EACrD,SAAS,GAAP;AACA,WAAO,CAAC;AAAA,EACV;AACF;AAEA,iCAAiC,cAAc;AAC7C,QAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,QAAM,eAAe,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK;AAC7D,SAAO,aAAa,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,GAAG;AACjD;AAEA,IAAO,sBAAQ;AAAA,EACb;AACF;",
4
+ "sourcesContent": ["\"use strict\";\n\n/**\n * Check if a string or array of domains has been provided\n * @param {string|array} domain - The domain to check, or an array of domains to be checked.\n */\n\nfunction check(domain) {\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkAgainstAPI(domain);\n } else {\n return checkDomainsAgainstAPI(domain);\n }\n}\n\n/**\n * Check if a domain is hosted by a green web host by querying the Green Web Foundation API.\n * @param {string} domain - The domain to check.\n * @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host.\n */\nasync function checkAgainstAPI(domain) {\n const req = await fetch(\n `https://api.thegreenwebfoundation.org/greencheck/${domain}`\n );\n const res = await req.json();\n return res.green;\n}\n\n/**\n * Check if an array of domains is hosted by a green web host by querying the Green Web Foundation API.\n * @param {array} domains - An array of domains to check.\n * @returns {array} - An array of domains that are hosted by a green web host.\n */\n\nasync function checkDomainsAgainstAPI(domains) {\n try {\n const apiPath = \"https://api.thegreenwebfoundation.org/v2/greencheckmulti\";\n const domainsString = JSON.stringify(domains);\n\n const req = await fetch(`${apiPath}/${domainsString}`);\n\n const allGreenCheckResults = await req.json();\n\n return greenDomainsFromResults(allGreenCheckResults);\n } catch (e) {\n return [];\n }\n}\n\n/**\n * Extract the green domains from the results of a green check.\n * @param {object} greenResults - The results of a green check.\n * @returns {array} - An array of domains that are hosted by a green web host.\n */\nfunction greenDomainsFromResults(greenResults) {\n const entries = Object.entries(greenResults);\n const greenEntries = entries.filter(([key, val]) => val.green);\n return greenEntries.map(([key, val]) => val.url);\n}\n\nexport default {\n check,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,eAAe,QAAQ;AAErB,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,gBAAgB,MAAM;AAAA,EAC/B,OAAO;AACL,WAAO,uBAAuB,MAAM;AAAA,EACtC;AACF;AAOA,+BAA+B,QAAQ;AACrC,QAAM,MAAM,MAAM,MAChB,oDAAoD,QACtD;AACA,QAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,SAAO,IAAI;AACb;AAQA,sCAAsC,SAAS;AAC7C,MAAI;AACF,UAAM,UAAU;AAChB,UAAM,gBAAgB,KAAK,UAAU,OAAO;AAE5C,UAAM,MAAM,MAAM,MAAM,GAAG,WAAW,eAAe;AAErD,UAAM,uBAAuB,MAAM,IAAI,KAAK;AAE5C,WAAO,wBAAwB,oBAAoB;AAAA,EACrD,SAAS,GAAP;AACA,WAAO,CAAC;AAAA,EACV;AACF;AAOA,iCAAiC,cAAc;AAC7C,QAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,QAAM,eAAe,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK;AAC7D,SAAO,aAAa,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,GAAG;AACjD;AAEA,IAAO,sBAAQ;AAAA,EACb;AACF;",
6
6
  "names": []
7
7
  }
@@ -17,10 +17,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
17
17
  var import_fs = __toESM(require("fs"));
18
18
  var import_zlib = __toESM(require("zlib"));
19
19
  var import_util = require("util");
20
- var import_debug = __toESM(require("debug"));
21
20
  const readFile = (0, import_util.promisify)(import_fs.default.readFile);
22
21
  const gunzip = (0, import_util.promisify)(import_zlib.default.gunzip);
23
- const log = (0, import_debug.default)("tgwf:hostingCache");
24
22
  async function streamToString(stream) {
25
23
  return new Promise((resolve, reject) => {
26
24
  const chunks = [];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hosting-json.node.js"],
4
- "sourcesContent": ["\"use strict\";\n\nimport fs from \"fs\";\nimport zlib from \"zlib\";\nimport { promisify } from \"util\";\n\nconst readFile = promisify(fs.readFile);\nconst gunzip = promisify(zlib.gunzip);\n\nimport debugFactory from \"debug\";\nconst log = debugFactory(\"tgwf:hostingCache\");\n\nasync function streamToString(stream) {\n return new Promise((resolve, reject) => {\n const chunks = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (chunk) => chunks.push(chunk));\n stream.on(\"end\", () => resolve(Buffer.concat(chunks)));\n });\n}\n\nasync function getGzippedFileAsJson(jsonPath) {\n const readStream = fs.createReadStream(jsonPath);\n const text = await streamToString(readStream);\n const unzipped = await gunzip(text);\n return unzipped.toString();\n}\n\nasync function loadJSON(jsonPath) {\n const jsonBuffer = jsonPath.endsWith(\".gz\")\n ? await getGzippedFileAsJson(jsonPath)\n : await readFile(jsonPath);\n return JSON.parse(jsonBuffer);\n}\n\nasync function check(domain, db) {\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkInJSON(domain, db);\n } else {\n return checkDomainsInJSON(domain, db);\n }\n}\n\nfunction checkInJSON(domain, db) {\n if (db.indexOf(domain) > -1) {\n return true;\n }\n return false;\n}\n\nfunction greenDomainsFromResults(greenResults) {\n const entries = Object.entries(greenResults);\n const greenEntries = entries.filter(([key, val]) => val.green);\n\n return greenEntries.map(([key, val]) => val.url);\n}\n\nfunction checkDomainsInJSON(domains, db) {\n let greenDomains = [];\n\n for (let domain of domains) {\n if (db.indexOf(domain) > -1) {\n greenDomains.push(domain);\n }\n }\n return greenDomains;\n}\n\nmodule.exports = {\n check,\n loadJSON,\n greenDomainsFromResults,\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;AAEA,gBAAe;AACf,kBAAiB;AACjB,kBAA0B;AAK1B,mBAAyB;AAHzB,MAAM,WAAW,2BAAU,kBAAG,QAAQ;AACtC,MAAM,SAAS,2BAAU,oBAAK,MAAM;AAGpC,MAAM,MAAM,0BAAa,mBAAmB;AAE5C,8BAA8B,QAAQ;AACpC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,CAAC;AAChB,WAAO,GAAG,SAAS,MAAM;AACzB,WAAO,GAAG,QAAQ,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC;AAC/C,WAAO,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,EACvD,CAAC;AACH;AAEA,oCAAoC,UAAU;AAC5C,QAAM,aAAa,kBAAG,iBAAiB,QAAQ;AAC/C,QAAM,OAAO,MAAM,eAAe,UAAU;AAC5C,QAAM,WAAW,MAAM,OAAO,IAAI;AAClC,SAAO,SAAS,SAAS;AAC3B;AAEA,wBAAwB,UAAU;AAChC,QAAM,aAAa,SAAS,SAAS,KAAK,IACtC,MAAM,qBAAqB,QAAQ,IACnC,MAAM,SAAS,QAAQ;AAC3B,SAAO,KAAK,MAAM,UAAU;AAC9B;AAEA,qBAAqB,QAAQ,IAAI;AAE/B,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,YAAY,QAAQ,EAAE;AAAA,EAC/B,OAAO;AACL,WAAO,mBAAmB,QAAQ,EAAE;AAAA,EACtC;AACF;AAEA,qBAAqB,QAAQ,IAAI;AAC/B,MAAI,GAAG,QAAQ,MAAM,IAAI,IAAI;AAC3B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,iCAAiC,cAAc;AAC7C,QAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,QAAM,eAAe,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK;AAE7D,SAAO,aAAa,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,GAAG;AACjD;AAEA,4BAA4B,SAAS,IAAI;AACvC,MAAI,eAAe,CAAC;AAEpB,WAAS,UAAU,SAAS;AAC1B,QAAI,GAAG,QAAQ,MAAM,IAAI,IAAI;AAC3B,mBAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEA,OAAO,UAAU;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["\"use strict\";\n\nimport fs from \"fs\";\nimport zlib from \"zlib\";\nimport { promisify } from \"util\";\n\nconst readFile = promisify(fs.readFile);\nconst gunzip = promisify(zlib.gunzip);\n\n/**\n * Converts a readable stream to a string.\n * @param {ReadableStream} stream - The readable stream to convert.\n * @returns {Promise<string>} A promise that resolves to the string representation of the stream.\n */\nasync function streamToString(stream) {\n return new Promise((resolve, reject) => {\n const chunks = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (chunk) => chunks.push(chunk));\n stream.on(\"end\", () => resolve(Buffer.concat(chunks)));\n });\n}\n\n/**\n * Get the contents of a gzipped file as a JSON string.\n * @param {string} jsonPath - The path to the gzipped JSON file.\n * @returns {Promise<string>} A promise that resolves to the JSON string.\n */\nasync function getGzippedFileAsJson(jsonPath) {\n const readStream = fs.createReadStream(jsonPath);\n const text = await streamToString(readStream);\n const unzipped = await gunzip(text);\n return unzipped.toString();\n}\n\n/**\n * Loads JSON data from a file path.\n * @param {string} jsonPath - The path to the JSON file.\n * @returns {Promise<object>} A promise that resolves to the parsed JSON object.\n */\nasync function loadJSON(jsonPath) {\n const jsonBuffer = jsonPath.endsWith(\".gz\")\n ? await getGzippedFileAsJson(jsonPath)\n : await readFile(jsonPath);\n return JSON.parse(jsonBuffer);\n}\n\n/**\n * Check if a string or array of domains has been provided\n * @param {string|array} domain - The domain to check, or an array of domains to be checked.\n */\nasync function check(domain, db) {\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkInJSON(domain, db);\n } else {\n return checkDomainsInJSON(domain, db);\n }\n}\n\n/**\n * Check if a domain is hosted by a green web host by querying the database.\n * @param {string} domain - The domain to check.\n * @param {object} db - The database to check against.\n * @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host.\n */\nfunction checkInJSON(domain, db) {\n if (db.indexOf(domain) > -1) {\n return true;\n }\n return false;\n}\n\n/**\n * Extract the green domains from the results of a green check.\n * @param {object} greenResults - The results of a green check.\n * @returns {array} - An array of domains that are hosted by a green web host.\n */\nfunction greenDomainsFromResults(greenResults) {\n const entries = Object.entries(greenResults);\n const greenEntries = entries.filter(([key, val]) => val.green);\n\n return greenEntries.map(([key, val]) => val.url);\n}\n\n/**\n * Check if an array of domains is hosted by a green web host by querying the database.\n * @param {array} domains - An array of domains to check.\n * @param {object} db - The database to check against.\n * @returns {array} - An array of domains that are hosted by a green web host.\n */\nfunction checkDomainsInJSON(domains, db) {\n let greenDomains = [];\n\n for (let domain of domains) {\n if (db.indexOf(domain) > -1) {\n greenDomains.push(domain);\n }\n }\n return greenDomains;\n}\n\nmodule.exports = {\n check,\n loadJSON,\n greenDomainsFromResults,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;AAEA,gBAAe;AACf,kBAAiB;AACjB,kBAA0B;AAE1B,MAAM,WAAW,2BAAU,kBAAG,QAAQ;AACtC,MAAM,SAAS,2BAAU,oBAAK,MAAM;AAOpC,8BAA8B,QAAQ;AACpC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,CAAC;AAChB,WAAO,GAAG,SAAS,MAAM;AACzB,WAAO,GAAG,QAAQ,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC;AAC/C,WAAO,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,EACvD,CAAC;AACH;AAOA,oCAAoC,UAAU;AAC5C,QAAM,aAAa,kBAAG,iBAAiB,QAAQ;AAC/C,QAAM,OAAO,MAAM,eAAe,UAAU;AAC5C,QAAM,WAAW,MAAM,OAAO,IAAI;AAClC,SAAO,SAAS,SAAS;AAC3B;AAOA,wBAAwB,UAAU;AAChC,QAAM,aAAa,SAAS,SAAS,KAAK,IACtC,MAAM,qBAAqB,QAAQ,IACnC,MAAM,SAAS,QAAQ;AAC3B,SAAO,KAAK,MAAM,UAAU;AAC9B;AAMA,qBAAqB,QAAQ,IAAI;AAE/B,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,YAAY,QAAQ,EAAE;AAAA,EAC/B,OAAO;AACL,WAAO,mBAAmB,QAAQ,EAAE;AAAA,EACtC;AACF;AAQA,qBAAqB,QAAQ,IAAI;AAC/B,MAAI,GAAG,QAAQ,MAAM,IAAI,IAAI;AAC3B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOA,iCAAiC,cAAc;AAC7C,QAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,QAAM,eAAe,QAAQ,OAAO,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK;AAE7D,SAAO,aAAa,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,GAAG;AACjD;AAQA,4BAA4B,SAAS,IAAI;AACvC,MAAI,eAAe,CAAC;AAEpB,WAAS,UAAU,SAAS;AAC1B,QAAI,GAAG,QAAQ,MAAM,IAAI,IAAI;AAC3B,mBAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEA,OAAO,UAAU;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -24,15 +24,12 @@ __export(hosting_node_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(hosting_node_exports);
26
26
  var import_https = __toESM(require("https"));
27
- var import_debug = __toESM(require("debug"));
28
27
  var import_hosting_json_node = __toESM(require("./hosting-json.node.js"));
29
- const log = (0, import_debug.default)("tgwf:hosting-node");
30
28
  async function getBody(url) {
31
29
  return new Promise(function(resolve, reject) {
32
30
  const req = import_https.default.get(url, function(res) {
33
31
  if (res.statusCode < 200 || res.statusCode >= 300) {
34
- log("Could not get info from the Green Web Foundation API, %s for %s", res.statusCode, url);
35
- return reject(new Error(`Status Code: ${res.statusCode}`));
32
+ return reject(new Error(`Could not get info from: ${url}. Status Code: ${res.statusCode}`));
36
33
  }
37
34
  const data = [];
38
35
  res.on("data", (chunk) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hosting-node.js"],
4
- "sourcesContent": ["/*\n\nWe have a separate node-specific hosting.js file for node.\nThis uses the node-specific APIs for making http requests,\nand doing lookups against local JSON and sqlite databases.\nThis is used in the CommonJS build of co2.js\n\nThis lets us keep the total library small, and dependencies minimal.\n*/\n\nimport https from \"https\";\n\nimport debugFactory from \"debug\";\nconst log = debugFactory(\"tgwf:hosting-node\");\n\nimport hostingJSON from \"./hosting-json.node.js\";\n\n/**\n * Accept a url and perform an http request, returning the body\n * for parsing as JSON.\n *\n * @param {string} url\n * @return {string}\n */\nasync function getBody(url) {\n return new Promise(function (resolve, reject) {\n // Do async job\n const req = https.get(url, function (res) {\n if (res.statusCode < 200 || res.statusCode >= 300) {\n log(\n \"Could not get info from the Green Web Foundation API, %s for %s\",\n res.statusCode,\n url\n );\n return reject(new Error(`Status Code: ${res.statusCode}`));\n }\n const data = [];\n\n res.on(\"data\", (chunk) => {\n data.push(chunk);\n });\n\n res.on(\"end\", () => resolve(Buffer.concat(data).toString()));\n });\n req.end();\n });\n}\n\nfunction check(domain, db) {\n if (db) {\n return hostingJSON.check(domain, db);\n }\n\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkAgainstAPI(domain);\n } else {\n return checkDomainsAgainstAPI(domain);\n }\n}\n\nasync function checkAgainstAPI(domain) {\n const res = JSON.parse(\n await getBody(`https://api.thegreenwebfoundation.org/greencheck/${domain}`)\n );\n return res.green;\n}\n\nasync function checkDomainsAgainstAPI(domains) {\n try {\n const allGreenCheckResults = JSON.parse(\n await getBody(\n `https://api.thegreenwebfoundation.org/v2/greencheckmulti/${JSON.stringify(\n domains\n )}`\n )\n );\n return hostingJSON.greenDomainsFromResults(allGreenCheckResults);\n } catch (e) {\n return [];\n }\n}\n\nasync function checkPage(pageXray, db) {\n const domains = Object.keys(pageXray.domains);\n return check(domains, db);\n}\n\nexport default {\n check,\n checkPage,\n greendomains: hostingJSON.greenDomainsFromResults,\n loadJSON: hostingJSON.loadJSON,\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,mBAAkB;AAElB,mBAAyB;AAGzB,+BAAwB;AAFxB,MAAM,MAAM,0BAAa,mBAAmB;AAW5C,uBAAuB,KAAK;AAC1B,SAAO,IAAI,QAAQ,SAAU,SAAS,QAAQ;AAE5C,UAAM,MAAM,qBAAM,IAAI,KAAK,SAAU,KAAK;AACxC,UAAI,IAAI,aAAa,OAAO,IAAI,cAAc,KAAK;AACjD,YACE,mEACA,IAAI,YACJ,GACF;AACA,eAAO,OAAO,IAAI,MAAM,gBAAgB,IAAI,YAAY,CAAC;AAAA,MAC3D;AACA,YAAM,OAAO,CAAC;AAEd,UAAI,GAAG,QAAQ,CAAC,UAAU;AACxB,aAAK,KAAK,KAAK;AAAA,MACjB,CAAC;AAED,UAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,IAAI,EAAE,SAAS,CAAC,CAAC;AAAA,IAC7D,CAAC;AACD,QAAI,IAAI;AAAA,EACV,CAAC;AACH;AAEA,eAAe,QAAQ,IAAI;AACzB,MAAI,IAAI;AACN,WAAO,iCAAY,MAAM,QAAQ,EAAE;AAAA,EACrC;AAGA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,gBAAgB,MAAM;AAAA,EAC/B,OAAO;AACL,WAAO,uBAAuB,MAAM;AAAA,EACtC;AACF;AAEA,+BAA+B,QAAQ;AACrC,QAAM,MAAM,KAAK,MACf,MAAM,QAAQ,oDAAoD,QAAQ,CAC5E;AACA,SAAO,IAAI;AACb;AAEA,sCAAsC,SAAS;AAC7C,MAAI;AACF,UAAM,uBAAuB,KAAK,MAChC,MAAM,QACJ,4DAA4D,KAAK,UAC/D,OACF,GACF,CACF;AACA,WAAO,iCAAY,wBAAwB,oBAAoB;AAAA,EACjE,SAAS,GAAP;AACA,WAAO,CAAC;AAAA,EACV;AACF;AAEA,yBAAyB,UAAU,IAAI;AACrC,QAAM,UAAU,OAAO,KAAK,SAAS,OAAO;AAC5C,SAAO,MAAM,SAAS,EAAE;AAC1B;AAEA,IAAO,uBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA,cAAc,iCAAY;AAAA,EAC1B,UAAU,iCAAY;AACxB;",
4
+ "sourcesContent": ["/*\n\nWe have a separate node-specific hosting.js file for node.\nThis uses the node-specific APIs for making http requests,\nand doing lookups against local JSON and sqlite databases.\nThis is used in the CommonJS build of co2.js\n\nThis lets us keep the total library small, and dependencies minimal.\n*/\n\nimport https from \"https\";\n\nimport hostingJSON from \"./hosting-json.node.js\";\n\n/**\n * Accept a url and perform an http request, returning the body\n * for parsing as JSON.\n *\n * @param {string} url\n * @return {string}\n */\nasync function getBody(url) {\n return new Promise(function (resolve, reject) {\n // Do async job\n const req = https.get(url, function (res) {\n if (res.statusCode < 200 || res.statusCode >= 300) {\n return reject(\n new Error(\n `Could not get info from: ${url}. Status Code: ${res.statusCode}`\n )\n );\n }\n const data = [];\n\n res.on(\"data\", (chunk) => {\n data.push(chunk);\n });\n\n res.on(\"end\", () => resolve(Buffer.concat(data).toString()));\n });\n req.end();\n });\n}\n\n/**\n * Check if a domain is hosted by a green web host.\n * @param {string|array} domain - The domain to check, or an array of domains to be checked.\n * @param {object} db - Optional. A database object to use for lookups.\n * @returns {boolean|array} - A boolean if a string was provided, or an array of booleans if an array of domains was provided.\n */\n\nfunction check(domain, db) {\n if (db) {\n return hostingJSON.check(domain, db);\n }\n\n // is it a single domain or an array of them?\n if (typeof domain === \"string\") {\n return checkAgainstAPI(domain);\n } else {\n return checkDomainsAgainstAPI(domain);\n }\n}\n\n/**\n * Check if a domain is hosted by a green web host by querying the Green Web Foundation API.\n * @param {string} domain - The domain to check.\n * @returns {boolean} - A boolean indicating whether the domain is hosted by a green web host.\n */\nasync function checkAgainstAPI(domain) {\n const res = JSON.parse(\n await getBody(`https://api.thegreenwebfoundation.org/greencheck/${domain}`)\n );\n return res.green;\n}\n\n/**\n * Check if an array of domains is hosted by a green web host by querying the Green Web Foundation API.\n * @param {array} domains - An array of domains to check.\n * @returns {array} - An array of domains that are hosted by a green web host.\n */\nasync function checkDomainsAgainstAPI(domains) {\n try {\n const allGreenCheckResults = JSON.parse(\n await getBody(\n `https://api.thegreenwebfoundation.org/v2/greencheckmulti/${JSON.stringify(\n domains\n )}`\n )\n );\n return hostingJSON.greenDomainsFromResults(allGreenCheckResults);\n } catch (e) {\n return [];\n }\n}\n\n/**\n * Take the result of a pageXray and check the domains in it against the database.\n * @param {object} pageXray - The result of a pageXray.\n * @param {object} db - A database object to use for lookups.\n * @returns {array} - An array indicating whether the domain is hosted by a green web host.\n */\nasync function checkPage(pageXray, db) {\n const domains = Object.keys(pageXray.domains);\n return check(domains, db);\n}\n\nexport default {\n check,\n checkPage,\n greendomains: hostingJSON.greenDomainsFromResults,\n loadJSON: hostingJSON.loadJSON,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,mBAAkB;AAElB,+BAAwB;AASxB,uBAAuB,KAAK;AAC1B,SAAO,IAAI,QAAQ,SAAU,SAAS,QAAQ;AAE5C,UAAM,MAAM,qBAAM,IAAI,KAAK,SAAU,KAAK;AACxC,UAAI,IAAI,aAAa,OAAO,IAAI,cAAc,KAAK;AACjD,eAAO,OACL,IAAI,MACF,4BAA4B,qBAAqB,IAAI,YACvD,CACF;AAAA,MACF;AACA,YAAM,OAAO,CAAC;AAEd,UAAI,GAAG,QAAQ,CAAC,UAAU;AACxB,aAAK,KAAK,KAAK;AAAA,MACjB,CAAC;AAED,UAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,IAAI,EAAE,SAAS,CAAC,CAAC;AAAA,IAC7D,CAAC;AACD,QAAI,IAAI;AAAA,EACV,CAAC;AACH;AASA,eAAe,QAAQ,IAAI;AACzB,MAAI,IAAI;AACN,WAAO,iCAAY,MAAM,QAAQ,EAAE;AAAA,EACrC;AAGA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,gBAAgB,MAAM;AAAA,EAC/B,OAAO;AACL,WAAO,uBAAuB,MAAM;AAAA,EACtC;AACF;AAOA,+BAA+B,QAAQ;AACrC,QAAM,MAAM,KAAK,MACf,MAAM,QAAQ,oDAAoD,QAAQ,CAC5E;AACA,SAAO,IAAI;AACb;AAOA,sCAAsC,SAAS;AAC7C,MAAI;AACF,UAAM,uBAAuB,KAAK,MAChC,MAAM,QACJ,4DAA4D,KAAK,UAC/D,OACF,GACF,CACF;AACA,WAAO,iCAAY,wBAAwB,oBAAoB;AAAA,EACjE,SAAS,GAAP;AACA,WAAO,CAAC;AAAA,EACV;AACF;AAQA,yBAAyB,UAAU,IAAI;AACrC,QAAM,UAAU,OAAO,KAAK,SAAS,OAAO;AAC5C,SAAO,MAAM,SAAS,EAAE;AAC1B;AAEA,IAAO,uBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA,cAAc,iCAAY;AAAA,EAC1B,UAAU,iCAAY;AACxB;",
6
6
  "names": []
7
7
  }
@@ -24,10 +24,8 @@ __export(hosting_exports, {
24
24
  default: () => hosting_default
25
25
  });
26
26
  module.exports = __toCommonJS(hosting_exports);
27
- var import_debug = __toESM(require("debug"));
28
27
  var import_hosting_api = __toESM(require("./hosting-api.js"));
29
- const log = (0, import_debug.default)("tgwf:hosting");
30
- function check(domain, db) {
28
+ function check(domain) {
31
29
  return import_hosting_api.default.check(domain);
32
30
  }
33
31
  var hosting_default = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hosting.js"],
4
- "sourcesContent": ["\"use strict\";\n\nimport debugFactory from \"debug\";\nconst log = debugFactory(\"tgwf:hosting\");\n\nimport hostingAPI from \"./hosting-api.js\";\n\nfunction check(domain, db) {\n return hostingAPI.check(domain);\n}\n\nexport default {\n check,\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAyB;AAGzB,yBAAuB;AAFvB,MAAM,MAAM,0BAAa,cAAc;AAIvC,eAAe,QAAQ,IAAI;AACzB,SAAO,2BAAW,MAAM,MAAM;AAChC;AAEA,IAAO,kBAAQ;AAAA,EACb;AACF;",
4
+ "sourcesContent": ["\"use strict\";\n\nimport hostingAPI from \"./hosting-api.js\";\n\n/**\n * Check if a domain is hosted by a green web host.\n * @param {string|array} domain - The domain to check, or an array of domains to be checked.\n * @returns {boolean|array} - A boolean if a string was provided, or an array of booleans if an array of domains was provided.\n */\nfunction check(domain) {\n return hostingAPI.check(domain);\n}\n\nexport default {\n check,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,yBAAuB;AAOvB,eAAe,QAAQ;AACrB,SAAO,2BAAW,MAAM,MAAM;AAChC;AAEA,IAAO,kBAAQ;AAAA,EACb;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,7 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- 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));
21
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
19
  var sustainable_web_design_exports = {};
23
20
  __export(sustainable_web_design_exports, {
@@ -25,10 +22,8 @@ __export(sustainable_web_design_exports, {
25
22
  default: () => sustainable_web_design_default
26
23
  });
27
24
  module.exports = __toCommonJS(sustainable_web_design_exports);
28
- var import_debug = __toESM(require("debug"));
29
25
  var import_constants = require("./constants/index.js");
30
26
  var import_helpers = require("./helpers/index.js");
31
- const log = (0, import_debug.default)("tgwf:sustainable-web-design");
32
27
  class SustainableWebDesign {
33
28
  constructor(options) {
34
29
  this.options = options;
@@ -120,13 +115,11 @@ class SustainableWebDesign {
120
115
  }
121
116
  const energyBycomponent = this.energyPerByteByComponent(bytes);
122
117
  const cacheAdjustedSegmentEnergy = {};
123
- log({ energyBycomponent });
124
118
  const energyValues = Object.values(energyBycomponent);
125
119
  for (const [key, value] of Object.entries(energyBycomponent)) {
126
120
  cacheAdjustedSegmentEnergy[`${key} - first`] = value * firstView;
127
121
  cacheAdjustedSegmentEnergy[`${key} - subsequent`] = value * returnView * dataReloadRatio;
128
122
  }
129
- log({ cacheAdjustedSegmentEnergy });
130
123
  return cacheAdjustedSegmentEnergy;
131
124
  }
132
125
  energyPerVisit(bytes) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sustainable-web-design.js"],
4
- "sourcesContent": ["\"use strict\";\n\n/**\n * Sustainable Web Design\n *\n * Updated calculations and figures from\n * https://sustainablewebdesign.org/calculating-digital-emissions/\n *\n */\nimport debugFactory from \"debug\";\nconst log = debugFactory(\"tgwf:sustainable-web-design\");\n\nimport {\n fileSize,\n KWH_PER_GB,\n END_USER_DEVICE_ENERGY,\n NETWORK_ENERGY,\n DATACENTER_ENERGY,\n PRODUCTION_ENERGY,\n GLOBAL_GRID_INTENSITY,\n RENEWABLES_GRID_INTENSITY,\n FIRST_TIME_VIEWING_PERCENTAGE,\n RETURNING_VISITOR_PERCENTAGE,\n PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD,\n} from \"./constants/index.js\";\nimport { formatNumber } from \"./helpers/index.js\";\n\nclass SustainableWebDesign {\n constructor(options) {\n this.options = options;\n }\n\n /**\n * Accept a figure for bytes transferred and return an object representing\n * the share of the total enrgy use of the entire system, broken down\n * by each corresponding system component\n *\n * @param {number} bytes - the data transferred in bytes\n * @return {object} Object containing the energy in kilowatt hours, keyed by system component\n */\n energyPerByteByComponent(bytes) {\n const transferedBytesToGb = bytes / fileSize.GIGABYTE;\n const energyUsage = transferedBytesToGb * KWH_PER_GB;\n\n // return the total energy, with breakdown by component\n return {\n consumerDeviceEnergy: energyUsage * END_USER_DEVICE_ENERGY,\n networkEnergy: energyUsage * NETWORK_ENERGY,\n productionEnergy: energyUsage * PRODUCTION_ENERGY,\n dataCenterEnergy: energyUsage * DATACENTER_ENERGY,\n };\n }\n /**\n * Accept an object keys by the different system components, and\n * return an object with the co2 figures key by the each component\n *\n * @param {object} energyByComponent - energy grouped by the four system components\n * @param {number} [carbonIntensity] - carbon intensity to apply to the datacentre values\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n co2byComponent(\n energyByComponent,\n carbonIntensity = GLOBAL_GRID_INTENSITY,\n options = {}\n ) {\n let deviceCarbonIntensity = GLOBAL_GRID_INTENSITY;\n let networkCarbonIntensity = GLOBAL_GRID_INTENSITY;\n let dataCenterCarbonIntensity = GLOBAL_GRID_INTENSITY;\n\n let globalEmissions = GLOBAL_GRID_INTENSITY;\n\n if (options?.gridIntensity) {\n const { device, network, dataCenter } = options.gridIntensity;\n\n if (device?.value) {\n deviceCarbonIntensity = device.value;\n }\n if (network?.value) {\n networkCarbonIntensity = network.value;\n }\n // If the user has set a carbon intensity value for the datacentre, then that overrides everything and is used\n if (dataCenter?.value) {\n dataCenterCarbonIntensity = dataCenter.value;\n }\n }\n\n // If the user passes in a TRUE value (green web host), then use the renewables intensity value\n if (carbonIntensity === true) {\n dataCenterCarbonIntensity = RENEWABLES_GRID_INTENSITY;\n }\n\n const returnCO2ByComponent = {};\n for (const [key, value] of Object.entries(energyByComponent)) {\n // we update the datacentre, as that's what we have information\n // about.\n if (key.startsWith(\"dataCenterEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * dataCenterCarbonIntensity;\n } else if (key.startsWith(\"consumerDeviceEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * deviceCarbonIntensity;\n } else if (key.startsWith(\"networkEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * networkCarbonIntensity;\n } else {\n // Use the global intensity for the remaining segments\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * globalEmissions;\n }\n }\n\n return returnCO2ByComponent;\n }\n\n /**\n * Accept a figure for bytes transferred and return a single figure for CO2\n * emissions. Where information exists about the origin data is being\n * fetched from, a different carbon intensity figure\n * is applied for the datacentre share of the carbon intensity.\n *\n * @param {number} bytes - the data transferred in bytes\n * @param {number} `carbonIntensity` the carbon intensity for datacentre (average figures, not marginal ones)\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n perByte(\n bytes,\n carbonIntensity = false,\n segmentResults = false,\n options = {}\n ) {\n const energyBycomponent = this.energyPerByteByComponent(bytes, options);\n\n // otherwise when faced with non numeric values throw an error\n if (typeof carbonIntensity !== \"boolean\") {\n throw new Error(\n `perByte expects a boolean for the carbon intensity value. Received: ${carbonIntensity}`\n );\n }\n\n const co2ValuesbyComponent = this.co2byComponent(\n energyBycomponent,\n carbonIntensity,\n options\n );\n\n // pull out our values\u2026\n const co2Values = Object.values(co2ValuesbyComponent);\n const co2ValuesSum = co2Values.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n\n if (segmentResults) {\n return { ...co2ValuesbyComponent, total: co2ValuesSum };\n }\n\n return co2ValuesSum;\n }\n\n /**\n * Accept a figure for bytes transferred and return a single figure for CO2\n * emissions. This method applies caching assumptions from the original Sustainable Web Design model.\n *\n * @param {number} bytes - the data transferred in bytes\n * @param {number} `carbonIntensity` the carbon intensity for datacentre (average figures, not marginal ones)\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n perVisit(\n bytes,\n carbonIntensity = false,\n segmentResults = false,\n options = {}\n ) {\n const energyBycomponent = this.energyPerVisitByComponent(bytes, options);\n\n if (typeof carbonIntensity !== \"boolean\") {\n // otherwise when faced with non numeric values throw an error\n throw new Error(\n `perVisit expects a boolean for the carbon intensity value. Received: ${carbonIntensity}`\n );\n }\n\n const co2ValuesbyComponent = this.co2byComponent(\n energyBycomponent,\n carbonIntensity,\n options\n );\n\n // pull out our values\u2026\n const co2Values = Object.values(co2ValuesbyComponent);\n const co2ValuesSum = co2Values.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n\n if (segmentResults) {\n return { ...co2ValuesbyComponent, total: co2ValuesSum };\n }\n\n // so we can return their sum\n return co2ValuesSum;\n }\n\n /**\n * Accept a figure for bytes transferred and return the number of kilowatt hours used\n * by the total system for this data transfer\n *\n * @param {number} bytes\n * @return {number} the number of kilowatt hours used\n */\n energyPerByte(bytes) {\n const energyByComponent = this.energyPerByteByComponent(bytes);\n\n // pull out our values\u2026\n const energyValues = Object.values(energyByComponent);\n\n // so we can return their sum\n return energyValues.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n }\n\n /**\n * Accept a figure for bytes transferred, and return an object containing figures\n * per system component, with the caching assumptions applied. This tries to account\n * for webpages being loaded from a cache by browsers, so if you had a thousand page views,\n * and tried to work out the energy per visit, the numbers would reflect the reduced amounts\n * of transfer.\n *\n * @param {number} bytes - the data transferred in bytes for loading a webpage\n * @param {number} firstView - what percentage of visits are loading this page for the first time\n * @param {number} returnView - what percentage of visits are loading this page for subsequent times\n * @param {number} dataReloadRatio - what percentage of a page is reloaded on each subsequent page view\n *\n * @return {object} Object containing the energy in kilowatt hours, keyed by system component\n */\n energyPerVisitByComponent(\n bytes,\n options = {},\n firstView = FIRST_TIME_VIEWING_PERCENTAGE,\n returnView = RETURNING_VISITOR_PERCENTAGE,\n dataReloadRatio = PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD\n ) {\n if (options.dataReloadRatio) {\n dataReloadRatio = options.dataReloadRatio;\n }\n\n if (options.firstVisitPercentage) {\n firstView = options.firstVisitPercentage;\n }\n\n if (options.returnVisitPercentage) {\n returnView = options.returnVisitPercentage;\n }\n\n const energyBycomponent = this.energyPerByteByComponent(bytes);\n const cacheAdjustedSegmentEnergy = {};\n\n log({ energyBycomponent });\n const energyValues = Object.values(energyBycomponent);\n\n // for this, we want\n for (const [key, value] of Object.entries(energyBycomponent)) {\n // represent the first load\n cacheAdjustedSegmentEnergy[`${key} - first`] = value * firstView;\n\n // then represent the subsequent load\n cacheAdjustedSegmentEnergy[`${key} - subsequent`] =\n value * returnView * dataReloadRatio;\n }\n log({ cacheAdjustedSegmentEnergy });\n\n return cacheAdjustedSegmentEnergy;\n }\n\n /**\n * Accept a figure for bytes, and return the total figure for energy per visit\n * using the default caching assumptions for loading a single website\n *\n * @param {number} bytes\n * @return {number} the total energy use for the visit, after applying the caching assumptions\n */\n energyPerVisit(bytes) {\n // fetch the values using the default caching assumptions\n // const energyValues = Object.values(this.energyPerVisitByComponent(bytes));\n\n let firstVisits = 0;\n let subsequentVisits = 0;\n\n const energyBycomponent = Object.entries(\n this.energyPerVisitByComponent(bytes)\n );\n\n for (const [key, val] of energyBycomponent) {\n if (key.indexOf(\"first\") > 0) {\n firstVisits += val;\n }\n }\n\n for (const [key, val] of energyBycomponent) {\n if (key.indexOf(\"subsequent\") > 0) {\n subsequentVisits += val;\n }\n }\n\n return firstVisits + subsequentVisits;\n }\n\n emissionsPerVisitInGrams(\n energyPerVisit,\n carbonintensity = GLOBAL_GRID_INTENSITY\n ) {\n return formatNumber(energyPerVisit * carbonintensity);\n }\n\n annualEnergyInKwh(energyPerVisit, monthlyVisitors = 1000) {\n return energyPerVisit * monthlyVisitors * 12;\n }\n\n annualEmissionsInGrams(co2grams, monthlyVisitors = 1000) {\n return co2grams * monthlyVisitors * 12;\n }\n\n annualSegmentEnergy(annualEnergy) {\n return {\n consumerDeviceEnergy: formatNumber(annualEnergy * END_USER_DEVICE_ENERGY),\n networkEnergy: formatNumber(annualEnergy * NETWORK_ENERGY),\n dataCenterEnergy: formatNumber(annualEnergy * DATACENTER_ENERGY),\n productionEnergy: formatNumber(annualEnergy * PRODUCTION_ENERGY),\n };\n }\n}\n\nexport { SustainableWebDesign };\nexport default SustainableWebDesign;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use strict\";\n\n/**\n * Sustainable Web Design\n *\n * Updated calculations and figures from\n * https://sustainablewebdesign.org/calculating-digital-emissions/\n *\n */\n\nimport {\n fileSize,\n KWH_PER_GB,\n END_USER_DEVICE_ENERGY,\n NETWORK_ENERGY,\n DATACENTER_ENERGY,\n PRODUCTION_ENERGY,\n GLOBAL_GRID_INTENSITY,\n RENEWABLES_GRID_INTENSITY,\n FIRST_TIME_VIEWING_PERCENTAGE,\n RETURNING_VISITOR_PERCENTAGE,\n PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD,\n} from \"./constants/index.js\";\nimport { formatNumber } from \"./helpers/index.js\";\n\nclass SustainableWebDesign {\n constructor(options) {\n this.options = options;\n }\n\n /**\n * Accept a figure for bytes transferred and return an object representing\n * the share of the total enrgy use of the entire system, broken down\n * by each corresponding system component\n *\n * @param {number} bytes - the data transferred in bytes\n * @return {object} Object containing the energy in kilowatt hours, keyed by system component\n */\n energyPerByteByComponent(bytes) {\n const transferedBytesToGb = bytes / fileSize.GIGABYTE;\n const energyUsage = transferedBytesToGb * KWH_PER_GB;\n\n // return the total energy, with breakdown by component\n return {\n consumerDeviceEnergy: energyUsage * END_USER_DEVICE_ENERGY,\n networkEnergy: energyUsage * NETWORK_ENERGY,\n productionEnergy: energyUsage * PRODUCTION_ENERGY,\n dataCenterEnergy: energyUsage * DATACENTER_ENERGY,\n };\n }\n /**\n * Accept an object keys by the different system components, and\n * return an object with the co2 figures key by the each component\n *\n * @param {object} energyByComponent - energy grouped by the four system components\n * @param {number} [carbonIntensity] - carbon intensity to apply to the datacentre values\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n co2byComponent(\n energyByComponent,\n carbonIntensity = GLOBAL_GRID_INTENSITY,\n options = {}\n ) {\n let deviceCarbonIntensity = GLOBAL_GRID_INTENSITY;\n let networkCarbonIntensity = GLOBAL_GRID_INTENSITY;\n let dataCenterCarbonIntensity = GLOBAL_GRID_INTENSITY;\n\n let globalEmissions = GLOBAL_GRID_INTENSITY;\n\n if (options?.gridIntensity) {\n const { device, network, dataCenter } = options.gridIntensity;\n\n if (device?.value) {\n deviceCarbonIntensity = device.value;\n }\n if (network?.value) {\n networkCarbonIntensity = network.value;\n }\n // If the user has set a carbon intensity value for the datacentre, then that overrides everything and is used\n if (dataCenter?.value) {\n dataCenterCarbonIntensity = dataCenter.value;\n }\n }\n\n // If the user passes in a TRUE value (green web host), then use the renewables intensity value\n if (carbonIntensity === true) {\n dataCenterCarbonIntensity = RENEWABLES_GRID_INTENSITY;\n }\n\n const returnCO2ByComponent = {};\n for (const [key, value] of Object.entries(energyByComponent)) {\n // we update the datacentre, as that's what we have information\n // about.\n if (key.startsWith(\"dataCenterEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * dataCenterCarbonIntensity;\n } else if (key.startsWith(\"consumerDeviceEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * deviceCarbonIntensity;\n } else if (key.startsWith(\"networkEnergy\")) {\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * networkCarbonIntensity;\n } else {\n // Use the global intensity for the remaining segments\n returnCO2ByComponent[key.replace(\"Energy\", \"CO2\")] =\n value * globalEmissions;\n }\n }\n\n return returnCO2ByComponent;\n }\n\n /**\n * Accept a figure for bytes transferred and return a single figure for CO2\n * emissions. Where information exists about the origin data is being\n * fetched from, a different carbon intensity figure\n * is applied for the datacentre share of the carbon intensity.\n *\n * @param {number} bytes - the data transferred in bytes\n * @param {number} `carbonIntensity` the carbon intensity for datacentre (average figures, not marginal ones)\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n perByte(\n bytes,\n carbonIntensity = false,\n segmentResults = false,\n options = {}\n ) {\n const energyBycomponent = this.energyPerByteByComponent(bytes, options);\n\n // otherwise when faced with non numeric values throw an error\n if (typeof carbonIntensity !== \"boolean\") {\n throw new Error(\n `perByte expects a boolean for the carbon intensity value. Received: ${carbonIntensity}`\n );\n }\n\n const co2ValuesbyComponent = this.co2byComponent(\n energyBycomponent,\n carbonIntensity,\n options\n );\n\n // pull out our values\u2026\n const co2Values = Object.values(co2ValuesbyComponent);\n const co2ValuesSum = co2Values.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n\n if (segmentResults) {\n return { ...co2ValuesbyComponent, total: co2ValuesSum };\n }\n\n return co2ValuesSum;\n }\n\n /**\n * Accept a figure for bytes transferred and return a single figure for CO2\n * emissions. This method applies caching assumptions from the original Sustainable Web Design model.\n *\n * @param {number} bytes - the data transferred in bytes\n * @param {number} `carbonIntensity` the carbon intensity for datacentre (average figures, not marginal ones)\n * @return {number} the total number in grams of CO2 equivalent emissions\n */\n perVisit(\n bytes,\n carbonIntensity = false,\n segmentResults = false,\n options = {}\n ) {\n const energyBycomponent = this.energyPerVisitByComponent(bytes, options);\n\n if (typeof carbonIntensity !== \"boolean\") {\n // otherwise when faced with non numeric values throw an error\n throw new Error(\n `perVisit expects a boolean for the carbon intensity value. Received: ${carbonIntensity}`\n );\n }\n\n const co2ValuesbyComponent = this.co2byComponent(\n energyBycomponent,\n carbonIntensity,\n options\n );\n\n // pull out our values\u2026\n const co2Values = Object.values(co2ValuesbyComponent);\n const co2ValuesSum = co2Values.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n\n if (segmentResults) {\n return { ...co2ValuesbyComponent, total: co2ValuesSum };\n }\n\n // so we can return their sum\n return co2ValuesSum;\n }\n\n /**\n * Accept a figure for bytes transferred and return the number of kilowatt hours used\n * by the total system for this data transfer\n *\n * @param {number} bytes\n * @return {number} the number of kilowatt hours used\n */\n energyPerByte(bytes) {\n const energyByComponent = this.energyPerByteByComponent(bytes);\n\n // pull out our values\u2026\n const energyValues = Object.values(energyByComponent);\n\n // so we can return their sum\n return energyValues.reduce(\n (prevValue, currentValue) => prevValue + currentValue\n );\n }\n\n /**\n * Accept a figure for bytes transferred, and return an object containing figures\n * per system component, with the caching assumptions applied. This tries to account\n * for webpages being loaded from a cache by browsers, so if you had a thousand page views,\n * and tried to work out the energy per visit, the numbers would reflect the reduced amounts\n * of transfer.\n *\n * @param {number} bytes - the data transferred in bytes for loading a webpage\n * @param {number} firstView - what percentage of visits are loading this page for the first time\n * @param {number} returnView - what percentage of visits are loading this page for subsequent times\n * @param {number} dataReloadRatio - what percentage of a page is reloaded on each subsequent page view\n *\n * @return {object} Object containing the energy in kilowatt hours, keyed by system component\n */\n energyPerVisitByComponent(\n bytes,\n options = {},\n firstView = FIRST_TIME_VIEWING_PERCENTAGE,\n returnView = RETURNING_VISITOR_PERCENTAGE,\n dataReloadRatio = PERCENTAGE_OF_DATA_LOADED_ON_SUBSEQUENT_LOAD\n ) {\n if (options.dataReloadRatio) {\n dataReloadRatio = options.dataReloadRatio;\n }\n\n if (options.firstVisitPercentage) {\n firstView = options.firstVisitPercentage;\n }\n\n if (options.returnVisitPercentage) {\n returnView = options.returnVisitPercentage;\n }\n\n const energyBycomponent = this.energyPerByteByComponent(bytes);\n const cacheAdjustedSegmentEnergy = {};\n\n const energyValues = Object.values(energyBycomponent);\n\n // for this, we want\n for (const [key, value] of Object.entries(energyBycomponent)) {\n // represent the first load\n cacheAdjustedSegmentEnergy[`${key} - first`] = value * firstView;\n\n // then represent the subsequent load\n cacheAdjustedSegmentEnergy[`${key} - subsequent`] =\n value * returnView * dataReloadRatio;\n }\n\n return cacheAdjustedSegmentEnergy;\n }\n\n /**\n * Accept a figure for bytes, and return the total figure for energy per visit\n * using the default caching assumptions for loading a single website\n *\n * @param {number} bytes\n * @return {number} the total energy use for the visit, after applying the caching assumptions\n */\n energyPerVisit(bytes) {\n // fetch the values using the default caching assumptions\n // const energyValues = Object.values(this.energyPerVisitByComponent(bytes));\n\n let firstVisits = 0;\n let subsequentVisits = 0;\n\n const energyBycomponent = Object.entries(\n this.energyPerVisitByComponent(bytes)\n );\n\n for (const [key, val] of energyBycomponent) {\n if (key.indexOf(\"first\") > 0) {\n firstVisits += val;\n }\n }\n\n for (const [key, val] of energyBycomponent) {\n if (key.indexOf(\"subsequent\") > 0) {\n subsequentVisits += val;\n }\n }\n\n return firstVisits + subsequentVisits;\n }\n\n emissionsPerVisitInGrams(\n energyPerVisit,\n carbonintensity = GLOBAL_GRID_INTENSITY\n ) {\n return formatNumber(energyPerVisit * carbonintensity);\n }\n\n annualEnergyInKwh(energyPerVisit, monthlyVisitors = 1000) {\n return energyPerVisit * monthlyVisitors * 12;\n }\n\n annualEmissionsInGrams(co2grams, monthlyVisitors = 1000) {\n return co2grams * monthlyVisitors * 12;\n }\n\n annualSegmentEnergy(annualEnergy) {\n return {\n consumerDeviceEnergy: formatNumber(annualEnergy * END_USER_DEVICE_ENERGY),\n networkEnergy: formatNumber(annualEnergy * NETWORK_ENERGY),\n dataCenterEnergy: formatNumber(annualEnergy * DATACENTER_ENERGY),\n productionEnergy: formatNumber(annualEnergy * PRODUCTION_ENERGY),\n };\n }\n}\n\nexport { SustainableWebDesign };\nexport default SustainableWebDesign;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,11 @@
1
1
  import fileSize from "./file-size.js";
2
+ import { averageIntensity } from "../index.js";
2
3
  const KWH_PER_GB = 0.81;
3
4
  const END_USER_DEVICE_ENERGY = 0.52;
4
5
  const NETWORK_ENERGY = 0.14;
5
6
  const DATACENTER_ENERGY = 0.15;
6
7
  const PRODUCTION_ENERGY = 0.19;
7
- const GLOBAL_GRID_INTENSITY = 442;
8
+ const GLOBAL_GRID_INTENSITY = averageIntensity.data["WORLD"];
8
9
  const RENEWABLES_GRID_INTENSITY = 50;
9
10
  const FIRST_TIME_VIEWING_PERCENTAGE = 0.75;
10
11
  const RETURNING_VISITOR_PERCENTAGE = 0.25;
@@ -1,6 +1,4 @@
1
1
  "use strict";
2
- import debugFactory from "debug";
3
- const log = debugFactory("tgwf:hostingAPI");
4
2
  function check(domain) {
5
3
  if (typeof domain === "string") {
6
4
  return checkAgainstAPI(domain);
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
- import debugFactory from "debug";
3
- const log = debugFactory("tgwf:hosting");
4
2
  import hostingAPI from "./hosting-api.js";
5
- function check(domain, db) {
3
+ function check(domain) {
6
4
  return hostingAPI.check(domain);
7
5
  }
8
6
  var hosting_default = {
@@ -18,8 +18,6 @@ var __spreadValues = (a, b) => {
18
18
  return a;
19
19
  };
20
20
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
- import debugFactory from "debug";
22
- const log = debugFactory("tgwf:sustainable-web-design");
23
21
  import {
24
22
  fileSize,
25
23
  KWH_PER_GB,
@@ -125,13 +123,11 @@ class SustainableWebDesign {
125
123
  }
126
124
  const energyBycomponent = this.energyPerByteByComponent(bytes);
127
125
  const cacheAdjustedSegmentEnergy = {};
128
- log({ energyBycomponent });
129
126
  const energyValues = Object.values(energyBycomponent);
130
127
  for (const [key, value] of Object.entries(energyBycomponent)) {
131
128
  cacheAdjustedSegmentEnergy[`${key} - first`] = value * firstView;
132
129
  cacheAdjustedSegmentEnergy[`${key} - subsequent`] = value * returnView * dataReloadRatio;
133
130
  }
134
- log({ cacheAdjustedSegmentEnergy });
135
131
  return cacheAdjustedSegmentEnergy;
136
132
  }
137
133
  energyPerVisit(bytes) {
@@ -1,20 +1,20 @@
1
- var co2=(()=>{var Ee=Object.create;var _=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,pe=Object.prototype.hasOwnProperty;var L=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),he=(r,e)=>{for(var t in e)_(r,t,{get:e[t],enumerable:!0})},ee=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ye(e))!pe.call(r,n)&&n!==t&&_(r,n,{get:()=>e[n],enumerable:!(o=Re(e,n))||o.enumerable});return r};var D=(r,e,t)=>(t=r!=null?Ee(me(r)):{},ee(e||!r||!r.__esModule?_(t,"default",{value:r,enumerable:!0}):t,r)),Ne=r=>ee(_({},"__esModule",{value:!0}),r);var ne=L((ze,re)=>{var h=1e3,N=h*60,I=N*60,p=I*24,Ie=p*7,Ae=p*365.25;re.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return Te(r);if(t==="number"&&isFinite(r))return e.long?Oe(r):be(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function Te(r){if(r=String(r),!(r.length>100)){var e=/^(-?(?:\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(!!e){var t=parseFloat(e[1]),o=(e[2]||"ms").toLowerCase();switch(o){case"years":case"year":case"yrs":case"yr":case"y":return t*Ae;case"weeks":case"week":case"w":return t*Ie;case"days":case"day":case"d":return t*p;case"hours":case"hour":case"hrs":case"hr":case"h":return t*I;case"minutes":case"minute":case"mins":case"min":case"m":return t*N;case"seconds":case"second":case"secs":case"sec":case"s":return t*h;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function be(r){var e=Math.abs(r);return e>=p?Math.round(r/p)+"d":e>=I?Math.round(r/I)+"h":e>=N?Math.round(r/N)+"m":e>=h?Math.round(r/h)+"s":r+"ms"}function Oe(r){var e=Math.abs(r);return e>=p?G(r,e,p,"day"):e>=I?G(r,e,I,"hour"):e>=N?G(r,e,N,"minute"):e>=h?G(r,e,h,"second"):r+" ms"}function G(r,e,t,o){var n=e>=t*1.5;return Math.round(r/t)+" "+o+(n?"s":"")}});var se=L((Je,oe)=>{function Se(r){t.debug=t,t.default=t,t.coerce=C,t.disable=i,t.enable=n,t.enabled=a,t.humanize=ne(),t.destroy=l,Object.keys(r).forEach(s=>{t[s]=r[s]}),t.names=[],t.skips=[],t.formatters={};function e(s){let c=0;for(let d=0;d<s.length;d++)c=(c<<5)-c+s.charCodeAt(d),c|=0;return t.colors[Math.abs(c)%t.colors.length]}t.selectColor=e;function t(s){let c,d=null,F,q;function R(...E){if(!R.enabled)return;let m=R,P=Number(new Date),fe=P-(c||P);m.diff=fe,m.prev=c,m.curr=P,c=P,E[0]=t.coerce(E[0]),typeof E[0]!="string"&&E.unshift("%O");let B=0;E[0]=E[0].replace(/%([a-zA-Z%])/g,(M,Ce)=>{if(M==="%%")return"%";B++;let X=t.formatters[Ce];if(typeof X=="function"){let ge=E[B];M=X.call(m,ge),E.splice(B,1),B--}return M}),t.formatArgs.call(m,E),(m.log||t.log).apply(m,E)}return R.namespace=s,R.useColors=t.useColors(),R.color=t.selectColor(s),R.extend=o,R.destroy=t.destroy,Object.defineProperty(R,"enabled",{enumerable:!0,configurable:!1,get:()=>d!==null?d:(F!==t.namespaces&&(F=t.namespaces,q=t.enabled(s)),q),set:E=>{d=E}}),typeof t.init=="function"&&t.init(R),R}function o(s,c){let d=t(this.namespace+(typeof c>"u"?":":c)+s);return d.log=this.log,d}function n(s){t.save(s),t.namespaces=s,t.names=[],t.skips=[];let c,d=(typeof s=="string"?s:"").split(/[\s,]+/),F=d.length;for(c=0;c<F;c++)!d[c]||(s=d[c].replace(/\*/g,".*?"),s[0]==="-"?t.skips.push(new RegExp("^"+s.slice(1)+"$")):t.names.push(new RegExp("^"+s+"$")))}function i(){let s=[...t.names.map(f),...t.skips.map(f).map(c=>"-"+c)].join(",");return t.enable(""),s}function a(s){if(s[s.length-1]==="*")return!0;let c,d;for(c=0,d=t.skips.length;c<d;c++)if(t.skips[c].test(s))return!1;for(c=0,d=t.names.length;c<d;c++)if(t.names[c].test(s))return!0;return!1}function f(s){return s.toString().substring(2,s.toString().length-2).replace(/\.\*\?$/,"*")}function C(s){return s instanceof Error?s.stack||s.message:s}function l(){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 t.enable(t.load()),t}oe.exports=Se});var w=L((g,v)=>{g.formatArgs=Pe;g.save=Be;g.load=_e;g.useColors=Fe;g.storage=Ge();g.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`."))}})();g.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 Pe(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+v.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;r.splice(1,0,e,"color: inherit");let t=0,o=0;r[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(t++,n==="%c"&&(o=t))}),r.splice(o,0,e)}g.log=console.debug||console.log||(()=>{});function Be(r){try{r?g.storage.setItem("debug",r):g.storage.removeItem("debug")}catch{}}function _e(){let r;try{r=g.storage.getItem("debug")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function Ge(){try{return localStorage}catch{}}v.exports=se()(g);var{formatters:ve}=v.exports;ve.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var xe={};he(xe,{averageIntensity:()=>y,co2:()=>z,default:()=>He,hosting:()=>J,marginalIntensity:()=>Q});var V=4883333333333333e-25;var U=class{constructor(e){this.options=e,this.KWH_PER_BYTE_FOR_NETWORK=V}perByte(e,t){if(e<1)return 0;if(t){let n=e*72e-12*0,i=e*V*475;return n+i}let o=72e-12+V;return e*o*519}};var te=U;var ce=D(w());var K={GIGABYTE:1e9};var ie=.81,W=.52,Y=.14,k=.15,H=.19,u=442,T=50,b=.75,O=.25,S=.02;var A=r=>parseFloat(r.toFixed(2));function x(r){if(typeof r!="object")throw new Error("Options must be an object");let e={};if(r?.gridIntensity){e.gridIntensity={};let{device:t,dataCenter:o,network:n}=r.gridIntensity;t&&(typeof t=="object"?(y.data[t.country?.toUpperCase()]||(console.warn(`"${t.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
1
+ var co2=(()=>{var I=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var F=(o,e)=>{for(var r in e)I(o,r,{get:e[r],enumerable:!0})},W=(o,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of K(e))!w.call(o,t)&&t!==r&&I(o,t,{get:()=>e[t],enumerable:!(n=U(e,t))||n.enumerable});return o};var Y=o=>W(I({},"__esModule",{value:!0}),o);var ee={};F(ee,{averageIntensity:()=>E,co2:()=>h,default:()=>X,hosting:()=>b,marginalIntensity:()=>M});var m=4883333333333333e-25;var T=class{constructor(e){this.options=e,this.KWH_PER_BYTE_FOR_NETWORK=m}perByte(e,r){if(e<1)return 0;if(r){let t=e*72e-12*0,s=e*m*475;return t+s}let n=72e-12+m;return e*n*519}};var D=T;var A={GIGABYTE:1e9};var V=.81,C=.52,p=.14,O=.15,S=.19,a=E.data.WORLD,f=50,y=.75,g=.25,N=.02;var R=o=>parseFloat(o.toFixed(2));function B(o){if(typeof o!="object")throw new Error("Options must be an object");let e={};if(o?.gridIntensity){e.gridIntensity={};let{device:r,dataCenter:n,network:t}=o.gridIntensity;r&&(typeof r=="object"?(E.data[r.country?.toUpperCase()]||(console.warn(`"${r.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
2
2
  See https://developers.thegreenwebfoundation.org/co2js/data/ for more information.
3
- Falling back to global average grid intensity.`),e.gridIntensity.device={value:u}),e.gridIntensity.device={country:t.country,value:parseFloat(y.data[t.country?.toUpperCase()])}):typeof t=="number"?e.gridIntensity.device={value:t}:(e.gridIntensity.device={value:u},console.warn(`The device grid intensity must be a number or an object. You passed in a ${typeof t}.
4
- Falling back to global average grid intensity.`))),o&&(typeof o=="object"?(y.data[o.country?.toUpperCase()]||(console.warn(`"${o.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
3
+ Falling back to global average grid intensity.`),e.gridIntensity.device={value:a}),e.gridIntensity.device={country:r.country,value:parseFloat(E.data[r.country?.toUpperCase()])}):typeof r=="number"?e.gridIntensity.device={value:r}:(e.gridIntensity.device={value:a},console.warn(`The device grid intensity must be a number or an object. You passed in a ${typeof r}.
4
+ Falling back to global average grid intensity.`))),n&&(typeof n=="object"?(E.data[n.country?.toUpperCase()]||(console.warn(`"${n.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
5
5
  See https://developers.thegreenwebfoundation.org/co2js/data/ for more information.
6
- Falling back to global average grid intensity.`),e.gridIntensity.dataCenter={value:u}),e.gridIntensity.dataCenter={country:o.country,value:parseFloat(y.data[o.country?.toUpperCase()])}):typeof o=="number"?e.gridIntensity.dataCenter={value:o}:(e.gridIntensity.dataCenter={value:u},console.warn(`The data center grid intensity must be a number or an object. You passed in a ${typeof o}.
7
- Falling back to global average grid intensity.`))),n&&(typeof n=="object"?(y.data[n.country?.toUpperCase()]||(console.warn(`"${n.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
6
+ Falling back to global average grid intensity.`),e.gridIntensity.dataCenter={value:a}),e.gridIntensity.dataCenter={country:n.country,value:parseFloat(E.data[n.country?.toUpperCase()])}):typeof n=="number"?e.gridIntensity.dataCenter={value:n}:(e.gridIntensity.dataCenter={value:a},console.warn(`The data center grid intensity must be a number or an object. You passed in a ${typeof n}.
7
+ Falling back to global average grid intensity.`))),t&&(typeof t=="object"?(E.data[t.country?.toUpperCase()]||(console.warn(`"${t.country}" is not a valid country. Please use a valid 3 digit ISO 3166 country code.
8
8
  See https://developers.thegreenwebfoundation.org/co2js/data/ for more information. Falling back to global average grid intensity.
9
- Falling back to global average grid intensity.`),e.gridIntensity.network={value:u}),e.gridIntensity.network={country:n.country,value:parseFloat(y.data[n.country?.toUpperCase()])}):typeof n=="number"?e.gridIntensity.network={value:n}:(e.gridIntensity.network={value:u},console.warn(`The network grid intensity must be a number or an object. You passed in a ${typeof n}.
10
- Falling back to global average grid intensity.`)))}return r?.dataReloadRatio&&(typeof r.dataReloadRatio=="number"?r.dataReloadRatio>=0&&r.dataReloadRatio<=1?e.dataReloadRatio=r.dataReloadRatio:(e.dataReloadRatio=S,console.warn(`The dataReloadRatio option must be a number between 0 and 1. You passed in ${r.dataReloadRatio}.
11
- Falling back to default value.`)):(e.dataReloadRatio=S,console.warn(`The dataReloadRatio option must be a number. You passed in a ${typeof r.dataReloadRatio}.
12
- Falling back to default value.`))),r?.firstVisitPercentage&&(typeof r.firstVisitPercentage=="number"?r.firstVisitPercentage>=0&&r.firstVisitPercentage<=1?e.firstVisitPercentage=r.firstVisitPercentage:(e.firstVisitPercentage=b,console.warn(`The firstVisitPercentage option must be a number between 0 and 1. You passed in ${r.firstVisitPercentage}.
13
- Falling back to default value.`)):(e.firstVisitPercentage=b,console.warn(`The firstVisitPercentage option must be a number. You passed in a ${typeof r.firstVisitPercentage}.
14
- Falling back to default value.`))),r?.returnVisitPercentage&&(typeof r.returnVisitPercentage=="number"?r.returnVisitPercentage>=0&&r.returnVisitPercentage<=1?e.returnVisitPercentage=r.returnVisitPercentage:(e.returnVisitPercentage=O,console.warn(`The returnVisitPercentage option must be a number between 0 and 1. You passed in ${r.returnVisitPercentage}.
15
- Falling back to default value.`)):(e.returnVisitPercentage=O,console.warn(`The returnVisitPercentage option must be a number. You passed in a ${typeof r.returnVisitPercentage}.
16
- Falling back to default value.`))),e}var ae=(0,ce.default)("tgwf:sustainable-web-design"),j=class{constructor(e){this.options=e}energyPerByteByComponent(e){let o=e/K.GIGABYTE*ie;return{consumerDeviceEnergy:o*W,networkEnergy:o*Y,productionEnergy:o*H,dataCenterEnergy:o*k}}co2byComponent(e,t=u,o={}){let n=u,i=u,a=u,f=u;if(o?.gridIntensity){let{device:l,network:s,dataCenter:c}=o.gridIntensity;l?.value&&(n=l.value),s?.value&&(i=s.value),c?.value&&(a=c.value)}t===!0&&(a=T);let C={};for(let[l,s]of Object.entries(e))l.startsWith("dataCenterEnergy")?C[l.replace("Energy","CO2")]=s*a:l.startsWith("consumerDeviceEnergy")?C[l.replace("Energy","CO2")]=s*n:l.startsWith("networkEnergy")?C[l.replace("Energy","CO2")]=s*i:C[l.replace("Energy","CO2")]=s*f;return C}perByte(e,t=!1,o=!1,n={}){let i=this.energyPerByteByComponent(e,n);if(typeof t!="boolean")throw new Error(`perByte expects a boolean for the carbon intensity value. Received: ${t}`);let a=this.co2byComponent(i,t,n),C=Object.values(a).reduce((l,s)=>l+s);return o?{...a,total:C}:C}perVisit(e,t=!1,o=!1,n={}){let i=this.energyPerVisitByComponent(e,n);if(typeof t!="boolean")throw new Error(`perVisit expects a boolean for the carbon intensity value. Received: ${t}`);let a=this.co2byComponent(i,t,n),C=Object.values(a).reduce((l,s)=>l+s);return o?{...a,total:C}:C}energyPerByte(e){let t=this.energyPerByteByComponent(e);return Object.values(t).reduce((n,i)=>n+i)}energyPerVisitByComponent(e,t={},o=b,n=O,i=S){t.dataReloadRatio&&(i=t.dataReloadRatio),t.firstVisitPercentage&&(o=t.firstVisitPercentage),t.returnVisitPercentage&&(n=t.returnVisitPercentage);let a=this.energyPerByteByComponent(e),f={};ae({energyBycomponent:a});let C=Object.values(a);for(let[l,s]of Object.entries(a))f[`${l} - first`]=s*o,f[`${l} - subsequent`]=s*n*i;return ae({cacheAdjustedSegmentEnergy:f}),f}energyPerVisit(e){let t=0,o=0,n=Object.entries(this.energyPerVisitByComponent(e));for(let[i,a]of n)i.indexOf("first")>0&&(t+=a);for(let[i,a]of n)i.indexOf("subsequent")>0&&(o+=a);return t+o}emissionsPerVisitInGrams(e,t=u){return A(e*t)}annualEnergyInKwh(e,t=1e3){return e*t*12}annualEmissionsInGrams(e,t=1e3){return e*t*12}annualSegmentEnergy(e){return{consumerDeviceEnergy:A(e*W),networkEnergy:A(e*Y),dataCenterEnergy:A(e*k),productionEnergy:A(e*H)}}};var Z=j;var $=class{constructor(e){if(this.model=new Z,e?.model==="1byte")this.model=new te;else if(e?.model==="swd")this.model=new Z;else if(e?.model)throw new Error(`"${e.model}" is not a valid model. Please use "1byte" for the OneByte model, and "swd" for the Sustainable Web Design model.
17
- See https://developers.thegreenwebfoundation.org/co2js/models/ to learn more about the models available in CO2.js.`);e?.results==="segment"?this.model.results={segment:!0}:this.model.results={segment:!1}}perByte(e,t=!1){return this.model.perByte(e,t,this.model.results.segment)}perVisit(e,t=!1){if(this.model?.perVisit)return this.model.perVisit(e,t,this.model.results.segment);throw new Error(`The perVisit() method is not supported in the model you are using. Try using perByte() instead.
18
- See https://developers.thegreenwebfoundation.org/co2js/methods/ to learn more about the methods available in CO2.js.`)}perByteTrace(e,t=!1,o={}){let n={};return o&&(n=x(o)),{co2:this.model.perByte(e,t,this.model.results.segment,n),green:t,variables:{description:"Below are the variables used to calculate this CO2 estimate.",bytes:e,gridIntensity:{description:"The grid intensity (grams per kilowatt-hour) used to calculate this CO2 estimate.",network:n?.gridIntensity?.network?.value||u,dataCenter:t?T:n?.gridIntensity?.dataCenter?.value||u,production:u,device:n?.gridIntensity?.device?.value||u}}}}perVisitTrace(e,t=!1,o={}){if(this.model?.perVisit){let n={};return o&&(n=x(o)),{co2:this.model.perVisit(e,t,this.model.results.segment,n),green:t,variables:{description:"Below are the variables used to calculate this CO2 estimate.",bytes:e,gridIntensity:{description:"The grid intensity (grams per kilowatt-hour) used to calculate this CO2 estimate.",network:n?.gridIntensity?.network?.value||u,dataCenter:t?T:n?.gridIntensity?.dataCenter?.value||u,production:u,device:n?.gridIntensity?.device?.value||u},dataReloadRatio:n?.dataReloadRatio||.02,firstVisitPercentage:n?.firstVisitPercentage||.75,returnVisitPercentage:n?.returnVisitPercentage||.25}}}else throw new Error(`The perVisitDetailed() method is not supported in the model you are using. Try using perByte() instead.
19
- See https://developers.thegreenwebfoundation.org/co2js/methods/ to learn more about the methods available in CO2.js.`)}perDomain(e,t){let o=[];for(let n of Object.keys(e.domains)){let i;t&&t.indexOf(n)>-1?i=this.perByte(e.domains[n].transferSize,!0):i=this.perByte(e.domains[n].transferSize),o.push({domain:n,co2:i,transferSize:e.domains[n].transferSize})}return o.sort((n,i)=>i.co2-n.co2),o}perPage(e,t){let o=this.perDomain(e,t),n=0;for(let i of o)n+=i.co2;return n}perContentType(e,t){let o={};for(let i of e.assets){let a=new URL(i.url).domain,f=i.transferSize,C=this.perByte(f,t&&t.indexOf(a)>-1),l=i.type;o[l]||(o[l]={co2:0,transferSize:0}),o[l].co2+=C,o[l].transferSize+=f}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,a)=>a.co2-i.co2),n}dirtiestResources(e,t){let o=[];for(let n of e.assets){let i=new URL(n.url).domain,a=n.transferSize,f=this.perByte(a,t&&t.indexOf(i)>-1);o.push({url:n.url,co2:f,transferSize:a})}return o.sort((n,i)=>i.co2-n.co2),o.slice(0,o.length>10?10:o.length)}perParty(e,t){let o=0,n=0,i=e.firstPartyRegEx;for(let a of Object.keys(e.domains))a.match(i)?o+=this.perByte(e.domains[a].transferSize,t&&t.indexOf(a)>-1):n+=this.perByte(e.domains[a].transferSize,t&&t.indexOf(a)>-1);return{firstParty:o,thirdParty:n}}};var z=$;var de=D(w());var le=D(w()),dt=(0,le.default)("tgwf:hostingAPI");function we(r){return typeof r=="string"?Me(r):Le(r)}async function Me(r){return(await(await fetch(`https://api.thegreenwebfoundation.org/greencheck/${r}`)).json()).green}async function Le(r){try{let e="https://api.thegreenwebfoundation.org/v2/greencheckmulti",t=JSON.stringify(r),n=await(await fetch(`${e}/${t}`)).json();return De(n)}catch{return[]}}function De(r){return Object.entries(r).filter(([o,n])=>n.green).map(([o,n])=>n.url)}var ue={check:we};var Ct=(0,de.default)("tgwf:hosting");function Ve(r,e){return ue.check(r)}var J={check:Ve};var Ue={AFG:120.482,AFRICA:483.78,ALB:23.438,DZA:488.393,ASM:687.5,AGO:168.594,ATG:657.143,ARG:337.533,ARM:222.678,ABW:591.398,ASIA:531.78,AUS:503.179,AUT:157.52,AZE:532.902,BHS:698.113,BHR:489.924,BGD:581.485,BRB:644.86,BLR:415.774,BEL:165.363,BLZ:484.375,BEN:666.667,BTN:24.444,BOL:319.432,BIH:516.626,BWA:794.521,BRA:102.411,BRN:658.849,BGR:399.565,BFA:611.429,BDI:250,CPV:600,KHM:399.31,CMR:278.261,CAN:125.55,CYM:684.932,CAF:0,TCD:677.419,CHL:333.173,CHN:530.214,COL:169.309,COM:714.286,COG:398.01,COD:25.362,COK:400,CRI:37.213,CIV:390.71,HRV:246.459,CUB:574.684,CYP:589.354,CZE:415.345,DNK:180.709,DJI:666.667,DMA:529.412,DOM:540.387,ECU:169.384,EGY:485.367,SLV:194.226,GNQ:492.958,ERI:688.889,EST:464.029,SWZ:189.189,ETH:25.187,EU:277.35,EUROPE:298.01,FLK:500,FRO:428.571,FJI:292.035,FIN:130.977,FRA:84.817,GUF:254.717,PYF:471.429,G20:440.39,G7:341.23,GAB:397.38,GMB:700,GEO:134.831,DEU:385.467,GHA:362.942,GRC:343.822,GRL:133.333,GRD:714.286,GLP:611.765,GUM:670.33,GTM:313.019,GIN:208.633,GNB:750,GUY:634.146,HTI:606.061,HND:374.269,HKG:684.823,HUN:222.973,ISL:28.557,IND:632.406,IDN:623.281,IRN:493.595,IRQ:500.206,IRL:345.347,ISR:550.493,ITA:371.692,JAM:524.138,JPN:483.039,JOR:399.909,KAZ:635.574,KEN:99.919,KIR:666.667,XKX:766.605,KWT:489.61,KGZ:104.354,LAO:242.182,"LATIN AMERICA AND CARIBBEAN":238.27,LVA:181.818,LBN:545.941,LSO:20,LBR:304.348,LBY:496.565,LTU:194.245,LUX:168.142,MAC:491.525,MDG:483.254,MWI:133.803,MYS:543.737,MDV:651.515,MLI:466.077,MLT:442.478,MTQ:698.63,MRT:526.596,MUS:611.111,MEX:421.402,"MIDDLE EAST":514.89,MDA:685.874,MNG:749.656,MNE:399.381,MSR:1e3,MAR:610.412,MOZ:125.063,MMR:348.837,NAM:63.694,NRU:750,NPL:24.51,NLD:354.988,NCL:610.119,NZL:98.639,NIC:354.212,NER:622.222,NGA:368.421,"NORTH AMERICA":336.4,PRK:157.785,MKD:529.328,NOR:28.818,OCEANIA:446.65,OECD:338.75,OMN:488.272,PAK:343.366,PSE:465.116,PAN:193.923,PNG:526.749,PRY:25.487,PER:254.521,POL:634.579,PRT:234.029,PRI:681.469,QAT:489.867,REU:519.031,ROU:264.121,RUS:367.189,RWA:294.118,KNA:681.818,LCA:685.714,SPM:800,VCT:500,WSM:470.588,STP:600,SAU:571.336,SEN:502.674,SRB:569.375,SYC:615.385,SLE:47.619,SGP:489.234,SVK:140.666,SVN:237.378,SLB:727.273,SOM:634.146,ZAF:709.002,KOR:435.689,SSD:684.211,ESP:217.373,LKA:479.829,SDN:242.917,SUR:356.436,SWE:45.084,CHE:45.622,SYR:540.573,TWN:561.431,TJK:84.136,TZA:361.077,THA:503.07,PHL:582.365,TGO:507.937,TON:625,TTO:520.046,TUN:469.428,TUR:413.628,TKM:544.393,TCA:703.704,UGA:52.273,UKR:206.539,ARE:461.845,GBR:257.379,USA:367.768,URY:116.168,UZB:506.164,VUT:571.429,VEN:189.446,VNM:376.828,VGB:714.286,VIR:685.714,WORLD:435.99,YEM:528.409,ZMB:84.698,ZWE:393.035},Ke="average";var y={data:Ue,type:Ke};var We={AFG:"414",ALB:"0",DZA:"528",ASM:"753",AND:"188",AGO:"1476",AIA:"753",ATG:"753",ARG:"478",ARM:"390",ABW:"753",AUS:"808",AUT:"242",AZE:"534","AZORES (PORTUGAL)":"753",BHS:"753",BHR:"726",BGD:"528",BRB:"749",BLR:"400",BEL:"252",BLZ:"403",BEN:"745",BMU:"753",BTN:"0",BOL:"604",BES:"753",BIH:"1197",BWA:"1486",BRA:"284",VGB:"753",BRN:"681",BGR:"911",BFA:"753",BDI:"414",KHM:"1046",CMR:"659",CAN:"372",CYM:"753",CPV:"753",CAF:"188",TCD:"753","CHANNEL ISLANDS (U.K)":"753",CHL:"657",CHN:"899",COL:"410",COM:"753",COD:"0",COG:"659",COK:"753",CRI:"108",CIV:"466",HRV:"294",CUB:"559",CUW:"876",CYP:"751",CZE:"902",DNK:"362",DJI:"753",DMA:"753",DOM:"601",ECU:"560",EGY:"554",SLV:"547",GNQ:"632",ERI:"915",EST:"1057",SWZ:"0",ETH:"0",FLK:"753",FRO:"753",FJI:"640",FIN:"267",FRA:"158",GUF:"423",PYF:"753",GAB:"946",GMB:"753",GEO:"289",DEU:"650",GHA:"495",GIB:"779",GRC:"507",GRL:"264",GRD:"753",GLP:"753",GUM:"753",GTM:"798",GIN:"753",GNB:"753",GUY:"847",HTI:"1048",HND:"662",HUN:"296",ISL:"0",IND:"951",IDN:"783",IRN:"592",IRQ:"1080",IRL:"380",IMN:"436",ISR:"394",ITA:"414",JAM:"711",JPN:"471",JOR:"529",KAZ:"797",KEN:"574",KIR:"753",PRK:"754",KOR:"555",XKX:"1145",KWT:"675",KGZ:"217",LAO:"1069",LVA:"240",LBN:"794",LSO:"0",LBR:"677",LBY:"668",LIE:"151",LTU:"211",LUX:"220",MDG:"876","MADEIRA (PORTUGAL)":"663",MWI:"489",MYS:"551",MDV:"753",MLI:"1076",MLT:"520",MHL:"753",MTQ:"753",MRT:"753",MUS:"700",MYT:"753",MEX:"531",FSM:"753",MDA:"541",MCO:"158",MNG:"1366",MNE:"899",MSR:"753",MAR:"729",MOZ:"234",MMR:"719",NAM:"355",NRU:"753",NPL:"0",NLD:"326",NCL:"779",NZL:"246",NIC:"675",NER:"772",NGA:"526",NIU:"753",MKD:"851",MNP:"753",NOR:"47",OMN:"479",PAK:"592",PLW:"753",PSE:"719",PAN:"477",PNG:"597",PRY:"0",PER:"473",PHL:"672",POL:"828",PRT:"389",PRI:"596",QAT:"503",REU:"772",ROU:"489",RUS:"476",RWA:"712",SHN:"753",KNA:"753",LCA:"753",MAF:"753",SPM:"753",VCT:"753",WSM:"753",SMR:"414",STP:"753",SAU:"592",SEN:"870",SRB:"1086",SYC:"753",SLE:"489",SGP:"379",SXM:"753",SVK:"332",SVN:"620",SLB:"753",SOM:"753",ZAF:"1070",SSD:"890",ESP:"402",LKA:"731",SDN:"736",SUR:"1029",SWE:"68",CHE:"48",SYR:"713",TWN:"484",TJK:"255",TZA:"531",THA:"450",TLS:"753",TGO:"859",TON:"753",TTO:"559",TUN:"468",TUR:"376",TKM:"927",TCA:"753",TUV:"753",UGA:"279",UKR:"768",ARE:"556",GBR:"380",USA:"416",URY:"174",UZB:"612",VUT:"753",VEN:"711",VNM:"560",VIR:"650",YEM:"807",ZMB:"416",ZWE:"1575","MEMO: EU 27":"409"},Ye="marginal",ke="2021";var Q={data:We,type:Ye,year:ke};var He={co2:z,hosting:J,averageIntensity:y,marginalIntensity:Q};return Ne(xe);})();
9
+ Falling back to global average grid intensity.`),e.gridIntensity.network={value:a}),e.gridIntensity.network={country:t.country,value:parseFloat(E.data[t.country?.toUpperCase()])}):typeof t=="number"?e.gridIntensity.network={value:t}:(e.gridIntensity.network={value:a},console.warn(`The network grid intensity must be a number or an object. You passed in a ${typeof t}.
10
+ Falling back to global average grid intensity.`)))}return o?.dataReloadRatio&&(typeof o.dataReloadRatio=="number"?o.dataReloadRatio>=0&&o.dataReloadRatio<=1?e.dataReloadRatio=o.dataReloadRatio:(e.dataReloadRatio=N,console.warn(`The dataReloadRatio option must be a number between 0 and 1. You passed in ${o.dataReloadRatio}.
11
+ Falling back to default value.`)):(e.dataReloadRatio=N,console.warn(`The dataReloadRatio option must be a number. You passed in a ${typeof o.dataReloadRatio}.
12
+ Falling back to default value.`))),o?.firstVisitPercentage&&(typeof o.firstVisitPercentage=="number"?o.firstVisitPercentage>=0&&o.firstVisitPercentage<=1?e.firstVisitPercentage=o.firstVisitPercentage:(e.firstVisitPercentage=y,console.warn(`The firstVisitPercentage option must be a number between 0 and 1. You passed in ${o.firstVisitPercentage}.
13
+ Falling back to default value.`)):(e.firstVisitPercentage=y,console.warn(`The firstVisitPercentage option must be a number. You passed in a ${typeof o.firstVisitPercentage}.
14
+ Falling back to default value.`))),o?.returnVisitPercentage&&(typeof o.returnVisitPercentage=="number"?o.returnVisitPercentage>=0&&o.returnVisitPercentage<=1?e.returnVisitPercentage=o.returnVisitPercentage:(e.returnVisitPercentage=g,console.warn(`The returnVisitPercentage option must be a number between 0 and 1. You passed in ${o.returnVisitPercentage}.
15
+ Falling back to default value.`)):(e.returnVisitPercentage=g,console.warn(`The returnVisitPercentage option must be a number. You passed in a ${typeof o.returnVisitPercentage}.
16
+ Falling back to default value.`))),e}var P=class{constructor(e){this.options=e}energyPerByteByComponent(e){let n=e/A.GIGABYTE*V;return{consumerDeviceEnergy:n*C,networkEnergy:n*p,productionEnergy:n*S,dataCenterEnergy:n*O}}co2byComponent(e,r=a,n={}){let t=a,s=a,i=a,d=a;if(n?.gridIntensity){let{device:c,network:u,dataCenter:L}=n.gridIntensity;c?.value&&(t=c.value),u?.value&&(s=u.value),L?.value&&(i=L.value)}r===!0&&(i=f);let l={};for(let[c,u]of Object.entries(e))c.startsWith("dataCenterEnergy")?l[c.replace("Energy","CO2")]=u*i:c.startsWith("consumerDeviceEnergy")?l[c.replace("Energy","CO2")]=u*t:c.startsWith("networkEnergy")?l[c.replace("Energy","CO2")]=u*s:l[c.replace("Energy","CO2")]=u*d;return l}perByte(e,r=!1,n=!1,t={}){let s=this.energyPerByteByComponent(e,t);if(typeof r!="boolean")throw new Error(`perByte expects a boolean for the carbon intensity value. Received: ${r}`);let i=this.co2byComponent(s,r,t),l=Object.values(i).reduce((c,u)=>c+u);return n?{...i,total:l}:l}perVisit(e,r=!1,n=!1,t={}){let s=this.energyPerVisitByComponent(e,t);if(typeof r!="boolean")throw new Error(`perVisit expects a boolean for the carbon intensity value. Received: ${r}`);let i=this.co2byComponent(s,r,t),l=Object.values(i).reduce((c,u)=>c+u);return n?{...i,total:l}:l}energyPerByte(e){let r=this.energyPerByteByComponent(e);return Object.values(r).reduce((t,s)=>t+s)}energyPerVisitByComponent(e,r={},n=y,t=g,s=N){r.dataReloadRatio&&(s=r.dataReloadRatio),r.firstVisitPercentage&&(n=r.firstVisitPercentage),r.returnVisitPercentage&&(t=r.returnVisitPercentage);let i=this.energyPerByteByComponent(e),d={},l=Object.values(i);for(let[c,u]of Object.entries(i))d[`${c} - first`]=u*n,d[`${c} - subsequent`]=u*t*s;return d}energyPerVisit(e){let r=0,n=0,t=Object.entries(this.energyPerVisitByComponent(e));for(let[s,i]of t)s.indexOf("first")>0&&(r+=i);for(let[s,i]of t)s.indexOf("subsequent")>0&&(n+=i);return r+n}emissionsPerVisitInGrams(e,r=a){return R(e*r)}annualEnergyInKwh(e,r=1e3){return e*r*12}annualEmissionsInGrams(e,r=1e3){return e*r*12}annualSegmentEnergy(e){return{consumerDeviceEnergy:R(e*C),networkEnergy:R(e*p),dataCenterEnergy:R(e*O),productionEnergy:R(e*S)}}};var G=P;var _=class{constructor(e){if(this.model=new G,e?.model==="1byte")this.model=new D;else if(e?.model==="swd")this.model=new G;else if(e?.model)throw new Error(`"${e.model}" is not a valid model. Please use "1byte" for the OneByte model, and "swd" for the Sustainable Web Design model.
17
+ See https://developers.thegreenwebfoundation.org/co2js/models/ to learn more about the models available in CO2.js.`);e?.results==="segment"?this.model.results={segment:!0}:this.model.results={segment:!1}}perByte(e,r=!1){return this.model.perByte(e,r,this.model.results.segment)}perVisit(e,r=!1){if(this.model?.perVisit)return this.model.perVisit(e,r,this.model.results.segment);throw new Error(`The perVisit() method is not supported in the model you are using. Try using perByte() instead.
18
+ See https://developers.thegreenwebfoundation.org/co2js/methods/ to learn more about the methods available in CO2.js.`)}perByteTrace(e,r=!1,n={}){let t={};return n&&(t=B(n)),{co2:this.model.perByte(e,r,this.model.results.segment,t),green:r,variables:{description:"Below are the variables used to calculate this CO2 estimate.",bytes:e,gridIntensity:{description:"The grid intensity (grams per kilowatt-hour) used to calculate this CO2 estimate.",network:t?.gridIntensity?.network?.value||a,dataCenter:r?f:t?.gridIntensity?.dataCenter?.value||a,production:a,device:t?.gridIntensity?.device?.value||a}}}}perVisitTrace(e,r=!1,n={}){if(this.model?.perVisit){let t={};return n&&(t=B(n)),{co2:this.model.perVisit(e,r,this.model.results.segment,t),green:r,variables:{description:"Below are the variables used to calculate this CO2 estimate.",bytes:e,gridIntensity:{description:"The grid intensity (grams per kilowatt-hour) used to calculate this CO2 estimate.",network:t?.gridIntensity?.network?.value||a,dataCenter:r?f:t?.gridIntensity?.dataCenter?.value||a,production:a,device:t?.gridIntensity?.device?.value||a},dataReloadRatio:t?.dataReloadRatio||.02,firstVisitPercentage:t?.firstVisitPercentage||.75,returnVisitPercentage:t?.returnVisitPercentage||.25}}}else throw new Error(`The perVisitDetailed() method is not supported in the model you are using. Try using perByte() instead.
19
+ See https://developers.thegreenwebfoundation.org/co2js/methods/ to learn more about the methods available in CO2.js.`)}perDomain(e,r){let n=[];for(let t of Object.keys(e.domains)){let s;r&&r.indexOf(t)>-1?s=this.perByte(e.domains[t].transferSize,!0):s=this.perByte(e.domains[t].transferSize),n.push({domain:t,co2:s,transferSize:e.domains[t].transferSize})}return n.sort((t,s)=>s.co2-t.co2),n}perPage(e,r){let n=this.perDomain(e,r),t=0;for(let s of n)t+=s.co2;return t}perContentType(e,r){let n={};for(let s of e.assets){let i=new URL(s.url).domain,d=s.transferSize,l=this.perByte(d,r&&r.indexOf(i)>-1),c=s.type;n[c]||(n[c]={co2:0,transferSize:0}),n[c].co2+=l,n[c].transferSize+=d}let t=[];for(let s of Object.keys(n))t.push({type:s,co2:n[s].co2,transferSize:n[s].transferSize});return t.sort((s,i)=>i.co2-s.co2),t}dirtiestResources(e,r){let n=[];for(let t of e.assets){let s=new URL(t.url).domain,i=t.transferSize,d=this.perByte(i,r&&r.indexOf(s)>-1);n.push({url:t.url,co2:d,transferSize:i})}return n.sort((t,s)=>s.co2-t.co2),n.slice(0,n.length>10?10:n.length)}perParty(e,r){let n=0,t=0,s=e.firstPartyRegEx;for(let i of Object.keys(e.domains))i.match(s)?n+=this.perByte(e.domains[i].transferSize,r&&r.indexOf(i)>-1):t+=this.perByte(e.domains[i].transferSize,r&&r.indexOf(i)>-1);return{firstParty:n,thirdParty:t}}};var h=_;function H(o){return typeof o=="string"?k(o):j(o)}async function k(o){return(await(await fetch(`https://api.thegreenwebfoundation.org/greencheck/${o}`)).json()).green}async function j(o){try{let e="https://api.thegreenwebfoundation.org/v2/greencheckmulti",r=JSON.stringify(o),t=await(await fetch(`${e}/${r}`)).json();return x(t)}catch{return[]}}function x(o){return Object.entries(o).filter(([n,t])=>t.green).map(([n,t])=>t.url)}var v={check:H};function Z(o){return v.check(o)}var b={check:Z};var $={AFG:120.482,AFRICA:483.78,ALB:23.438,DZA:488.393,ASM:687.5,AGO:168.594,ATG:657.143,ARG:337.533,ARM:222.678,ABW:591.398,ASIA:531.78,AUS:503.179,AUT:157.52,AZE:532.902,BHS:698.113,BHR:489.924,BGD:581.485,BRB:644.86,BLR:415.774,BEL:165.363,BLZ:484.375,BEN:666.667,BTN:24.444,BOL:319.432,BIH:516.626,BWA:794.521,BRA:102.411,BRN:658.849,BGR:399.565,BFA:611.429,BDI:250,CPV:600,KHM:399.31,CMR:278.261,CAN:125.55,CYM:684.932,CAF:0,TCD:677.419,CHL:333.173,CHN:530.214,COL:169.309,COM:714.286,COG:398.01,COD:25.362,COK:400,CRI:37.213,CIV:390.71,HRV:246.459,CUB:574.684,CYP:589.354,CZE:415.345,DNK:180.709,DJI:666.667,DMA:529.412,DOM:540.387,ECU:169.384,EGY:485.367,SLV:194.226,GNQ:492.958,ERI:688.889,EST:464.029,SWZ:189.189,ETH:25.187,EU:277.35,EUROPE:298.01,FLK:500,FRO:428.571,FJI:292.035,FIN:130.977,FRA:84.817,GUF:254.717,PYF:471.429,G20:440.39,G7:341.23,GAB:397.38,GMB:700,GEO:134.831,DEU:385.467,GHA:362.942,GRC:343.822,GRL:133.333,GRD:714.286,GLP:611.765,GUM:670.33,GTM:313.019,GIN:208.633,GNB:750,GUY:634.146,HTI:606.061,HND:374.269,HKG:684.823,HUN:222.973,ISL:28.557,IND:632.406,IDN:623.281,IRN:493.595,IRQ:500.206,IRL:345.347,ISR:550.493,ITA:371.692,JAM:524.138,JPN:483.039,JOR:399.909,KAZ:635.574,KEN:99.919,KIR:666.667,XKX:766.605,KWT:489.61,KGZ:104.354,LAO:242.182,"LATIN AMERICA AND CARIBBEAN":238.27,LVA:181.818,LBN:545.941,LSO:20,LBR:304.348,LBY:496.565,LTU:194.245,LUX:168.142,MAC:491.525,MDG:483.254,MWI:133.803,MYS:543.737,MDV:651.515,MLI:466.077,MLT:442.478,MTQ:698.63,MRT:526.596,MUS:611.111,MEX:421.402,"MIDDLE EAST":514.89,MDA:685.874,MNG:749.656,MNE:399.381,MSR:1e3,MAR:610.412,MOZ:125.063,MMR:348.837,NAM:63.694,NRU:750,NPL:24.51,NLD:354.988,NCL:610.119,NZL:98.639,NIC:354.212,NER:622.222,NGA:368.421,"NORTH AMERICA":336.4,PRK:157.785,MKD:529.328,NOR:28.818,OCEANIA:446.65,OECD:338.75,OMN:488.272,PAK:343.366,PSE:465.116,PAN:193.923,PNG:526.749,PRY:25.487,PER:254.521,POL:634.579,PRT:234.029,PRI:681.469,QAT:489.867,REU:519.031,ROU:264.121,RUS:367.189,RWA:294.118,KNA:681.818,LCA:685.714,SPM:800,VCT:500,WSM:470.588,STP:600,SAU:571.336,SEN:502.674,SRB:569.375,SYC:615.385,SLE:47.619,SGP:489.234,SVK:140.666,SVN:237.378,SLB:727.273,SOM:634.146,ZAF:709.002,KOR:435.689,SSD:684.211,ESP:217.373,LKA:479.829,SDN:242.917,SUR:356.436,SWE:45.084,CHE:45.622,SYR:540.573,TWN:561.431,TJK:84.136,TZA:361.077,THA:503.07,PHL:582.365,TGO:507.937,TON:625,TTO:520.046,TUN:469.428,TUR:413.628,TKM:544.393,TCA:703.704,UGA:52.273,UKR:206.539,ARE:461.845,GBR:257.379,USA:367.768,URY:116.168,UZB:506.164,VUT:571.429,VEN:189.446,VNM:376.828,VGB:714.286,VIR:685.714,WORLD:435.99,YEM:528.409,ZMB:84.698,ZWE:393.035},z="average";var E={data:$,type:z};var J={AFG:"414",ALB:"0",DZA:"528",ASM:"753",AND:"188",AGO:"1476",AIA:"753",ATG:"753",ARG:"478",ARM:"390",ABW:"753",AUS:"808",AUT:"242",AZE:"534","AZORES (PORTUGAL)":"753",BHS:"753",BHR:"726",BGD:"528",BRB:"749",BLR:"400",BEL:"252",BLZ:"403",BEN:"745",BMU:"753",BTN:"0",BOL:"604",BES:"753",BIH:"1197",BWA:"1486",BRA:"284",VGB:"753",BRN:"681",BGR:"911",BFA:"753",BDI:"414",KHM:"1046",CMR:"659",CAN:"372",CYM:"753",CPV:"753",CAF:"188",TCD:"753","CHANNEL ISLANDS (U.K)":"753",CHL:"657",CHN:"899",COL:"410",COM:"753",COD:"0",COG:"659",COK:"753",CRI:"108",CIV:"466",HRV:"294",CUB:"559",CUW:"876",CYP:"751",CZE:"902",DNK:"362",DJI:"753",DMA:"753",DOM:"601",ECU:"560",EGY:"554",SLV:"547",GNQ:"632",ERI:"915",EST:"1057",SWZ:"0",ETH:"0",FLK:"753",FRO:"753",FJI:"640",FIN:"267",FRA:"158",GUF:"423",PYF:"753",GAB:"946",GMB:"753",GEO:"289",DEU:"650",GHA:"495",GIB:"779",GRC:"507",GRL:"264",GRD:"753",GLP:"753",GUM:"753",GTM:"798",GIN:"753",GNB:"753",GUY:"847",HTI:"1048",HND:"662",HUN:"296",ISL:"0",IND:"951",IDN:"783",IRN:"592",IRQ:"1080",IRL:"380",IMN:"436",ISR:"394",ITA:"414",JAM:"711",JPN:"471",JOR:"529",KAZ:"797",KEN:"574",KIR:"753",PRK:"754",KOR:"555",XKX:"1145",KWT:"675",KGZ:"217",LAO:"1069",LVA:"240",LBN:"794",LSO:"0",LBR:"677",LBY:"668",LIE:"151",LTU:"211",LUX:"220",MDG:"876","MADEIRA (PORTUGAL)":"663",MWI:"489",MYS:"551",MDV:"753",MLI:"1076",MLT:"520",MHL:"753",MTQ:"753",MRT:"753",MUS:"700",MYT:"753",MEX:"531",FSM:"753",MDA:"541",MCO:"158",MNG:"1366",MNE:"899",MSR:"753",MAR:"729",MOZ:"234",MMR:"719",NAM:"355",NRU:"753",NPL:"0",NLD:"326",NCL:"779",NZL:"246",NIC:"675",NER:"772",NGA:"526",NIU:"753",MKD:"851",MNP:"753",NOR:"47",OMN:"479",PAK:"592",PLW:"753",PSE:"719",PAN:"477",PNG:"597",PRY:"0",PER:"473",PHL:"672",POL:"828",PRT:"389",PRI:"596",QAT:"503",REU:"772",ROU:"489",RUS:"476",RWA:"712",SHN:"753",KNA:"753",LCA:"753",MAF:"753",SPM:"753",VCT:"753",WSM:"753",SMR:"414",STP:"753",SAU:"592",SEN:"870",SRB:"1086",SYC:"753",SLE:"489",SGP:"379",SXM:"753",SVK:"332",SVN:"620",SLB:"753",SOM:"753",ZAF:"1070",SSD:"890",ESP:"402",LKA:"731",SDN:"736",SUR:"1029",SWE:"68",CHE:"48",SYR:"713",TWN:"484",TJK:"255",TZA:"531",THA:"450",TLS:"753",TGO:"859",TON:"753",TTO:"559",TUN:"468",TUR:"376",TKM:"927",TCA:"753",TUV:"753",UGA:"279",UKR:"768",ARE:"556",GBR:"380",USA:"416",URY:"174",UZB:"612",VUT:"753",VEN:"711",VNM:"560",VIR:"650",YEM:"807",ZMB:"416",ZWE:"1575","MEMO: EU 27":"409"},Q="marginal",q="2021";var M={data:J,type:Q,year:q};var X={co2:h,hosting:b,averageIntensity:E,marginalIntensity:M};return Y(ee);})();
20
20
  //# sourceMappingURL=index.js.map