diff --git a/packages/create-gatsby/package.json b/packages/create-gatsby/package.json index 05731910d136f..3558a0202c82d 100644 --- a/packages/create-gatsby/package.json +++ b/packages/create-gatsby/package.json @@ -30,11 +30,13 @@ "gatsby-plugin-utils": "^0.4.0-next.0", "joi": "^17.2.1", "microbundle": "^0.12.4", + "node-fetch": "^2.6.1", "prettier": "^2.1.2", "string-length": "^4.0.1", "terminal-link": "^2.1.1", "tiny-spin": "^1.0.2", - "typescript": "^4.0.5" + "typescript": "^4.0.5", + "uuid": "3.4.0" }, "repository": { "type": "git", diff --git a/packages/create-gatsby/src/index.ts b/packages/create-gatsby/src/index.ts index 3a5ef0ed29ac0..dcbea986198c2 100644 --- a/packages/create-gatsby/src/index.ts +++ b/packages/create-gatsby/src/index.ts @@ -11,6 +11,11 @@ import { plugin } from "./components/plugin" import { makePluginConfigQuestions } from "./plugin-options-form" import { center, rule, wrap } from "./components/utils" import { stripIndent } from "common-tags" +import { trackCli } from "./tracking" +import crypto from "crypto" + +const sha256 = (str: string): string => + crypto.createHash(`sha256`).update(str).digest(`hex`) /** * Hide string on windows (for emojis) @@ -128,6 +133,8 @@ export type PluginConfigMap = Record> const removeKey = (plugin: string): string => plugin.split(`:`)[0] export async function run(): Promise { + trackCli(`CREATE_GATSBY_START`) + const { version } = require(`../package.json`) console.log(c.grey(`create-gatsby version ${version}`)) @@ -137,8 +144,8 @@ export async function run(): Promise { ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))} - - + + ` ) console.log(c.red(rule())) @@ -167,6 +174,23 @@ ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))} const data = await enquirer.prompt(questions) + trackCli(`CREATE_GATSBY_SELECT_OPTION`, { + name: `project_name`, + valueString: sha256(data.project), + }) + trackCli(`CREATE_GATSBY_SELECT_OPTION`, { + name: `CMS`, + valueString: data.cms || `none`, + }) + trackCli(`CREATE_GATSBY_SELECT_OPTION`, { + name: `CSS_TOOLS`, + valueString: data.styling || `none`, + }) + trackCli(`CREATE_GATSBY_SELECT_OPTION`, { + name: `PLUGIN`, + valueStringArray: data.features || [], + }) + const messages: Array = [ `${w(`🛠 `)}Create a new Gatsby site in the folder ${c.magenta( data.project @@ -245,9 +269,14 @@ ${center(c.blueBright.bold.underline(`Welcome to Gatsby!`))} `\nGreat! A few of the selections you made need to be configured. Please fill in the options for each plugin now:\n` ) + trackCli(`CREATE_GATSBY_SET_PLUGINS_START`) + const enquirer = new Enquirer>() enquirer.use(plugin) + pluginConfig = { ...pluginConfig, ...(await enquirer.prompt(config)) } + + trackCli(`CREATE_GATSBY_SET_PLUGINS_STOP`) } console.log(` @@ -266,6 +295,8 @@ ${c.bold(`Thanks! Here's what we'll now do:`)} }) if (!confirm) { + trackCli(`CREATE_GATSBY_CANCEL`) + console.log(`OK, bye!`) return } @@ -289,7 +320,7 @@ ${c.bold(`Thanks! Here's what we'll now do:`)} stripIndent` ${w(`🎉 `)}Your new Gatsby site ${c.bold( data.project - )} has been successfully bootstrapped + )} has been successfully bootstrapped at ${c.bold(path.resolve(data.project))}. ` ) @@ -304,4 +335,14 @@ ${c.bold(`Thanks! Here's what we'll now do:`)} console.log(`See all commands at\n ${c.blueBright(`https://www.gatsbyjs.com/docs/gatsby-cli/`)} `) + + trackCli(`CREATE_GATSBY_SUCCESS`) } + +process.on(`exit`, exitCode => { + trackCli(`CREATE_GATSBY_END`, { exitCode }) + + if (exitCode === -1) { + trackCli(`CREATE_GATSBY_ERROR`) + } +}) diff --git a/packages/create-gatsby/src/tracking.ts b/packages/create-gatsby/src/tracking.ts new file mode 100644 index 0000000000000..531b5bdd916dc --- /dev/null +++ b/packages/create-gatsby/src/tracking.ts @@ -0,0 +1,46 @@ +import fetch from "node-fetch" +import uuidv4 from "uuid/v4" +import { getConfigStore } from "./get-config-store" + +const store = getConfigStore() +const gatsbyCliVersion = require(`../package.json`).version +const analyticsApi = + process.env.GATSBY_TELEMETRY_API || `https://analytics.gatsbyjs.com/events` + +const getMachineId = (): string => { + let machineId = store.get(`telemetry.machineId`) + + if (typeof machineId !== `string`) { + machineId = uuidv4() + store.set(`telemetry.machineId`, machineId) + } + + return machineId +} + +export interface ITrackCliArgs { + name?: string + valueString?: string + exitCode?: number + valueStringArray?: Array +} + +export const trackCli = (eventType: string, args?: ITrackCliArgs): void => { + fetch(analyticsApi, { + method: `POST`, + headers: { + "content-type": `application/json`, + "user-agent": `create-gatsby:${gatsbyCliVersion}`, + }, + body: JSON.stringify({ + eventType, + time: new Date(), + sessionId: uuidv4(), + machineId: getMachineId(), + componentId: `create-gatsby`, + componentVersion: 1, + gatsbyCliVersion, + ...args, + }), + }).catch(() => {}) /* do nothing, it's telemetry */ +} diff --git a/packages/create-gatsby/src/types.d.ts b/packages/create-gatsby/src/types.d.ts index 0acf19b243a69..105fddd102e9d 100644 --- a/packages/create-gatsby/src/types.d.ts +++ b/packages/create-gatsby/src/types.d.ts @@ -1,2 +1,3 @@ declare module "stream-filter" declare module "ansi-wordwrap" +declare module 'uuid/v4'; diff --git a/packages/gatsby-telemetry/src/in-memory-store.ts b/packages/gatsby-telemetry/src/in-memory-store.ts index 371480e56dedb..ec4ead3fc611c 100644 --- a/packages/gatsby-telemetry/src/in-memory-store.ts +++ b/packages/gatsby-telemetry/src/in-memory-store.ts @@ -1,4 +1,4 @@ -import uuidv4 from "uuid" +import uuidv4 from "uuid/v4" import os from "os" import { join } from "path"