feat: medusa-telemetry (#328)
* feat: adds a telemetry package to collect anonymous usage data * fix: update telemetry host * fix: adds medusa telemetry --disable * fix: add tracking of link,login,new * fix: interactively collect db credentials * fix: require seed file * fix: removes tracking from reporter
This commit is contained in:
@@ -3,11 +3,14 @@ const inquirer = require("inquirer")
|
||||
const open = require("open")
|
||||
const execa = require("execa")
|
||||
const resolveCwd = require(`resolve-cwd`)
|
||||
const { track } = require("medusa-telemetry")
|
||||
|
||||
const { getToken } = require("../util/token-store")
|
||||
const logger = require("../reporter").default
|
||||
|
||||
module.exports = {
|
||||
link: async argv => {
|
||||
track("CLI_LINK", { args: argv })
|
||||
const port = process.env.PORT || 9000
|
||||
const appHost =
|
||||
process.env.MEDUSA_APP_HOST || "https://app.medusa-commerce.com"
|
||||
@@ -15,18 +18,6 @@ module.exports = {
|
||||
const apiHost =
|
||||
process.env.MEDUSA_API_HOST || "https://api.medusa-commerce.com"
|
||||
|
||||
function resolveLocalCommand(command) {
|
||||
try {
|
||||
const cmdPath = resolveCwd.silent(
|
||||
`@medusajs/medusa/dist/commands/${command}`
|
||||
)
|
||||
return require(cmdPath).default
|
||||
} catch (err) {
|
||||
console.log("Could not find local user command.")
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if there is already a token from a previous log in; this is
|
||||
// necessary to redirect the customer to the page where local linking is
|
||||
// done
|
||||
@@ -88,6 +79,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
logger.success(linkActivity, "Local project linked")
|
||||
track("CLI_LINK_COMPLETED")
|
||||
|
||||
console.log()
|
||||
console.log(
|
||||
@@ -125,6 +117,8 @@ module.exports = {
|
||||
`Could not open browser go to: ${appHost}/local-link?lurl=http://localhost:9000<oken=${auth.user.id}`
|
||||
)
|
||||
})
|
||||
|
||||
track("CLI_LINK_BROWSER_OPENED")
|
||||
})
|
||||
|
||||
if (argv.develop) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const axios = require("axios").default
|
||||
const open = require("open")
|
||||
const inquirer = require("inquirer")
|
||||
const { track } = require("medusa-telemetry")
|
||||
|
||||
const logger = require("../reporter").default
|
||||
const { setToken } = require("../util/token-store")
|
||||
@@ -12,6 +13,7 @@ const { setToken } = require("../util/token-store")
|
||||
*/
|
||||
module.exports = {
|
||||
login: async _ => {
|
||||
track("CLI_LOGIN")
|
||||
const apiHost =
|
||||
process.env.MEDUSA_API_HOST || "https://api.medusa-commerce.com"
|
||||
|
||||
@@ -80,9 +82,11 @@ module.exports = {
|
||||
})
|
||||
|
||||
if (user) {
|
||||
track("CLI_LOGIN_SUCCEEDED")
|
||||
logger.success(spinner, "Log in succeeded.")
|
||||
setToken(auth.password)
|
||||
} else {
|
||||
track("CLI_LOGIN_FAILED")
|
||||
logger.failure(spinner, "Log in failed.")
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,8 +10,11 @@ import hostedGitInfo from "hosted-git-info"
|
||||
import isValid from "is-valid-path"
|
||||
import sysPath from "path"
|
||||
import prompts from "prompts"
|
||||
import { Pool } from "pg"
|
||||
import url from "url"
|
||||
import { createDatabase } from "pg-god"
|
||||
import { track } from "medusa-telemetry"
|
||||
import inquirer from "inquirer"
|
||||
|
||||
import reporter from "../reporter"
|
||||
import { getPackageManager, setPackageManager } from "../util/package-manager"
|
||||
@@ -76,7 +79,7 @@ const createInitialGitCommit = async (rootPath, starterUrl) => {
|
||||
// use execSync instead of spawn to handle git clients using
|
||||
// pgp signatures (with password)
|
||||
try {
|
||||
execSync(`git commit -m "Initial commit from gatsby: (${starterUrl})"`, {
|
||||
execSync(`git commit -m "Initial commit from medusa: (${starterUrl})"`, {
|
||||
cwd: rootPath,
|
||||
})
|
||||
} catch {
|
||||
@@ -91,6 +94,8 @@ const install = async rootPath => {
|
||||
const prevDir = process.cwd()
|
||||
|
||||
reporter.info(`Installing packages...`)
|
||||
console.log() // Add some space
|
||||
|
||||
process.chdir(rootPath)
|
||||
|
||||
const npmConfigUserAgent = process.env.npm_config_user_agent
|
||||
@@ -145,6 +150,7 @@ const copy = async (starterPath, rootPath) => {
|
||||
await fs.copy(starterPath, rootPath, { filter: ignored })
|
||||
|
||||
reporter.success(copyActivity, `Created starter directory layout`)
|
||||
console.log() // Add some space
|
||||
|
||||
await install(rootPath)
|
||||
|
||||
@@ -242,8 +248,122 @@ const defaultDBCreds = {
|
||||
host: "localhost",
|
||||
}
|
||||
|
||||
const verifyPgCreds = async creds => {
|
||||
const pool = new Pool(creds)
|
||||
return new Promise((resolve, reject) => {
|
||||
pool.query("SELECT NOW()", (err, res) => {
|
||||
pool.end()
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const interactiveDbCreds = async (dbName, dbCreds = {}) => {
|
||||
const credentials = Object.assign({}, defaultDBCreds, dbCreds)
|
||||
let collecting = true
|
||||
while (collecting) {
|
||||
const result = await inquirer
|
||||
.prompt([
|
||||
{
|
||||
type: "list",
|
||||
name: "continueWithDefault",
|
||||
message: `
|
||||
|
||||
Will attempt to setup database "${dbName}" with credentials:
|
||||
user: ${credentials.user}
|
||||
password: ***
|
||||
database: ${credentials.database}
|
||||
port: ${credentials.port}
|
||||
host: ${credentials.host}
|
||||
Do you wish to continue with these credentials?
|
||||
|
||||
`,
|
||||
choices: [`Continue`, `Change credentials`, `Skip database setup`],
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
when: ({ continueWithDefault }) =>
|
||||
continueWithDefault === `Change credentials`,
|
||||
name: "user",
|
||||
default: credentials.user,
|
||||
message: `DB user`,
|
||||
},
|
||||
{
|
||||
type: "password",
|
||||
when: ({ continueWithDefault }) =>
|
||||
continueWithDefault === `Change credentials`,
|
||||
name: "password",
|
||||
default: credentials.password,
|
||||
message: `DB password`,
|
||||
},
|
||||
{
|
||||
type: "number",
|
||||
when: ({ continueWithDefault }) =>
|
||||
continueWithDefault === `Change credentials`,
|
||||
name: "port",
|
||||
default: credentials.port,
|
||||
message: `DB port`,
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
when: ({ continueWithDefault }) =>
|
||||
continueWithDefault === `Change credentials`,
|
||||
name: "host",
|
||||
default: credentials.host,
|
||||
message: `DB host`,
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
when: ({ continueWithDefault }) =>
|
||||
continueWithDefault === `Change credentials`,
|
||||
name: "database",
|
||||
default: credentials.database,
|
||||
message: `DB database`,
|
||||
},
|
||||
])
|
||||
.then(async answers => {
|
||||
const collectedCreds = Object.assign({}, credentials, {
|
||||
user: answers.user,
|
||||
password: answers.password,
|
||||
host: answers.host,
|
||||
port: answers.port,
|
||||
database: answers.database,
|
||||
})
|
||||
|
||||
switch (answers.continueWithDefault) {
|
||||
case "Continue": {
|
||||
const done = await verifyPgCreds(credentials).catch(_ => false)
|
||||
if (done) {
|
||||
return credentials
|
||||
}
|
||||
return false
|
||||
}
|
||||
case "Change credentials": {
|
||||
const done = await verifyPgCreds(collectedCreds).catch(_ => false)
|
||||
if (done) {
|
||||
return collectedCreds
|
||||
}
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
if (result !== false) {
|
||||
return result
|
||||
}
|
||||
|
||||
console.log("\n\nCould not verify DB credentials - please try again\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
const setupDB = async (dbName, dbCreds = {}) => {
|
||||
const credentials = Object.assign(defaultDBCreds, dbCreds)
|
||||
const credentials = Object.assign({}, defaultDBCreds, dbCreds)
|
||||
|
||||
const dbActivity = reporter.activity(`Setting up database "${dbName}"...`)
|
||||
await createDatabase(
|
||||
@@ -257,7 +377,7 @@ const setupDB = async (dbName, dbCreds = {}) => {
|
||||
reporter.success(dbActivity, `Created database "${dbName}"`)
|
||||
})
|
||||
.catch(err => {
|
||||
if ((err.name = "PDG_ERR::DuplicateDatabase")) {
|
||||
if (err.name === "PDG_ERR::DuplicateDatabase") {
|
||||
reporter.success(
|
||||
dbActivity,
|
||||
`Database ${dbName} already exists; skipping setup`
|
||||
@@ -273,23 +393,26 @@ const setupDB = async (dbName, dbCreds = {}) => {
|
||||
}
|
||||
|
||||
const setupEnvVars = async (rootPath, dbName, dbCreds = {}) => {
|
||||
const credentials = Object.assign(defaultDBCreds, dbCreds)
|
||||
const credentials = Object.assign({}, defaultDBCreds, dbCreds)
|
||||
|
||||
let dbUrl = ""
|
||||
if (
|
||||
credentials.user !== defaultDBCreds.user ||
|
||||
credentials.password !== defaultDBCreds.password
|
||||
) {
|
||||
dbUrl = `postgres://${credentials.user}:${credentials.password}@${credentials.host}:${credentials.port}/${dbName}`
|
||||
} else {
|
||||
dbUrl = `postgres://${credentials.host}:${credentials.port}/${dbName}`
|
||||
}
|
||||
|
||||
const templatePath = sysPath.join(rootPath, ".env.template")
|
||||
const destination = sysPath.join(rootPath, ".env")
|
||||
if (existsSync(templatePath)) {
|
||||
fs.renameSync(templatePath, destination)
|
||||
fs.appendFileSync(
|
||||
destination,
|
||||
`DATABASE_URL=postgres://${credentials.user}:${credentials.password}@${credentials.host}:${credentials.port}/${dbName}\n`
|
||||
)
|
||||
} else {
|
||||
reporter.info(`No .env.template found. Creating .env.`)
|
||||
fs.appendFileSync(
|
||||
destination,
|
||||
`DATABASE_URL=postgres://${credentials.user}:${credentials.password}@${credentials.host}:${credentials.port}/${dbName}\n`
|
||||
)
|
||||
}
|
||||
fs.appendFileSync(destination, `DATABASE_URL=${dbUrl}\n`)
|
||||
}
|
||||
|
||||
const runMigrations = async rootPath => {
|
||||
@@ -354,6 +477,8 @@ const attemptSeed = async rootPath => {
|
||||
* Main function that clones or copies the starter.
|
||||
*/
|
||||
export const newStarter = async args => {
|
||||
track("CLI_NEW")
|
||||
|
||||
const {
|
||||
starter,
|
||||
root,
|
||||
@@ -361,6 +486,7 @@ export const newStarter = async args => {
|
||||
skipMigrations,
|
||||
skipEnv,
|
||||
seed,
|
||||
useDefaults,
|
||||
dbUser,
|
||||
dbDatabase,
|
||||
dbPass,
|
||||
@@ -430,21 +556,38 @@ export const newStarter = async args => {
|
||||
await copy(starterPath, rootPath)
|
||||
}
|
||||
|
||||
if (!skipDb) {
|
||||
await setupDB(root, dbCredentials)
|
||||
track("CLI_NEW_LAYOUT_COMPLETED")
|
||||
|
||||
let creds = dbCredentials
|
||||
|
||||
if (!useDefaults && !skipDb && !skipEnv) {
|
||||
creds = await interactiveDbCreds(root, dbCredentials)
|
||||
}
|
||||
|
||||
if (!skipEnv) {
|
||||
await setupEnvVars(rootPath, root, dbCredentials)
|
||||
}
|
||||
if (creds === null) {
|
||||
reporter.info("Skipping automatic database setup")
|
||||
} else {
|
||||
if (!skipDb) {
|
||||
track("CLI_NEW_SETUP_DB")
|
||||
await setupDB(root, creds)
|
||||
}
|
||||
|
||||
if (!skipMigrations) {
|
||||
await runMigrations(rootPath)
|
||||
}
|
||||
if (!skipEnv) {
|
||||
track("CLI_NEW_SETUP_ENV")
|
||||
await setupEnvVars(rootPath, root, creds)
|
||||
}
|
||||
|
||||
if (seed) {
|
||||
await attemptSeed(rootPath)
|
||||
if (!skipMigrations) {
|
||||
track("CLI_NEW_RUN_MIGRATIONS")
|
||||
await runMigrations(rootPath)
|
||||
}
|
||||
|
||||
if (seed) {
|
||||
track("CLI_NEW_SEED_DB")
|
||||
await attemptSeed(rootPath)
|
||||
}
|
||||
}
|
||||
|
||||
successMessage(rootPath)
|
||||
track("CLI_NEW_SUCCEEDED")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user