UNPKG

next

Version:

The React Framework

31 lines 6.86 kB
"use strict";exports.__esModule=true;exports.Telemetry=void 0;var _chalk=_interopRequireDefault(require("chalk"));var _conf=_interopRequireDefault(require("next/dist/compiled/conf"));var _crypto=require("crypto");var _isDocker=_interopRequireDefault(require("next/dist/compiled/is-docker"));var _path=_interopRequireDefault(require("path"));var _anonymousMeta=require("./anonymous-meta");var ciEnvironment=_interopRequireWildcard(require("./ci-info"));var _postPayload2=require("./post-payload");var _projectId=require("./project-id");function _getRequireWildcardCache(){if(typeof WeakMap!=="function")return null;var cache=new WeakMap();_getRequireWildcardCache=function(){return cache;};return cache;}function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache();if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}// This is the key that stores whether or not telemetry is enabled or disabled. const TELEMETRY_KEY_ENABLED='telemetry.enabled';// This is the key that specifies when the user was informed about anonymous // telemetry collection. const TELEMETRY_KEY_NOTIFY_DATE='telemetry.notifiedAt';// This is a quasi-persistent identifier used to dedupe recurring events. It's // generated from random data and completely anonymous. const TELEMETRY_KEY_ID=`telemetry.anonymousId`;// This is the cryptographic salt that is included within every hashed value. // This salt value is never sent to us, ensuring privacy and the one-way nature // of the hash (prevents dictionary lookups of pre-computed hashes). // See the `oneWayHash` function. const TELEMETRY_KEY_SALT=`telemetry.salt`;class Telemetry{constructor({distDir}){this.conf=void 0;this.sessionId=void 0;this.rawProjectId=void 0;this.NEXT_TELEMETRY_DISABLED=void 0;this.NEXT_TELEMETRY_DEBUG=void 0;this.queue=void 0;this.notify=()=>{if(this.isDisabled||!this.conf){return;}// The end-user has already been notified about our telemetry integration. We // don't need to constantly annoy them about it. // We will re-inform users about the telemetry if significant changes are // ever made. if(this.conf.get(TELEMETRY_KEY_NOTIFY_DATE,'')){return;}this.conf.set(TELEMETRY_KEY_NOTIFY_DATE,Date.now().toString());console.log(`${_chalk.default.magenta.bold('Attention')}: Next.js now collects completely anonymous telemetry regarding usage.`);console.log(`This information is used to shape Next.js' roadmap and prioritize features.`);console.log(`You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:`);console.log(_chalk.default.cyan('https://nextjs.org/telemetry'));console.log();};this.setEnabled=_enabled=>{const enabled=!!_enabled;this.conf&&this.conf.set(TELEMETRY_KEY_ENABLED,enabled);};this.oneWayHash=payload=>{const hash=(0,_crypto.createHash)('sha256');// Always prepend the payload value with salt. This ensures the hash is truly // one-way. hash.update(this.salt);// Update is an append operation, not a replacement. The salt from the prior // update is still present! hash.update(payload);return hash.digest('hex');};this.record=_events=>{const _this=this;// pseudo try-catch async function wrapper(){return await _this.submitRecord(_events);}const prom=wrapper().then(value=>({isFulfilled:true,isRejected:false,value})).catch(reason=>({isFulfilled:false,isRejected:true,reason}))// Acts as `Promise#finally` because `catch` transforms the error .then(res=>{// Clean up the event to prevent unbounded `Set` growth this.queue.delete(prom);return res;});// Track this `Promise` so we can flush pending events this.queue.add(prom);return prom;};this.flush=async()=>Promise.all(this.queue).catch(()=>null);this.submitRecord=_events=>{let events;if(Array.isArray(_events)){events=_events;}else{events=[_events];}if(events.length<1){return Promise.resolve();}if(this.NEXT_TELEMETRY_DEBUG){// Print to standard error to simplify selecting the output events.forEach(({eventName,payload})=>console.error(`[telemetry] `+JSON.stringify({eventName,payload},null,2)));// Do not send the telemetry data if debugging. Users may use this feature // to preview what data would be sent. return Promise.resolve();}// Skip recording telemetry if the feature is disabled if(this.isDisabled){return Promise.resolve();}const context={anonymousId:this.anonymousId,projectId:this.projectId,sessionId:this.sessionId};const meta=(0,_anonymousMeta.getAnonymousMeta)();return(0,_postPayload2._postPayload)(`https://telemetry.nextjs.org/api/v1/record`,{context,meta,events:events.map(({eventName,payload})=>({eventName,fields:payload}))});};// Read in the constructor so that .env can be loaded before reading const{NEXT_TELEMETRY_DISABLED,NEXT_TELEMETRY_DEBUG}=process.env;this.NEXT_TELEMETRY_DISABLED=NEXT_TELEMETRY_DISABLED;this.NEXT_TELEMETRY_DEBUG=NEXT_TELEMETRY_DEBUG;const storageDirectory=getStorageDirectory(distDir);try{// `conf` incorrectly throws a permission error during initialization // instead of waiting for first use. We need to handle it, otherwise the // process may crash. this.conf=new _conf.default({projectName:'nextjs',cwd:storageDirectory});}catch(_){this.conf=null;}this.sessionId=(0,_crypto.randomBytes)(32).toString('hex');this.rawProjectId=(0,_projectId.getRawProjectId)();this.queue=new Set();this.notify();}get anonymousId(){const val=this.conf&&this.conf.get(TELEMETRY_KEY_ID);if(val){return val;}const generated=(0,_crypto.randomBytes)(32).toString('hex');this.conf&&this.conf.set(TELEMETRY_KEY_ID,generated);return generated;}get salt(){const val=this.conf&&this.conf.get(TELEMETRY_KEY_SALT);if(val){return val;}const generated=(0,_crypto.randomBytes)(16).toString('hex');this.conf&&this.conf.set(TELEMETRY_KEY_SALT,generated);return generated;}get isDisabled(){if(!!this.NEXT_TELEMETRY_DISABLED||!this.conf){return true;}return this.conf.get(TELEMETRY_KEY_ENABLED,true)===false;}get isEnabled(){return!!this.conf&&this.conf.get(TELEMETRY_KEY_ENABLED,true)!==false;}get projectId(){return this.oneWayHash(this.rawProjectId);}}exports.Telemetry=Telemetry;function getStorageDirectory(distDir){const isLikelyEphemeral=ciEnvironment.isCI||(0,_isDocker.default)();if(isLikelyEphemeral){return _path.default.join(distDir,'cache');}return undefined;} //# sourceMappingURL=storage.js.map