mercur-cli 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/backend-setup.js +9 -13
- package/cli/data.js +121 -0
- package/cli/pull-and-install.js +38 -1
- package/cli/start.js +1 -1
- package/index.js +1 -1
- package/mercur/backend/.env.template +8 -0
- package/mercur/backend/.env.test +0 -0
- package/mercur/backend/.github/dependabot.yml +21 -0
- package/mercur/backend/.github/scripts/wait-for-server-live.sh +29 -0
- package/mercur/backend/.github/workflows/test-cli.yml +222 -0
- package/mercur/backend/.github/workflows/update-preview-deps-ci.yml +69 -0
- package/mercur/backend/.github/workflows/update-preview-deps.yml +67 -0
- package/mercur/backend/.vscode/settings.json +2 -0
- package/mercur/backend/.yarnrc.yml +1 -0
- package/mercur/backend/README.md +62 -0
- package/mercur/backend/instrumentation.ts +24 -0
- package/mercur/backend/integration-tests/http/README.md +29 -0
- package/mercur/backend/integration-tests/http/health.spec.ts +15 -0
- package/mercur/backend/integration-tests/setup.js +3 -0
- package/mercur/backend/jest.config.js +27 -0
- package/mercur/backend/medusa-config.ts +88 -0
- package/mercur/backend/package.json +65 -0
- package/mercur/backend/src/admin/README.md +33 -0
- package/mercur/backend/src/admin/tsconfig.json +24 -0
- package/mercur/backend/src/admin/vite-env.d.ts +1 -0
- package/mercur/backend/src/api/README.md +135 -0
- package/mercur/backend/src/api/admin/custom/route.ts +8 -0
- package/mercur/backend/src/api/store/custom/route.ts +8 -0
- package/mercur/backend/src/jobs/README.md +38 -0
- package/mercur/backend/src/links/README.md +26 -0
- package/mercur/backend/src/modules/README.md +117 -0
- package/mercur/backend/src/scripts/README.md +63 -0
- package/mercur/backend/src/scripts/seed/seed-functions.ts +519 -0
- package/mercur/backend/src/scripts/seed/seed-products.ts +601 -0
- package/mercur/backend/src/scripts/seed.ts +75 -0
- package/mercur/backend/src/subscribers/README.md +61 -0
- package/mercur/backend/src/workflows/README.md +81 -0
- package/mercur/backend/tsconfig.json +35 -0
- package/mercur/backend/yarn.lock +11469 -0
- package/package.json +10 -8
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Custom Module
|
|
2
|
+
|
|
3
|
+
A module is a package of reusable functionalities. It can be integrated into your Medusa application without affecting the overall system. You can create a module as part of a plugin.
|
|
4
|
+
|
|
5
|
+
> Learn more about modules in [this documentation](https://docs.medusajs.com/learn/fundamentals/modules).
|
|
6
|
+
|
|
7
|
+
To create a module:
|
|
8
|
+
|
|
9
|
+
## 1. Create a Data Model
|
|
10
|
+
|
|
11
|
+
A data model represents a table in the database. You create a data model in a TypeScript or JavaScript file under the `models` directory of a module.
|
|
12
|
+
|
|
13
|
+
For example, create the file `src/modules/blog/models/post.ts` with the following content:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { model } from "@medusajs/framework/utils"
|
|
17
|
+
|
|
18
|
+
const Post = model.define("post", {
|
|
19
|
+
id: model.id().primaryKey(),
|
|
20
|
+
title: model.text(),
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export default Post
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2. Create a Service
|
|
27
|
+
|
|
28
|
+
A module must define a service. A service is a TypeScript or JavaScript class holding methods related to a business logic or commerce functionality.
|
|
29
|
+
|
|
30
|
+
For example, create the file `src/modules/blog/service.ts` with the following content:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { MedusaService } from "@medusajs/framework/utils"
|
|
34
|
+
import Post from "./models/post"
|
|
35
|
+
|
|
36
|
+
class BlogModuleService extends MedusaService({
|
|
37
|
+
Post,
|
|
38
|
+
}){
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default BlogModuleService
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 3. Export Module Definition
|
|
45
|
+
|
|
46
|
+
A module must have an `index.ts` file in its root directory that exports its definition. The definition specifies the main service of the module.
|
|
47
|
+
|
|
48
|
+
For example, create the file `src/modules/blog/index.ts` with the following content:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import BlogModuleService from "./service"
|
|
52
|
+
import { Module } from "@medusajs/framework/utils"
|
|
53
|
+
|
|
54
|
+
export const BLOG_MODULE = "blog"
|
|
55
|
+
|
|
56
|
+
export default Module(BLOG_MODULE, {
|
|
57
|
+
service: BlogModuleService,
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 4. Add Module to Medusa's Configurations
|
|
62
|
+
|
|
63
|
+
To start using the module, add it to `medusa-config.ts`:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
module.exports = defineConfig({
|
|
67
|
+
projectConfig: {
|
|
68
|
+
// ...
|
|
69
|
+
},
|
|
70
|
+
modules: [
|
|
71
|
+
{
|
|
72
|
+
resolve: "./src/modules/blog",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 5. Generate and Run Migrations
|
|
79
|
+
|
|
80
|
+
To generate migrations for your module, run the following command:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx medusa db:generate blog
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then, to run migrations, run the following command:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx medusa db:migrate
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Use Module
|
|
93
|
+
|
|
94
|
+
You can use the module in customizations within the Medusa application, such as workflows and API routes.
|
|
95
|
+
|
|
96
|
+
For example, to use the module in an API route:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { MedusaRequest, MedusaResponse } from "@medusajs/framework"
|
|
100
|
+
import BlogModuleService from "../../../modules/blog/service"
|
|
101
|
+
import { BLOG_MODULE } from "../../../modules/blog"
|
|
102
|
+
|
|
103
|
+
export async function GET(
|
|
104
|
+
req: MedusaRequest,
|
|
105
|
+
res: MedusaResponse
|
|
106
|
+
): Promise<void> {
|
|
107
|
+
const blogModuleService: BlogModuleService = req.scope.resolve(
|
|
108
|
+
BLOG_MODULE
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
const posts = await blogModuleService.listPosts()
|
|
112
|
+
|
|
113
|
+
res.json({
|
|
114
|
+
posts
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Custom CLI Script
|
|
2
|
+
|
|
3
|
+
A custom CLI script is a function to execute through Medusa's CLI tool. This is useful when creating custom Medusa tooling to run as a CLI tool.
|
|
4
|
+
|
|
5
|
+
> Learn more about custom CLI scripts in [this documentation](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts).
|
|
6
|
+
|
|
7
|
+
## How to Create a Custom CLI Script?
|
|
8
|
+
|
|
9
|
+
To create a custom CLI script, create a TypeScript or JavaScript file under the `src/scripts` directory. The file must default export a function.
|
|
10
|
+
|
|
11
|
+
For example, create the file `src/scripts/my-script.ts` with the following content:
|
|
12
|
+
|
|
13
|
+
```ts title="src/scripts/my-script.ts"
|
|
14
|
+
import {
|
|
15
|
+
ExecArgs,
|
|
16
|
+
} from "@medusajs/framework/types"
|
|
17
|
+
|
|
18
|
+
export default async function myScript ({
|
|
19
|
+
container
|
|
20
|
+
}: ExecArgs) {
|
|
21
|
+
const productModuleService = container.resolve("product")
|
|
22
|
+
|
|
23
|
+
const [, count] = await productModuleService.listAndCountProducts()
|
|
24
|
+
|
|
25
|
+
console.log(`You have ${count} product(s)`)
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The function receives as a parameter an object having a `container` property, which is an instance of the Medusa Container. Use it to resolve resources in your Medusa application.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## How to Run Custom CLI Script?
|
|
34
|
+
|
|
35
|
+
To run the custom CLI script, run the `exec` command:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx medusa exec ./src/scripts/my-script.ts
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Custom CLI Script Arguments
|
|
44
|
+
|
|
45
|
+
Your script can accept arguments from the command line. Arguments are passed to the function's object parameter in the `args` property.
|
|
46
|
+
|
|
47
|
+
For example:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { ExecArgs } from "@medusajs/framework/types"
|
|
51
|
+
|
|
52
|
+
export default async function myScript ({
|
|
53
|
+
args
|
|
54
|
+
}: ExecArgs) {
|
|
55
|
+
console.log(`The arguments you passed: ${args}`)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then, pass the arguments in the `exec` command after the file path:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx medusa exec ./src/scripts/my-script.ts arg1 arg2
|
|
63
|
+
```
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import { MedusaContainer } from '@medusajs/framework'
|
|
2
|
+
import { ContainerRegistrationKeys, Modules } from '@medusajs/framework/utils'
|
|
3
|
+
import {
|
|
4
|
+
createApiKeysWorkflow,
|
|
5
|
+
createCollectionsWorkflow,
|
|
6
|
+
createInventoryLevelsWorkflow,
|
|
7
|
+
createProductCategoriesWorkflow,
|
|
8
|
+
createProductsWorkflow,
|
|
9
|
+
createRegionsWorkflow,
|
|
10
|
+
createSalesChannelsWorkflow,
|
|
11
|
+
createServiceZonesWorkflow,
|
|
12
|
+
createShippingOptionsWorkflow,
|
|
13
|
+
createStockLocationsWorkflow,
|
|
14
|
+
createTaxRegionsWorkflow,
|
|
15
|
+
linkSalesChannelsToApiKeyWorkflow,
|
|
16
|
+
updateStoresWorkflow
|
|
17
|
+
} from '@medusajs/medusa/core-flows'
|
|
18
|
+
|
|
19
|
+
import { SELLER_MODULE } from '@mercurjs/b2c-core/modules/seller'
|
|
20
|
+
import {
|
|
21
|
+
createConfigurationRuleWorkflow,
|
|
22
|
+
createLocationFulfillmentSetAndAssociateWithSellerWorkflow,
|
|
23
|
+
createSellerWorkflow
|
|
24
|
+
} from '@mercurjs/b2c-core/workflows'
|
|
25
|
+
import { createCommissionRuleWorkflow } from '@mercurjs/commission/workflows'
|
|
26
|
+
import {
|
|
27
|
+
ConfigurationRuleDefaults,
|
|
28
|
+
SELLER_SHIPPING_PROFILE_LINK
|
|
29
|
+
} from '@mercurjs/framework'
|
|
30
|
+
|
|
31
|
+
import { productsToInsert } from './seed-products'
|
|
32
|
+
|
|
33
|
+
const countries = ['be', 'de', 'dk', 'se', 'fr', 'es', 'it', 'pl', 'cz', 'nl']
|
|
34
|
+
|
|
35
|
+
export async function createSalesChannel(container: MedusaContainer) {
|
|
36
|
+
const salesChannelModuleService = container.resolve(Modules.SALES_CHANNEL)
|
|
37
|
+
let [defaultSalesChannel] = await salesChannelModuleService.listSalesChannels(
|
|
38
|
+
{
|
|
39
|
+
name: 'Default Sales Channel'
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!defaultSalesChannel) {
|
|
44
|
+
const {
|
|
45
|
+
result: [salesChannelResult]
|
|
46
|
+
} = await createSalesChannelsWorkflow(container).run({
|
|
47
|
+
input: {
|
|
48
|
+
salesChannelsData: [
|
|
49
|
+
{
|
|
50
|
+
name: 'Default Sales Channel'
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
defaultSalesChannel = salesChannelResult
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return defaultSalesChannel
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function createStore(
|
|
62
|
+
container: MedusaContainer,
|
|
63
|
+
salesChannelId: string,
|
|
64
|
+
regionId: string
|
|
65
|
+
) {
|
|
66
|
+
const storeModuleService = container.resolve(Modules.STORE)
|
|
67
|
+
const [store] = await storeModuleService.listStores()
|
|
68
|
+
|
|
69
|
+
if (!store) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await updateStoresWorkflow(container).run({
|
|
74
|
+
input: {
|
|
75
|
+
selector: { id: store.id },
|
|
76
|
+
update: {
|
|
77
|
+
supported_currencies: [
|
|
78
|
+
{
|
|
79
|
+
currency_code: 'eur',
|
|
80
|
+
is_default: true
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
default_sales_channel_id: salesChannelId,
|
|
84
|
+
default_region_id: regionId
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
export async function createRegions(container: MedusaContainer) {
|
|
90
|
+
const {
|
|
91
|
+
result: [region]
|
|
92
|
+
} = await createRegionsWorkflow(container).run({
|
|
93
|
+
input: {
|
|
94
|
+
regions: [
|
|
95
|
+
{
|
|
96
|
+
name: 'Europe',
|
|
97
|
+
currency_code: 'eur',
|
|
98
|
+
countries,
|
|
99
|
+
payment_providers: ['pp_system_default']
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
await createTaxRegionsWorkflow(container).run({
|
|
106
|
+
input: countries.map((country_code) => ({
|
|
107
|
+
country_code
|
|
108
|
+
}))
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
return region
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function createPublishableKey(
|
|
115
|
+
container: MedusaContainer,
|
|
116
|
+
salesChannelId: string
|
|
117
|
+
) {
|
|
118
|
+
const apiKeyService = container.resolve(Modules.API_KEY)
|
|
119
|
+
|
|
120
|
+
let [key] = await apiKeyService.listApiKeys({ type: 'publishable' })
|
|
121
|
+
|
|
122
|
+
if (!key) {
|
|
123
|
+
const {
|
|
124
|
+
result: [publishableApiKeyResult]
|
|
125
|
+
} = await createApiKeysWorkflow(container).run({
|
|
126
|
+
input: {
|
|
127
|
+
api_keys: [
|
|
128
|
+
{
|
|
129
|
+
title: 'Default publishable key',
|
|
130
|
+
type: 'publishable',
|
|
131
|
+
created_by: ''
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
key = publishableApiKeyResult
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
await linkSalesChannelsToApiKeyWorkflow(container).run({
|
|
140
|
+
input: {
|
|
141
|
+
id: key.id,
|
|
142
|
+
add: [salesChannelId]
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
return key
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function createProductCategories(container: MedusaContainer) {
|
|
150
|
+
const { result } = await createProductCategoriesWorkflow(container).run({
|
|
151
|
+
input: {
|
|
152
|
+
product_categories: [
|
|
153
|
+
{
|
|
154
|
+
name: 'Sneakers',
|
|
155
|
+
is_active: true
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'Sandals',
|
|
159
|
+
is_active: true
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'Boots',
|
|
163
|
+
is_active: true
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'Sport',
|
|
167
|
+
is_active: true
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'Accessories',
|
|
171
|
+
is_active: true
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'Tops',
|
|
175
|
+
is_active: true
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return result
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function createProductCollections(container: MedusaContainer) {
|
|
185
|
+
const { result } = await createCollectionsWorkflow(container).run({
|
|
186
|
+
input: {
|
|
187
|
+
collections: [
|
|
188
|
+
{
|
|
189
|
+
title: 'Luxury'
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
title: 'Vintage'
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
title: 'Casual'
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
title: 'Soho'
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
title: 'Streetwear'
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: 'Y2K'
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
return result
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export async function createSeller(container: MedusaContainer) {
|
|
214
|
+
const authService = container.resolve(Modules.AUTH)
|
|
215
|
+
|
|
216
|
+
const { authIdentity } = await authService.register('emailpass', {
|
|
217
|
+
body: {
|
|
218
|
+
email: 'seller@mercurjs.com',
|
|
219
|
+
password: 'secret'
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
const { result: seller } = await createSellerWorkflow.run({
|
|
224
|
+
container,
|
|
225
|
+
input: {
|
|
226
|
+
auth_identity_id: authIdentity?.id,
|
|
227
|
+
member: {
|
|
228
|
+
name: 'John Doe',
|
|
229
|
+
email: 'seller@mercurjs.com'
|
|
230
|
+
},
|
|
231
|
+
seller: {
|
|
232
|
+
name: 'MercurJS Store'
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
return seller
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export async function createSellerStockLocation(
|
|
241
|
+
container: MedusaContainer,
|
|
242
|
+
sellerId: string,
|
|
243
|
+
salesChannelId: string
|
|
244
|
+
) {
|
|
245
|
+
const link = container.resolve(ContainerRegistrationKeys.LINK)
|
|
246
|
+
const {
|
|
247
|
+
result: [stock]
|
|
248
|
+
} = await createStockLocationsWorkflow(container).run({
|
|
249
|
+
input: {
|
|
250
|
+
locations: [
|
|
251
|
+
{
|
|
252
|
+
name: `Stock Location for seller ${sellerId}`,
|
|
253
|
+
address: {
|
|
254
|
+
address_1: 'Random Strasse',
|
|
255
|
+
city: 'Berlin',
|
|
256
|
+
country_code: 'de'
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
await link.create([
|
|
264
|
+
{
|
|
265
|
+
[SELLER_MODULE]: {
|
|
266
|
+
seller_id: sellerId
|
|
267
|
+
},
|
|
268
|
+
[Modules.STOCK_LOCATION]: {
|
|
269
|
+
stock_location_id: stock.id
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
[Modules.STOCK_LOCATION]: {
|
|
274
|
+
stock_location_id: stock.id
|
|
275
|
+
},
|
|
276
|
+
[Modules.FULFILLMENT]: {
|
|
277
|
+
fulfillment_provider_id: 'manual_manual'
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
[Modules.SALES_CHANNEL]: {
|
|
282
|
+
sales_channel_id: salesChannelId
|
|
283
|
+
},
|
|
284
|
+
[Modules.STOCK_LOCATION]: {
|
|
285
|
+
stock_location_id: stock.id
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
])
|
|
289
|
+
|
|
290
|
+
await createLocationFulfillmentSetAndAssociateWithSellerWorkflow.run({
|
|
291
|
+
container,
|
|
292
|
+
input: {
|
|
293
|
+
fulfillment_set_data: {
|
|
294
|
+
name: `${sellerId} fulfillment set`,
|
|
295
|
+
type: 'shipping'
|
|
296
|
+
},
|
|
297
|
+
location_id: stock.id,
|
|
298
|
+
seller_id: sellerId
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
const query = container.resolve(ContainerRegistrationKeys.QUERY)
|
|
303
|
+
|
|
304
|
+
const {
|
|
305
|
+
data: [stockLocation]
|
|
306
|
+
} = await query.graph({
|
|
307
|
+
entity: 'stock_location',
|
|
308
|
+
fields: ['*', 'fulfillment_sets.*'],
|
|
309
|
+
filters: {
|
|
310
|
+
id: stock.id
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
return stockLocation
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export async function createServiceZoneForFulfillmentSet(
|
|
318
|
+
container: MedusaContainer,
|
|
319
|
+
sellerId: string,
|
|
320
|
+
fulfillmentSetId: string
|
|
321
|
+
) {
|
|
322
|
+
await createServiceZonesWorkflow.run({
|
|
323
|
+
container,
|
|
324
|
+
input: {
|
|
325
|
+
data: [
|
|
326
|
+
{
|
|
327
|
+
fulfillment_set_id: fulfillmentSetId,
|
|
328
|
+
name: `Europe`,
|
|
329
|
+
geo_zones: countries.map((c) => ({
|
|
330
|
+
type: 'country',
|
|
331
|
+
country_code: c
|
|
332
|
+
}))
|
|
333
|
+
}
|
|
334
|
+
]
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
const fulfillmentService = container.resolve(Modules.FULFILLMENT)
|
|
339
|
+
|
|
340
|
+
const [zone] = await fulfillmentService.listServiceZones({
|
|
341
|
+
fulfillment_set: {
|
|
342
|
+
id: fulfillmentSetId
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
const link = container.resolve(ContainerRegistrationKeys.LINK)
|
|
347
|
+
await link.create({
|
|
348
|
+
[SELLER_MODULE]: {
|
|
349
|
+
seller_id: sellerId
|
|
350
|
+
},
|
|
351
|
+
[Modules.FULFILLMENT]: {
|
|
352
|
+
service_zone_id: zone.id
|
|
353
|
+
}
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
return zone
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export async function createSellerShippingOption(
|
|
360
|
+
container: MedusaContainer,
|
|
361
|
+
sellerId: string,
|
|
362
|
+
sellerName: string,
|
|
363
|
+
regionId: string,
|
|
364
|
+
serviceZoneId: string
|
|
365
|
+
) {
|
|
366
|
+
const query = container.resolve(ContainerRegistrationKeys.QUERY)
|
|
367
|
+
const {
|
|
368
|
+
data: [shippingProfile]
|
|
369
|
+
} = await query.graph({
|
|
370
|
+
entity: SELLER_SHIPPING_PROFILE_LINK,
|
|
371
|
+
fields: ['shipping_profile_id'],
|
|
372
|
+
filters: {
|
|
373
|
+
seller_id: sellerId
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
const {
|
|
378
|
+
result: [shippingOption]
|
|
379
|
+
} = await createShippingOptionsWorkflow.run({
|
|
380
|
+
container,
|
|
381
|
+
input: [
|
|
382
|
+
{
|
|
383
|
+
name: `${sellerName} shipping`,
|
|
384
|
+
shipping_profile_id: shippingProfile.shipping_profile_id,
|
|
385
|
+
service_zone_id: serviceZoneId,
|
|
386
|
+
provider_id: 'manual_manual',
|
|
387
|
+
type: {
|
|
388
|
+
label: `${sellerName} shipping`,
|
|
389
|
+
code: sellerName,
|
|
390
|
+
description: 'Europe shipping'
|
|
391
|
+
},
|
|
392
|
+
rules: [
|
|
393
|
+
{ value: 'true', attribute: 'enabled_in_store', operator: 'eq' },
|
|
394
|
+
{ attribute: 'is_return', value: 'false', operator: 'eq' }
|
|
395
|
+
],
|
|
396
|
+
prices: [
|
|
397
|
+
{ currency_code: 'eur', amount: 10 },
|
|
398
|
+
{ amount: 10, region_id: regionId }
|
|
399
|
+
],
|
|
400
|
+
price_type: 'flat',
|
|
401
|
+
data: { id: 'manual-fulfillment' }
|
|
402
|
+
}
|
|
403
|
+
]
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
const link = container.resolve(ContainerRegistrationKeys.LINK)
|
|
407
|
+
await link.create({
|
|
408
|
+
[SELLER_MODULE]: {
|
|
409
|
+
seller_id: sellerId
|
|
410
|
+
},
|
|
411
|
+
[Modules.FULFILLMENT]: {
|
|
412
|
+
shipping_option_id: shippingOption.id
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
return shippingOption
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export async function createSellerProducts(
|
|
420
|
+
container: MedusaContainer,
|
|
421
|
+
sellerId: string,
|
|
422
|
+
salesChannelId: string
|
|
423
|
+
) {
|
|
424
|
+
const productService = container.resolve(Modules.PRODUCT)
|
|
425
|
+
const collections = await productService.listProductCollections(
|
|
426
|
+
{},
|
|
427
|
+
{ select: ['id', 'title'] }
|
|
428
|
+
)
|
|
429
|
+
const categories = await productService.listProductCategories(
|
|
430
|
+
{},
|
|
431
|
+
{ select: ['id', 'name'] }
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
const randomCategory = () =>
|
|
435
|
+
categories[Math.floor(Math.random() * categories.length)]
|
|
436
|
+
const randomCollection = () =>
|
|
437
|
+
collections[Math.floor(Math.random() * collections.length)]
|
|
438
|
+
|
|
439
|
+
const toInsert = productsToInsert.map((p) => ({
|
|
440
|
+
...p,
|
|
441
|
+
categories: [
|
|
442
|
+
{
|
|
443
|
+
id: randomCategory().id
|
|
444
|
+
}
|
|
445
|
+
],
|
|
446
|
+
collection_id: randomCollection().id,
|
|
447
|
+
sales_channels: [
|
|
448
|
+
{
|
|
449
|
+
id: salesChannelId
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}))
|
|
453
|
+
|
|
454
|
+
const { result } = await createProductsWorkflow.run({
|
|
455
|
+
container,
|
|
456
|
+
input: {
|
|
457
|
+
products: toInsert,
|
|
458
|
+
additional_data: {
|
|
459
|
+
seller_id: sellerId
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
return result
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export async function createInventoryItemStockLevels(
|
|
468
|
+
container: MedusaContainer,
|
|
469
|
+
stockLocationId: string
|
|
470
|
+
) {
|
|
471
|
+
const inventoryService = container.resolve(Modules.INVENTORY)
|
|
472
|
+
const items = await inventoryService.listInventoryItems(
|
|
473
|
+
{},
|
|
474
|
+
{ select: ['id'] }
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
const toCreate = items.map((i) => ({
|
|
478
|
+
inventory_item_id: i.id,
|
|
479
|
+
location_id: stockLocationId,
|
|
480
|
+
stocked_quantity: Math.floor(Math.random() * 50) + 1
|
|
481
|
+
}))
|
|
482
|
+
|
|
483
|
+
const { result } = await createInventoryLevelsWorkflow.run({
|
|
484
|
+
container,
|
|
485
|
+
input: {
|
|
486
|
+
inventory_levels: toCreate
|
|
487
|
+
}
|
|
488
|
+
})
|
|
489
|
+
return result
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export async function createDefaultCommissionLevel(container: MedusaContainer) {
|
|
493
|
+
await createCommissionRuleWorkflow.run({
|
|
494
|
+
container,
|
|
495
|
+
input: {
|
|
496
|
+
name: 'default',
|
|
497
|
+
is_active: true,
|
|
498
|
+
reference: 'site',
|
|
499
|
+
reference_id: '',
|
|
500
|
+
rate: {
|
|
501
|
+
include_tax: true,
|
|
502
|
+
type: 'percentage',
|
|
503
|
+
percentage_rate: 2
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
export async function createConfigurationRules(container: MedusaContainer) {
|
|
510
|
+
for (const [ruleType, isEnabled] of ConfigurationRuleDefaults) {
|
|
511
|
+
await createConfigurationRuleWorkflow.run({
|
|
512
|
+
container,
|
|
513
|
+
input: {
|
|
514
|
+
rule_type: ruleType,
|
|
515
|
+
is_enabled: isEnabled
|
|
516
|
+
}
|
|
517
|
+
})
|
|
518
|
+
}
|
|
519
|
+
}
|