fix: working api

This commit is contained in:
Sebastian Rindom
2021-04-06 15:01:13 +02:00
parent 2b2555004e
commit 9d810971a7
8 changed files with 86 additions and 49 deletions
@@ -41,6 +41,7 @@
"dependencies": { "dependencies": {
"@medusajs/medusa": "^1.1.17", "@medusajs/medusa": "^1.1.17",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"express": "^4.17.1",
"medusa-core-utils": "^1.1.3" "medusa-core-utils": "^1.1.3"
}, },
"gitHead": "0646bd395a6056657cb0aa93c13699c4a9dbbcdd" "gitHead": "0646bd395a6056657cb0aa93c13699c4a9dbbcdd"
@@ -1,7 +1,7 @@
import { Validator, MedusaError } from "medusa-core-utils" import { Validator, MedusaError } from "medusa-core-utils"
export default async (req, res) => { export default async (req, res) => {
const { variant_id } = req.parmas const { variant_id } = req.params
const schema = Validator.object().keys({ const schema = Validator.object().keys({
email: Validator.string().required(), email: Validator.string().required(),
@@ -9,7 +9,8 @@ export default async (req, res) => {
const { value, error } = schema.validate(req.body) const { value, error } = schema.validate(req.body)
if (error) { if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) res.status(400).json({ message: error.message })
return
} }
try { try {
@@ -19,6 +20,6 @@ export default async (req, res) => {
await restockNotificationService.addEmail(variant_id, value.email) await restockNotificationService.addEmail(variant_id, value.email)
res.sendStatus(200) res.sendStatus(200)
} catch (err) { } catch (err) {
res.sendStatus(400).json({ message: err.message }) res.status(400).json({ message: err.message })
} }
} }
@@ -9,7 +9,7 @@ export default (app) => {
route.post( route.post(
"/variants/:variant_id", "/variants/:variant_id",
bodyParser.raw({ type: "application/json" }), bodyParser.json(),
middlewares.wrap(require("./add-email").default) middlewares.wrap(require("./add-email").default)
) )
return app return app
@@ -16,6 +16,23 @@ class RestockNotificationService extends BaseService {
this.eventBus_ = eventBusService this.eventBus_ = eventBusService
} }
withTransaction(transactionManager) {
if (!transactionManager) {
return this
}
const cloned = new RestockNotificationService({
manager: transactionManager,
options: this.options_,
eventBusService: this.eventBus_,
productVariantService: this.productVariantService_,
})
cloned.transactionManager_ = transactionManager
return cloned
}
async retrieve(variantId) { async retrieve(variantId) {
const restockRepo = this.manager_.getRepository(RestockNotification) const restockRepo = this.manager_.getRepository(RestockNotification)
return await restockRepo.findOne({ where: { variant_id: variantId } }) return await restockRepo.findOne({ where: { variant_id: variantId } })
@@ -29,13 +46,13 @@ class RestockNotificationService extends BaseService {
if (existing) { if (existing) {
// Converting to a set handles duplicates for us // Converting to a set handles duplicates for us
const emailSet = new Set(existing.emails) const emailSet = new Set(existing.emails)
emailSet.push(email) emailSet.add(email)
existing.emails = Array.from(emailSet) existing.emails = Array.from(emailSet)
return await restockRepo.save(existing) return await restockRepo.save(existing)
} else { } else {
const variant = await productVariantService.retrieve(variantId) const variant = await this.productVariantService_.retrieve(variantId)
if (variant.inventory_quantity > 0) { if (variant.inventory_quantity > 0) {
throw new MedusaError( throw new MedusaError(
@@ -54,15 +71,10 @@ class RestockNotificationService extends BaseService {
}) })
} }
async delete(variantId) {
return this.atomicPhase_(async (manager) => {
const restockRepo = manager.getRepository(RestockNotification)
return restockRepo.delete(variantId)
})
}
async triggerRestock(variantId) { async triggerRestock(variantId) {
return this.atomicPhase_(async (manager) => { return this.atomicPhase_(async (manager) => {
const restockRepo = manager.getRepository(RestockNotification)
const existing = await this.retrieve(variantId) const existing = await this.retrieve(variantId)
if (!existing) { if (!existing) {
return return
@@ -70,10 +82,13 @@ class RestockNotificationService extends BaseService {
const variant = await this.productVariantService_.retrieve(variantId) const variant = await this.productVariantService_.retrieve(variantId)
if (variant.inventory_quantity > 0) { if (variant.inventory_quantity > 0) {
await eventBus_ await this.eventBus_
.withTransaction(manager) .withTransaction(manager)
.emit("restock_notification.restocked") .emit("restock_notification.restocked", {
await this.delete(variantId) variant_id: variantId,
emails: existing.emails,
})
await restockRepo.delete(variantId)
} }
}) })
} }
@@ -1,9 +1,10 @@
class VariantSubscriber { class VariantSubscriber {
constructor({ eventBusService, restockNotificationService }) { constructor({ manager, eventBusService, restockNotificationService }) {
this.manager_ = manager
this.restockNotificationService_ = restockNotificationService this.restockNotificationService_ = restockNotificationService
eventBusService.subscribe( eventBusService.subscribe(
"product_variant.updated", "product-variant.updated",
this.handleVariantUpdate this.handleVariantUpdate
) )
} }
@@ -11,7 +12,12 @@ class VariantSubscriber {
handleVariantUpdate = async (data) => { handleVariantUpdate = async (data) => {
const { id, fields } = data const { id, fields } = data
if (fields.includes("inventory_quantity")) { if (fields.includes("inventory_quantity")) {
return this.restockNotificationService_.triggerRestock(id) return await this.manager_.transaction(
async (m) =>
await this.restockNotificationService_
.withTransaction(m)
.triggerRestock(id)
)
} }
} }
} }
+4 -1
View File
@@ -11,7 +11,7 @@ import modelsLoader from "./models"
import servicesLoader from "./services" import servicesLoader from "./services"
import subscribersLoader from "./subscribers" import subscribersLoader from "./subscribers"
import passportLoader from "./passport" import passportLoader from "./passport"
import pluginsLoader from "./plugins" import pluginsLoader, { registerPluginModels } from "./plugins"
import defaultsLoader from "./defaults" import defaultsLoader from "./defaults"
import Logger from "./logger" import Logger from "./logger"
import { getManager } from "typeorm" import { getManager } from "typeorm"
@@ -64,6 +64,9 @@ export default async ({ directory: rootDirectory, expressApp }) => {
await modelsLoader({ container }) await modelsLoader({ container })
Logger.info("Models initialized") Logger.info("Models initialized")
await registerPluginModels({ rootDirectory, container })
Logger.info("Models initialized")
await repositoriesLoader({ container }) await repositoriesLoader({ container })
Logger.info("Repositories initialized") Logger.info("Repositories initialized")
+31 -20
View File
@@ -13,13 +13,32 @@ import { getConfigFile, createRequireFromPath } from "medusa-core-utils"
import _ from "lodash" import _ from "lodash"
import path from "path" import path from "path"
import fs from "fs" import fs from "fs"
import { asFunction, aliasTo } from "awilix" import { asValue, asClass, asFunction, aliasTo } from "awilix"
import { sync as existsSync } from "fs-exists-cached" import { sync as existsSync } from "fs-exists-cached"
/** /**
* Registers all services in the services directory * Registers all services in the services directory
*/ */
export default async ({ rootDirectory, container, app }) => { export default async ({ rootDirectory, container, app }) => {
const resolved = getResolvedPlugins(rootDirectory)
await Promise.all(
resolved.map(async pluginDetails => {
registerRepositories(pluginDetails, container)
await registerServices(pluginDetails, container)
registerMedusaApi(pluginDetails, container)
registerApi(pluginDetails, app, rootDirectory, container)
registerCoreRouters(pluginDetails, container)
registerSubscribers(pluginDetails, container)
})
)
await Promise.all(
resolved.map(async pluginDetails => runLoaders(pluginDetails, container))
)
}
function getResolvedPlugins(rootDirectory) {
const { configModule } = getConfigFile(rootDirectory, `medusa-config`) const { configModule } = getConfigFile(rootDirectory, `medusa-config`)
if (!configModule) { if (!configModule) {
@@ -47,21 +66,16 @@ export default async ({ rootDirectory, container, app }) => {
version: createFileContentHash(process.cwd(), `**`), version: createFileContentHash(process.cwd(), `**`),
}) })
return resolved
}
export async function registerPluginModels({ rootDirectory, container }) {
const resolved = getResolvedPlugins(rootDirectory)
await Promise.all( await Promise.all(
resolved.map(async pluginDetails => { resolved.map(async pluginDetails => {
// registerModels(pluginDetails, container) registerModels(pluginDetails, container)
registerRepositories(pluginDetails, container)
await registerServices(pluginDetails, container)
registerMedusaApi(pluginDetails, container)
registerApi(pluginDetails, app, rootDirectory, container)
registerCoreRouters(pluginDetails, container)
registerSubscribers(pluginDetails, container)
}) })
) )
await Promise.all(
resolved.map(async pluginDetails => runLoaders(pluginDetails, container))
)
} }
async function runLoaders(pluginDetails, container) { async function runLoaders(pluginDetails, container) {
@@ -309,7 +323,6 @@ function registerRepositories(pluginDetails, container) {
Object.entries(loaded).map(([key, val]) => { Object.entries(loaded).map(([key, val]) => {
if (typeof val === "function") { if (typeof val === "function") {
const name = formatRegistrationName(fn) const name = formatRegistrationName(fn)
console.log(name)
container.register({ container.register({
[name]: asClass(val), [name]: asClass(val),
}) })
@@ -336,14 +349,12 @@ function registerModels(pluginDetails, container) {
Object.entries(loaded).map(([key, val]) => { Object.entries(loaded).map(([key, val]) => {
if (typeof val === "function" || val instanceof EntitySchema) { if (typeof val === "function" || val instanceof EntitySchema) {
if (config.register) { const name = formatRegistrationName(fn)
const name = formatRegistrationName(fn) container.register({
container.register({ [name]: asClass(val),
[name]: asClass(val), })
})
container.registerAdd("db_entities", asValue(val)) container.registerAdd("db_entities", asValue(val))
}
} }
}) })
}) })
+9 -9
View File
@@ -5662,21 +5662,21 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
medusa-core-utils@^1.1.0: medusa-core-utils@^1.1.4:
version "1.1.0" version "1.1.4"
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.0.tgz#0641b365b769dbf99856025d935eef5cf5d81f2c" resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.4.tgz#ec2bb98c83426d7033632cd225b3b5dc62c26f1a"
integrity sha512-zocRthKhLK3eSjrXbAhZZkIMBRxyvU7GcAMFh5UCEgfe7f935vjE7r5lGTr5jTEwgwaoTUk9ep0VBekz0SEdyw== integrity sha512-SzFfMmNbE9ukSfhapJOuYEksOKDo3yYSCeuBLFWnCZZRDnUV4ttH4Yp/ydT+cZKtqZwF2vKceXNbrT4uJYjHgw==
dependencies: dependencies:
joi "^17.3.0" joi "^17.3.0"
joi-objectid "^3.0.1" joi-objectid "^3.0.1"
medusa-test-utils@^1.1.3: medusa-test-utils@^1.1.7:
version "1.1.3" version "1.1.7"
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.3.tgz#c2b45d44b9567fa2255e936d7bed73a31dfb42dd" resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.7.tgz#19d0bdf3f6f7fef0bc7f2f8e258f8c66167c692f"
integrity sha512-0saYG5BhEjc4BZP76/2IJL7CyqIdbCasAci+EYXzwnwgS+nCUhKDjzzNAnC+PZMK/teD3M7x4n7isFtjgNSIDQ== integrity sha512-kcN4oJjUEAkFeko7DEaok9Qy3aty41gEzGSdR4F3KPORXZJ+YADHuj4F219/X1k+3iGqCUgmNQ9eKl6Aobq44g==
dependencies: dependencies:
"@babel/plugin-transform-classes" "^7.9.5" "@babel/plugin-transform-classes" "^7.9.5"
medusa-core-utils "^1.1.0" medusa-core-utils "^1.1.4"
randomatic "^3.1.1" randomatic "^3.1.1"
merge-descriptors@1.0.1: merge-descriptors@1.0.1: