Merge pull request #268 from medusajs/feat/cli

Feat/cli
This commit is contained in:
Sebastian Rindom
2021-06-08 15:47:08 +02:00
committed by GitHub
28 changed files with 792 additions and 7113 deletions

View File

@@ -1,3 +1,4 @@
.env
dist/
node_modules/

1
packages/medusa-cli/cli.js Normal file → Executable file
View File

@@ -1,3 +1,4 @@
#!/usr/bin/env node
require("dotenv").config()
require("./dist/index.js")

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}

View 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&ltoken=${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&ltoken=${auth.user.id}`
)
})
},
}

View 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)
}
})
},
}

View 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}`)
}
},
}

View File

@@ -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`,

View 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)
},
}

View File

@@ -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"

View File

@@ -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"
}

View File

@@ -1,5 +1,9 @@
src
.prettierrc
.env
.babelrc.js
.eslintrc
.gitignore
ormconfig.json
tsconfig.json
jest.config.md

View File

@@ -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"
}

View File

@@ -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 }) {

View File

@@ -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,

View 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

View File

@@ -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"

View File

@@ -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()
}

View 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
}

View File

@@ -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`
)
}
}

View File

@@ -25,7 +25,7 @@ export class User {
@Column({ nullable: true })
last_name: string
@Column()
@Column({ nullable: true })
password_hash: string
@Column({ nullable: true })

View File

@@ -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"),

View File

@@ -359,6 +359,9 @@ describe("ShippingOptionService", () => {
}
const regionService = {
withTransaction: function() {
return this
},
retrieve: () => {
return Promise.resolve({ fulfillment_providers: [{ id: "provider" }] })
},

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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(

View File

@@ -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)

View File

@@ -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"