1
packages/medusa-cli/.gitignore
vendored
1
packages/medusa-cli/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.env
|
||||
dist/
|
||||
node_modules/
|
||||
|
||||
|
||||
1
packages/medusa-cli/cli.js
Normal file → Executable file
1
packages/medusa-cli/cli.js
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require("dotenv").config()
|
||||
require("./dist/index.js")
|
||||
|
||||
6959
packages/medusa-cli/package-lock.json
generated
6959
packages/medusa-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@medusajs/medusa-cli",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.5-cloud-cli.38+43a3e56",
|
||||
"description": "Command Line interface for Medusa Commerce",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
@@ -38,15 +38,21 @@
|
||||
"@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"
|
||||
},
|
||||
"gitHead": "982da259ed93fe1b618800c8693a5c9dfe312532"
|
||||
"gitHead": "43a3e5680387cdeddb0d92a1bb0762235f15ca9a"
|
||||
}
|
||||
|
||||
76
packages/medusa-cli/src/commands/link.js
Normal file
76
packages/medusa-cli/src/commands/link.js
Normal file
@@ -0,0 +1,76 @@
|
||||
const axios = require("axios").default
|
||||
const open = require("open")
|
||||
const resolveCwd = require(`resolve-cwd`)
|
||||
const { getToken } = require("../util/token-store")
|
||||
|
||||
module.exports = {
|
||||
link: async argv => {
|
||||
const appHost =
|
||||
process.env.MEDUSA_APP_HOST || "https://app.medusa-commerce.com"
|
||||
|
||||
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
|
||||
const tok = getToken()
|
||||
if (!tok) {
|
||||
console.log(
|
||||
"You must login to Medusa Cloud first. Please run medusa login."
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Get the currenty 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
|
||||
.get(`${apiHost}/auth`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${tok}`,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
// 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,
|
||||
})
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
)
|
||||
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}`
|
||||
)
|
||||
})
|
||||
},
|
||||
}
|
||||
80
packages/medusa-cli/src/commands/login.js
Normal file
80
packages/medusa-cli/src/commands/login.js
Normal file
@@ -0,0 +1,80 @@
|
||||
const axios = require("axios").default
|
||||
const open = require("open")
|
||||
const inquirer = require("inquirer")
|
||||
|
||||
const { setToken } = require("../util/token-store")
|
||||
|
||||
/**
|
||||
* The login command allows the CLI to keep track of Cloud users; the command
|
||||
* makes a cli-login request to the cloud server and keeps an open connection
|
||||
* until the user has authenticated via the Medusa Cloud website.
|
||||
*/
|
||||
module.exports = {
|
||||
login: async _ => {
|
||||
const apiHost =
|
||||
process.env.MEDUSA_API_HOST || "https://api.medusa-commerce.com"
|
||||
|
||||
const authHost = process.env.MEDUSA_AUTH_HOST || `${apiHost}/cli-auth`
|
||||
|
||||
const loginHost =
|
||||
process.env.MEDUSA_APP_HOST || "https://app.medusa-commerce.com"
|
||||
|
||||
const { data: urls } = await axios.post(authHost)
|
||||
|
||||
const qs = [
|
||||
{
|
||||
type: "input",
|
||||
name: "open",
|
||||
message: "Press enter key to open browser for login or n to exit",
|
||||
},
|
||||
]
|
||||
|
||||
await inquirer.prompt(qs).then(async a => {
|
||||
if (a.open === "n") {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const bo = await open(`${loginHost}${urls.browser_url}`, {
|
||||
app: "browser",
|
||||
wait: false,
|
||||
})
|
||||
bo.on("error", err => {
|
||||
console.warn(err)
|
||||
console.log(
|
||||
`Could not open browser go to: ${loginHost}${urls.browser_url}`
|
||||
)
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
40
packages/medusa-cli/src/commands/whoami.js
Normal file
40
packages/medusa-cli/src/commands/whoami.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const axios = require("axios").default
|
||||
const { getToken } = require("../util/token-store")
|
||||
|
||||
/**
|
||||
* Fetches the locally logged in user.
|
||||
*/
|
||||
module.exports = {
|
||||
whoami: async argv => {
|
||||
const apiHost =
|
||||
process.env.MEDUSA_API_HOST || "https://api.medusa-commerce.com"
|
||||
|
||||
const tok = getToken()
|
||||
|
||||
if (!tok) {
|
||||
console.log(
|
||||
"You are not logged into Medusa Cloud. Please run medusa login."
|
||||
)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const { data: auth } = await axios
|
||||
.get(`${apiHost}/auth`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${tok}`,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
if (auth.user) {
|
||||
console.log(`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}`)
|
||||
console.log(`last_name: ${auth.user.last_name}`)
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
const path = require(`path`)
|
||||
const resolveCwd = require(`resolve-cwd`)
|
||||
const yargs = require(`yargs`)
|
||||
const existsSync = require(`fs-exists-cached`).sync
|
||||
|
||||
const { getLocalMedusaVersion } = require(`./util/version`)
|
||||
const { didYouMean } = require(`./did-you-mean`)
|
||||
const existsSync = require(`fs-exists-cached`).sync
|
||||
|
||||
const { whoami } = require("./commands/whoami")
|
||||
const { login } = require("./commands/login")
|
||||
const { link } = require("./commands/link")
|
||||
|
||||
const handlerP = fn => (...args) => {
|
||||
Promise.resolve(fn(...args)).then(
|
||||
@@ -61,6 +66,27 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
}
|
||||
|
||||
cli
|
||||
.command({
|
||||
command: `seed`,
|
||||
desc: `Migrates and populates the database with the provided file.`,
|
||||
builder: _ =>
|
||||
_.option(`f`, {
|
||||
alias: `seed-file`,
|
||||
type: `string`,
|
||||
describe: `Path to the file where the seed is defined.`,
|
||||
}).option(`m`, {
|
||||
alias: `migrate`,
|
||||
type: `boolean`,
|
||||
default: true,
|
||||
describe: `Flag to indicate if migrations should be run prior to seeding the database`,
|
||||
}),
|
||||
handler: handlerP(
|
||||
getCommandHandler(`seed`, (args, cmd) => {
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || `development`
|
||||
return cmd(args)
|
||||
})
|
||||
),
|
||||
})
|
||||
.command({
|
||||
command: `migrations [action]`,
|
||||
desc: `Migrate the database to the most recent version.`,
|
||||
@@ -77,6 +103,37 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
})
|
||||
),
|
||||
})
|
||||
.command({
|
||||
command: `whoami`,
|
||||
desc: `View the details of the currently logged in user.`,
|
||||
handler: handlerP(whoami),
|
||||
})
|
||||
.command({
|
||||
command: `link`,
|
||||
desc: `Creates your Medusa Cloud user in your local database for local testing.`,
|
||||
builder: _ =>
|
||||
_.option(`skip-local-user`, {
|
||||
alias: `skipLocalUser`,
|
||||
type: `boolean`,
|
||||
default: false,
|
||||
describe: `If set a user will not be created in the database.`,
|
||||
}),
|
||||
handler: handlerP(argv => {
|
||||
if (!isLocalProject) {
|
||||
console.log("must be a local project")
|
||||
cli.showHelp()
|
||||
}
|
||||
|
||||
const args = { ...argv, ...projectInfo, useYarn }
|
||||
|
||||
return link(args)
|
||||
}),
|
||||
})
|
||||
.command({
|
||||
command: `login`,
|
||||
desc: `Logs you into Medusa Cloud.`,
|
||||
handler: handlerP(login),
|
||||
})
|
||||
.command({
|
||||
command: `develop`,
|
||||
desc: `Start development server. Watches file and rebuilds when something changes`,
|
||||
|
||||
20
packages/medusa-cli/src/util/token-store.js
Normal file
20
packages/medusa-cli/src/util/token-store.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const ConfigStore = require("configstore")
|
||||
|
||||
let config
|
||||
|
||||
module.exports = {
|
||||
getToken: function() {
|
||||
if (!config) {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
|
||||
return config.get("login_token")
|
||||
},
|
||||
setToken: function(token) {
|
||||
if (!config) {
|
||||
config = new ConfigStore(`medusa`, {}, { globalConfigPath: true })
|
||||
}
|
||||
|
||||
return config.set("login_token", token)
|
||||
},
|
||||
}
|
||||
@@ -1326,6 +1326,13 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
||||
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
||||
|
||||
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"
|
||||
@@ -1560,6 +1567,14 @@ chalk@^4.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
|
||||
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chardet@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
@@ -1611,6 +1626,11 @@ cli-width@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
|
||||
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
|
||||
|
||||
cli-width@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
|
||||
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
|
||||
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
@@ -1684,6 +1704,18 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
configstore@5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||
integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
|
||||
dependencies:
|
||||
dot-prop "^5.2.0"
|
||||
graceful-fs "^4.1.2"
|
||||
make-dir "^3.0.0"
|
||||
unique-string "^2.0.0"
|
||||
write-file-atomic "^3.0.0"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||
@@ -1746,6 +1778,11 @@ cross-spawn@^7.0.0:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-random-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
||||
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
||||
|
||||
cssom@^0.4.1:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
|
||||
@@ -1786,6 +1823,13 @@ debug@^2.2.0, debug@^2.3.3:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.1.0:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
@@ -1813,6 +1857,11 @@ deepmerge@^4.2.2:
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||
|
||||
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.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
@@ -1871,6 +1920,18 @@ domexception@^1.0.1:
|
||||
dependencies:
|
||||
webidl-conversions "^4.0.2"
|
||||
|
||||
dot-prop@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
|
||||
integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
|
||||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dotenv@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
@@ -2036,6 +2097,19 @@ exec-sh@^0.3.2:
|
||||
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
|
||||
integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==
|
||||
|
||||
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"
|
||||
@@ -2235,6 +2309,11 @@ flatted@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
|
||||
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
|
||||
|
||||
follow-redirects@^1.10.0:
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
|
||||
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
|
||||
|
||||
for-in@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||
@@ -2309,6 +2388,11 @@ get-caller-file@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
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:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
@@ -2379,6 +2463,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.2.4:
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||
|
||||
graceful-fs@^4.1.2:
|
||||
version "4.2.6"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
|
||||
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
|
||||
|
||||
growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
@@ -2539,6 +2628,25 @@ inquirer@^7.0.0:
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
inquirer@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.0.0.tgz#957a46db1abcf0fdd2ab82deb7470e90afc7d0ac"
|
||||
integrity sha512-ON8pEJPPCdyjxj+cxsYRe6XfCJepTxANdNnTebsTuQgXpRyZRRT9t4dJwjRubgmvn20CLSEnozRUayXyM9VTXA==
|
||||
dependencies:
|
||||
ansi-escapes "^4.2.1"
|
||||
chalk "^4.1.0"
|
||||
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"
|
||||
run-async "^2.4.0"
|
||||
rxjs "^6.6.6"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
invariant@^2.2.2, invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
@@ -2626,6 +2734,11 @@ is-docker@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b"
|
||||
integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==
|
||||
|
||||
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==
|
||||
|
||||
is-extendable@^0.1.0, is-extendable@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
|
||||
@@ -2684,6 +2797,11 @@ is-number@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-obj@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
|
||||
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
|
||||
|
||||
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||
@@ -2711,7 +2829,7 @@ is-windows@^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==
|
||||
@@ -3339,6 +3457,11 @@ lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
|
||||
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
lolex@^5.0.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367"
|
||||
@@ -3518,6 +3641,14 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
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"
|
||||
@@ -3647,6 +3778,15 @@ onetime@^5.1.0:
|
||||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
open@^8.0.6:
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/open/-/open-8.0.6.tgz#bdf94a80b4ef5685d8c7b58fb0fbbe5729b37204"
|
||||
integrity sha512-vDOC0KwGabMPFtIpCO2QOnQeOz0N2rEkbuCuxICwLMUCrpv+A7NHrrzJ2dQReJmVluHhO4pYRh/Pn6s8t7Op6Q==
|
||||
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"
|
||||
@@ -4149,6 +4289,13 @@ rxjs@^6.5.3:
|
||||
dependencies:
|
||||
tslib "^1.9.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==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
@@ -4714,6 +4861,13 @@ union-value@^1.0.0:
|
||||
is-extendable "^0.1.1"
|
||||
set-value "^2.0.1"
|
||||
|
||||
unique-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
||||
integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
|
||||
dependencies:
|
||||
crypto-random-string "^2.0.0"
|
||||
|
||||
unset-value@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
|
||||
@@ -4894,6 +5048,11 @@ ws@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.5.tgz#abb1370d4626a5a9cd79d8de404aa18b3465d10d"
|
||||
integrity sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==
|
||||
|
||||
xdg-basedir@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||
|
||||
xml-name-validator@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-plugin-restock-notification",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.4-cloud-cli.14+43a3e56",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -14,7 +14,7 @@
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/plugin-transform-typescript": "^7.13.0",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@medusajs/medusa": "^1.1.23",
|
||||
"@medusajs/medusa": "^1.1.20-cloud-cli.14+43a3e56",
|
||||
"babel-preset-medusa-package": "^1.1.3",
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.8.0",
|
||||
@@ -39,5 +39,5 @@
|
||||
"express": "^4.17.1",
|
||||
"medusa-core-utils": "^1.1.9"
|
||||
},
|
||||
"gitHead": "982da259ed93fe1b618800c8693a5c9dfe312532"
|
||||
"gitHead": "43a3e5680387cdeddb0d92a1bb0762235f15ca9a"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
src
|
||||
.prettierrc
|
||||
.env
|
||||
.babelrc.js
|
||||
.eslintrc
|
||||
.gitignore
|
||||
ormconfig.json
|
||||
tsconfig.json
|
||||
jest.config.md
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@medusajs/medusa",
|
||||
"version": "1.1.23",
|
||||
"version": "1.1.20-cloud-cli.14+43a3e56",
|
||||
"description": "E-commerce for JAMstack",
|
||||
"main": "dist/index.js",
|
||||
"repository": {
|
||||
@@ -21,6 +21,7 @@
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.8.0",
|
||||
"jest": "^25.5.2",
|
||||
"medusa-interfaces": "^1.1.10",
|
||||
"nodemon": "^2.0.1",
|
||||
"prettier": "^1.19.1",
|
||||
"supertest": "^4.0.2"
|
||||
@@ -77,5 +78,5 @@
|
||||
"uuid": "^8.3.1",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"gitHead": "982da259ed93fe1b618800c8693a5c9dfe312532"
|
||||
"gitHead": "43a3e5680387cdeddb0d92a1bb0762235f15ca9a"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { spawn, execSync } from "child_process"
|
||||
import mongoose from "mongoose"
|
||||
import chokidar from "chokidar"
|
||||
import express from "express"
|
||||
import path from "path"
|
||||
|
||||
import loaders from "../loaders"
|
||||
import Logger from "../loaders/logger"
|
||||
|
||||
export default async function({ port, directory }) {
|
||||
|
||||
@@ -1,136 +1,18 @@
|
||||
import { createConnection, MigrationExecutor } from "typeorm"
|
||||
import { spawn, execSync } from "child_process"
|
||||
import chokidar from "chokidar"
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
import _ from "lodash"
|
||||
import { getConfigFile, createRequireFromPath } from "medusa-core-utils"
|
||||
import { sync as existsSync } from "fs-exists-cached"
|
||||
import { createConnection } from "typeorm"
|
||||
import { getConfigFile } from "medusa-core-utils"
|
||||
|
||||
import loaders from "../loaders"
|
||||
import Logger from "../loaders/logger"
|
||||
|
||||
function createFileContentHash(path, files) {
|
||||
return path + files
|
||||
}
|
||||
import getMigrations from "./utils/get-migrations"
|
||||
|
||||
// TODO: Create unique id for each plugin
|
||||
function createPluginId(name) {
|
||||
return name
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the correct path for the plugin. If it is a local plugin it will be
|
||||
* found in the plugins folder. Otherwise we will look for the plugin in the
|
||||
* installed npm packages.
|
||||
* @param {string} pluginName - the name of the plugin to find. Should match
|
||||
* the name of the folder where the plugin is contained.
|
||||
* @return {object} the plugin details
|
||||
*/
|
||||
function resolvePlugin(pluginName) {
|
||||
// Only find plugins when we're not given an absolute path
|
||||
if (!existsSync(pluginName)) {
|
||||
// Find the plugin in the local plugins folder
|
||||
const resolvedPath = path.resolve(`./plugins/${pluginName}`)
|
||||
|
||||
if (existsSync(resolvedPath)) {
|
||||
if (existsSync(`${resolvedPath}/package.json`)) {
|
||||
const packageJSON = JSON.parse(
|
||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
||||
)
|
||||
const name = packageJSON.name || pluginName
|
||||
//warnOnIncompatiblePeerDependency(name, packageJSON)
|
||||
|
||||
return {
|
||||
resolve: resolvedPath,
|
||||
name,
|
||||
id: createPluginId(name),
|
||||
options: {},
|
||||
version:
|
||||
packageJSON.version || createFileContentHash(resolvedPath, `**`),
|
||||
}
|
||||
} else {
|
||||
// Make package.json a requirement for local plugins too
|
||||
throw new Error(`Plugin ${pluginName} requires a package.json file`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rootDir = path.resolve(".")
|
||||
|
||||
/**
|
||||
* Here we have an absolute path to an internal plugin, or a name of a module
|
||||
* which should be located in node_modules.
|
||||
*/
|
||||
try {
|
||||
const requireSource =
|
||||
rootDir !== null
|
||||
? createRequireFromPath(`${rootDir}/:internal:`)
|
||||
: require
|
||||
|
||||
// If the path is absolute, resolve the directory of the internal plugin,
|
||||
// otherwise resolve the directory containing the package.json
|
||||
const resolvedPath = path.dirname(
|
||||
requireSource.resolve(`${pluginName}/package.json`)
|
||||
)
|
||||
|
||||
const packageJSON = JSON.parse(
|
||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
||||
)
|
||||
// warnOnIncompatiblePeerDependency(packageJSON.name, packageJSON)
|
||||
|
||||
return {
|
||||
resolve: resolvedPath,
|
||||
id: createPluginId(packageJSON.name),
|
||||
name: packageJSON.name,
|
||||
version: packageJSON.version,
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Unable to find plugin "${pluginName}". Perhaps you need to install its package?`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const t = async function({ port, directory }) {
|
||||
const t = async function({ directory }) {
|
||||
const args = process.argv
|
||||
args.shift()
|
||||
args.shift()
|
||||
args.shift()
|
||||
|
||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
||||
const { plugins } = configModule
|
||||
|
||||
const resolved = plugins.map(plugin => {
|
||||
if (_.isString(plugin)) {
|
||||
return resolvePlugin(plugin)
|
||||
}
|
||||
|
||||
const details = resolvePlugin(plugin.resolve)
|
||||
details.options = plugin.options
|
||||
|
||||
return details
|
||||
})
|
||||
|
||||
resolved.push({
|
||||
resolve: `${directory}/dist`,
|
||||
name: `project-plugin`,
|
||||
id: createPluginId(`project-plugin`),
|
||||
options: {},
|
||||
version: createFileContentHash(process.cwd(), `**`),
|
||||
})
|
||||
|
||||
const migrationDirs = []
|
||||
const coreMigrations = path.resolve(__dirname, "../migrations")
|
||||
|
||||
migrationDirs.push(`${coreMigrations}/*.js`)
|
||||
|
||||
for (const p of resolved) {
|
||||
const exists = existsSync(`${p.resolve}/migrations`)
|
||||
if (exists) {
|
||||
migrationDirs.push(`${p.resolve}/migrations/*.js`)
|
||||
}
|
||||
}
|
||||
const migrationDirs = getMigrations(directory)
|
||||
|
||||
const connection = await createConnection({
|
||||
type: configModule.projectConfig.database_type,
|
||||
|
||||
143
packages/medusa/src/commands/seed.js
Normal file
143
packages/medusa/src/commands/seed.js
Normal file
@@ -0,0 +1,143 @@
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
import express from "express"
|
||||
import { createConnection } from "typeorm"
|
||||
import { sync as existsSync } from "fs-exists-cached"
|
||||
import { getConfigFile } from "medusa-core-utils"
|
||||
|
||||
import Logger from "../loaders/logger"
|
||||
import loaders from "../loaders"
|
||||
|
||||
import getMigrations from "./utils/get-migrations"
|
||||
|
||||
const t = async function({ directory, migrate, seedFile }) {
|
||||
let resolvedPath = seedFile
|
||||
|
||||
// If we are already given an absolute path we can skip resolution step
|
||||
if (!existsSync(resolvedPath)) {
|
||||
resolvedPath = path.resolve(path.join(directory, seedFile))
|
||||
|
||||
if (!existsSync(resolvedPath)) {
|
||||
console.error(`Could not find a seed file at: ${seedFile}`)
|
||||
console.error(`Resolved path: ${resolvedPath}`)
|
||||
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if (migrate) {
|
||||
const migrationDirs = getMigrations(directory)
|
||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
||||
const connection = await createConnection({
|
||||
type: configModule.projectConfig.database_type,
|
||||
url: configModule.projectConfig.database_url,
|
||||
extra: configModule.projectConfig.database_extra || {},
|
||||
migrations: migrationDirs,
|
||||
logging: true,
|
||||
})
|
||||
|
||||
await connection.runMigrations()
|
||||
await connection.close()
|
||||
Logger.info("Migrations completed.")
|
||||
}
|
||||
|
||||
const app = express()
|
||||
const { container } = await loaders({
|
||||
directory,
|
||||
expressApp: app,
|
||||
})
|
||||
|
||||
const manager = container.resolve("manager")
|
||||
|
||||
const storeService = container.resolve("storeService")
|
||||
const userService = container.resolve("userService")
|
||||
const regionService = container.resolve("regionService")
|
||||
const productService = container.resolve("productService")
|
||||
const productVariantService = container.resolve("productVariantService")
|
||||
const shippingOptionService = container.resolve("shippingOptionService")
|
||||
const shippingProfileService = container.resolve("shippingProfileService")
|
||||
|
||||
await manager.transaction(async tx => {
|
||||
const { store, regions, products, shipping_options, users } = JSON.parse(
|
||||
fs.readFileSync(resolvedPath, `utf-8`)
|
||||
)
|
||||
|
||||
const gcProfile = await shippingProfileService.retrieveGiftCardDefault()
|
||||
const defaultProfile = await shippingProfileService.retrieveDefault()
|
||||
|
||||
if (store) {
|
||||
await storeService.withTransaction(tx).update(store)
|
||||
}
|
||||
|
||||
for (const u of users) {
|
||||
let pass = u.password
|
||||
if (pass) {
|
||||
delete u.password
|
||||
}
|
||||
await userService.withTransaction(tx).create(u, pass)
|
||||
}
|
||||
|
||||
let regionIds = {}
|
||||
for (const r of regions) {
|
||||
let dummyId
|
||||
if (!r.id || !r.id.startsWith("reg_")) {
|
||||
dummyId = r.id
|
||||
delete r.id
|
||||
}
|
||||
|
||||
const reg = await regionService.withTransaction(tx).create(r)
|
||||
|
||||
if (dummyId) {
|
||||
regionIds[dummyId] = reg.id
|
||||
}
|
||||
}
|
||||
|
||||
for (const so of shipping_options) {
|
||||
if (regionIds[so.region_id]) {
|
||||
so.region_id = regionIds[so.region_id]
|
||||
}
|
||||
|
||||
so.profile_id = defaultProfile.id
|
||||
if (so.is_giftcard) {
|
||||
so.profile_id = gcProfile.id
|
||||
delete so.is_giftcard
|
||||
}
|
||||
|
||||
await shippingOptionService.withTransaction(tx).create(so)
|
||||
}
|
||||
|
||||
for (const p of products) {
|
||||
const variants = p.variants
|
||||
delete p.variants
|
||||
|
||||
p.profile_id = defaultProfile.id
|
||||
if (p.is_giftcard) {
|
||||
p.profile_id = gcProfile.id
|
||||
}
|
||||
|
||||
const newProd = await productService.withTransaction(tx).create(p)
|
||||
|
||||
if (variants && variants.length) {
|
||||
const optionIds = p.options.map(
|
||||
o => newProd.options.find(newO => newO.title === o.title).id
|
||||
)
|
||||
|
||||
for (const v of variants) {
|
||||
const variant = {
|
||||
...v,
|
||||
options: v.options.map((o, index) => ({
|
||||
...o,
|
||||
option_id: optionIds[index],
|
||||
})),
|
||||
}
|
||||
|
||||
await productVariantService
|
||||
.withTransaction(tx)
|
||||
.create(newProd.id, variant)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default t
|
||||
@@ -1,10 +1,7 @@
|
||||
import "core-js/stable"
|
||||
import "regenerator-runtime/runtime"
|
||||
|
||||
import mongoose from "mongoose"
|
||||
import chokidar from "chokidar"
|
||||
import express from "express"
|
||||
import cwdResolve from "resolve-cwd"
|
||||
|
||||
import loaders from "../loaders"
|
||||
import Logger from "../loaders/logger"
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
import "core-js/stable"
|
||||
import "regenerator-runtime/runtime"
|
||||
|
||||
import mongoose from "mongoose"
|
||||
import chokidar from "chokidar"
|
||||
import express from "express"
|
||||
import cwdResolve from "resolve-cwd"
|
||||
|
||||
import loaders from "../loaders"
|
||||
import Logger from "../loaders/logger"
|
||||
|
||||
export default async function({ directory, email, password }) {
|
||||
export default async function({ directory, id, email, password }) {
|
||||
const app = express()
|
||||
const { container, dbConnection } = await loaders({
|
||||
const { container } = await loaders({
|
||||
directory,
|
||||
expressApp: app,
|
||||
})
|
||||
|
||||
const userService = container.resolve("userService")
|
||||
const user = await userService.create({ email }, password)
|
||||
await userService.create({ id, email }, password)
|
||||
|
||||
process.exit()
|
||||
}
|
||||
|
||||
127
packages/medusa/src/commands/utils/get-migrations.js
Normal file
127
packages/medusa/src/commands/utils/get-migrations.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
import { isString } from "lodash"
|
||||
import { sync as existsSync } from "fs-exists-cached"
|
||||
import { getConfigFile, createRequireFromPath } from "medusa-core-utils"
|
||||
|
||||
function createFileContentHash(path, files) {
|
||||
return path + files
|
||||
}
|
||||
|
||||
// TODO: Create unique id for each plugin
|
||||
function createPluginId(name) {
|
||||
return name
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the correct path for the plugin. If it is a local plugin it will be
|
||||
* found in the plugins folder. Otherwise we will look for the plugin in the
|
||||
* installed npm packages.
|
||||
* @param {string} pluginName - the name of the plugin to find. Should match
|
||||
* the name of the folder where the plugin is contained.
|
||||
* @return {object} the plugin details
|
||||
*/
|
||||
function resolvePlugin(pluginName) {
|
||||
// Only find plugins when we're not given an absolute path
|
||||
if (!existsSync(pluginName)) {
|
||||
// Find the plugin in the local plugins folder
|
||||
const resolvedPath = path.resolve(`./plugins/${pluginName}`)
|
||||
|
||||
if (existsSync(resolvedPath)) {
|
||||
if (existsSync(`${resolvedPath}/package.json`)) {
|
||||
const packageJSON = JSON.parse(
|
||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
||||
)
|
||||
const name = packageJSON.name || pluginName
|
||||
//warnOnIncompatiblePeerDependency(name, packageJSON)
|
||||
|
||||
return {
|
||||
resolve: resolvedPath,
|
||||
name,
|
||||
id: createPluginId(name),
|
||||
options: {},
|
||||
version:
|
||||
packageJSON.version || createFileContentHash(resolvedPath, `**`),
|
||||
}
|
||||
} else {
|
||||
// Make package.json a requirement for local plugins too
|
||||
throw new Error(`Plugin ${pluginName} requires a package.json file`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rootDir = path.resolve(".")
|
||||
|
||||
/**
|
||||
* Here we have an absolute path to an internal plugin, or a name of a module
|
||||
* which should be located in node_modules.
|
||||
*/
|
||||
try {
|
||||
const requireSource =
|
||||
rootDir !== null
|
||||
? createRequireFromPath(`${rootDir}/:internal:`)
|
||||
: require
|
||||
|
||||
// If the path is absolute, resolve the directory of the internal plugin,
|
||||
// otherwise resolve the directory containing the package.json
|
||||
const resolvedPath = path.dirname(
|
||||
requireSource.resolve(`${pluginName}/package.json`)
|
||||
)
|
||||
|
||||
const packageJSON = JSON.parse(
|
||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
||||
)
|
||||
// warnOnIncompatiblePeerDependency(packageJSON.name, packageJSON)
|
||||
|
||||
return {
|
||||
resolve: resolvedPath,
|
||||
id: createPluginId(packageJSON.name),
|
||||
name: packageJSON.name,
|
||||
version: packageJSON.version,
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Unable to find plugin "${pluginName}". Perhaps you need to install its package?`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default directory => {
|
||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
||||
const { plugins } = configModule
|
||||
|
||||
const resolved = plugins.map(plugin => {
|
||||
if (isString(plugin)) {
|
||||
return resolvePlugin(plugin)
|
||||
}
|
||||
|
||||
const details = resolvePlugin(plugin.resolve)
|
||||
details.options = plugin.options
|
||||
|
||||
return details
|
||||
})
|
||||
|
||||
resolved.push({
|
||||
resolve: `${directory}/dist`,
|
||||
name: `project-plugin`,
|
||||
id: createPluginId(`project-plugin`),
|
||||
options: {},
|
||||
version: createFileContentHash(process.cwd(), `**`),
|
||||
})
|
||||
|
||||
const migrationDirs = []
|
||||
const coreMigrations = path.resolve(
|
||||
path.join(__dirname, "..", "..", "migrations")
|
||||
)
|
||||
|
||||
migrationDirs.push(path.join(coreMigrations, "*.js"))
|
||||
|
||||
for (const p of resolved) {
|
||||
const exists = existsSync(`${p.resolve}/migrations`)
|
||||
if (exists) {
|
||||
migrationDirs.push(`${p.resolve}/migrations/*.js`)
|
||||
}
|
||||
}
|
||||
|
||||
return migrationDirs
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class nullablePassword1619108646647 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "user" ALTER COLUMN "password_hash" DROP NOT NULL`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "user" ALTER COLUMN "password_hash" TYPE character varying, ALTER COLUMN "password_hash" NOT NULL`
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export class User {
|
||||
@Column({ nullable: true })
|
||||
last_name: string
|
||||
|
||||
@Column()
|
||||
@Column({ nullable: true })
|
||||
password_hash: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
|
||||
@@ -45,6 +45,9 @@ describe("RegionService", () => {
|
||||
})
|
||||
|
||||
const storeService = {
|
||||
withTransaction: function() {
|
||||
return this
|
||||
},
|
||||
retrieve: () => {
|
||||
return {
|
||||
id: IdMap.getId("test-store"),
|
||||
@@ -221,6 +224,9 @@ describe("RegionService", () => {
|
||||
})
|
||||
|
||||
const storeService = {
|
||||
withTransaction: function() {
|
||||
return this
|
||||
},
|
||||
retrieve: () => {
|
||||
return {
|
||||
id: IdMap.getId("test-store"),
|
||||
@@ -312,6 +318,9 @@ describe("RegionService", () => {
|
||||
})
|
||||
|
||||
const storeService = {
|
||||
withTransaction: function() {
|
||||
return this
|
||||
},
|
||||
retrieve: () => {
|
||||
return {
|
||||
id: IdMap.getId("test-store"),
|
||||
|
||||
@@ -359,6 +359,9 @@ describe("ShippingOptionService", () => {
|
||||
}
|
||||
|
||||
const regionService = {
|
||||
withTransaction: function() {
|
||||
return this
|
||||
},
|
||||
retrieve: () => {
|
||||
return Promise.resolve({ fulfillment_providers: [{ id: "provider" }] })
|
||||
},
|
||||
|
||||
@@ -40,6 +40,16 @@ class AuthService extends BaseService {
|
||||
* error: a string with the error message
|
||||
*/
|
||||
async authenticateAPIToken(token) {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
try {
|
||||
const user = await this.userService_.retrieve(token)
|
||||
return {
|
||||
success: true,
|
||||
user,
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await this.userService_.retrieveByApiToken(token)
|
||||
return {
|
||||
|
||||
@@ -57,6 +57,7 @@ class RegionService extends BaseService {
|
||||
const cloned = new RegionService({
|
||||
manager: transactionManager,
|
||||
regionRepository: this.regionRepository_,
|
||||
currencyRepository: this.currencyRepository_,
|
||||
countryRepository: this.countryRepository_,
|
||||
storeService: this.storeService_,
|
||||
paymentProviderRepository: this.paymentProviderRepository_,
|
||||
@@ -114,7 +115,7 @@ class RegionService extends BaseService {
|
||||
regionObject[key] = value
|
||||
}
|
||||
|
||||
const created = await regionRepository.create(regionObject)
|
||||
const created = regionRepository.create(regionObject)
|
||||
const result = await regionRepository.save(created)
|
||||
return result
|
||||
})
|
||||
@@ -253,7 +254,9 @@ class RegionService extends BaseService {
|
||||
* @param {string} currencyCode - an ISO currency code
|
||||
*/
|
||||
async validateCurrency_(currencyCode) {
|
||||
const store = await this.storeService_.retrieve(["currencies"])
|
||||
const store = await this.storeService_
|
||||
.withTransaction(this.transactionManager_)
|
||||
.retrieve(["currencies"])
|
||||
|
||||
const storeCurrencies = store.currencies.map(curr => curr.code)
|
||||
|
||||
|
||||
@@ -319,9 +319,11 @@ class ShippingOptionService extends BaseService {
|
||||
const optionRepo = manager.getCustomRepository(this.optionRepository_)
|
||||
const option = await optionRepo.create(data)
|
||||
|
||||
const region = await this.regionService_.retrieve(option.region_id, {
|
||||
relations: ["fulfillment_providers"],
|
||||
})
|
||||
const region = await this.regionService_
|
||||
.withTransaction(manager)
|
||||
.retrieve(option.region_id, {
|
||||
relations: ["fulfillment_providers"],
|
||||
})
|
||||
|
||||
if (
|
||||
!region.fulfillment_providers.find(
|
||||
|
||||
@@ -153,9 +153,12 @@ class UserService extends BaseService {
|
||||
const userRepo = manager.getCustomRepository(this.userRepository_)
|
||||
|
||||
const validatedEmail = this.validateEmail_(user.email)
|
||||
const hashedPassword = await this.hashPassword_(password)
|
||||
if (password) {
|
||||
const hashedPassword = await this.hashPassword_(password)
|
||||
user.password_hash = hashedPassword
|
||||
}
|
||||
|
||||
user.email = validatedEmail
|
||||
user.password_hash = hashedPassword
|
||||
|
||||
const created = await userRepo.create(user)
|
||||
|
||||
|
||||
@@ -5095,6 +5095,13 @@ medusa-core-utils@^1.1.9:
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-interfaces@^1.1.10:
|
||||
version "1.1.10"
|
||||
resolved "https://registry.yarnpkg.com/medusa-interfaces/-/medusa-interfaces-1.1.10.tgz#e81b885e11d6c2f05db8d2971edf30b8f8e7ddaa"
|
||||
integrity sha512-FJSpX3CE5jx2mYqRARFSp5C6x5Hq+MEZ6p2UikuWnm40qjGsbHNl4naZFdBS1u/vSnXq+607oHuZnCNnpRDrPQ==
|
||||
dependencies:
|
||||
medusa-core-utils "^1.1.9"
|
||||
|
||||
medusa-test-utils@^1.1.12:
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.12.tgz#1a731a3bd0c7266105b75d88dce7c09657432002"
|
||||
|
||||
Reference in New Issue
Block a user