feat: CLI + local linking (#313)
* fix: allow local cmd without exiting process * fix: improves cli experience * fix: allow running link with --develop * test: adds snapshot testing of error logs * chore: cleanup * feat(medusa-cli): new command (#320) * adds: new command * fix: creates command for easy project setup * chore: deps * chore: deps * fix: loggin * fix: logging * fix: adds cli as dependency in core * fix: consolidates CLI in medusa * fix: use project deps medusa bin * fix: use project deps medusa bin * fix: use cli path * fix: new command setup db + env vars * fix: new command with db seed * fix: cleanup
This commit is contained in:
@@ -43,15 +43,26 @@
|
||||
"configstore": "5.0.1",
|
||||
"core-js": "^3.6.5",
|
||||
"dotenv": "^8.2.0",
|
||||
"execa": "^5.1.1",
|
||||
"fs-exists-cached": "^1.0.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"hosted-git-info": "^4.0.2",
|
||||
"inquirer": "^8.0.0",
|
||||
"is-valid-path": "^0.1.1",
|
||||
"joi-objectid": "^3.0.1",
|
||||
"meant": "^1.0.1",
|
||||
"medusa-core-utils": "^0.1.27",
|
||||
"netrc-parser": "^3.1.6",
|
||||
"open": "^8.0.6",
|
||||
"ora": "^5.4.1",
|
||||
"pg-god": "^1.0.11",
|
||||
"prompts": "^2.4.1",
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"resolve-cwd": "^3.0.0",
|
||||
"stack-trace": "^0.0.10",
|
||||
"ulid": "^2.3.0",
|
||||
"url": "^0.11.0",
|
||||
"winston": "^3.3.3",
|
||||
"yargs": "^15.3.1"
|
||||
},
|
||||
"gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f"
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
const axios = require("axios").default
|
||||
const inquirer = require("inquirer")
|
||||
const open = require("open")
|
||||
const execa = require("execa")
|
||||
const resolveCwd = require(`resolve-cwd`)
|
||||
const { getToken } = require("../util/token-store")
|
||||
const logger = require("../reporter").default
|
||||
|
||||
module.exports = {
|
||||
link: async argv => {
|
||||
const port = process.env.PORT || 9000
|
||||
const appHost =
|
||||
process.env.MEDUSA_APP_HOST || "https://app.medusa-commerce.com"
|
||||
|
||||
@@ -34,7 +38,7 @@ module.exports = {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Get the currenty logged in user; we will be using the Cloud user id to
|
||||
// Get the currently logged in user; we will be using the Cloud user id to
|
||||
// create a user in the local DB with the same user id; allowing you to
|
||||
// authenticate to the local API.
|
||||
const { data: auth } = await axios
|
||||
@@ -48,29 +52,86 @@ module.exports = {
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
const linkActivity = logger.activity("Linking local project")
|
||||
|
||||
// Create the user with the user id
|
||||
if (!argv.skipLocalUser && auth.user) {
|
||||
const localCmd = resolveLocalCommand(`user`)
|
||||
await localCmd({
|
||||
directory: argv.directory,
|
||||
id: auth.user.id,
|
||||
email: auth.user.email,
|
||||
})
|
||||
let proc
|
||||
try {
|
||||
proc = execa(
|
||||
`./node_modules/@medusajs/medusa/cli.js`,
|
||||
[`user`, `--id`, auth.user.id, `--email`, auth.user.email],
|
||||
{
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_ENV: "command",
|
||||
},
|
||||
}
|
||||
)
|
||||
const res = await proc
|
||||
if (res.stderr) {
|
||||
const err = new Error("stderr error")
|
||||
err.stderr = res.stderr
|
||||
throw err
|
||||
}
|
||||
} catch (error) {
|
||||
logger.failure(linkActivity, "Failed to perform local linking")
|
||||
if (error.stderr) {
|
||||
console.error(error.stderr)
|
||||
} else if (error.code === "ENOENT") {
|
||||
logger.error(
|
||||
`Couldn't find the Medusa CLI - please make sure that you have installed it globally`
|
||||
)
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// This step sets the Cloud link by opening a browser
|
||||
const bo = await open(
|
||||
`${appHost}/local-link?lurl=http://localhost:9000<oken=${auth.user.id}`,
|
||||
{
|
||||
app: "browser",
|
||||
wait: false,
|
||||
}
|
||||
logger.success(linkActivity, "Local project linked")
|
||||
|
||||
console.log()
|
||||
console.log(
|
||||
"Link Medusa Cloud to your local server. This will open the browser"
|
||||
)
|
||||
bo.on("error", err => {
|
||||
console.warn(err)
|
||||
console.log(
|
||||
`Could not open browser go to: ${appHost}/local-link?lurl=http://localhost:9000<oken=${auth.user.id}`
|
||||
console.log()
|
||||
|
||||
const prompts = [
|
||||
{
|
||||
type: "input",
|
||||
name: "open",
|
||||
message: "Press enter key to open browser for linking or n to exit",
|
||||
},
|
||||
]
|
||||
|
||||
await inquirer.prompt(prompts).then(async a => {
|
||||
if (a.open === "n") {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const params = `lurl=http://localhost:${port}<oken=${auth.user.id}`
|
||||
|
||||
// This step sets the Cloud link by opening a browser
|
||||
const browserOpen = await open(
|
||||
`${appHost}/local-link?${encodeURI(params)}`,
|
||||
{
|
||||
app: "browser",
|
||||
wait: false,
|
||||
}
|
||||
)
|
||||
|
||||
browserOpen.on("error", err => {
|
||||
console.warn(err)
|
||||
console.log(
|
||||
`Could not open browser go to: ${appHost}/local-link?lurl=http://localhost:9000<oken=${auth.user.id}`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
if (argv.develop) {
|
||||
const proc = execa(`./node_modules/@medusajs/medusa/cli.js`, [`develop`])
|
||||
proc.stdout.pipe(process.stdout)
|
||||
proc.stderr.pipe(process.stderr)
|
||||
await proc
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ const axios = require("axios").default
|
||||
const open = require("open")
|
||||
const inquirer = require("inquirer")
|
||||
|
||||
const logger = require("../reporter").default
|
||||
const { setToken } = require("../util/token-store")
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,9 @@ module.exports = {
|
||||
|
||||
const { data: urls } = await axios.post(authHost)
|
||||
|
||||
const qs = [
|
||||
const loginUri = `${loginHost}${urls.browser_url}`
|
||||
|
||||
const prompts = [
|
||||
{
|
||||
type: "input",
|
||||
name: "open",
|
||||
@@ -29,52 +32,58 @@ module.exports = {
|
||||
},
|
||||
]
|
||||
|
||||
await inquirer.prompt(qs).then(async a => {
|
||||
console.log()
|
||||
console.log("Login to Medusa Cloud")
|
||||
console.log()
|
||||
|
||||
await inquirer.prompt(prompts).then(async a => {
|
||||
if (a.open === "n") {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const bo = await open(`${loginHost}${urls.browser_url}`, {
|
||||
const browserOpen = await open(loginUri, {
|
||||
app: "browser",
|
||||
wait: false,
|
||||
})
|
||||
bo.on("error", err => {
|
||||
browserOpen.on("error", err => {
|
||||
console.warn(err)
|
||||
console.log(
|
||||
`Could not open browser go to: ${loginHost}${urls.browser_url}`
|
||||
)
|
||||
console.log(`Could not open browser go to: ${loginUri}`)
|
||||
})
|
||||
})
|
||||
|
||||
const spinner = logger.activity(`Waiting for login at ${loginUri}`)
|
||||
const fetchAuth = async (retries = 3) => {
|
||||
try {
|
||||
const { data: auth } = await axios.get(`${authHost}${urls.cli_url}`, {
|
||||
headers: { authorization: `Bearer ${urls.cli_token}` },
|
||||
})
|
||||
return auth
|
||||
} catch (err) {
|
||||
if (retries > 0 && err.http && err.http.statusCode > 500)
|
||||
return fetchAuth(retries - 1)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
const auth = await fetchAuth()
|
||||
|
||||
// This is kept alive for several seconds until the user has authenticated
|
||||
// in the browser.
|
||||
const { data: user } = await axios
|
||||
.get(`${apiHost}/auth`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${auth.password}`,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
const fetchAuth = async (retries = 3) => {
|
||||
try {
|
||||
const { data: auth } = await axios.get(`${authHost}${urls.cli_url}`, {
|
||||
headers: { authorization: `Bearer ${urls.cli_token}` },
|
||||
})
|
||||
return auth
|
||||
} catch (err) {
|
||||
if (retries > 0 && err.http && err.http.statusCode > 500)
|
||||
return fetchAuth(retries - 1)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
const auth = await fetchAuth()
|
||||
|
||||
// This is kept alive for several seconds until the user has authenticated
|
||||
// in the browser.
|
||||
const { data: user } = await axios
|
||||
.get(`${apiHost}/auth`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${auth.password}`,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
if (user) {
|
||||
setToken(auth.password)
|
||||
}
|
||||
})
|
||||
if (user) {
|
||||
logger.success(spinner, "Log in succeeded.")
|
||||
setToken(auth.password)
|
||||
} else {
|
||||
logger.failure(spinner, "Log in failed.")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
450
packages/medusa-cli/src/commands/new.js
Normal file
450
packages/medusa-cli/src/commands/new.js
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-cli/src/init-starter.ts
|
||||
*/
|
||||
|
||||
import { execSync } from "child_process"
|
||||
import execa from "execa"
|
||||
import { sync as existsSync } from "fs-exists-cached"
|
||||
import fs from "fs-extra"
|
||||
import hostedGitInfo from "hosted-git-info"
|
||||
import isValid from "is-valid-path"
|
||||
import sysPath from "path"
|
||||
import prompts from "prompts"
|
||||
import url from "url"
|
||||
import { createDatabase } from "pg-god"
|
||||
|
||||
import reporter from "../reporter"
|
||||
import { getPackageManager, setPackageManager } from "../util/package-manager"
|
||||
|
||||
const spawnWithArgs = (file, args, options) =>
|
||||
execa(file, args, { stdio: `inherit`, preferLocal: false, ...options })
|
||||
|
||||
const spawn = (cmd, options) => {
|
||||
const [file, ...args] = cmd.split(/\s+/)
|
||||
return spawnWithArgs(file, args, options)
|
||||
}
|
||||
// Checks the existence of yarn package
|
||||
// We use yarnpkg instead of yarn to avoid conflict with Hadoop yarn
|
||||
// Refer to https://github.com/yarnpkg/yarn/issues/673
|
||||
const checkForYarn = () => {
|
||||
try {
|
||||
execSync(`yarnpkg --version`, { stdio: `ignore` })
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const isAlreadyGitRepository = async () => {
|
||||
try {
|
||||
return await spawn(`git rev-parse --is-inside-work-tree`, {
|
||||
stdio: `pipe`,
|
||||
}).then(output => output.stdout === `true`)
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize newly cloned directory as a git repo
|
||||
const gitInit = async rootPath => {
|
||||
reporter.info(`Initialising git in ${rootPath}`)
|
||||
|
||||
return await spawn(`git init`, { cwd: rootPath })
|
||||
}
|
||||
|
||||
// Create a .gitignore file if it is missing in the new directory
|
||||
const maybeCreateGitIgnore = async rootPath => {
|
||||
if (existsSync(sysPath.join(rootPath, `.gitignore`))) {
|
||||
return
|
||||
}
|
||||
|
||||
const gignore = reporter.activity(
|
||||
`Creating minimal .gitignore in ${rootPath}`
|
||||
)
|
||||
await fs.writeFile(
|
||||
sysPath.join(rootPath, `.gitignore`),
|
||||
`.cache\nnode_modules\npublic\n`
|
||||
)
|
||||
reporter.success(gignore, `Created .gitignore in ${rootPath}`)
|
||||
}
|
||||
|
||||
// Create an initial git commit in the new directory
|
||||
const createInitialGitCommit = async (rootPath, starterUrl) => {
|
||||
reporter.info(`Create initial git commit in ${rootPath}`)
|
||||
|
||||
await spawn(`git add -A`, { cwd: rootPath })
|
||||
// use execSync instead of spawn to handle git clients using
|
||||
// pgp signatures (with password)
|
||||
try {
|
||||
execSync(`git commit -m "Initial commit from gatsby: (${starterUrl})"`, {
|
||||
cwd: rootPath,
|
||||
})
|
||||
} catch {
|
||||
// Remove git support if initial commit fails
|
||||
reporter.warn(`Initial git commit failed - removing git support\n`)
|
||||
fs.removeSync(sysPath.join(rootPath, `.git`))
|
||||
}
|
||||
}
|
||||
|
||||
// Executes `npm install` or `yarn install` in rootPath.
|
||||
const install = async rootPath => {
|
||||
const prevDir = process.cwd()
|
||||
|
||||
reporter.info(`Installing packages...`)
|
||||
process.chdir(rootPath)
|
||||
|
||||
const npmConfigUserAgent = process.env.npm_config_user_agent
|
||||
|
||||
try {
|
||||
if (!getPackageManager()) {
|
||||
if (npmConfigUserAgent?.includes(`yarn`)) {
|
||||
setPackageManager(`yarn`)
|
||||
} else {
|
||||
setPackageManager(`npm`)
|
||||
}
|
||||
}
|
||||
if (getPackageManager() === `yarn` && checkForYarn()) {
|
||||
await fs.remove(`package-lock.json`)
|
||||
await spawn(`yarnpkg`)
|
||||
} else {
|
||||
await fs.remove(`yarn.lock`)
|
||||
await spawn(`npm install`)
|
||||
}
|
||||
} finally {
|
||||
process.chdir(prevDir)
|
||||
}
|
||||
}
|
||||
|
||||
const ignored = path => !/^\.(git|hg)$/.test(sysPath.basename(path))
|
||||
|
||||
// Copy starter from file system.
|
||||
const copy = async (starterPath, rootPath) => {
|
||||
// Chmod with 755.
|
||||
// 493 = parseInt('755', 8)
|
||||
await fs.ensureDir(rootPath, { mode: 493 })
|
||||
|
||||
if (!existsSync(starterPath)) {
|
||||
throw new Error(`starter ${starterPath} doesn't exist`)
|
||||
}
|
||||
|
||||
if (starterPath === `.`) {
|
||||
throw new Error(
|
||||
`You can't create a starter from the existing directory. If you want to
|
||||
create a new project in the current directory, the trailing dot isn't
|
||||
necessary. If you want to create a project from a local starter, run
|
||||
something like "medusa new my-medusa-store ../local-medusa-starter"`
|
||||
)
|
||||
}
|
||||
|
||||
reporter.info(`Creating new site from local starter: ${starterPath}`)
|
||||
|
||||
const copyActivity = reporter.activity(
|
||||
`Copying local starter to ${rootPath} ...`
|
||||
)
|
||||
|
||||
await fs.copy(starterPath, rootPath, { filter: ignored })
|
||||
|
||||
reporter.success(copyActivity, `Created starter directory layout`)
|
||||
|
||||
await install(rootPath)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Clones starter from URI.
|
||||
const clone = async (hostInfo, rootPath) => {
|
||||
let url
|
||||
// Let people use private repos accessed over SSH.
|
||||
if (hostInfo.getDefaultRepresentation() === `sshurl`) {
|
||||
url = hostInfo.ssh({ noCommittish: true })
|
||||
// Otherwise default to normal git syntax.
|
||||
} else {
|
||||
url = hostInfo.https({ noCommittish: true, noGitPlus: true })
|
||||
}
|
||||
|
||||
const branch = hostInfo.committish ? [`-b`, hostInfo.committish] : []
|
||||
|
||||
const createAct = reporter.activity(`Creating new project from git: ${url}`)
|
||||
|
||||
const args = [
|
||||
`clone`,
|
||||
...branch,
|
||||
url,
|
||||
rootPath,
|
||||
`--recursive`,
|
||||
`--depth=1`,
|
||||
].filter(arg => Boolean(arg))
|
||||
|
||||
await execa(`git`, args, {})
|
||||
.then(() => {
|
||||
reporter.success(createAct, `Created starter directory layout`)
|
||||
})
|
||||
.catch(err => {
|
||||
reporter.failure(createAct, `Failed to clone repository`)
|
||||
throw err
|
||||
})
|
||||
|
||||
await fs.remove(sysPath.join(rootPath, `.git`))
|
||||
|
||||
await install(rootPath)
|
||||
const isGit = await isAlreadyGitRepository()
|
||||
if (!isGit) await gitInit(rootPath)
|
||||
await maybeCreateGitIgnore(rootPath)
|
||||
if (!isGit) await createInitialGitCommit(rootPath, url)
|
||||
}
|
||||
|
||||
const getPaths = async (starterPath, rootPath) => {
|
||||
let selectedOtherStarter = false
|
||||
|
||||
// if no args are passed, prompt user for path and starter
|
||||
if (!starterPath && !rootPath) {
|
||||
const response = await prompts.prompt([
|
||||
{
|
||||
type: `text`,
|
||||
name: `path`,
|
||||
message: `What is your project called?`,
|
||||
initial: `my-medusa-store`,
|
||||
},
|
||||
])
|
||||
// exit gracefully if responses aren't provided
|
||||
if (!response.starter || !response.path.trim()) {
|
||||
throw new Error(
|
||||
`Please mention both starter package and project name along with path(if its not in the root)`
|
||||
)
|
||||
}
|
||||
|
||||
selectedOtherStarter = response.starter === `different`
|
||||
starterPath = `medusajs/medusa-starter-default`
|
||||
rootPath = response.path
|
||||
}
|
||||
|
||||
// set defaults if no root or starter has been set yet
|
||||
rootPath = rootPath || process.cwd()
|
||||
starterPath = starterPath || `medusajs/medusa-starter-default`
|
||||
|
||||
return { starterPath, rootPath, selectedOtherStarter }
|
||||
}
|
||||
|
||||
const successMessage = path => {
|
||||
reporter.info(`
|
||||
Your new Medusa project is ready for you! To start developing run:
|
||||
|
||||
cd ${path}
|
||||
medusa develop
|
||||
`)
|
||||
}
|
||||
|
||||
const defaultDBCreds = {
|
||||
user: "postgres",
|
||||
database: "postgres",
|
||||
password: "",
|
||||
port: 5432,
|
||||
host: "localhost",
|
||||
}
|
||||
|
||||
const setupDB = async (dbName, dbCreds = {}) => {
|
||||
const credentials = Object.assign(defaultDBCreds, dbCreds)
|
||||
|
||||
const dbActivity = reporter.activity(`Setting up database "${dbName}"...`)
|
||||
await createDatabase(
|
||||
{
|
||||
databaseName: dbName,
|
||||
errorIfExist: true,
|
||||
},
|
||||
credentials
|
||||
)
|
||||
.then(() => {
|
||||
reporter.success(dbActivity, `Created database "${dbName}"`)
|
||||
})
|
||||
.catch(err => {
|
||||
if ((err.name = "PDG_ERR::DuplicateDatabase")) {
|
||||
reporter.success(
|
||||
dbActivity,
|
||||
`Database ${dbName} already exists; skipping setup`
|
||||
)
|
||||
} else {
|
||||
reporter.failure(dbActivity, `Skipping database setup.`)
|
||||
reporter.warn(
|
||||
`Failed to setup database; install PostgresQL or make sure to manage your database connection manually`
|
||||
)
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const setupEnvVars = async (rootPath, dbName, dbCreds = {}) => {
|
||||
const credentials = Object.assign(defaultDBCreds, dbCreds)
|
||||
|
||||
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`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const runMigrations = async rootPath => {
|
||||
const migrationActivity = reporter.activity("Applying database migrations...")
|
||||
|
||||
const cliPath = sysPath.join(
|
||||
`node_modules`,
|
||||
`@medusajs`,
|
||||
`medusa-cli`,
|
||||
`cli.js`
|
||||
)
|
||||
|
||||
return await execa(cliPath, [`migrations`, `run`], {
|
||||
cwd: rootPath,
|
||||
})
|
||||
.then(() => {
|
||||
reporter.success(migrationActivity, "Database migrations completed.")
|
||||
})
|
||||
.catch(err => {
|
||||
reporter.failure(
|
||||
migrationActivity,
|
||||
"Failed to migrate database you must complete migration manually before starting your server."
|
||||
)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
const attemptSeed = async rootPath => {
|
||||
const seedActivity = reporter.activity("Seeding database")
|
||||
|
||||
const pkgPath = sysPath.resolve(rootPath, "package.json")
|
||||
if (existsSync(pkgPath)) {
|
||||
const pkg = require(pkgPath)
|
||||
if (pkg.scripts && pkg.scripts.seed) {
|
||||
const proc = execa(getPackageManager(), [`run`, `seed`], {
|
||||
cwd: rootPath,
|
||||
})
|
||||
|
||||
// Useful for development
|
||||
// proc.stdout.pipe(process.stdout)
|
||||
|
||||
await proc
|
||||
.then(() => {
|
||||
reporter.success(seedActivity, "Seed completed")
|
||||
})
|
||||
.catch(err => {
|
||||
reporter.failure(seedActivity, "Failed to complete seed; skipping")
|
||||
console.error(err)
|
||||
})
|
||||
} else {
|
||||
reporter.failure(
|
||||
seedActivity,
|
||||
"Starter doesn't provide a seed command; skipping."
|
||||
)
|
||||
}
|
||||
} else {
|
||||
reporter.failure(seedActivity, "Could not find package.json")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function that clones or copies the starter.
|
||||
*/
|
||||
export const newStarter = async args => {
|
||||
const {
|
||||
starter,
|
||||
root,
|
||||
skipDb,
|
||||
skipMigrations,
|
||||
skipEnv,
|
||||
seed,
|
||||
dbUser,
|
||||
dbDatabase,
|
||||
dbPass,
|
||||
dbPort,
|
||||
dbHost,
|
||||
} = args
|
||||
|
||||
const dbCredentials = {
|
||||
user: dbUser,
|
||||
database: dbDatabase,
|
||||
password: dbPass,
|
||||
port: dbPort,
|
||||
host: dbHost,
|
||||
}
|
||||
|
||||
const { starterPath, rootPath } = await getPaths(starter, root)
|
||||
|
||||
const urlObject = url.parse(rootPath)
|
||||
|
||||
if (urlObject.protocol && urlObject.host) {
|
||||
const isStarterAUrl =
|
||||
starter && !url.parse(starter).hostname && !url.parse(starter).protocol
|
||||
|
||||
if (/medusa-starter/gi.test(rootPath) && isStarterAUrl) {
|
||||
reporter.panic({
|
||||
id: `11610`,
|
||||
context: {
|
||||
starter,
|
||||
rootPath,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
reporter.panic({
|
||||
id: `11611`,
|
||||
context: {
|
||||
rootPath,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!isValid(rootPath)) {
|
||||
reporter.panic({
|
||||
id: `11612`,
|
||||
context: {
|
||||
path: sysPath.resolve(rootPath),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (existsSync(sysPath.join(rootPath, `package.json`))) {
|
||||
reporter.panic({
|
||||
id: `11613`,
|
||||
context: {
|
||||
rootPath,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const hostedInfo = hostedGitInfo.fromUrl(starterPath)
|
||||
if (hostedInfo) {
|
||||
await clone(hostedInfo, rootPath)
|
||||
} else {
|
||||
await copy(starterPath, rootPath)
|
||||
}
|
||||
|
||||
if (!skipDb) {
|
||||
await setupDB(root, dbCredentials)
|
||||
}
|
||||
|
||||
if (!skipEnv) {
|
||||
await setupEnvVars(rootPath, root, dbCredentials)
|
||||
}
|
||||
|
||||
if (!skipMigrations) {
|
||||
await runMigrations(rootPath)
|
||||
}
|
||||
|
||||
if (seed) {
|
||||
await attemptSeed(rootPath)
|
||||
}
|
||||
|
||||
successMessage(rootPath)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
const axios = require("axios").default
|
||||
const { getToken } = require("../util/token-store")
|
||||
const logger = require("../reporter").default
|
||||
|
||||
/**
|
||||
* Fetches the locally logged in user.
|
||||
@@ -18,6 +19,8 @@ module.exports = {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const activity = logger.activity("checking login details")
|
||||
|
||||
const { data: auth } = await axios
|
||||
.get(`${apiHost}/auth`, {
|
||||
headers: {
|
||||
@@ -25,12 +28,17 @@ module.exports = {
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
logger.failure(activity, "Couldn't gather login details")
|
||||
logger.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
if (auth.user) {
|
||||
console.log(`Hi, ${auth.user.first_name}! Here are your details:`)
|
||||
logger.success(
|
||||
activity,
|
||||
`Hi, ${auth.user.first_name}! Here are your details:`
|
||||
)
|
||||
|
||||
console.log(`id: ${auth.user.id}`)
|
||||
console.log(`email: ${auth.user.email}`)
|
||||
console.log(`first_name: ${auth.user.first_name}`)
|
||||
|
||||
@@ -6,6 +6,7 @@ const existsSync = require(`fs-exists-cached`).sync
|
||||
const { getLocalMedusaVersion } = require(`./util/version`)
|
||||
const { didYouMean } = require(`./did-you-mean`)
|
||||
|
||||
const { newStarter } = require("./commands/new")
|
||||
const { whoami } = require("./commands/whoami")
|
||||
const { login } = require("./commands/login")
|
||||
const { link } = require("./commands/link")
|
||||
@@ -66,6 +67,57 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
}
|
||||
|
||||
cli
|
||||
.command({
|
||||
command: `new [root] [starter]`,
|
||||
builder: _ =>
|
||||
_.option(`seed`, {
|
||||
type: `boolean`,
|
||||
describe: `If flag is set the command will attempt to seed the database after setup.`,
|
||||
default: false,
|
||||
})
|
||||
.option(`skip-db`, {
|
||||
type: `boolean`,
|
||||
describe: `If flag is set the command will not attempt to complete database setup`,
|
||||
default: false,
|
||||
})
|
||||
.option(`skip-migrations`, {
|
||||
type: `boolean`,
|
||||
describe: `If flag is set the command will not attempt to complete database migration`,
|
||||
default: false,
|
||||
})
|
||||
.option(`skip-env`, {
|
||||
type: `boolean`,
|
||||
describe: `If flag is set the command will not attempt to populate .env`,
|
||||
default: false,
|
||||
})
|
||||
.option(`db-user`, {
|
||||
type: `string`,
|
||||
describe: `The database user to use for database setup and migrations.`,
|
||||
default: `postgres`,
|
||||
})
|
||||
.option(`db-database`, {
|
||||
type: `string`,
|
||||
describe: `The database use for database setup and migrations.`,
|
||||
default: `postgres`,
|
||||
})
|
||||
.option(`db-pass`, {
|
||||
type: `string`,
|
||||
describe: `The database password to use for database setup and migrations.`,
|
||||
default: ``,
|
||||
})
|
||||
.option(`db-port`, {
|
||||
type: `number`,
|
||||
describe: `The database port to use for database setup and migrations.`,
|
||||
default: 5432,
|
||||
})
|
||||
.option(`db-host`, {
|
||||
type: `string`,
|
||||
describe: `The database host to use for database setup and migrations.`,
|
||||
default: `localhost`,
|
||||
}),
|
||||
desc: `Create a new Medusa project.`,
|
||||
handler: handlerP(newStarter),
|
||||
})
|
||||
.command({
|
||||
command: `seed`,
|
||||
desc: `Migrates and populates the database with the provided file.`,
|
||||
@@ -112,11 +164,15 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
command: `link`,
|
||||
desc: `Creates your Medusa Cloud user in your local database for local testing.`,
|
||||
builder: _ =>
|
||||
_.option(`skip-local-user`, {
|
||||
alias: `skipLocalUser`,
|
||||
_.option(`su`, {
|
||||
alias: `skip-local-user`,
|
||||
type: `boolean`,
|
||||
default: false,
|
||||
describe: `If set a user will not be created in the database.`,
|
||||
}).option(`develop`, {
|
||||
type: `boolean`,
|
||||
default: false,
|
||||
describe: `If set medusa develop will be run after successful linking.`,
|
||||
}),
|
||||
handler: handlerP(argv => {
|
||||
if (!isLocalProject) {
|
||||
@@ -198,11 +254,17 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
alias: `email`,
|
||||
type: `string`,
|
||||
describe: `User's email.`,
|
||||
}).option(`p`, {
|
||||
alias: `password`,
|
||||
type: `string`,
|
||||
describe: `User's password.`,
|
||||
}),
|
||||
})
|
||||
.option(`p`, {
|
||||
alias: `password`,
|
||||
type: `string`,
|
||||
describe: `User's password.`,
|
||||
})
|
||||
.option(`i`, {
|
||||
alias: `id`,
|
||||
type: `string`,
|
||||
describe: `User's id.`,
|
||||
}),
|
||||
handler: handlerP(
|
||||
getCommandHandler(`user`, (args, cmd) => {
|
||||
cmd(args)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Reporter handles "Error" signature correctly 1`] = `
|
||||
Object {
|
||||
"level": "error",
|
||||
"message": "Error",
|
||||
"stack": Any<Array>,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Reporter handles "String" signature correctly 1`] = `
|
||||
Object {
|
||||
"level": "error",
|
||||
"message": "Test log",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Reporter handles "String, Error" signature correctly 1`] = `
|
||||
Object {
|
||||
"level": "error",
|
||||
"message": "Test log",
|
||||
"stack": Any<Array>,
|
||||
}
|
||||
`;
|
||||
49
packages/medusa-cli/src/reporter/__tests__/index.js
Normal file
49
packages/medusa-cli/src/reporter/__tests__/index.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import logger, { Reporter } from "../"
|
||||
|
||||
describe(`Reporter`, () => {
|
||||
const winstonMock = {
|
||||
log: jest.fn(),
|
||||
}
|
||||
|
||||
const reporter = new Reporter({
|
||||
logger: winstonMock,
|
||||
activityLogger: {},
|
||||
})
|
||||
|
||||
const getErrorMessages = fn =>
|
||||
fn.mock.calls
|
||||
.map(([firstArg]) => firstArg)
|
||||
.filter(structuredMessage => structuredMessage.level === `error`)
|
||||
|
||||
beforeEach(() => {
|
||||
winstonMock.log.mockClear()
|
||||
})
|
||||
|
||||
it(`handles "String" signature correctly`, () => {
|
||||
reporter.error("Test log")
|
||||
|
||||
const generated = getErrorMessages(winstonMock.log)[0]
|
||||
|
||||
expect(generated).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it(`handles "String, Error" signature correctly`, () => {
|
||||
reporter.error("Test log", new Error("String Error"))
|
||||
|
||||
const generated = getErrorMessages(winstonMock.log)[0]
|
||||
|
||||
expect(generated).toMatchSnapshot({
|
||||
stack: expect.any(Array),
|
||||
})
|
||||
})
|
||||
|
||||
it(`handles "Error" signature correctly`, () => {
|
||||
reporter.error(new Error("Error"))
|
||||
|
||||
const generated = getErrorMessages(winstonMock.log)[0]
|
||||
|
||||
expect(generated).toMatchSnapshot({
|
||||
stack: expect.any(Array),
|
||||
})
|
||||
})
|
||||
})
|
||||
254
packages/medusa-cli/src/reporter/index.js
Normal file
254
packages/medusa-cli/src/reporter/index.js
Normal file
@@ -0,0 +1,254 @@
|
||||
import stackTrace from "stack-trace"
|
||||
import { ulid } from "ulid"
|
||||
import winston from "winston"
|
||||
import ora from "ora"
|
||||
|
||||
const LOG_LEVEL = process.env.LOG_LEVEL || "silly"
|
||||
const NODE_ENV = process.env.NODE_ENV || "development"
|
||||
|
||||
const transports = []
|
||||
if (process.env.NODE_ENV && process.env.NODE_ENV !== "development") {
|
||||
transports.push(new winston.transports.Console())
|
||||
} else {
|
||||
transports.push(
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.cli(),
|
||||
winston.format.splat()
|
||||
),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const loggerInstance = winston.createLogger({
|
||||
level: LOG_LEVEL,
|
||||
levels: winston.config.npm.levels,
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
}),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.splat(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports,
|
||||
})
|
||||
|
||||
export class Reporter {
|
||||
constructor({ logger, activityLogger }) {
|
||||
this.activities_ = []
|
||||
this.loggerInstance_ = logger
|
||||
this.ora_ = activityLogger
|
||||
}
|
||||
|
||||
panic = error => {
|
||||
this.loggerInstance_.log({
|
||||
level: "error",
|
||||
details: error,
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the logger should log at a given level.
|
||||
* @param {string} level - the level to check if logger is configured for
|
||||
* @return {boolean} whether we should log
|
||||
*/
|
||||
shouldLog = level => {
|
||||
level = this.loggerInstance_.levels[level]
|
||||
const logLevel = this.loggerInstance_.levels[this.loggerInstance_.level]
|
||||
return level <= logLevel
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the log level of the logger.
|
||||
* @param {string} level - the level to set the logger to
|
||||
*/
|
||||
setLogLevel = level => {
|
||||
this.loggerInstance_.level = level
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the logger to the value specified by the LOG_LEVEL env var. If no
|
||||
* LOG_LEVEL is set it defaults to "silly".
|
||||
*/
|
||||
unsetLogLevel = () => {
|
||||
this.loggerInstance_.level = LOG_LEVEL
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin an activity. In development an activity is displayed as a spinner;
|
||||
* in other environments it will log the activity at the info level.
|
||||
* @param {string} message - the message to log the activity under
|
||||
* @returns {string} the id of the activity; this should be passed to do
|
||||
* further operations on the activity such as success, failure, progress.
|
||||
*/
|
||||
activity = message => {
|
||||
const id = ulid()
|
||||
if (NODE_ENV === "development" && this.shouldLog("info")) {
|
||||
const activity = this.ora_(message).start()
|
||||
|
||||
this.activities_[id] = {
|
||||
activity,
|
||||
start: Date.now(),
|
||||
}
|
||||
|
||||
return id
|
||||
} else {
|
||||
this.activities_[id] = {
|
||||
start: Date.now(),
|
||||
}
|
||||
this.loggerInstance_.log({
|
||||
activity_id: id,
|
||||
level: "info",
|
||||
message,
|
||||
})
|
||||
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports progress on an activity. In development this will update the
|
||||
* activity log message, in other environments a log message will be issued
|
||||
* at the info level. Logging will include the activityId.
|
||||
* @param {string} activityId - the id of the activity as returned by activity
|
||||
* @param {string} message - the message to log
|
||||
*/
|
||||
progress = (activityId, message) => {
|
||||
const toLog = {
|
||||
level: "info",
|
||||
message,
|
||||
}
|
||||
|
||||
if (typeof activityId === "string" && this.activities_[activityId]) {
|
||||
const activity = this.activities_[activityId]
|
||||
if (activity.activity) {
|
||||
activity.text = message
|
||||
} else {
|
||||
toLog.activity_id = activityId
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
} else {
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error. If an error object is provided the stack trace for the error
|
||||
* will also be logged.
|
||||
* @param {String | Error} messageOrError - can either be a string with a
|
||||
* message to log the error under; or an error object.
|
||||
* @param {Error?} error - an error object to log message with
|
||||
*/
|
||||
error = (messageOrError, error) => {
|
||||
let message = messageOrError
|
||||
if (typeof messageOrError === "object") {
|
||||
message = messageOrError.message
|
||||
error = messageOrError
|
||||
}
|
||||
|
||||
const toLog = {
|
||||
level: "error",
|
||||
message,
|
||||
}
|
||||
|
||||
if (error) {
|
||||
toLog.stack = stackTrace.parse(error)
|
||||
}
|
||||
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports failure of an activity. In development the activity will be udpated
|
||||
* with the failure message in other environments the failure will be logged
|
||||
* at the error level.
|
||||
* @param {string} activityId - the id of the activity as returned by activity
|
||||
* @param {string} message - the message to log
|
||||
*/
|
||||
failure = (activityId, message) => {
|
||||
const toLog = {
|
||||
level: "error",
|
||||
message,
|
||||
}
|
||||
|
||||
if (typeof activityId === "string" && this.activities_[activityId]) {
|
||||
const time = Date.now()
|
||||
const activity = this.activities_[activityId]
|
||||
if (activity.activity) {
|
||||
activity.activity.fail(`${message} – ${time - activity.start}`)
|
||||
} else {
|
||||
toLog.duration = time - activity.start
|
||||
toLog.activity_id = activityId
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
} else {
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports success of an activity. In development the activity will be udpated
|
||||
* with the failure message in other environments the failure will be logged
|
||||
* at the info level.
|
||||
* @param {string} activityId - the id of the activity as returned by activity
|
||||
* @param {string} message - the message to log
|
||||
*/
|
||||
success = (activityId, message) => {
|
||||
const toLog = {
|
||||
level: "info",
|
||||
message,
|
||||
}
|
||||
|
||||
if (typeof activityId === "string" && this.activities_[activityId]) {
|
||||
const time = Date.now()
|
||||
const activity = this.activities_[activityId]
|
||||
if (activity.activity) {
|
||||
activity.activity.succeed(`${message} – ${time - activity.start}ms`)
|
||||
} else {
|
||||
toLog.duration = time - activity.start
|
||||
toLog.activity_id = activityId
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
} else {
|
||||
this.loggerInstance_.log(toLog)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message at the info level.
|
||||
* @param {string} message - the message to log
|
||||
*/
|
||||
info = message => {
|
||||
this.loggerInstance_.log({
|
||||
level: "info",
|
||||
message,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message at the warn level.
|
||||
* @param {string} message - the message to log
|
||||
*/
|
||||
warn = message => {
|
||||
this.loggerInstance_.warn({
|
||||
level: "warn",
|
||||
message,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around winston's log method.
|
||||
*/
|
||||
log = (...args) => {
|
||||
this.loggerInstance_.log(...args)
|
||||
}
|
||||
}
|
||||
|
||||
const logger = new Reporter({
|
||||
logger: loggerInstance,
|
||||
activityLogger: ora,
|
||||
})
|
||||
|
||||
export default logger
|
||||
22
packages/medusa-cli/src/util/package-manager.js
Normal file
22
packages/medusa-cli/src/util/package-manager.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import ConfigStore from "configstore"
|
||||
import reporter from "../reporter"
|
||||
|
||||
let config
|
||||
|
||||
const packageMangerConfigKey = `cli.packageManager`
|
||||
|
||||
export const getPackageManager = () => {
|
||||
if (!config) {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
|
||||
return config.get(packageMangerConfigKey)
|
||||
}
|
||||
|
||||
export const setPackageManager = packageManager => {
|
||||
if (!config) {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
config.set(packageMangerConfigKey, packageManager)
|
||||
reporter.info(`Preferred package manager set to "${packageManager}"`)
|
||||
}
|
||||
@@ -8,13 +8,13 @@ module.exports = {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
|
||||
return config.get("login_token")
|
||||
return config.get("cloud.login_token")
|
||||
},
|
||||
setToken: function(token) {
|
||||
if (!config) {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
|
||||
return config.set("login_token", token)
|
||||
return config.set("cloud.login_token", token)
|
||||
},
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3
packages/medusa/cli.js
Normal file
3
packages/medusa/cli.js
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require(`./dist/bin/medusa.js`)
|
||||
@@ -3,6 +3,9 @@
|
||||
"version": "1.1.32",
|
||||
"description": "E-commerce for JAMstack",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
"medusa": "./cli.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
@@ -41,6 +44,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/joi": "^16.1.8",
|
||||
"@medusajs/medusa-cli": "^1.1.13",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"awilix": "^4.2.3",
|
||||
"body-parser": "^1.19.0",
|
||||
|
||||
3
packages/medusa/src/bin/medusa.js
Normal file
3
packages/medusa/src/bin/medusa.js
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require(`@medusajs/medusa-cli`)
|
||||
@@ -14,7 +14,8 @@ export default async function({ port, directory }) {
|
||||
stdio: ["ignore", process.stdout, process.stderr],
|
||||
})
|
||||
|
||||
let child = spawn("medusa", [`start`, ...args], {
|
||||
const cliPath = "./node_modules/@medusajs/medusa/cli.js"
|
||||
let child = spawn(cliPath, [`start`, ...args], {
|
||||
cwd: directory,
|
||||
env: process.env,
|
||||
stdio: ["pipe", process.stdout, process.stderr],
|
||||
@@ -32,7 +33,7 @@ export default async function({ port, directory }) {
|
||||
|
||||
Logger.info("Rebuilt")
|
||||
|
||||
child = spawn("medusa", [`start`, ...args], {
|
||||
child = spawn(cliPath, [`start`, ...args], {
|
||||
cwd: directory,
|
||||
env: process.env,
|
||||
stdio: ["pipe", process.stdout, process.stderr],
|
||||
|
||||
@@ -11,11 +11,12 @@ export default async function({ port, directory }) {
|
||||
const app = express()
|
||||
|
||||
const { dbConnection } = await loaders({ directory, expressApp: app })
|
||||
const serverActivity = Logger.activity(`Creating server`)
|
||||
const server = app.listen(port, err => {
|
||||
if (err) {
|
||||
return
|
||||
}
|
||||
Logger.info(`Server is ready on port: ${port}!`)
|
||||
Logger.success(serverActivity, `Server is ready on port: ${port}`)
|
||||
})
|
||||
|
||||
return { dbConnection, server }
|
||||
|
||||
@@ -5,15 +5,22 @@ import express from "express"
|
||||
|
||||
import loaders from "../loaders"
|
||||
|
||||
export default async function({ directory, id, email, password }) {
|
||||
export default async function({ directory, id, email, password, keepAlive }) {
|
||||
const app = express()
|
||||
const { container } = await loaders({
|
||||
directory,
|
||||
expressApp: app,
|
||||
})
|
||||
try {
|
||||
const { container } = await loaders({
|
||||
directory,
|
||||
expressApp: app,
|
||||
})
|
||||
|
||||
const userService = container.resolve("userService")
|
||||
await userService.create({ id, email }, password)
|
||||
const userService = container.resolve("userService")
|
||||
await userService.create({ id, email }, password)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
process.exit()
|
||||
if (!keepAlive) {
|
||||
process.exit()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,33 +61,54 @@ export default async ({ directory: rootDirectory, expressApp }) => {
|
||||
logger: asValue(Logger),
|
||||
})
|
||||
|
||||
await modelsLoader({ container })
|
||||
Logger.info("Models initialized")
|
||||
const modelsActivity = Logger.activity("Initializing models")
|
||||
await modelsLoader({ container, activityId: modelsActivity })
|
||||
Logger.success(modelsActivity, "Models initialized")
|
||||
|
||||
await registerPluginModels({ rootDirectory, container })
|
||||
Logger.info("Models initialized")
|
||||
const pmActivity = Logger.activity("Initializing plugin models")
|
||||
await registerPluginModels({
|
||||
rootDirectory,
|
||||
container,
|
||||
activityId: pmActivity,
|
||||
})
|
||||
Logger.success(pmActivity, "Plugin models initialized")
|
||||
|
||||
await repositoriesLoader({ container })
|
||||
Logger.info("Repositories initialized")
|
||||
const repoActivity = Logger.activity("Initializing repositories")
|
||||
await repositoriesLoader({ container, activityId: repoActivity })
|
||||
Logger.success(repoActivity, "Repositories initialized")
|
||||
|
||||
const dbConnection = await databaseLoader({ container, configModule })
|
||||
Logger.info("Database initialized")
|
||||
const dbActivity = Logger.activity("Initializing database")
|
||||
const dbConnection = await databaseLoader({
|
||||
container,
|
||||
configModule,
|
||||
activityId: dbActivity,
|
||||
})
|
||||
Logger.success(dbActivity, "Database initialized")
|
||||
|
||||
container.register({
|
||||
manager: asValue(dbConnection.manager),
|
||||
})
|
||||
|
||||
await servicesLoader({ container, configModule })
|
||||
Logger.info("Services initialized")
|
||||
const servicesActivity = Logger.activity("Initializing services")
|
||||
await servicesLoader({
|
||||
container,
|
||||
configModule,
|
||||
activityId: servicesActivity,
|
||||
})
|
||||
Logger.success(servicesActivity, "Services initialized")
|
||||
|
||||
await subscribersLoader({ container })
|
||||
Logger.info("Subscribers initialized")
|
||||
const subActivity = Logger.activity("Initializing subscribers")
|
||||
await subscribersLoader({ container, activityId: subActivity })
|
||||
Logger.success(subActivity, "Subscribers initialized")
|
||||
|
||||
await expressLoader({ app: expressApp, configModule })
|
||||
Logger.info("Express Intialized")
|
||||
|
||||
await passportLoader({ app: expressApp, container })
|
||||
Logger.info("Passport initialized")
|
||||
const expActivity = Logger.activity("Initializing express")
|
||||
await expressLoader({
|
||||
app: expressApp,
|
||||
configModule,
|
||||
activityId: expActivity,
|
||||
})
|
||||
await passportLoader({ app: expressApp, container, activityId: expActivity })
|
||||
Logger.success(expActivity, "Express intialized")
|
||||
|
||||
// Add the registered services to the request scope
|
||||
expressApp.use((req, res, next) => {
|
||||
@@ -98,14 +119,27 @@ export default async ({ directory: rootDirectory, expressApp }) => {
|
||||
next()
|
||||
})
|
||||
|
||||
await pluginsLoader({ container, rootDirectory, app: expressApp })
|
||||
Logger.info("Plugins Intialized")
|
||||
const pluginsActivity = Logger.activity("Initializing plugins")
|
||||
await pluginsLoader({
|
||||
container,
|
||||
rootDirectory,
|
||||
app: expressApp,
|
||||
activityId: pluginsActivity,
|
||||
})
|
||||
Logger.success(pluginsActivity, "Plugins intialized")
|
||||
|
||||
await apiLoader({ container, rootDirectory, app: expressApp })
|
||||
Logger.info("API initialized")
|
||||
const apiActivity = Logger.activity("Initializing API")
|
||||
await apiLoader({
|
||||
container,
|
||||
rootDirectory,
|
||||
app: expressApp,
|
||||
activityId: apiActivity,
|
||||
})
|
||||
Logger.success(apiActivity, "API initialized")
|
||||
|
||||
await defaultsLoader({ container })
|
||||
Logger.info("Defaults initialized")
|
||||
const defaultsActivity = Logger.activity("Initializing defaults")
|
||||
await defaultsLoader({ container, activityId: defaultsActivity })
|
||||
Logger.success(defaultsActivity, "Defaults initialized")
|
||||
|
||||
return { container, dbConnection, app: expressApp }
|
||||
}
|
||||
|
||||
@@ -1,32 +1,2 @@
|
||||
import winston from "winston"
|
||||
import config from "../config"
|
||||
|
||||
const transports = []
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
transports.push(new winston.transports.Console())
|
||||
} else {
|
||||
transports.push(
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.cli(),
|
||||
winston.format.splat()
|
||||
),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const LoggerInstance = winston.createLogger({
|
||||
level: config.logs.level,
|
||||
levels: winston.config.npm.levels,
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
}),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.splat(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports,
|
||||
})
|
||||
|
||||
export default LoggerInstance
|
||||
import logger from "@medusajs/medusa-cli/dist/reporter"
|
||||
export default logger
|
||||
|
||||
@@ -21,7 +21,7 @@ import formatRegistrationName from "../utils/format-registration-name"
|
||||
/**
|
||||
* Registers all services in the services directory
|
||||
*/
|
||||
export default async ({ rootDirectory, container, app }) => {
|
||||
export default async ({ rootDirectory, container, app, activityId }) => {
|
||||
const resolved = getResolvedPlugins(rootDirectory)
|
||||
|
||||
await Promise.all(
|
||||
@@ -29,7 +29,7 @@ export default async ({ rootDirectory, container, app }) => {
|
||||
registerRepositories(pluginDetails, container)
|
||||
await registerServices(pluginDetails, container)
|
||||
registerMedusaApi(pluginDetails, container)
|
||||
registerApi(pluginDetails, app, rootDirectory, container)
|
||||
registerApi(pluginDetails, app, rootDirectory, container, activityId)
|
||||
registerCoreRouters(pluginDetails, container)
|
||||
registerSubscribers(pluginDetails, container)
|
||||
})
|
||||
@@ -159,9 +159,18 @@ function registerCoreRouters(pluginDetails, container) {
|
||||
/**
|
||||
* Registers the plugin's api routes.
|
||||
*/
|
||||
function registerApi(pluginDetails, app, rootDirectory = "", container) {
|
||||
function registerApi(
|
||||
pluginDetails,
|
||||
app,
|
||||
rootDirectory = "",
|
||||
container,
|
||||
activityId
|
||||
) {
|
||||
const logger = container.resolve("logger")
|
||||
logger.info(`Registering custom endpoints for ${pluginDetails.name}`)
|
||||
logger.progress(
|
||||
activityId,
|
||||
`Registering custom endpoints for ${pluginDetails.name}`
|
||||
)
|
||||
try {
|
||||
const routes = require(`${pluginDetails.resolve}/api`).default
|
||||
if (routes) {
|
||||
@@ -170,10 +179,10 @@ function registerApi(pluginDetails, app, rootDirectory = "", container) {
|
||||
return app
|
||||
} catch (err) {
|
||||
if (err.message !== `Cannot find module '${pluginDetails.resolve}/api'`) {
|
||||
logger.warn(
|
||||
`An error occured while registering customer endpoints for ${pluginDetails.name}`
|
||||
logger.progress(
|
||||
activityId,
|
||||
`No customer endpoints registered for ${pluginDetails.name}`
|
||||
)
|
||||
logger.error(err.stack)
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -821,6 +821,14 @@
|
||||
"@babel/helper-create-regexp-features-plugin" "^7.12.13"
|
||||
"@babel/helper-plugin-utils" "^7.12.13"
|
||||
|
||||
"@babel/polyfill@^7.8.7":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96"
|
||||
integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==
|
||||
dependencies:
|
||||
core-js "^2.6.5"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/preset-env@^7.12.7":
|
||||
version "7.14.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.4.tgz#73fc3228c59727e5e974319156f304f0d6685a2d"
|
||||
@@ -927,6 +935,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.9.6":
|
||||
version "7.14.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
|
||||
integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.12.13", "@babel/template@^7.3.3":
|
||||
version "7.12.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
|
||||
@@ -1214,6 +1229,30 @@
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^3.0.0"
|
||||
|
||||
"@medusajs/medusa-cli@^1.1.13":
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/@medusajs/medusa-cli/-/medusa-cli-1.1.13.tgz#1a7f28c0912b257b7eee1eb1eeaccc4b8bc20ad1"
|
||||
integrity sha512-7DK8l1wY/s9Wd1oka/+lkMmI+szC8F4u0hxcHod509oQnX8kS+UfXtQ0cVNiyDGJoc7GqB7teDILiUbBr3HI4w==
|
||||
dependencies:
|
||||
"@babel/polyfill" "^7.8.7"
|
||||
"@babel/runtime" "^7.9.6"
|
||||
"@hapi/joi" "^16.1.8"
|
||||
axios "^0.21.1"
|
||||
chalk "^4.0.0"
|
||||
configstore "5.0.1"
|
||||
core-js "^3.6.5"
|
||||
dotenv "^8.2.0"
|
||||
fs-exists-cached "^1.0.0"
|
||||
inquirer "^8.0.0"
|
||||
joi-objectid "^3.0.1"
|
||||
meant "^1.0.1"
|
||||
medusa-core-utils "^0.1.27"
|
||||
netrc-parser "^3.1.6"
|
||||
open "^8.0.6"
|
||||
regenerator-runtime "^0.13.5"
|
||||
resolve-cwd "^3.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents":
|
||||
version "2.1.8-no-fsevents"
|
||||
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b"
|
||||
@@ -1576,6 +1615,13 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
|
||||
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
babel-jest@^25.5.1:
|
||||
version "25.5.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.5.1.tgz#bc2e6101f849d6f6aec09720ffc7bc5332e62853"
|
||||
@@ -1693,6 +1739,11 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
base@^0.11.1:
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
||||
@@ -1730,6 +1781,15 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
bl@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
inherits "^2.0.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
body-parser@1.19.0, body-parser@^1.19.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
@@ -1836,6 +1896,14 @@ buffer-writer@2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
||||
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
|
||||
|
||||
buffer@^5.5.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
bull@^3.12.1:
|
||||
version "3.22.8"
|
||||
resolved "https://registry.yarnpkg.com/bull/-/bull-3.22.8.tgz#ca15630d5eab2d41cc6f98a786bafcab15d1575f"
|
||||
@@ -1953,7 +2021,7 @@ chalk@^3.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^4.1.0:
|
||||
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
|
||||
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
|
||||
@@ -2008,6 +2076,11 @@ cli-cursor@^3.1.0:
|
||||
dependencies:
|
||||
restore-cursor "^3.1.0"
|
||||
|
||||
cli-spinners@^2.5.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.0.tgz#36c7dc98fb6a9a76bd6238ec3f77e2425627e939"
|
||||
integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==
|
||||
|
||||
cli-width@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
|
||||
@@ -2029,6 +2102,11 @@ clone-response@^1.0.2:
|
||||
dependencies:
|
||||
mimic-response "^1.0.0"
|
||||
|
||||
clone@^1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
||||
|
||||
cluster-key-slot@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
|
||||
@@ -2142,7 +2220,7 @@ concat-stream@^1.5.2:
|
||||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
configstore@^5.0.1:
|
||||
configstore@5.0.1, configstore@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||
integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
|
||||
@@ -2219,6 +2297,11 @@ core-js-compat@^3.9.0, core-js-compat@^3.9.1:
|
||||
browserslist "^4.16.6"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js@^2.6.5:
|
||||
version "2.6.12"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.6.5, core-js@^3.7.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.14.0.tgz#62322b98c71cc2018b027971a69419e2425c2a6c"
|
||||
@@ -2368,11 +2451,23 @@ deepmerge@^4.2.2:
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||
|
||||
defaults@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
|
||||
integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
|
||||
dependencies:
|
||||
clone "^1.0.2"
|
||||
|
||||
defer-to-connect@^1.0.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||
|
||||
define-lazy-prop@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
||||
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
|
||||
|
||||
define-properties@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
@@ -2719,6 +2814,19 @@ exec-sh@^0.3.2:
|
||||
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc"
|
||||
integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==
|
||||
|
||||
execa@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
|
||||
integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
|
||||
dependencies:
|
||||
cross-spawn "^6.0.0"
|
||||
get-stream "^3.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
@@ -2984,6 +3092,11 @@ fn.name@1.x.x:
|
||||
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||
|
||||
follow-redirects@^1.10.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
|
||||
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
|
||||
|
||||
for-each@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
@@ -3100,6 +3213,11 @@ get-port@^5.1.1:
|
||||
resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193"
|
||||
integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==
|
||||
|
||||
get-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
|
||||
|
||||
get-stream@^4.0.0, get-stream@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
@@ -3340,6 +3458,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
ieee754@^1.1.13:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ignore-by-default@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||
@@ -3384,7 +3507,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@@ -3423,6 +3546,26 @@ inquirer@^7.0.0:
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
inquirer@^8.0.0:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.1.1.tgz#7c53d94c6d03011c7bb2a947f0dca3b98246c26a"
|
||||
integrity sha512-hUDjc3vBkh/uk1gPfMAD/7Z188Q8cvTGl0nxwaCdwSbzFh6ZKkZh+s2ozVxbE5G9ZNRyeY0+lgbAIOUFsFf98w==
|
||||
dependencies:
|
||||
ansi-escapes "^4.2.1"
|
||||
chalk "^4.1.1"
|
||||
cli-cursor "^3.1.0"
|
||||
cli-width "^3.0.0"
|
||||
external-editor "^3.0.3"
|
||||
figures "^3.0.0"
|
||||
lodash "^4.17.21"
|
||||
mute-stream "0.0.8"
|
||||
ora "^5.3.0"
|
||||
run-async "^2.4.0"
|
||||
rxjs "^6.6.6"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
ioredis@^4.17.3, ioredis@^4.27.0:
|
||||
version "4.27.5"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.5.tgz#b62192bb6198f8a5a02947902117150aef39b7f1"
|
||||
@@ -3560,7 +3703,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
|
||||
is-data-descriptor "^1.0.0"
|
||||
kind-of "^6.0.2"
|
||||
|
||||
is-docker@^2.0.0:
|
||||
is-docker@^2.0.0, is-docker@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
|
||||
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
|
||||
@@ -3619,6 +3762,11 @@ is-installed-globally@^0.3.1:
|
||||
global-dirs "^2.0.1"
|
||||
is-path-inside "^3.0.1"
|
||||
|
||||
is-interactive@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
||||
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
|
||||
|
||||
is-nan@^1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
|
||||
@@ -3711,12 +3859,17 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
|
||||
is-unicode-supported@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
|
||||
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
|
||||
|
||||
is-windows@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
|
||||
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
|
||||
|
||||
is-wsl@^2.1.1:
|
||||
is-wsl@^2.1.1, is-wsl@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
|
||||
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
|
||||
@@ -4459,6 +4612,14 @@ lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21:
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
log-symbols@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
|
||||
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
|
||||
dependencies:
|
||||
chalk "^4.1.0"
|
||||
is-unicode-supported "^0.1.0"
|
||||
|
||||
logform@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
|
||||
@@ -4540,11 +4701,24 @@ math-random@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
|
||||
integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
|
||||
|
||||
meant@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.3.tgz#67769af9de1d158773e928ae82c456114903554c"
|
||||
integrity sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
medusa-core-utils@^0.1.27:
|
||||
version "0.1.39"
|
||||
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-0.1.39.tgz#d57816c9bd43f9a92883650c1e66add1665291df"
|
||||
integrity sha512-R8+U1ile7if+nR6Cjh5exunx0ETV0OfkWUUBUpz1KmHSDv0V0CcvQqU9lcZesPFDEbu3Y2iEjsCqidVA4nG2nQ==
|
||||
dependencies:
|
||||
"@hapi/joi" "^16.1.8"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-core-utils@^1.1.18:
|
||||
version "1.1.18"
|
||||
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.18.tgz#2c2c49eeee796493a81bfab58db3f1ef164e6b1b"
|
||||
@@ -4754,6 +4928,14 @@ negotiator@0.6.2:
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||
|
||||
netrc-parser@^3.1.6:
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/netrc-parser/-/netrc-parser-3.1.6.tgz#7243c9ec850b8e805b9bdc7eae7b1450d4a96e72"
|
||||
integrity sha512-lY+fmkqSwntAAjfP63jB4z5p5WbuZwyMCD3pInT7dpHU/Gc6Vv90SAC6A0aNiqaRGHiuZFBtiwu+pu8W/Eyotw==
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
execa "^0.10.0"
|
||||
|
||||
nice-try@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
@@ -4957,6 +5139,15 @@ onetime@^5.1.0:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
open@^8.0.6:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/open/-/open-8.2.1.tgz#82de42da0ccbf429bc12d099dad2e0975e14e8af"
|
||||
integrity sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==
|
||||
dependencies:
|
||||
define-lazy-prop "^2.0.0"
|
||||
is-docker "^2.1.1"
|
||||
is-wsl "^2.2.0"
|
||||
|
||||
optionator@^0.8.1, optionator@^0.8.3:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||
@@ -4969,6 +5160,21 @@ optionator@^0.8.1, optionator@^0.8.3:
|
||||
type-check "~0.3.2"
|
||||
word-wrap "~1.2.3"
|
||||
|
||||
ora@^5.3.0:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
|
||||
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
|
||||
dependencies:
|
||||
bl "^4.1.0"
|
||||
chalk "^4.1.0"
|
||||
cli-cursor "^3.1.0"
|
||||
cli-spinners "^2.5.0"
|
||||
is-interactive "^1.0.0"
|
||||
is-unicode-supported "^0.1.0"
|
||||
log-symbols "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wcwidth "^1.0.1"
|
||||
|
||||
os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
@@ -5534,7 +5740,7 @@ regenerate@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
|
||||
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
|
||||
|
||||
regenerator-runtime@^0.13.4:
|
||||
regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5:
|
||||
version "0.13.7"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
|
||||
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
|
||||
@@ -5750,7 +5956,7 @@ run-async@^2.4.0:
|
||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
|
||||
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
|
||||
|
||||
rxjs@^6.6.0:
|
||||
rxjs@^6.6.0, rxjs@^6.6.6:
|
||||
version "6.6.7"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
||||
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
|
||||
@@ -6714,6 +6920,13 @@ walker@^1.0.7, walker@~1.0.5:
|
||||
dependencies:
|
||||
makeerror "1.0.x"
|
||||
|
||||
wcwidth@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
|
||||
integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
|
||||
dependencies:
|
||||
defaults "^1.0.3"
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
|
||||
Reference in New Issue
Block a user