chore: fix yarn.lock conflicts
This commit is contained in:
commit
915359d84b
400 files changed
+16918
-15217
No files matched your search
@@ -0,0 +1,8 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json",
|
||||
"changelog": ["@changesets/changelog-github", { "repo": "medusajs/medusa" }],
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"baseBranch": "master",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ module.exports = {
|
||||
files: [`*.ts`],
|
||||
parser: `@typescript-eslint/parser`,
|
||||
plugins: [`@typescript-eslint/eslint-plugin`],
|
||||
extends: [`plugin:@typescript-eslint/recommended`],
|
||||
extends: [`plugin:@typescript-eslint/recommended`, "prettier"],
|
||||
rules: {
|
||||
"valid-jsdoc": [
|
||||
"error",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#.kodiak.toml
|
||||
version = 1
|
||||
|
||||
[merge]
|
||||
automerge_label = "automerge"
|
||||
require_automerge_label = true
|
||||
blocking_labels = ["on hold", "wip", "blocked"]
|
||||
method = "squash"
|
||||
delete_branch_on_merge = true
|
||||
optimistic_updates = false
|
||||
prioritize_ready_to_merge = true
|
||||
notify_on_conflict = true
|
||||
|
||||
[merge.message]
|
||||
title = "pull_request_title"
|
||||
body = "pull_request_body"
|
||||
include_coauthors= true
|
||||
include_pr_number = true
|
||||
body_type = "markdown"
|
||||
strip_html_comments = true
|
||||
@@ -0,0 +1,42 @@
|
||||
name: "Setup test env"
|
||||
description: "Setup test environment for actions"
|
||||
|
||||
inputs:
|
||||
node-version:
|
||||
description: "Node version"
|
||||
required: false
|
||||
default: "14"
|
||||
cache-extension:
|
||||
description: "Extension for fetching cached dependencies"
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
cache: "yarn"
|
||||
|
||||
- name: Bootstrap packages
|
||||
uses: ./.github/actions/cache-bootstrap
|
||||
with:
|
||||
extension: ${{ inputs.cache-extension }}
|
||||
|
||||
- name: Build Packages
|
||||
shell: "bash"
|
||||
run: yarn build
|
||||
|
||||
- name: Install dev cli
|
||||
shell: "bash"
|
||||
run: sudo npm i -g medusa-dev-cli
|
||||
|
||||
- name: Set path to medusa repo
|
||||
shell: "bash"
|
||||
run: medusa-dev --set-path-to-repo $(pwd)
|
||||
@@ -0,0 +1,33 @@
|
||||
name: "Test server"
|
||||
description: "Test the currently running medusa server to see if a user has been created and that the server is seeded"
|
||||
|
||||
inputs:
|
||||
email:
|
||||
description: "email of user to log in"
|
||||
required: false
|
||||
default: "test@test.com"
|
||||
password:
|
||||
description: "password of user to log in"
|
||||
required: false
|
||||
default: "password"
|
||||
pathToSeedData:
|
||||
description: "path to seed data"
|
||||
required: false
|
||||
default: "../cli-test/data/seed.json"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Wait for live server response
|
||||
shell: "bash"
|
||||
run: ./integration-tests/scripts/cli/wait-for-server-live.sh
|
||||
- name: Log in with user
|
||||
shell: "bash"
|
||||
run: ./integration-tests/scripts/cli/login.sh ${{ inputs.email }} ${{ inputs.password }}
|
||||
- name: GetProducts
|
||||
shell: "bash"
|
||||
run: ./integration-tests/scripts/cli/get-products.sh ${{ inputs.pathToSeedData }}
|
||||
|
||||
- name: Kill server
|
||||
shell: "bash"
|
||||
run: kill -9 $(lsof -t -i :9000)
|
||||
@@ -1,9 +1,9 @@
|
||||
name: Medusa Pipeline
|
||||
on:
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'www/**'
|
||||
- "docs/**"
|
||||
- "www/**"
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
@@ -43,6 +43,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
postgres:
|
||||
image: postgres
|
||||
env:
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
# Inspired from https://github.com/Shopify/quilt/blob/main/.github/workflows/snapit.yml
|
||||
name: Snapshot This
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types:
|
||||
- created
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
snapshot:
|
||||
name: Snapshot Release
|
||||
if: |
|
||||
github.event.issue.pull_request &&
|
||||
github.event.comment.body == '/snapshot-this'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate pull request
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
// Add a rocket reaction to the comment
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
...context.repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: 'rocket',
|
||||
})
|
||||
|
||||
// Only allow comment creators who have "write" permissions to repo
|
||||
const actorPermission = (await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
...context.repo,
|
||||
username: context.actor
|
||||
})).data.permission
|
||||
const isPermitted = ['write', 'admin'].includes(actorPermission)
|
||||
if (!isPermitted) {
|
||||
const errorMessage = 'Only users with write permission to the respository can run /snapshot-this'
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: errorMessage,
|
||||
})
|
||||
core.setFailed(errorMessage)
|
||||
return;
|
||||
}
|
||||
|
||||
const pullRequest = await github.rest.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: context.issue.number,
|
||||
})
|
||||
// Pull request from fork
|
||||
if (context.payload.repository.full_name !== pullRequest.data.head.repo.full_name) {
|
||||
const errorMessage = '`/snapshot-this` is not supported on pull requests from forked repositories.'
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: errorMessage,
|
||||
})
|
||||
core.setFailed(errorMessage)
|
||||
}
|
||||
} catch (err) {
|
||||
core.setFailed(`Request failed with error ${err}`)
|
||||
}
|
||||
- name: Checkout pull request branch
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ format('refs/pull/{0}/merge', github.event.issue.number) }}
|
||||
|
||||
# Because changeset entries are consumed and removed on the
|
||||
# 'changeset-release/main' branch, we need to reset the files
|
||||
# so the following 'changeset version --snapshot' command will
|
||||
# regenerate the package version bumps with the snapshot releases
|
||||
- name: Reset changeset entries on changeset-release/main branch
|
||||
run: |
|
||||
if [[ $(git branch --show-current) == 'changeset-release/main' ]]; then
|
||||
git checkout origin/main -- .changeset
|
||||
fi
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: "yarn"
|
||||
|
||||
- name: Bootstrap packages
|
||||
uses: ./.github/actions/cache-bootstrap
|
||||
with:
|
||||
extension: snapshot-this
|
||||
|
||||
- name: Create an .npmrc
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
cat << EOF > "$HOME/.npmrc"
|
||||
//registry.npmjs.org/:_authToken=$NPM_TOKEN
|
||||
EOF
|
||||
|
||||
- name: Create and publish snapshot release
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
script: |
|
||||
await exec.exec('yarn run changeset version --snapshot snapshot')
|
||||
const {stdout} = await exec.getExecOutput('yarn run release:snapshot')
|
||||
const newTags = Array
|
||||
.from(stdout.matchAll(/New tag:\s+([^\s\n]+)/g))
|
||||
.map(([_, tag]) => tag)
|
||||
if (newTags.length) {
|
||||
const multiple = newTags.length > 1
|
||||
const body = (
|
||||
`#### :rocket: A snapshot release has been made for this PR\n\n` +
|
||||
`Test the snapshot${multiple ? 's' : ''} by updating your \`package.json\` ` +
|
||||
`with the newly published version${multiple ? 's' : ''}:\n` +
|
||||
newTags.map(tag => (
|
||||
'```sh\n' +
|
||||
`yarn add ${tag}\n` +
|
||||
'```'
|
||||
)).join('\n') +
|
||||
`\n\n> Latest commit: ${context.sha}`
|
||||
|
||||
)
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: context.issue.number,
|
||||
body,
|
||||
})
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
...context.repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: 'hooray',
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
name: CLI Pipeline
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
test-cli-with-database:
|
||||
env:
|
||||
REDIS_URL: redis://localhost:6379
|
||||
DATABASE_URL: "postgres://postgres:postgres@localhost/cli-test"
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
db: [sqlite, postgres]
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
# Set health checks to wait until redis has started
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
postgres:
|
||||
image: postgres
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: cli-test
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup development server
|
||||
uses: ./.github/actions/setup-server
|
||||
with:
|
||||
cache-extension: "cli-test"
|
||||
|
||||
- name: Install Medusa cli
|
||||
run: yarn global add @medusajs/medusa-cli
|
||||
|
||||
- name: Create Medusa project
|
||||
run: |
|
||||
medusa new cli-test
|
||||
working-directory: ..
|
||||
|
||||
- name: Install postgres config
|
||||
if: matrix.db == 'postgres'
|
||||
run: |
|
||||
curl \
|
||||
https://raw.githubusercontent.com/medusajs/medusa-starter-default/feat/postgres-config/medusa-config.js \
|
||||
--output medusa-config.js
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: run medusa dev
|
||||
run: medusa-dev --force-install
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: Run migrations
|
||||
run: medusa migrations run
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: Seed db
|
||||
run: yarn seed
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: Create admin user
|
||||
run: medusa user -e test@test.com -p password -i admin_123
|
||||
working-directory: ../cli-test
|
||||
|
||||
########################## Test medusa develop ###############################
|
||||
|
||||
- name: Run development server
|
||||
run: medusa develop > /dev/null 2>&1 &
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: Testing development server
|
||||
uses: ./.github/actions/test-server
|
||||
|
||||
########################### Test medusa start ################################
|
||||
|
||||
- name: Starting medusa
|
||||
run: medusa start > /dev/null 2>&1 &
|
||||
working-directory: ../cli-test
|
||||
|
||||
- name: Testing server
|
||||
uses: ./.github/actions/test-server
|
||||
@@ -49,7 +49,6 @@ A basic Medusa server installed with the `medusa new` command has dependencies s
|
||||
"medusa-interfaces": "^1.3.0",
|
||||
"medusa-payment-manual": "^1.0.16",
|
||||
"medusa-payment-stripe": "^1.1.38",
|
||||
"mongoose": "^5.13.3",
|
||||
"typeorm": "^0.2.36"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -169,10 +168,10 @@ const plugins = [
|
||||
{
|
||||
resolve: `medusa-plugin-custom`,
|
||||
options: {
|
||||
name: 'My Store'
|
||||
}
|
||||
}
|
||||
];
|
||||
name: "My Store",
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
Then, you can have access to your plugin configuration in the constructor of services in your plugin:
|
||||
@@ -195,11 +194,11 @@ export default (rootDirectory, options) => {
|
||||
|
||||
router.get("/hello-world", (req, res) => {
|
||||
res.json({
|
||||
message: `Welcome to ${options.name ? options.name : 'Medusa'}!`
|
||||
message: `Welcome to ${options.name ? options.name : "Medusa"}!`,
|
||||
})
|
||||
})
|
||||
|
||||
return router;
|
||||
return router
|
||||
}
|
||||
```
|
||||
|
||||
@@ -249,10 +248,10 @@ const plugins = [
|
||||
resolve: `medusa-plugin-custom`,
|
||||
//if your plugin has configurations
|
||||
options: {
|
||||
name: 'My Store'
|
||||
}
|
||||
}
|
||||
];
|
||||
name: "My Store",
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
:::note
|
||||
@@ -269,7 +268,7 @@ npm run start
|
||||
|
||||
## NPM Ignore File
|
||||
|
||||
Not all files that you use while developing your plugin are necessary to be published.
|
||||
Not all files that you use while developing your plugin are necessary to be published.
|
||||
|
||||
For example, the files you add in the `src` directory are compiled to a `dist` directory before publishing. Then, when a developer installs your plugin, they’ll just be using the files under the `dist` directory.
|
||||
|
||||
|
||||
@@ -189,20 +189,20 @@ Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"handle": "test-collection",
|
||||
"id": "test-collection",
|
||||
"handle": "test-collection2",
|
||||
"id": "test-collection2",
|
||||
"products": Array [
|
||||
Object {
|
||||
"collection_id": "test-collection",
|
||||
"collection_id": "test-collection2",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description",
|
||||
"discountable": true,
|
||||
"external_id": null,
|
||||
"handle": "test-product",
|
||||
"handle": "test-product_filtering_2",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-product",
|
||||
"id": "test-product_filtering_2",
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
@@ -210,44 +210,17 @@ Object {
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"status": "published",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "Test product",
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"collection_id": "test-collection",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description1",
|
||||
"discountable": true,
|
||||
"external_id": null,
|
||||
"handle": "test-product1",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-product1",
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "Test product1",
|
||||
"title": "Test product filtering 2",
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
],
|
||||
"title": "Test collection",
|
||||
"title": "Test collection 2",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
@@ -315,20 +288,20 @@ Object {
|
||||
},
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"handle": "test-collection2",
|
||||
"id": "test-collection2",
|
||||
"handle": "test-collection",
|
||||
"id": "test-collection",
|
||||
"products": Array [
|
||||
Object {
|
||||
"collection_id": "test-collection2",
|
||||
"collection_id": "test-collection",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description",
|
||||
"discountable": true,
|
||||
"external_id": null,
|
||||
"handle": "test-product_filtering_2",
|
||||
"handle": "test-product",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-product_filtering_2",
|
||||
"id": "test-product",
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
@@ -336,17 +309,44 @@ Object {
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "published",
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "Test product filtering 2",
|
||||
"title": "Test product",
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"collection_id": "test-collection",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description1",
|
||||
"discountable": true,
|
||||
"external_id": null,
|
||||
"handle": "test-product1",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-product1",
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "Test product1",
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
],
|
||||
"title": "Test collection 2",
|
||||
"title": "Test collection",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -12,13 +12,13 @@ Array [
|
||||
"created_at": Any<String>,
|
||||
"id": "tag3",
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
"value": "1235",
|
||||
},
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"id": "tag4",
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
"value": "1234",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -35,13 +35,13 @@ Array [
|
||||
"created_at": Any<String>,
|
||||
"id": "tag3",
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
"value": "1235",
|
||||
},
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"id": "tag4",
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
"value": "1234",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -79,6 +79,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -105,6 +107,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -123,6 +127,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
@@ -133,6 +138,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean2",
|
||||
@@ -159,6 +166,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -177,6 +186,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku2",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc2",
|
||||
"updated_at": Any<String>,
|
||||
@@ -187,6 +197,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode 1",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean1",
|
||||
@@ -213,6 +225,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -231,6 +245,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku1",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (1)",
|
||||
"upc": "test-upc1",
|
||||
"updated_at": Any<String>,
|
||||
@@ -241,6 +256,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode-sale",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean-sale",
|
||||
@@ -267,6 +284,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 1000,
|
||||
@@ -285,6 +304,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku-sale",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc-sale",
|
||||
"updated_at": Any<String>,
|
||||
@@ -353,6 +373,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean4",
|
||||
@@ -379,6 +401,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -397,6 +421,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku4",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc4",
|
||||
"updated_at": Any<String>,
|
||||
@@ -407,6 +432,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean3",
|
||||
@@ -433,6 +460,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -451,6 +480,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku3",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc3",
|
||||
"updated_at": Any<String>,
|
||||
@@ -609,6 +639,8 @@ Array [
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": null,
|
||||
@@ -635,6 +667,8 @@ Array [
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -653,6 +687,7 @@ Array [
|
||||
],
|
||||
"product_id": StringMatching /\\^prod_\\*/,
|
||||
"sku": null,
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": null,
|
||||
"updated_at": Any<String>,
|
||||
@@ -769,6 +804,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": null,
|
||||
@@ -805,6 +842,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -851,6 +890,7 @@ Object {
|
||||
],
|
||||
"product_id": StringMatching /\\^prod_\\*/,
|
||||
"sku": null,
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": null,
|
||||
"updated_at": Any<String>,
|
||||
@@ -933,6 +973,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -959,6 +1001,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 75,
|
||||
@@ -977,6 +1021,7 @@ Object {
|
||||
],
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
|
||||
@@ -176,20 +176,14 @@ describe("/admin/collections", () => {
|
||||
expect(response.data).toMatchSnapshot({
|
||||
collections: [
|
||||
{
|
||||
id: "test-collection",
|
||||
handle: "test-collection",
|
||||
title: "Test collection",
|
||||
id: "test-collection2",
|
||||
handle: "test-collection2",
|
||||
title: "Test collection 2",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
products: [
|
||||
{
|
||||
collection_id: "test-collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
},
|
||||
{
|
||||
collection_id: "test-collection",
|
||||
collection_id: "test-collection2",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
@@ -218,14 +212,20 @@ describe("/admin/collections", () => {
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "test-collection2",
|
||||
handle: "test-collection2",
|
||||
title: "Test collection 2",
|
||||
id: "test-collection",
|
||||
handle: "test-collection",
|
||||
title: "Test collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
products: [
|
||||
{
|
||||
collection_id: "test-collection2",
|
||||
collection_id: "test-collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
},
|
||||
{
|
||||
collection_id: "test-collection",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
profile_id: expect.stringMatching(/^sp_*/),
|
||||
|
||||
@@ -353,6 +353,84 @@ describe("/admin/draft-orders", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("creates a draft order with discount and free shipping along the line item", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
email: "oli@test.dk",
|
||||
shipping_address: "oli-shipping",
|
||||
discounts: [{ code: "TEST" }, { code: "free-shipping"}],
|
||||
items: [
|
||||
{
|
||||
variant_id: "test-variant",
|
||||
quantity: 2,
|
||||
metadata: {},
|
||||
},
|
||||
],
|
||||
region_id: "test-region",
|
||||
customer_id: "oli-test",
|
||||
shipping_methods: [
|
||||
{
|
||||
option_id: "test-option",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/draft-orders", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const created = await api
|
||||
.get(`/admin/draft-orders/${response.data.draft_order.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const draftOrder = created.data.draft_order
|
||||
const lineItemId = draftOrder.cart.items[0].id
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(draftOrder.cart.items).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
variant_id: "test-variant",
|
||||
unit_price: 8000,
|
||||
quantity: 2,
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
item_id: lineItemId,
|
||||
amount: 1600,
|
||||
description: "discount",
|
||||
discount_id: "test-discount",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
// Check that discounts are applied
|
||||
expect(draftOrder.cart.discounts).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
code: "TEST",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
code: "free-shipping",
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("creates a draft order with created shipping address", async () => {
|
||||
const api = useApi()
|
||||
|
||||
|
||||
@@ -89,11 +89,10 @@ describe("/admin/product-tags", () => {
|
||||
updated_at: expect.any(String),
|
||||
}
|
||||
|
||||
expect(res.data.product_tags.map((pt) => pt.value)).toEqual([
|
||||
"123",
|
||||
"123",
|
||||
"123",
|
||||
])
|
||||
expect(res.data.product_tags.length).toEqual(3)
|
||||
expect(res.data.product_tags.map((pt) => pt.value)).toEqual(
|
||||
expect.arrayContaining(["123", "1235", "1234"])
|
||||
)
|
||||
|
||||
expect(res.data.product_tags).toMatchSnapshot([
|
||||
tagMatch,
|
||||
|
||||
@@ -6,7 +6,11 @@ const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const productSeeder = require("../../helpers/product-seeder")
|
||||
const { ProductVariant, ProductOptionValue, MoneyAmount } = require("@medusajs/medusa")
|
||||
const {
|
||||
ProductVariant,
|
||||
ProductOptionValue,
|
||||
MoneyAmount,
|
||||
} = require("@medusajs/medusa")
|
||||
const priceListSeeder = require("../../helpers/price-list-seeder")
|
||||
|
||||
jest.setTimeout(50000)
|
||||
@@ -18,7 +22,7 @@ describe("/admin/products", () => {
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
medusaProcess = await setupServer({ cwd, verbose: false })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -232,6 +236,7 @@ describe("/admin/products", () => {
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "test-product_filtering_4",
|
||||
@@ -256,6 +261,36 @@ describe("/admin/products", () => {
|
||||
expect(response.data.products.length).toEqual(2)
|
||||
})
|
||||
|
||||
it("returns a list of products with free text query including variant prices", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/products?q=test+product1", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const expectedVariantPrices = response.data.products[0].variants
|
||||
.map((v) => v.prices)
|
||||
.flat(1)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(expectedVariantPrices).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "test-price4",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-price3",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("returns a list of products with free text query and offset", async () => {
|
||||
const api = useApi()
|
||||
|
||||
@@ -1388,7 +1423,7 @@ describe("/admin/products", () => {
|
||||
})
|
||||
|
||||
describe("GET /admin/products/:id/variants", () => {
|
||||
beforeEach(async() => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
@@ -1398,12 +1433,12 @@ describe("/admin/products", () => {
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async() => {
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it('should return the variants related to the requested product', async () => {
|
||||
it("should return the variants related to the requested product", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api
|
||||
@@ -1420,10 +1455,22 @@ describe("/admin/products", () => {
|
||||
expect(res.data.variants.length).toBe(4)
|
||||
expect(res.data.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: "test-variant", product_id: "test-product" }),
|
||||
expect.objectContaining({ id: "test-variant_1", product_id: "test-product" }),
|
||||
expect.objectContaining({ id: "test-variant_2", product_id: "test-product" }),
|
||||
expect.objectContaining({ id: "test-variant-sale", product_id: "test-product" }),
|
||||
expect.objectContaining({
|
||||
id: "test-variant",
|
||||
product_id: "test-product",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-variant_1",
|
||||
product_id: "test-product",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-variant_2",
|
||||
product_id: "test-product",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-variant-sale",
|
||||
product_id: "test-product",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
@@ -1812,16 +1859,22 @@ describe("/admin/products", () => {
|
||||
expect(optValPost).toEqual(undefined)
|
||||
|
||||
// Validate that the option still exists in the DB with deleted_at
|
||||
const optValDeleted = await dbConnection.manager.findOne(ProductOptionValue, {
|
||||
variant_id: "test-variant_2",
|
||||
}, {
|
||||
withDeleted: true,
|
||||
})
|
||||
const optValDeleted = await dbConnection.manager.findOne(
|
||||
ProductOptionValue,
|
||||
{
|
||||
variant_id: "test-variant_2",
|
||||
},
|
||||
{
|
||||
withDeleted: true,
|
||||
}
|
||||
)
|
||||
|
||||
expect(optValDeleted).toEqual(expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
variant_id: "test-variant_2",
|
||||
}))
|
||||
expect(optValDeleted).toEqual(
|
||||
expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
variant_id: "test-variant_2",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("successfully deletes a product and any option value associated with one of its variants", async () => {
|
||||
@@ -1854,16 +1907,22 @@ describe("/admin/products", () => {
|
||||
expect(optValPost).toEqual(undefined)
|
||||
|
||||
// Validate that the option still exists in the DB with deleted_at
|
||||
const optValDeleted = await dbConnection.manager.findOne(ProductOptionValue, {
|
||||
variant_id: "test-variant_2",
|
||||
}, {
|
||||
withDeleted: true,
|
||||
})
|
||||
const optValDeleted = await dbConnection.manager.findOne(
|
||||
ProductOptionValue,
|
||||
{
|
||||
variant_id: "test-variant_2",
|
||||
},
|
||||
{
|
||||
withDeleted: true,
|
||||
}
|
||||
)
|
||||
|
||||
expect(optValDeleted).toEqual(expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
variant_id: "test-variant_2",
|
||||
}))
|
||||
expect(optValDeleted).toEqual(
|
||||
expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
variant_id: "test-variant_2",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("successfully deletes a product variant and its associated prices", async () => {
|
||||
@@ -1889,26 +1948,29 @@ describe("/admin/products", () => {
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
// Validate that the price was deleted
|
||||
const pricePost = await dbConnection.manager.findOne(
|
||||
MoneyAmount,
|
||||
{
|
||||
id: "test-price",
|
||||
}
|
||||
)
|
||||
const pricePost = await dbConnection.manager.findOne(MoneyAmount, {
|
||||
id: "test-price",
|
||||
})
|
||||
|
||||
expect(pricePost).toEqual(undefined)
|
||||
|
||||
// Validate that the price still exists in the DB with deleted_at
|
||||
const optValDeleted = await dbConnection.manager.findOne(MoneyAmount, {
|
||||
id: "test-price",
|
||||
}, {
|
||||
withDeleted: true,
|
||||
})
|
||||
const optValDeleted = await dbConnection.manager.findOne(
|
||||
MoneyAmount,
|
||||
{
|
||||
id: "test-price",
|
||||
},
|
||||
{
|
||||
withDeleted: true,
|
||||
}
|
||||
)
|
||||
|
||||
expect(optValDeleted).toEqual(expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
id: "test-price",
|
||||
}))
|
||||
expect(optValDeleted).toEqual(
|
||||
expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
id: "test-price",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("successfully deletes a product and any prices associated with one of its variants", async () => {
|
||||
@@ -1938,16 +2000,22 @@ describe("/admin/products", () => {
|
||||
expect(pricePost).toEqual(undefined)
|
||||
|
||||
// Validate that the price still exists in the DB with deleted_at
|
||||
const optValDeleted = await dbConnection.manager.findOne(MoneyAmount, {
|
||||
id: "test-price",
|
||||
}, {
|
||||
withDeleted: true,
|
||||
})
|
||||
const optValDeleted = await dbConnection.manager.findOne(
|
||||
MoneyAmount,
|
||||
{
|
||||
id: "test-price",
|
||||
},
|
||||
{
|
||||
withDeleted: true,
|
||||
}
|
||||
)
|
||||
|
||||
expect(optValDeleted).toEqual(expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
id: "test-price",
|
||||
}))
|
||||
expect(optValDeleted).toEqual(
|
||||
expect.objectContaining({
|
||||
deleted_at: expect.any(Date),
|
||||
id: "test-price",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("successfully creates product with soft-deleted product handle and deletes it again", async () => {
|
||||
@@ -2182,4 +2250,45 @@ describe("/admin/products", () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /admin/products/tag-usage", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("successfully gets the tags usage", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api
|
||||
.get("/admin/products/tag-usage", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.tags.length).toEqual(3)
|
||||
expect(res.data.tags).toEqual(
|
||||
expect.arrayContaining([
|
||||
{ id: "tag1", usage_count: "2", value: "123" },
|
||||
{ id: "tag3", usage_count: "2", value: "1235" },
|
||||
{ id: "tag4", usage_count: "1", value: "1234" },
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,39 +1,142 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/admin/batch GET /admin/batch lists batch jobs created by the user 1`] = `
|
||||
exports[`/admin/batch-jobs GET /admin/batch-jobs lists batch jobs created by the user 1`] = `
|
||||
Object {
|
||||
"batch_jobs": Array [
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": "2022-06-27T22:00:00.000Z",
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_5",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "completed",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_3",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "batch_2",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_2",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "batch_2",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_1",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "batch_1",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
],
|
||||
"count": 4,
|
||||
"limit": 10,
|
||||
"offset": 0,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`/admin/batch-jobs GET /admin/batch-jobs lists batch jobs created by the user and where completed_at is null 1`] = `
|
||||
Object {
|
||||
"batch_jobs": Array [
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_3",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_2",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_1",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
],
|
||||
@@ -42,3 +145,64 @@ Object {
|
||||
"offset": 0,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`/admin/batch-jobs POST /admin/batch-jobs/ Creates a batch job 1`] = `
|
||||
Object {
|
||||
"canceled_at": null,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {
|
||||
"list_config": Object {
|
||||
"order": Object {
|
||||
"created_at": "DESC",
|
||||
},
|
||||
"relations": Array [
|
||||
"variants",
|
||||
"variants.prices",
|
||||
"variants.options",
|
||||
"images",
|
||||
"options",
|
||||
"tags",
|
||||
"type",
|
||||
"collection",
|
||||
"variants.prices.region",
|
||||
],
|
||||
"skip": 0,
|
||||
"take": 50,
|
||||
},
|
||||
},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": Any<String>,
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "created",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`/admin/batch-jobs POST /admin/batch-jobs/:id/cancel Cancels batch job created by the user 1`] = `
|
||||
Object {
|
||||
"canceled_at": Any<String>,
|
||||
"completed_at": null,
|
||||
"confirmed_at": null,
|
||||
"context": Object {},
|
||||
"created_at": Any<String>,
|
||||
"created_by": "admin_user",
|
||||
"deleted_at": null,
|
||||
"dry_run": false,
|
||||
"failed_at": null,
|
||||
"id": "job_1",
|
||||
"pre_processed_at": null,
|
||||
"processing_at": null,
|
||||
"result": null,
|
||||
"status": "canceled",
|
||||
"type": "product-export",
|
||||
"updated_at": Any<String>,
|
||||
}
|
||||
`;
|
||||
@@ -5,6 +5,8 @@ const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const userSeeder = require("../../helpers/user-seeder")
|
||||
|
||||
const { simpleBatchJobFactory } = require("../../factories")
|
||||
|
||||
jest.setTimeout(50000)
|
||||
@@ -15,14 +17,53 @@ const adminReqConfig = {
|
||||
},
|
||||
}
|
||||
|
||||
describe("/admin/batch", () => {
|
||||
const setupJobDb = async (dbConnection) => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await userSeeder(dbConnection)
|
||||
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_1",
|
||||
type: "product-export",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_2",
|
||||
type: "product-export",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_3",
|
||||
type: "product-export",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_4",
|
||||
type: "product-export",
|
||||
status: "awaiting_confirmation",
|
||||
created_by: "member-user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_5",
|
||||
type: "product-export",
|
||||
status: "completed",
|
||||
completed_at: "2022-06-27T22:00:00.000Z",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
describe("/admin/batch-jobs", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd, verbose: false })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -32,34 +73,9 @@ describe("/admin/batch", () => {
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/batch", () => {
|
||||
describe("GET /admin/batch-jobs", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_1",
|
||||
type: "batch_1",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_2",
|
||||
type: "batch_2",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_3",
|
||||
type: "batch_2",
|
||||
created_by: "admin_user",
|
||||
})
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_4",
|
||||
type: "batch_1",
|
||||
created_by: "not_this_user",
|
||||
})
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
await setupJobDb(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -69,26 +85,243 @@ describe("/admin/batch", () => {
|
||||
|
||||
it("lists batch jobs created by the user", async () => {
|
||||
const api = useApi()
|
||||
const response = await api.get("/admin/batch", adminReqConfig)
|
||||
const response = await api.get("/admin/batch-jobs", adminReqConfig)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.batch_jobs.length).toEqual(4)
|
||||
expect(response.data).toMatchSnapshot({
|
||||
batch_jobs: [
|
||||
{
|
||||
id: "job_5",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
{
|
||||
id: "job_3",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
{
|
||||
id: "job_2",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
{
|
||||
id: "job_1",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it("lists batch jobs created by the user and where completed_at is null ", async () => {
|
||||
const api = useApi()
|
||||
const response = await api.get(
|
||||
"/admin/batch-jobs?completed_at=null",
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.batch_jobs.length).toEqual(3)
|
||||
expect(response.data).toMatchSnapshot({
|
||||
batch_jobs: [
|
||||
{
|
||||
id: "job_3",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
{
|
||||
id: "job_2",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
{
|
||||
id: "job_1",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /admin/batch-jobs/:id", () => {
|
||||
beforeEach(async () => {
|
||||
await setupJobDb(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("return batch job created by the user", async () => {
|
||||
const api = useApi()
|
||||
const response = await api.get("/admin/batch-jobs/job_1", adminReqConfig)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.batch_job).toEqual(
|
||||
expect.objectContaining({
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
created_by: "admin_user",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail on batch job created by other user", async () => {
|
||||
const api = useApi()
|
||||
await api.get("/admin/batch-jobs/job_4", adminReqConfig).catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.type).toEqual("not_allowed")
|
||||
expect(err.response.data.message).toEqual(
|
||||
"Cannot access a batch job that does not belong to the logged in user"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/batch-jobs/", () => {
|
||||
beforeEach(async () => {
|
||||
await setupJobDb(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("Creates a batch job", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
{
|
||||
type: "product-export",
|
||||
context: {},
|
||||
},
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(201)
|
||||
expect(response.data.batch_job).toMatchSnapshot({
|
||||
created_by: "admin_user",
|
||||
status: "created",
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/batch-jobs/:id/confirm", () => {
|
||||
beforeEach(async () => {
|
||||
await setupJobDb(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("Fails to confirm a batch job created by a different user", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const jobId = "job_4"
|
||||
|
||||
api
|
||||
.post(`/admin/batch-jobs/${jobId}/confirm`, {}, adminReqConfig)
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.type).toEqual("not_allowed")
|
||||
expect(err.response.data.message).toEqual(
|
||||
"Cannot access a batch job that does not belong to the logged in user"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/batch-jobs/:id/cancel", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await setupJobDb(dbConnection)
|
||||
await simpleBatchJobFactory(dbConnection, {
|
||||
id: "job_complete",
|
||||
type: "product-export",
|
||||
created_by: "admin_user",
|
||||
completed_at: new Date(),
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("Cancels batch job created by the user", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const jobId = "job_1"
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/batch-jobs/${jobId}/cancel`,
|
||||
{},
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.batch_job).toMatchSnapshot({
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
canceled_at: expect.any(String),
|
||||
status: "canceled",
|
||||
})
|
||||
})
|
||||
|
||||
it("Fails to cancel a batch job created by a different user", async () => {
|
||||
expect.assertions(3)
|
||||
const api = useApi()
|
||||
|
||||
const jobId = "job_4"
|
||||
|
||||
api
|
||||
.post(`/admin/batch-jobs/${jobId}/cancel`, {}, adminReqConfig)
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.type).toEqual("not_allowed")
|
||||
expect(err.response.data.message).toEqual(
|
||||
"Cannot access a batch job that does not belong to the logged in user"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("Fails to cancel a batch job that is already complete", async () => {
|
||||
expect.assertions(3)
|
||||
const api = useApi()
|
||||
|
||||
const jobId = "job_complete"
|
||||
|
||||
await api
|
||||
.post(`/admin/batch-jobs/${jobId}/cancel`, {}, adminReqConfig)
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.type).toEqual("not_allowed")
|
||||
expect(err.response.data.message).toEqual(
|
||||
"Cannot cancel completed batch job"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,251 @@
|
||||
const path = require("path")
|
||||
const fs = require("fs/promises")
|
||||
import { sep, resolve } from "path"
|
||||
|
||||
const setupServer = require("../../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../../helpers/admin-seeder")
|
||||
const userSeeder = require("../../../helpers/user-seeder")
|
||||
const orderSeeder = require("../../../helpers/order-seeder")
|
||||
|
||||
const adminReqConfig = {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
describe("Batchjob with type order-export", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
let exportFilePath = ""
|
||||
let topDir = ""
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({
|
||||
cwd,
|
||||
redisUrl: "redis://127.0.0.1:6379",
|
||||
uploadDir: __dirname,
|
||||
verbose: false,
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (topDir !== "") {
|
||||
await fs.rm(resolve(__dirname, topDir), { recursive: true })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await userSeeder(dbConnection)
|
||||
await orderSeeder(dbConnection)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
|
||||
const isFileExists = (await fs.stat(exportFilePath))?.isFile()
|
||||
|
||||
if (isFileExists) {
|
||||
const [, relativeRoot] = exportFilePath.replace(__dirname, "").split(sep)
|
||||
|
||||
if ((await fs.stat(resolve(__dirname, relativeRoot)))?.isDirectory()) {
|
||||
topDir = relativeRoot
|
||||
}
|
||||
|
||||
await fs.unlink(exportFilePath)
|
||||
}
|
||||
})
|
||||
|
||||
it("Should export a file containing all orders", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "order-export",
|
||||
context: {},
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
|
||||
if (shouldContinuePulling) {
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const fileSize = (await fs.stat(exportFilePath)).size
|
||||
expect(batchJob.result?.file_size).toBe(fileSize)
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(6)
|
||||
|
||||
const csvLine = lines[0].split(";")
|
||||
|
||||
expect(csvLine[0]).toBe("discount-order")
|
||||
expect(csvLine[1]).toBe("6")
|
||||
expect(csvLine[14]).toBe("fulfilled")
|
||||
expect(csvLine[15]).toBe("captured")
|
||||
expect(csvLine[16]).toBe("8000")
|
||||
})
|
||||
|
||||
it("Should export a file containing a limited number of orders", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "order-export",
|
||||
context: { batch_size: 3 },
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
|
||||
if (shouldContinuePulling) {
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(3)
|
||||
})
|
||||
|
||||
it("Should export a file with orders from a single customer", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "order-export",
|
||||
context: { filterable_fields: { email: "test@email.com" } },
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
|
||||
if (shouldContinuePulling) {
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(1)
|
||||
|
||||
const csvLine = lines[0].split(";")
|
||||
|
||||
expect(csvLine[0]).toBe("test-order")
|
||||
expect(csvLine[6]).toBe("test@email.com")
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,237 @@
|
||||
const path = require("path")
|
||||
const fs = require("fs/promises")
|
||||
import { sep, resolve } from "path"
|
||||
|
||||
const setupServer = require("../../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../../helpers/admin-seeder")
|
||||
const userSeeder = require("../../../helpers/user-seeder")
|
||||
const productSeeder = require("../../../helpers/product-seeder")
|
||||
|
||||
const adminReqConfig = {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
|
||||
jest.setTimeout(1000000)
|
||||
|
||||
describe("Batch job of product-export type", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
let exportFilePath = ""
|
||||
let topDir = ""
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({
|
||||
cwd,
|
||||
redisUrl: "redis://127.0.0.1:6379",
|
||||
uploadDir: __dirname,
|
||||
verbose: false,
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (topDir !== "") {
|
||||
await fs.rm(resolve(__dirname, topDir), { recursive: true })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await userSeeder(dbConnection)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
|
||||
const isFileExists = (await fs.stat(exportFilePath))?.isFile()
|
||||
|
||||
if (isFileExists) {
|
||||
const [, relativeRoot] = exportFilePath.replace(__dirname, "").split(sep)
|
||||
|
||||
if ((await fs.stat(resolve(__dirname, relativeRoot)))?.isDirectory()) {
|
||||
topDir = relativeRoot
|
||||
}
|
||||
|
||||
await fs.unlink(exportFilePath)
|
||||
}
|
||||
})
|
||||
|
||||
it("should export a csv file containing the expected products", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
|
||||
const productPayload = {
|
||||
title: "Test export product",
|
||||
description: "test-product-description",
|
||||
type: { value: "test-type" },
|
||||
images: ["test-image.png", "test-image-2.png"],
|
||||
collection_id: "test-collection",
|
||||
tags: [{ value: "123" }, { value: "456" }],
|
||||
options: [{ title: "size" }, { title: "color" }],
|
||||
variants: [
|
||||
{
|
||||
title: "Test variant",
|
||||
inventory_quantity: 10,
|
||||
sku: "test-variant-sku-product-export",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "usd",
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "eur",
|
||||
amount: 45,
|
||||
},
|
||||
{
|
||||
currency_code: "dkk",
|
||||
amount: 30,
|
||||
},
|
||||
],
|
||||
options: [{ value: "large" }, { value: "green" }],
|
||||
},
|
||||
],
|
||||
}
|
||||
const createProductRes = await api.post(
|
||||
"/admin/products",
|
||||
productPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const productId = createProductRes.data.product.id
|
||||
const variantId = createProductRes.data.product.variants[0].id
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
filterable_fields: {
|
||||
title: "Test export product",
|
||||
},
|
||||
},
|
||||
}
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const fileSize = (await fs.stat(exportFilePath)).size
|
||||
expect(batchJob.result?.file_size).toBe(fileSize)
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(1)
|
||||
|
||||
const lineColumn = lines[0].split(";")
|
||||
|
||||
expect(lineColumn[0]).toBe(productId)
|
||||
expect(lineColumn[2]).toBe(productPayload.title)
|
||||
expect(lineColumn[4]).toBe(productPayload.description)
|
||||
expect(lineColumn[23]).toBe(variantId)
|
||||
expect(lineColumn[24]).toBe(productPayload.variants[0].title)
|
||||
expect(lineColumn[25]).toBe(productPayload.variants[0].sku)
|
||||
})
|
||||
|
||||
it("should export a csv file containing a limited number of products", async () => {
|
||||
jest.setTimeout(1000000)
|
||||
const api = useApi()
|
||||
|
||||
const batchPayload = {
|
||||
type: "product-export",
|
||||
context: {
|
||||
batch_size: 1,
|
||||
filterable_fields: { collection_id: "test-collection" },
|
||||
order: "created_at",
|
||||
},
|
||||
}
|
||||
|
||||
const batchJobRes = await api.post(
|
||||
"/admin/batch-jobs",
|
||||
batchPayload,
|
||||
adminReqConfig
|
||||
)
|
||||
const batchJobId = batchJobRes.data.batch_job.id
|
||||
|
||||
expect(batchJobId).toBeTruthy()
|
||||
|
||||
// Pull to check the status until it is completed
|
||||
let batchJob
|
||||
let shouldContinuePulling = true
|
||||
while (shouldContinuePulling) {
|
||||
const res = await api.get(
|
||||
`/admin/batch-jobs/${batchJobId}`,
|
||||
adminReqConfig
|
||||
)
|
||||
|
||||
await new Promise((resolve, _) => {
|
||||
setTimeout(resolve, 1000)
|
||||
})
|
||||
|
||||
batchJob = res.data.batch_job
|
||||
shouldContinuePulling = !(
|
||||
batchJob.status === "completed" || batchJob.status === "failed"
|
||||
)
|
||||
}
|
||||
|
||||
expect(batchJob.status).toBe("completed")
|
||||
|
||||
exportFilePath = path.resolve(__dirname, batchJob.result.file_key)
|
||||
const isFileExists = (await fs.stat(exportFilePath)).isFile()
|
||||
|
||||
expect(isFileExists).toBeTruthy()
|
||||
|
||||
const data = (await fs.readFile(exportFilePath)).toString()
|
||||
const [, ...lines] = data.split("\r\n").filter((l) => l)
|
||||
|
||||
expect(lines.length).toBe(4)
|
||||
|
||||
const csvLine = lines[0].split(";")
|
||||
expect(csvLine[0]).toBe("test-product")
|
||||
})
|
||||
})
|
||||
@@ -6,6 +6,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -32,6 +34,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -51,6 +55,7 @@ Object {
|
||||
"product": Any<Object>,
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
@@ -66,7 +71,9 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": 80,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_price_type": "sale",
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -93,6 +100,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": 100,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -137,6 +146,7 @@ Object {
|
||||
"product": Any<Object>,
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
@@ -153,6 +163,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": null,
|
||||
@@ -179,6 +191,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -198,6 +212,7 @@ Object {
|
||||
"product": Any<Object>,
|
||||
"product_id": Any<String>,
|
||||
"sku": null,
|
||||
"tax_rates": null,
|
||||
"title": "test2",
|
||||
"upc": null,
|
||||
"updated_at": Any<String>,
|
||||
@@ -214,7 +229,9 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": 80,
|
||||
"calculated_price_incl_tax": 80,
|
||||
"calculated_price_type": "sale",
|
||||
"calculated_tax": 0,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -241,6 +258,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": 100,
|
||||
"original_price_incl_tax": 100,
|
||||
"original_tax": 0,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -285,6 +304,13 @@ Object {
|
||||
"product": Any<Object>,
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": Array [
|
||||
Object {
|
||||
"code": "default",
|
||||
"name": "default",
|
||||
"rate": 0,
|
||||
},
|
||||
],
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
@@ -301,6 +327,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -327,6 +355,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -346,6 +376,7 @@ Object {
|
||||
"product": Any<Object>,
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
|
||||
@@ -131,6 +131,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
@@ -157,6 +159,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -200,6 +204,7 @@ Object {
|
||||
],
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
@@ -210,6 +215,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean2",
|
||||
@@ -236,6 +243,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -279,6 +288,7 @@ Object {
|
||||
],
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku2",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc2",
|
||||
"updated_at": Any<String>,
|
||||
@@ -289,6 +299,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode 1",
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean1",
|
||||
@@ -315,6 +327,8 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -358,6 +372,7 @@ Object {
|
||||
],
|
||||
"product_id": "test-product",
|
||||
"sku": "test-sku1",
|
||||
"tax_rates": null,
|
||||
"title": "Test variant rank (1)",
|
||||
"upc": "test-upc1",
|
||||
"updated_at": Any<String>,
|
||||
@@ -385,6 +400,8 @@ Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"calculated_price": null,
|
||||
"calculated_price_incl_tax": null,
|
||||
"calculated_tax": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": null,
|
||||
@@ -399,6 +416,8 @@ Object {
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"original_price": null,
|
||||
"original_price_incl_tax": null,
|
||||
"original_tax": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
@@ -417,6 +436,7 @@ Object {
|
||||
],
|
||||
"product_id": Any<String>,
|
||||
"sku": null,
|
||||
"tax_rates": null,
|
||||
"title": "test-variant",
|
||||
"upc": null,
|
||||
"updated_at": Any<String>,
|
||||
|
||||
@@ -58,6 +58,21 @@ describe("/store/customers", () => {
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
})
|
||||
|
||||
it("normalizes email", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/customers", {
|
||||
first_name: "James",
|
||||
last_name: "Bond",
|
||||
email: "James@Bond.com",
|
||||
password: "test",
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
expect(response.data.customer.email).toEqual("james@bond.com")
|
||||
})
|
||||
|
||||
it("responds 422 on duplicate", async () => {
|
||||
const api = useApi()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("/store/variants", () => {
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
medusaProcess = await setupServer({ cwd, verbose: false })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
const path = require("path")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { useDb, initDb } = require("../../../helpers/use-db")
|
||||
const {
|
||||
simpleDiscountFactory,
|
||||
simpleRegionFactory,
|
||||
simpleProductFactory,
|
||||
simpleProductTaxRateFactory,
|
||||
} = require("../../factories")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("Cart Totals Calculations", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("sets correct line item totals for a cart with item of price 100 and tax rate 10", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection)
|
||||
const product = await simpleProductFactory(dbConnection)
|
||||
await simpleProductTaxRateFactory(dbConnection, {
|
||||
product_id: product.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
// create cart
|
||||
const { cart } = await api
|
||||
.post("/store/carts", {
|
||||
region_id: region.id,
|
||||
})
|
||||
.then((res) => res.data)
|
||||
|
||||
// add product to cart
|
||||
const res = await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||
expect(res.data.cart.items[0].tax_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].total).toEqual(110)
|
||||
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].discount_total).toEqual(0)
|
||||
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||
})
|
||||
|
||||
it("sets correct line item totals for a cart with item of price 100; tax rate 10; discount 10", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection)
|
||||
const product = await simpleProductFactory(dbConnection)
|
||||
const discount = await simpleDiscountFactory(dbConnection, {
|
||||
regions: [region.id],
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
})
|
||||
|
||||
await simpleProductTaxRateFactory(dbConnection, {
|
||||
product_id: product.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const { cart } = await api
|
||||
.post("/store/carts", {
|
||||
region_id: region.id,
|
||||
})
|
||||
.then((res) => res.data)
|
||||
|
||||
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
const res = await api.post(`/store/carts/${cart.id}`, {
|
||||
discounts: [
|
||||
{
|
||||
code: discount.code,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||
expect(res.data.cart.items[0].tax_total).toEqual(9)
|
||||
expect(res.data.cart.items[0].total).toEqual(99)
|
||||
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||
})
|
||||
|
||||
it("doesn't include taxes in !automatic_taxes regions", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection, {
|
||||
automatic_taxes: false,
|
||||
})
|
||||
const product = await simpleProductFactory(dbConnection)
|
||||
const discount = await simpleDiscountFactory(dbConnection, {
|
||||
regions: [region.id],
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
})
|
||||
|
||||
await simpleProductTaxRateFactory(dbConnection, {
|
||||
product_id: product.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const { cart } = await api
|
||||
.post("/store/carts", {
|
||||
region_id: region.id,
|
||||
})
|
||||
.then((res) => res.data)
|
||||
|
||||
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
const res = await api.post(`/store/carts/${cart.id}`, {
|
||||
discounts: [
|
||||
{
|
||||
code: discount.code,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||
expect(res.data.cart.items[0].tax_total).toEqual(0)
|
||||
expect(res.data.cart.items[0].total).toEqual(90)
|
||||
expect(res.data.cart.items[0].original_total).toEqual(100)
|
||||
expect(res.data.cart.items[0].original_tax_total).toEqual(0)
|
||||
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||
})
|
||||
|
||||
it("includes taxes in !automatic_taxes regions when forced", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection, {
|
||||
automatic_taxes: false,
|
||||
})
|
||||
const product = await simpleProductFactory(dbConnection)
|
||||
const discount = await simpleDiscountFactory(dbConnection, {
|
||||
regions: [region.id],
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
})
|
||||
|
||||
await simpleProductTaxRateFactory(dbConnection, {
|
||||
product_id: product.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const { cart } = await api
|
||||
.post("/store/carts", {
|
||||
region_id: region.id,
|
||||
})
|
||||
.then((res) => res.data)
|
||||
|
||||
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||
variant_id: product.variants[0].id,
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
await api.post(`/store/carts/${cart.id}`, {
|
||||
discounts: [
|
||||
{
|
||||
code: discount.code,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const res = await api.post(`/store/carts/${cart.id}/taxes`)
|
||||
|
||||
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||
expect(res.data.cart.items[0].tax_total).toEqual(9)
|
||||
expect(res.data.cart.items[0].total).toEqual(99)
|
||||
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,109 @@
|
||||
const path = require("path")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { useDb, initDb } = require("../../../helpers/use-db")
|
||||
const {
|
||||
simpleRegionFactory,
|
||||
simpleProductFactory,
|
||||
simpleShippingTaxRateFactory,
|
||||
simpleShippingOptionFactory,
|
||||
} = require("../../factories")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("Shipping Options Totals Calculations", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("admin gets correct shipping prices", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection, {
|
||||
tax_rate: 25,
|
||||
})
|
||||
const so = await simpleShippingOptionFactory(dbConnection, {
|
||||
region_id: region.id,
|
||||
price: 100,
|
||||
})
|
||||
await simpleShippingTaxRateFactory(dbConnection, {
|
||||
shipping_option_id: so.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const res = await api.get(`/admin/shipping-options`, {
|
||||
headers: {
|
||||
Authorization: `Bearer test_token`,
|
||||
},
|
||||
})
|
||||
|
||||
expect(res.data.shipping_options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: so.id,
|
||||
amount: 100,
|
||||
price_incl_tax: 110,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("gets correct shipping prices", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const region = await simpleRegionFactory(dbConnection, {
|
||||
tax_rate: 25,
|
||||
})
|
||||
const so = await simpleShippingOptionFactory(dbConnection, {
|
||||
region_id: region.id,
|
||||
price: 100,
|
||||
})
|
||||
await simpleShippingTaxRateFactory(dbConnection, {
|
||||
shipping_option_id: so.id,
|
||||
rate: {
|
||||
region_id: region.id,
|
||||
rate: 10,
|
||||
},
|
||||
})
|
||||
|
||||
const res = await api.get(`/store/shipping-options?region_id=${region.id}`)
|
||||
|
||||
expect(res.data.shipping_options).toEqual([
|
||||
expect.objectContaining({
|
||||
id: so.id,
|
||||
amount: 100,
|
||||
price_incl_tax: 110,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./simple-payment-factory"
|
||||
export * from "./simple-batch-job-factory"
|
||||
export * from "./simple-discount-factory"
|
||||
export * from "./simple-order-factory"
|
||||
export * from "./simple-cart-factory"
|
||||
export * from "./simple-region-factory"
|
||||
@@ -13,3 +14,4 @@ export * from "./simple-shipping-option-factory"
|
||||
export * from "./simple-shipping-method-factory"
|
||||
export * from "./simple-product-type-tax-rate-factory"
|
||||
export * from "./simple-price-list-factory"
|
||||
export * from "./simple-batch-job-factory"
|
||||
@@ -7,6 +7,8 @@ export type BatchJobFactoryData = {
|
||||
status?: BatchJobStatus
|
||||
created_by?: string
|
||||
context?: Record<string, unknown>
|
||||
awaiting_confirmation_at?: Date | string
|
||||
completed_at?: Date | string
|
||||
}
|
||||
|
||||
export const simpleBatchJobFactory = async (
|
||||
@@ -15,13 +17,14 @@ export const simpleBatchJobFactory = async (
|
||||
): Promise<BatchJob> => {
|
||||
const manager = connection.manager
|
||||
|
||||
const job = manager.create(BatchJob, {
|
||||
const job = manager.create<BatchJob>(BatchJob, {
|
||||
id: data.id,
|
||||
status: data.status ?? BatchJobStatus.CREATED,
|
||||
completed_at: data.completed_at ?? null,
|
||||
type: data.type ?? "test-job",
|
||||
created_by: data.created_by ?? null,
|
||||
context: data.context ?? {},
|
||||
})
|
||||
|
||||
return await manager.save(job)
|
||||
return await manager.save<BatchJob>(job)
|
||||
}
|
||||
@@ -119,7 +119,15 @@ module.exports = async (connection, data = {}) => {
|
||||
type: "percentage",
|
||||
})
|
||||
|
||||
const d = manager.create(Discount, {
|
||||
await manager.insert(DiscountRule, {
|
||||
id: "free-shipping-rule",
|
||||
description: "Free shipping rule",
|
||||
type: "free_shipping",
|
||||
value: 100,
|
||||
allocation: "total",
|
||||
})
|
||||
|
||||
const testDiscount = manager.create(Discount, {
|
||||
id: "test-discount",
|
||||
code: "TEST",
|
||||
is_dynamic: false,
|
||||
@@ -127,7 +135,15 @@ module.exports = async (connection, data = {}) => {
|
||||
rule_id: "discount_rule_id",
|
||||
})
|
||||
|
||||
d.regions = [
|
||||
const freeShippingDiscount = manager.create(Discount, {
|
||||
id: "free-shipping-discount",
|
||||
code: "free-shipping",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
rule_id: "free-shipping-rule",
|
||||
})
|
||||
|
||||
testDiscount.regions = [
|
||||
{
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
@@ -136,7 +152,17 @@ module.exports = async (connection, data = {}) => {
|
||||
},
|
||||
]
|
||||
|
||||
await manager.save(d)
|
||||
freeShippingDiscount.regions = [
|
||||
{
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
},
|
||||
]
|
||||
|
||||
await manager.save(testDiscount)
|
||||
await manager.save(freeShippingDiscount)
|
||||
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='test-region' WHERE iso_2 = 'us'`
|
||||
|
||||
@@ -50,14 +50,14 @@ module.exports = async (connection, data = {}) => {
|
||||
|
||||
const tag3 = await manager.create(ProductTag, {
|
||||
id: "tag3",
|
||||
value: "123",
|
||||
value: "1235",
|
||||
})
|
||||
|
||||
await manager.save(tag3)
|
||||
|
||||
const tag4 = await manager.create(ProductTag, {
|
||||
id: "tag4",
|
||||
value: "123",
|
||||
value: "1234",
|
||||
})
|
||||
|
||||
await manager.save(tag4)
|
||||
|
||||
@@ -5,10 +5,10 @@ const workerId = parseInt(process.env.JEST_WORKER_ID || "1")
|
||||
module.exports = {
|
||||
plugins: [],
|
||||
projectConfig: {
|
||||
// redis_url: REDIS_URL,
|
||||
redis_url: process.env.REDIS_URL,
|
||||
database_url: `postgres://${DB_USERNAME}:${DB_PASSWORD}@localhost/medusa-integration-${workerId}`,
|
||||
database_type: "postgres",
|
||||
jwt_secret: 'test',
|
||||
cookie_secret: 'test'
|
||||
jwt_secret: "test",
|
||||
cookie_secret: "test",
|
||||
},
|
||||
}
|
||||
@@ -8,16 +8,16 @@
|
||||
"build": "babel src -d dist --extensions \".ts,.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/medusa": "1.3.0-dev-1652704115624",
|
||||
"@medusajs/medusa": "1.3.2-dev-1655728455189",
|
||||
"faker": "^5.5.3",
|
||||
"medusa-interfaces": "1.3.0-dev-1652704115624",
|
||||
"medusa-interfaces": "1.3.0-dev-1655728455189",
|
||||
"typeorm": "^0.2.31"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/node": "^7.12.10",
|
||||
"babel-preset-medusa-package": "1.1.19-dev-1652704115624",
|
||||
"babel-preset-medusa-package": "1.1.19-dev-1655728455189",
|
||||
"jest": "^26.6.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { AbstractFileService } from "@medusajs/medusa"
|
||||
import stream from "stream"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
|
||||
export default class LocalFileService extends AbstractFileService {
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
constructor({}, options) {
|
||||
super({})
|
||||
this.upload_dir_ =
|
||||
process.env.UPLOAD_DIR ?? options.upload_dir ?? "uploads/images"
|
||||
|
||||
if (!fs.existsSync(this.upload_dir_)) {
|
||||
fs.mkdirSync(this.upload_dir_)
|
||||
}
|
||||
}
|
||||
|
||||
async upload(file) {
|
||||
const uploadPath = path.join(
|
||||
this.upload_dir_,
|
||||
path.dirname(file.originalname)
|
||||
)
|
||||
|
||||
if (!fs.existsSync(uploadPath)) {
|
||||
fs.mkdirSync(uploadPath, { recursive: true })
|
||||
}
|
||||
|
||||
const filePath = path.resolve(this.upload_dir_, file.originalname)
|
||||
fs.writeFile(filePath, "", (error) => {
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
return { url: filePath }
|
||||
}
|
||||
|
||||
async delete({ name }) {
|
||||
return new Promise((resolve, _) => {
|
||||
const path = resolve(this.upload_dir_, name)
|
||||
fs.unlink(path, (err) => {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
|
||||
resolve("file unlinked")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async getUploadStreamDescriptor({ name, ext }) {
|
||||
const fileKey = `${name}-${Date.now()}.${ext}`
|
||||
const filePath = path.resolve(this.upload_dir_, fileKey)
|
||||
|
||||
const isFileExists = fs.existsSync(filePath)
|
||||
if (!isFileExists) {
|
||||
await this.upload({ originalname: fileKey })
|
||||
}
|
||||
|
||||
const pass = new stream.PassThrough()
|
||||
pass.pipe(fs.createWriteStream(filePath))
|
||||
|
||||
return {
|
||||
writeStream: pass,
|
||||
promise: Promise.resolve(),
|
||||
url: `${this.upload_dir_}/${fileKey}`,
|
||||
fileKey,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1327,10 +1327,10 @@
|
||||
semver "^7.3.5"
|
||||
tar "^6.1.11"
|
||||
|
||||
"@medusajs/medusa-cli@1.3.0-dev-1652704115624":
|
||||
version "1.3.0-dev-1652704115624"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.3.0-dev-1652704115624.tgz#9841fcc6123cd9c72d544d48316d66cf49ad8dc0"
|
||||
integrity sha512-Lhk6pdvgv4UrLLUY/aYuty3TKfgDlvSUfmG4cTgZXbLehnRSbLelPcX+YKCtiM4d0NYfgF364H7p0NAMuCkBIg==
|
||||
"@medusajs/medusa-cli@1.3.0-dev-1655728455189":
|
||||
version "1.3.0-dev-1655728455189"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.3.0-dev-1655728455189.tgz#1d6bf606fbd96167faf0824d221646f664e06d66"
|
||||
integrity sha512-wMDVBN6X6cG6Ni/0/H5K54Hs3RmYLiGvI81VqWQtisjia0T98Hf8MuhxlJ4kS3ny34r5M7Qjs+KCoiospgzbqA==
|
||||
dependencies:
|
||||
"@babel/polyfill" "^7.8.7"
|
||||
"@babel/runtime" "^7.9.6"
|
||||
@@ -1348,8 +1348,8 @@
|
||||
is-valid-path "^0.1.1"
|
||||
joi-objectid "^3.0.1"
|
||||
meant "^1.0.1"
|
||||
medusa-core-utils "1.1.31-dev-1652704115624"
|
||||
medusa-telemetry "0.0.11-dev-1652704115624"
|
||||
medusa-core-utils "1.1.31-dev-1655728455189"
|
||||
medusa-telemetry "0.0.11-dev-1655728455189"
|
||||
netrc-parser "^3.1.6"
|
||||
open "^8.0.6"
|
||||
ora "^5.4.1"
|
||||
@@ -1363,13 +1363,13 @@
|
||||
winston "^3.3.3"
|
||||
yargs "^15.3.1"
|
||||
|
||||
"@medusajs/medusa@1.3.0-dev-1652704115624":
|
||||
version "1.3.0-dev-1652704115624"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.3.0-dev-1652704115624.tgz#040eede718d0eec6b01b4471e9af8495314c3ff0"
|
||||
integrity sha512-x2Wg7lP5A25NMENqcZoC00O46Y3ojLaSnxa9L6E3u375nYWa99uxyT8ckXhklVqzhM3iBtReb/20H4r2+niwmw==
|
||||
"@medusajs/medusa@1.3.2-dev-1655728455189":
|
||||
version "1.3.2-dev-1655728455189"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.3.2-dev-1655728455189.tgz#c3c189fa7aebf94117349067acc0b0a0bc537a28"
|
||||
integrity sha512-oYMihSFpQKrAru2vRnCU9q6A6j6Zgq0/6153m+vibhrbuvW8NZUJSoRjEEA925c8Yprr4xWwFhYghB0jUjIAPA==
|
||||
dependencies:
|
||||
"@hapi/joi" "^16.1.8"
|
||||
"@medusajs/medusa-cli" "1.3.0-dev-1652704115624"
|
||||
"@medusajs/medusa-cli" "1.3.0-dev-1655728455189"
|
||||
"@types/lodash" "^4.14.168"
|
||||
awilix "^4.2.3"
|
||||
body-parser "^1.19.0"
|
||||
@@ -1392,10 +1392,12 @@
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
jsonwebtoken "^8.5.1"
|
||||
medusa-core-utils "1.1.31-dev-1652704115624"
|
||||
medusa-test-utils "1.1.37-dev-1652704115624"
|
||||
medusa-core-utils "1.1.31-dev-1655728455189"
|
||||
medusa-test-utils "1.1.37-dev-1655728455189"
|
||||
morgan "^1.9.1"
|
||||
multer "^1.4.2"
|
||||
node-schedule "^2.1.0"
|
||||
papaparse "^5.3.2"
|
||||
passport "^0.4.0"
|
||||
passport-http-bearer "^1.0.1"
|
||||
passport-jwt "^4.0.0"
|
||||
@@ -2039,10 +2041,10 @@ babel-preset-jest@^26.6.2:
|
||||
babel-plugin-jest-hoist "^26.6.2"
|
||||
babel-preset-current-node-syntax "^1.0.0"
|
||||
|
||||
babel-preset-medusa-package@1.1.19-dev-1652704115624:
|
||||
version "1.1.19-dev-1652704115624"
|
||||
resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.19-dev-1652704115624.tgz#fa584e39e7c0a1b808af25953f81653252225be7"
|
||||
integrity sha512-Nv8Si592nO+UZmMQuOGCs1pFs5ShIsCKclbqBybahjGZIPPD6bVNaz9dujSaZnlxvA9a3gn4dvuh3H8IRitUug==
|
||||
babel-preset-medusa-package@1.1.19-dev-1655728455189:
|
||||
version "1.1.19-dev-1655728455189"
|
||||
resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.19-dev-1655728455189.tgz#a7884d6869c9ac7adb23c5789d6dc858614381c7"
|
||||
integrity sha512-i8JKgbu59S+WU58tRV5iJtJ9UnJnpOPwEtU9b7WVz9X5LLDeUk6Mmhcb6XvTuYCfdC8bXJ/Hk8NlqETIZw1lPQ==
|
||||
dependencies:
|
||||
"@babel/plugin-proposal-class-properties" "^7.12.1"
|
||||
"@babel/plugin-proposal-decorators" "^7.12.1"
|
||||
@@ -2768,6 +2770,14 @@ cron-parser@^2.13.0:
|
||||
is-nan "^1.3.0"
|
||||
moment-timezone "^0.5.31"
|
||||
|
||||
cron-parser@^3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "http://localhost:4873/cron-parser/-/cron-parser-3.5.0.tgz#b1a9da9514c0310aa7ef99c2f3f1d0f8c235257c"
|
||||
integrity sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==
|
||||
dependencies:
|
||||
is-nan "^1.3.2"
|
||||
luxon "^1.26.0"
|
||||
|
||||
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "http://localhost:4873/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
@@ -4198,7 +4208,7 @@ is-lambda@^1.0.1:
|
||||
resolved "http://localhost:4873/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
|
||||
integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
|
||||
|
||||
is-nan@^1.3.0:
|
||||
is-nan@^1.3.0, is-nan@^1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "http://localhost:4873/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
|
||||
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
|
||||
@@ -5083,6 +5093,11 @@ logform@^2.3.2, logform@^2.4.0:
|
||||
safe-stable-stringify "^2.3.1"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
long-timeout@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "http://localhost:4873/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514"
|
||||
integrity sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==
|
||||
|
||||
lower-case@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "http://localhost:4873/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
||||
@@ -5097,6 +5112,11 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
luxon@^1.26.0:
|
||||
version "1.28.0"
|
||||
resolved "http://localhost:4873/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf"
|
||||
integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==
|
||||
|
||||
make-dir@^2.0.0, make-dir@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "http://localhost:4873/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
||||
@@ -5168,23 +5188,23 @@ media-typer@0.3.0:
|
||||
resolved "http://localhost:4873/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
medusa-core-utils@1.1.31-dev-1652704115624:
|
||||
version "1.1.31-dev-1652704115624"
|
||||
resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.31-dev-1652704115624.tgz#cda24aa1a292a1bd0a770774aae9a970fc7ab963"
|
||||
integrity sha512-evkWva10x6JaHBex5S8Zi9Ae/ZStG858nb18w5ITxbCHWvGYq6/VyLpo4vB7I6wuU3z6kDTMd/yyvsVXv33O2g==
|
||||
medusa-core-utils@1.1.31-dev-1655728455189:
|
||||
version "1.1.31-dev-1655728455189"
|
||||
resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.31-dev-1655728455189.tgz#d1765c3aa5ff294722a44c7f5b90dacb185f03ee"
|
||||
integrity sha512-hsyo22Hp5A18+qA5DhfQRvY5eAM3IpzxuuY/SVk50Pxrf+r3U4aWmL4uX0qGpQeKWv6gOLmPxt+OyJIDUPNrwg==
|
||||
dependencies:
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-interfaces@1.3.0-dev-1652704115624:
|
||||
version "1.3.0-dev-1652704115624"
|
||||
resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.3.0-dev-1652704115624.tgz#02dbbda562f99e7de96e7e6657a6af2a20855e36"
|
||||
integrity sha512-aSm6gYWF0gPHoIswHllB/YrGwkrYRr4ZrBmWh3QSulDYnjmtyBFHKkatrC1pscAEFG/5h4d1LEENUHYrBQ4tQg==
|
||||
medusa-interfaces@1.3.0-dev-1655728455189:
|
||||
version "1.3.0-dev-1655728455189"
|
||||
resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.3.0-dev-1655728455189.tgz#4eaa0dc41671bb24777b3630c8640124c4ca9f24"
|
||||
integrity sha512-lcYVYQUg5ImtXLtR4pHHOqXi1q1kl46Gi9rgjAUWVvldnssVDnGThjgnVCFeCkDz+qMqn7lxTHoZXaDIneadlA==
|
||||
|
||||
medusa-telemetry@0.0.11-dev-1652704115624:
|
||||
version "0.0.11-dev-1652704115624"
|
||||
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.11-dev-1652704115624.tgz#4de0f4a66a9f8bb4f61d8b7c24aa9cbd719039a7"
|
||||
integrity sha512-sfCzUM4mlXpBJVaqAycKAmeEWalzyg18+gUo+As/mxoEUIUR5XtpZ5Bdx484/2GUvRP8OdOYC1uPpbuTZbLXcw==
|
||||
medusa-telemetry@0.0.11-dev-1655728455189:
|
||||
version "0.0.11-dev-1655728455189"
|
||||
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.11-dev-1655728455189.tgz#552ba1e2038641321f152b5ba7df0d88f29c26bf"
|
||||
integrity sha512-MCTDiUg62y2xmRAFeOZHdaKXd2VhVw/9JE8Ewm9IY8QWSkumQOMKVPUAfdgra8EYsp3TD7LixWRlPB2TTn7DKg==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
axios-retry "^3.1.9"
|
||||
@@ -5196,13 +5216,13 @@ medusa-telemetry@0.0.11-dev-1652704115624:
|
||||
remove-trailing-slash "^0.1.1"
|
||||
uuid "^8.3.2"
|
||||
|
||||
medusa-test-utils@1.1.37-dev-1652704115624:
|
||||
version "1.1.37-dev-1652704115624"
|
||||
resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.37-dev-1652704115624.tgz#7118753a4afd1c6ed6f1d1ceb75fdf9bfb65afa3"
|
||||
integrity sha512-OnQEA/1jj4jnQGukMtbcqg2HWlKve0BqzeS8T5O2VDL5zldFG9SXFF3LupC51nh96u97dcKZk5A6JL8oHwonog==
|
||||
medusa-test-utils@1.1.37-dev-1655728455189:
|
||||
version "1.1.37-dev-1655728455189"
|
||||
resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.37-dev-1655728455189.tgz#d6283c0075a69dee988d437f5aedfbba334aa847"
|
||||
integrity sha512-SHkPjpiC6A37Duat9HrWPz+tBbZL50zDEXr/sjDiF0N8cEYNIxVRz2Y2/kbbKegSG3UTcckk5VUtxP17LiQKBw==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-classes" "^7.9.5"
|
||||
medusa-core-utils "1.1.31-dev-1652704115624"
|
||||
medusa-core-utils "1.1.31-dev-1655728455189"
|
||||
randomatic "^3.1.1"
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
@@ -5544,6 +5564,15 @@ node-releases@^2.0.3:
|
||||
resolved "http://localhost:4873/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476"
|
||||
integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==
|
||||
|
||||
node-schedule@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "http://localhost:4873/node-schedule/-/node-schedule-2.1.0.tgz#068ae38d7351c330616f7fe7cdb05036f977cbaf"
|
||||
integrity sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==
|
||||
dependencies:
|
||||
cron-parser "^3.5.0"
|
||||
long-timeout "0.1.1"
|
||||
sorted-array-functions "^1.3.0"
|
||||
|
||||
nopt@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "http://localhost:4873/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||
@@ -5815,6 +5844,11 @@ packet-reader@1.0.0:
|
||||
resolved "http://localhost:4873/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74"
|
||||
integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==
|
||||
|
||||
papaparse@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "http://localhost:4873/papaparse/-/papaparse-5.3.2.tgz#d1abed498a0ee299f103130a6109720404fbd467"
|
||||
integrity sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==
|
||||
|
||||
parse-json@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "http://localhost:4873/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
@@ -6760,6 +6794,11 @@ socks@^2.6.2:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.2.0"
|
||||
|
||||
sorted-array-functions@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "http://localhost:4873/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5"
|
||||
integrity sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==
|
||||
|
||||
source-map-resolve@^0.5.0:
|
||||
version "0.5.3"
|
||||
resolved "http://localhost:4873/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
|
||||
|
||||
+20
-16
@@ -5,26 +5,30 @@ const importFrom = require("import-from")
|
||||
|
||||
module.exports = {
|
||||
bootstrapApp: async ({ cwd } = {}) => {
|
||||
const app = express()
|
||||
try {
|
||||
const app = express()
|
||||
|
||||
const loaders = importFrom(
|
||||
cwd || process.cwd(),
|
||||
"@medusajs/medusa/dist/loaders"
|
||||
).default
|
||||
const loaders = importFrom(
|
||||
cwd || process.cwd(),
|
||||
"@medusajs/medusa/dist/loaders"
|
||||
).default
|
||||
|
||||
const { container, dbConnection } = await loaders({
|
||||
directory: path.resolve(cwd || process.cwd()),
|
||||
expressApp: app,
|
||||
isTest: false,
|
||||
})
|
||||
const { container, dbConnection } = await loaders({
|
||||
directory: path.resolve(cwd || process.cwd()),
|
||||
expressApp: app,
|
||||
isTest: false,
|
||||
})
|
||||
|
||||
const PORT = await getPort()
|
||||
const PORT = await getPort()
|
||||
|
||||
return {
|
||||
container,
|
||||
db: dbConnection,
|
||||
app,
|
||||
port: PORT,
|
||||
return {
|
||||
container,
|
||||
db: dbConnection,
|
||||
app,
|
||||
port: PORT,
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -2,9 +2,15 @@ const path = require("path")
|
||||
const { spawn } = require("child_process")
|
||||
const { setPort } = require("./use-api")
|
||||
|
||||
module.exports = ({ cwd, verbose }) => {
|
||||
module.exports = ({ cwd, redisUrl, uploadDir, verbose, env }) => {
|
||||
const serverPath = path.join(__dirname, "test-server.js")
|
||||
|
||||
// in order to prevent conflicts in redis, use a different db for each worker
|
||||
// same fix as for databases (works with up to 15)
|
||||
// redis dbs are 0-indexed and jest worker ids are indexed from 1
|
||||
const workerId = parseInt(process.env.JEST_WORKER_ID || "1")
|
||||
const redisUrlWithDatabase = `${redisUrl}/${workerId - 1}`
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const medusaProcess = spawn("node", [path.resolve(serverPath)], {
|
||||
cwd,
|
||||
@@ -13,6 +19,9 @@ module.exports = ({ cwd, verbose }) => {
|
||||
NODE_ENV: "development",
|
||||
JWT_SECRET: "test",
|
||||
COOKIE_SECRET: "test",
|
||||
REDIS_URL: redisUrl ? redisUrlWithDatabase : undefined, // If provided, will use a real instance, otherwise a fake instance
|
||||
UPLOAD_DIR: uploadDir, // If provided, will be used for the fake local file service
|
||||
...env,
|
||||
},
|
||||
stdio: verbose
|
||||
? ["inherit", "inherit", "inherit", "ipc"]
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
const setupServer = require("./setup-server")
|
||||
const { initDb } = require("./use-db")
|
||||
|
||||
const startServerWithEnvironment = async ({ cwd, verbose, env }) => {
|
||||
if (env) {
|
||||
Object.entries(env).forEach(([key, value]) => {
|
||||
process.env[key] = value
|
||||
})
|
||||
}
|
||||
|
||||
const dbConnection = await initDb({
|
||||
cwd,
|
||||
})
|
||||
|
||||
Object.entries(env).forEach(([key, value]) => {
|
||||
delete process.env[key]
|
||||
})
|
||||
|
||||
const medusaProcess = await setupServer({
|
||||
cwd,
|
||||
verbose,
|
||||
env,
|
||||
})
|
||||
|
||||
return [medusaProcess, dbConnection]
|
||||
}
|
||||
|
||||
export default startServerWithEnvironment
|
||||
@@ -79,6 +79,19 @@ const instance = DbTestUtil
|
||||
module.exports = {
|
||||
initDb: async function ({ cwd }) {
|
||||
const configPath = path.resolve(path.join(cwd, `medusa-config.js`))
|
||||
const { projectConfig, featureFlags } = require(configPath)
|
||||
|
||||
const featureFlagsLoader = require(path.join(
|
||||
cwd,
|
||||
`node_modules`,
|
||||
`@medusajs`,
|
||||
`medusa`,
|
||||
`dist`,
|
||||
`loaders`,
|
||||
`feature-flags`
|
||||
)).default
|
||||
|
||||
const featureFlagsRouter = featureFlagsLoader({ featureFlags })
|
||||
|
||||
const modelsLoader = require(path.join(
|
||||
cwd,
|
||||
@@ -89,9 +102,9 @@ module.exports = {
|
||||
`loaders`,
|
||||
`models`
|
||||
)).default
|
||||
|
||||
const entities = modelsLoader({}, { register: false })
|
||||
|
||||
const { projectConfig } = require(configPath)
|
||||
if (projectConfig.database_type === "sqlite") {
|
||||
connectionType = "sqlite"
|
||||
const dbConnection = await createConnection({
|
||||
@@ -108,12 +121,48 @@ module.exports = {
|
||||
|
||||
await dbFactory.createFromTemplate(databaseName)
|
||||
|
||||
// get migraitons with enabled featureflags
|
||||
const migrationDir = path.resolve(
|
||||
path.join(
|
||||
cwd,
|
||||
`node_modules`,
|
||||
`@medusajs`,
|
||||
`medusa`,
|
||||
`dist`,
|
||||
`migrations`,
|
||||
`*.js`
|
||||
)
|
||||
)
|
||||
|
||||
const { getEnabledMigrations } = require(path.join(
|
||||
cwd,
|
||||
`node_modules`,
|
||||
`@medusajs`,
|
||||
`medusa`,
|
||||
`dist`,
|
||||
`commands`,
|
||||
`utils`,
|
||||
`get-migrations`
|
||||
))
|
||||
|
||||
const enabledMigrations = await getEnabledMigrations(
|
||||
[migrationDir],
|
||||
(flag) => featureFlagsRouter.isFeatureEnabled(flag)
|
||||
)
|
||||
|
||||
const enabledEntities = entities.filter(
|
||||
(e) => typeof e.isFeatureEnabled === "undefined" || e.isFeatureEnabled()
|
||||
)
|
||||
|
||||
const dbConnection = await createConnection({
|
||||
type: "postgres",
|
||||
url: DB_URL,
|
||||
entities,
|
||||
entities: enabledEntities,
|
||||
migrations: enabledMigrations,
|
||||
})
|
||||
|
||||
await dbConnection.runMigrations()
|
||||
|
||||
instance.setDb(dbConnection)
|
||||
return dbConnection
|
||||
}
|
||||
|
||||
@@ -31,10 +31,28 @@ class DatabaseFactory {
|
||||
`@medusajs`,
|
||||
`medusa`,
|
||||
`dist`,
|
||||
`migrations`
|
||||
`migrations`,
|
||||
`*.js`
|
||||
)
|
||||
)
|
||||
|
||||
const { getEnabledMigrations } = require(path.join(
|
||||
cwd,
|
||||
`node_modules`,
|
||||
`@medusajs`,
|
||||
`medusa`,
|
||||
`dist`,
|
||||
`commands`,
|
||||
`utils`,
|
||||
`get-migrations`
|
||||
))
|
||||
|
||||
// filter migrations to only include those that dont have feature flags
|
||||
const enabledMigrations = await getEnabledMigrations(
|
||||
[migrationDir],
|
||||
(flag) => false
|
||||
)
|
||||
|
||||
await dropDatabase(
|
||||
{
|
||||
databaseName: this.templateDbName,
|
||||
@@ -51,7 +69,7 @@ class DatabaseFactory {
|
||||
type: "postgres",
|
||||
name: "templateConnection",
|
||||
url: `${DB_URL}/${this.templateDbName}`,
|
||||
migrations: [`${migrationDir}/*.js`],
|
||||
migrations: enabledMigrations,
|
||||
})
|
||||
|
||||
await templateDbConnection.runMigrations()
|
||||
@@ -92,7 +110,7 @@ class DatabaseFactory {
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
let connection = await this.getMasterConnection()
|
||||
const connection = await this.getMasterConnection()
|
||||
|
||||
await connection.query(`DROP DATABASE IF EXISTS "${this.templateDbName}";`)
|
||||
await connection.close()
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
seedJson=$(pwd)/$1
|
||||
|
||||
res=$(curl -s 'http://localhost:9000/store/products' | \
|
||||
python3 -c "
|
||||
|
||||
import sys, json;
|
||||
|
||||
loadedProducts = json.load(sys.stdin)['products'];
|
||||
|
||||
seededProducts = json.load(open(\""$seedJson"\"))['products'];
|
||||
|
||||
result = set([product['title'] for product in loadedProducts]) == set([product['title'] for product in seededProducts])
|
||||
|
||||
print(result)
|
||||
")
|
||||
|
||||
if [[ "$res" != "True" ]] ; then
|
||||
echo "Seed failed, products are not equal"
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
status_code=$(curl \
|
||||
-X POST\
|
||||
-H "Content-Type: application/json"\
|
||||
-d '{"email":"'$1'", "password":"'$2'"}'\
|
||||
--write-out %{http_code}\
|
||||
http://localhost:9000/admin/auth)
|
||||
|
||||
if [[ "$status_code" -ne 200 ]] ; then
|
||||
echo "Site status changed to $status_code"
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
for i in {1..6}
|
||||
do
|
||||
echo $i
|
||||
status_code=$(curl \
|
||||
-X GET \
|
||||
--write-out %{http_code} \
|
||||
--silent\
|
||||
--output /dev/null\
|
||||
http://localhost:9000/store/products)
|
||||
|
||||
echo $status_code
|
||||
if [[ "$status_code" -ne 000 ]] ; then
|
||||
echo "exiting"
|
||||
exit 0
|
||||
else
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
echo $status_code
|
||||
|
||||
if [[ "$status_code" = 000 ]] ; then
|
||||
echo "Site status changed to $status_code"
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
+4
-2
@@ -40,7 +40,6 @@
|
||||
"lerna": "^3.22.1",
|
||||
"lint-staged": "^11.2.3",
|
||||
"microbundle": "^0.13.3",
|
||||
"mongoose": "^5.10.15",
|
||||
"pg-god": "^1.0.11",
|
||||
"prettier": "^2.1.1",
|
||||
"resolve-cwd": "^3.0.0",
|
||||
@@ -67,9 +66,12 @@
|
||||
"test:integration:api": "jest --config=integration-tests/jest.config.js --projects=integration-tests/api",
|
||||
"test:integration:plugins": "jest --config=integration-tests/jest.config.js --projects=integration-tests/plugins",
|
||||
"test:fixtures": "jest --config=docs-util/jest.config.js --runInBand",
|
||||
"generate:services": "typedoc --options typedoc.services.js"
|
||||
"generate:services": "typedoc --options typedoc.services.js",
|
||||
"release:snapshot": "changeset publish --no-git-tags --snapshot --tag snapshot"
|
||||
},
|
||||
"dependencies": {
|
||||
"@changesets/changelog-github": "^0.4.5",
|
||||
"@changesets/cli": "^2.23.0",
|
||||
"global": "^4.4.0",
|
||||
"import-from": "^3.0.0",
|
||||
"oas-normalize": "^5.0.1",
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.3.1](https://github.com/medusajs/medusa/compare/@medusajs/medusa-cli@1.3.0...@medusajs/medusa-cli@1.3.1) (2022-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **medusa-cli:** Allow to revert migrations from the CLI ([#1353](https://github.com/medusajs/medusa/issues/1353)) ([012513b](https://github.com/medusajs/medusa/commit/012513b6a1e90169e9e0e53f7a59841a34fbaeb3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.3.0](https://github.com/medusajs/medusa/compare/@medusajs/medusa-cli@1.2.1...@medusajs/medusa-cli@1.3.0) (2022-05-01)
|
||||
|
||||
**Note:** Version bump only for package @medusajs/medusa-cli
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@medusajs/medusa-cli",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"description": "Command Line interface for Medusa Commerce",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
|
||||
@@ -166,11 +166,11 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
})
|
||||
.command({
|
||||
command: `migrations [action]`,
|
||||
desc: `Migrate the database to the most recent version.`,
|
||||
desc: `Manage migrations from the core and your own project`,
|
||||
builder: {
|
||||
action: {
|
||||
demand: true,
|
||||
choices: ["run", "show"],
|
||||
choices: ["run", "revert", "show"],
|
||||
},
|
||||
},
|
||||
handler: handlerP(
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.26](https://github.com/medusajs/medusa/compare/medusa-dev-cli@0.0.24...medusa-dev-cli@0.0.26) (2022-07-05)
|
||||
|
||||
**Note:** Version bump only for package medusa-dev-cli
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.25](https://github.com/medusajs/medusa/compare/medusa-dev-cli@0.0.24...medusa-dev-cli@0.0.25) (2022-07-05)
|
||||
|
||||
**Note:** Version bump only for package medusa-dev-cli
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.24](https://github.com/medusajs/medusa/compare/medusa-dev-cli@0.0.23...medusa-dev-cli@0.0.24) (2021-12-08)
|
||||
|
||||
**Note:** Version bump only for package medusa-dev-cli
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "medusa-dev-cli",
|
||||
"description": "CLI helpers for contributors working on Medusa",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.26",
|
||||
"author": "Sebastian Rindom <skrindom@gmail.com>",
|
||||
"bin": {
|
||||
"medusa-dev": "./dist/index.js"
|
||||
@@ -16,6 +16,7 @@
|
||||
"fs-extra": "^9.0.1",
|
||||
"got": "^11.8.5",
|
||||
"is-absolute": "^1.0.0",
|
||||
"jest": "^25.5.2",
|
||||
"lodash": "^4.17.21",
|
||||
"signal-exit": "^3.0.3",
|
||||
"verdaccio": "^4.10.0",
|
||||
@@ -39,10 +40,10 @@
|
||||
"directory": "packages/medusa-dev-cli"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src --out-dir dist --ignore \"**/__tests__\"",
|
||||
"prepare": "cross-env NODE_ENV=production npm run build",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"watch": "babel -w src --out-dir dist --ignore \"**/__tests__\""
|
||||
"build": "babel src --out-dir dist",
|
||||
"test": "jest",
|
||||
"watch": "babel -w src --out-dir dist"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const Configstore = require(`configstore`);
|
||||
const pkg = require(`../package.json`);
|
||||
const _ = require(`lodash`);
|
||||
const path = require(`path`);
|
||||
const os = require(`os`);
|
||||
const watch = require(`./watch`);
|
||||
const { getVersionInfo } = require(`./utils/version`);
|
||||
const Configstore = require(`configstore`)
|
||||
const pkg = require(`../package.json`)
|
||||
const _ = require(`lodash`)
|
||||
const path = require(`path`)
|
||||
const os = require(`os`)
|
||||
const watch = require(`./watch`)
|
||||
const { getVersionInfo } = require(`./utils/version`)
|
||||
const argv = require(`yargs`)
|
||||
.usage(`Usage: medusa-dev [options]`)
|
||||
.alias(`q`, `quiet`)
|
||||
@@ -19,7 +19,7 @@ const argv = require(`yargs`)
|
||||
.nargs(`p`, 1)
|
||||
.describe(
|
||||
`p`,
|
||||
`Set path to Medusa repository.
|
||||
`Set path to medusa repository.
|
||||
You typically only need to configure this once.`
|
||||
)
|
||||
.nargs(`force-install`, 0)
|
||||
@@ -27,6 +27,11 @@ You typically only need to configure this once.`
|
||||
`force-install`,
|
||||
`Disables copying files into node_modules and forces usage of local npm repository.`
|
||||
)
|
||||
.nargs(`external-registry`, 0)
|
||||
.describe(
|
||||
`external-registry`,
|
||||
`Run 'yarn add' commands without the --registry flag.`
|
||||
)
|
||||
.alias(`C`, `copy-all`)
|
||||
.nargs(`C`, 0)
|
||||
.describe(
|
||||
@@ -39,87 +44,101 @@ You typically only need to configure this once.`
|
||||
.alias(`h`, `help`)
|
||||
.nargs(`v`, 0)
|
||||
.alias(`v`, `version`)
|
||||
.describe(`v`, `Print the currently installed version of Medusa Dev CLI`)
|
||||
.argv;
|
||||
.describe(`v`, `Print the currently installed version of Medusa Dev CLI`).argv
|
||||
|
||||
if (argv.version) {
|
||||
console.log(getVersionInfo());
|
||||
process.exit();
|
||||
console.log(getVersionInfo())
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const conf = new Configstore(pkg.name);
|
||||
const conf = new Configstore(pkg.name)
|
||||
|
||||
const fs = require(`fs-extra`);
|
||||
const fs = require(`fs-extra`)
|
||||
|
||||
let pathToRepo = argv.setPathToRepo;
|
||||
let pathToRepo = argv.setPathToRepo
|
||||
|
||||
if (pathToRepo) {
|
||||
if (pathToRepo.includes(`~`)) {
|
||||
pathToRepo = path.join(os.homedir(), pathToRepo.split(`~`).pop());
|
||||
pathToRepo = path.join(os.homedir(), pathToRepo.split(`~`).pop())
|
||||
}
|
||||
conf.set(`medusa-location`, path.resolve(pathToRepo));
|
||||
process.exit();
|
||||
conf.set(`medusa-location`, path.resolve(pathToRepo))
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const havePackageJsonFile = fs.existsSync(`package.json`);
|
||||
const havePackageJsonFile = fs.existsSync(`package.json`)
|
||||
|
||||
if (!havePackageJsonFile) {
|
||||
console.error(`Current folder must have a package.json file!`);
|
||||
process.exit();
|
||||
console.error(`Current folder must have a package.json file!`)
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const medusaLocation = conf.get(`medusa-location`);
|
||||
const medusaLocation = conf.get(`medusa-location`)
|
||||
|
||||
if (!medusaLocation) {
|
||||
console.error(
|
||||
`
|
||||
You haven't set the path yet to your cloned
|
||||
version of medusa. Do so now by running:
|
||||
|
||||
medusa-dev --set-path-to-repo /path/to/my/cloned/version/medusa
|
||||
`
|
||||
);
|
||||
process.exit();
|
||||
)
|
||||
process.exit()
|
||||
}
|
||||
|
||||
// get list of packages from monorepo
|
||||
const monoRepoPackages = [];
|
||||
const packageNameToPath = new Map()
|
||||
const monoRepoPackages = fs
|
||||
.readdirSync(path.join(medusaLocation, `packages`))
|
||||
.map((dirName) => {
|
||||
try {
|
||||
const localPkg = JSON.parse(
|
||||
fs.readFileSync(
|
||||
path.join(medusaLocation, `packages`, dirName, `package.json`)
|
||||
)
|
||||
)
|
||||
|
||||
const pkgsDirs = fs.readdirSync(path.join(medusaLocation, `packages`));
|
||||
for (const dir of pkgsDirs) {
|
||||
const pack = JSON.parse(
|
||||
fs.readFileSync(path.join(medusaLocation, `packages`, dir, `package.json`))
|
||||
);
|
||||
monoRepoPackages.push(pack.name);
|
||||
}
|
||||
if (localPkg?.name) {
|
||||
packageNameToPath.set(
|
||||
localPkg.name,
|
||||
path.join(medusaLocation, `packages`, dirName)
|
||||
)
|
||||
return localPkg.name
|
||||
}
|
||||
} catch (error) {
|
||||
// fallback to generic one
|
||||
}
|
||||
|
||||
const localPkg = JSON.parse(fs.readFileSync(`package.json`));
|
||||
packageNameToPath.set(
|
||||
dirName,
|
||||
path.join(medusaLocation, `packages`, dirName)
|
||||
)
|
||||
return dirName
|
||||
})
|
||||
|
||||
const localPkg = JSON.parse(fs.readFileSync(`package.json`))
|
||||
// intersect dependencies with monoRepoPackages to get list of packages that are used
|
||||
const localPackages = _.intersection(
|
||||
monoRepoPackages,
|
||||
Object.keys(_.merge({}, localPkg.dependencies, localPkg.devDependencies))
|
||||
);
|
||||
)
|
||||
|
||||
if (!argv.packages && _.isEmpty(localPackages)) {
|
||||
console.error(
|
||||
`
|
||||
You haven't got any medusa dependencies into your current package.json
|
||||
|
||||
You probably want to pass in a list of packages to start
|
||||
developing on! For example:
|
||||
|
||||
medusa-dev --packages @medusajs/medusa
|
||||
|
||||
medusa-dev --packages medusa medusa-js
|
||||
If you prefer to place them in your package.json dependencies instead,
|
||||
medusa-dev will pick them up.
|
||||
`
|
||||
);
|
||||
)
|
||||
if (!argv.forceInstall) {
|
||||
process.exit();
|
||||
process.exit()
|
||||
} else {
|
||||
console.log(
|
||||
`Continuing other dependencies installation due to "--forceInstall" flag`
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,4 +148,6 @@ watch(medusaLocation, argv.packages, {
|
||||
scanOnce: argv.scanOnce,
|
||||
forceInstall: argv.forceInstall,
|
||||
monoRepoPackages,
|
||||
});
|
||||
packageNameToPath,
|
||||
externalRegistry: argv.externalRegistry,
|
||||
})
|
||||
@@ -1,23 +1,23 @@
|
||||
const startVerdaccio = require(`verdaccio`).default;
|
||||
const startVerdaccio = require(`verdaccio`).default
|
||||
|
||||
const fs = require(`fs-extra`);
|
||||
const _ = require(`lodash`);
|
||||
const fs = require(`fs-extra`)
|
||||
const _ = require(`lodash`)
|
||||
|
||||
let VerdaccioInitPromise = null;
|
||||
let VerdaccioInitPromise = null
|
||||
|
||||
const { verdaccioConfig } = require(`./verdaccio-config`);
|
||||
const { publishPackage } = require(`./publish-package`);
|
||||
const { installPackages } = require(`./install-packages`);
|
||||
const { verdaccioConfig } = require(`./verdaccio-config`)
|
||||
const { publishPackage } = require(`./publish-package`)
|
||||
const { installPackages } = require(`./install-packages`)
|
||||
|
||||
const startServer = () => {
|
||||
if (VerdaccioInitPromise) {
|
||||
return VerdaccioInitPromise;
|
||||
return VerdaccioInitPromise
|
||||
}
|
||||
|
||||
console.log(`Starting local verdaccio server`);
|
||||
console.log(`Starting local verdaccio server`)
|
||||
|
||||
// clear storage
|
||||
fs.removeSync(verdaccioConfig.storage);
|
||||
fs.removeSync(verdaccioConfig.storage)
|
||||
|
||||
VerdaccioInitPromise = new Promise((resolve) => {
|
||||
startVerdaccio(
|
||||
@@ -29,47 +29,49 @@ const startServer = () => {
|
||||
(webServer, addr, pkgName, pkgVersion) => {
|
||||
// console.log(webServer)
|
||||
webServer.listen(addr.port || addr.path, addr.host, () => {
|
||||
console.log(`Started local verdaccio server`);
|
||||
console.log(`Started local verdaccio server`)
|
||||
|
||||
resolve();
|
||||
});
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
return VerdaccioInitPromise;
|
||||
};
|
||||
return VerdaccioInitPromise
|
||||
}
|
||||
|
||||
exports.startVerdaccio = startServer;
|
||||
exports.startVerdaccio = startServer
|
||||
|
||||
exports.publishPackagesLocallyAndInstall = async ({
|
||||
packagesToPublish,
|
||||
localPackages,
|
||||
root,
|
||||
packageNameToPath,
|
||||
ignorePackageJSONChanges,
|
||||
yarnWorkspaceRoot,
|
||||
externalRegistry,
|
||||
}) => {
|
||||
await startServer();
|
||||
await startServer()
|
||||
|
||||
const versionPostFix = Date.now();
|
||||
const versionPostFix = Date.now()
|
||||
|
||||
const newlyPublishedPackageVersions = {};
|
||||
const newlyPublishedPackageVersions = {}
|
||||
|
||||
for (const packageName of packagesToPublish) {
|
||||
newlyPublishedPackageVersions[packageName] = await publishPackage({
|
||||
packageName,
|
||||
packagesToPublish,
|
||||
root,
|
||||
packageNameToPath,
|
||||
versionPostFix,
|
||||
ignorePackageJSONChanges,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const packagesToInstall = _.intersection(packagesToPublish, localPackages);
|
||||
const packagesToInstall = _.intersection(packagesToPublish, localPackages)
|
||||
|
||||
await installPackages({
|
||||
packagesToInstall,
|
||||
yarnWorkspaceRoot,
|
||||
newlyPublishedPackageVersions,
|
||||
});
|
||||
};
|
||||
externalRegistry,
|
||||
})
|
||||
}
|
||||
@@ -8,10 +8,11 @@ const installPackages = async ({
|
||||
packagesToInstall,
|
||||
yarnWorkspaceRoot,
|
||||
newlyPublishedPackageVersions,
|
||||
externalRegistry,
|
||||
}) => {
|
||||
console.log(
|
||||
`Installing packages from local registry:\n${packagesToInstall
|
||||
.map(packageAndVersion => ` - ${packageAndVersion}`)
|
||||
.map((packageAndVersion) => ` - ${packageAndVersion}`)
|
||||
.join(`\n`)}`
|
||||
)
|
||||
let installCmd
|
||||
@@ -80,22 +81,22 @@ const installPackages = async ({
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const handleDeps = deps => {
|
||||
const handleDeps = (deps) => {
|
||||
if (!deps) {
|
||||
return false
|
||||
}
|
||||
|
||||
let changed = false
|
||||
Object.keys(deps).forEach(depName => {
|
||||
Object.keys(deps).forEach((depName) => {
|
||||
if (packagesToInstall.includes(depName)) {
|
||||
deps[depName] = `gatsby-dev`
|
||||
deps[depName] = `medusa-dev`
|
||||
changed = true
|
||||
}
|
||||
})
|
||||
return changed
|
||||
}
|
||||
|
||||
Object.keys(workspacesLayout).forEach(workspaceName => {
|
||||
Object.keys(workspacesLayout).forEach((workspaceName) => {
|
||||
const { location } = workspacesLayout[workspaceName]
|
||||
const pkgJsonPath = path.join(yarnWorkspaceRoot, location, `package.json`)
|
||||
if (!fs.existsSync(pkgJsonPath)) {
|
||||
@@ -109,7 +110,7 @@ const installPackages = async ({
|
||||
changed |= handleDeps(pkg.peerDependencies)
|
||||
|
||||
if (changed) {
|
||||
console.log(`Changing deps in ${pkgJsonPath} to use @gatsby-dev`)
|
||||
console.log(`Changing deps in ${pkgJsonPath} to use @medusa-dev`)
|
||||
fs.outputJSONSync(pkgJsonPath, pkg, {
|
||||
spaces: 2,
|
||||
})
|
||||
@@ -118,24 +119,28 @@ const installPackages = async ({
|
||||
|
||||
// package.json files are changed - so we just want to install
|
||||
// using verdaccio registry
|
||||
installCmd = [
|
||||
`yarn`,
|
||||
[`install`, `--registry=${registryUrl}`, `--ignore-engines`],
|
||||
]
|
||||
const yarnCommands = [`install`]
|
||||
|
||||
if (!externalRegistry) {
|
||||
yarnCommands.push(`--registry=${registryUrl}`)
|
||||
}
|
||||
|
||||
installCmd = [`yarn`, yarnCommands]
|
||||
} else {
|
||||
installCmd = [
|
||||
`yarn`,
|
||||
[
|
||||
`add`,
|
||||
...packagesToInstall.map(packageName => {
|
||||
const packageVersion = newlyPublishedPackageVersions[packageName]
|
||||
return `${packageName}@${packageVersion}`
|
||||
}),
|
||||
`--registry=${registryUrl}`,
|
||||
`--exact`,
|
||||
`--ignore-engines`,
|
||||
],
|
||||
const yarnCommands = [
|
||||
`add`,
|
||||
...packagesToInstall.map((packageName) => {
|
||||
const packageVersion = newlyPublishedPackageVersions[packageName]
|
||||
return `${packageName}@${packageVersion}`
|
||||
}),
|
||||
`--exact`,
|
||||
]
|
||||
|
||||
if (!externalRegistry) {
|
||||
yarnCommands.push(`--registry=${registryUrl}`)
|
||||
}
|
||||
|
||||
installCmd = [`yarn`, yarnCommands]
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
const fs = require(`fs-extra`);
|
||||
const path = require(`path`);
|
||||
const fs = require(`fs-extra`)
|
||||
const path = require(`path`)
|
||||
|
||||
const { promisifiedSpawn } = require(`../utils/promisified-spawn`);
|
||||
const { registryUrl } = require(`./verdaccio-config`);
|
||||
const { promisifiedSpawn } = require(`../utils/promisified-spawn`)
|
||||
const { registryUrl } = require(`./verdaccio-config`)
|
||||
|
||||
const NPMRCContent = `${registryUrl.replace(
|
||||
/https?:/g,
|
||||
``
|
||||
)}/:_authToken="medusa-dev"`;
|
||||
)}/:_authToken="medusa-dev"`
|
||||
|
||||
const {
|
||||
getMonorepoPackageJsonPath,
|
||||
} = require(`../utils/get-monorepo-package-json-path`);
|
||||
const { registerCleanupTask } = require(`./cleanup-tasks`);
|
||||
} = require(`../utils/get-monorepo-package-json-path`)
|
||||
const { registerCleanupTask } = require(`./cleanup-tasks`)
|
||||
|
||||
/**
|
||||
* Edit package.json to:
|
||||
@@ -27,7 +27,7 @@ const adjustPackageJson = ({
|
||||
versionPostFix,
|
||||
packagesToPublish,
|
||||
ignorePackageJSONChanges,
|
||||
root,
|
||||
packageNameToPath,
|
||||
}) => {
|
||||
// we need to check if package depend on any other package to will be published and
|
||||
// adjust version selector to point to dev version of package so local registry is used
|
||||
@@ -36,10 +36,10 @@ const adjustPackageJson = ({
|
||||
const monorepoPKGjsonString = fs.readFileSync(
|
||||
monoRepoPackageJsonPath,
|
||||
`utf-8`
|
||||
);
|
||||
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString);
|
||||
)
|
||||
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString)
|
||||
|
||||
monorepoPKGjson.version = `${monorepoPKGjson.version}-dev-${versionPostFix}`;
|
||||
monorepoPKGjson.version = `${monorepoPKGjson.version}-dev-${versionPostFix}`
|
||||
packagesToPublish.forEach((packageThatWillBePublished) => {
|
||||
if (
|
||||
monorepoPKGjson.dependencies &&
|
||||
@@ -49,37 +49,37 @@ const adjustPackageJson = ({
|
||||
fs.readFileSync(
|
||||
getMonorepoPackageJsonPath({
|
||||
packageName: packageThatWillBePublished,
|
||||
root,
|
||||
packageNameToPath,
|
||||
}),
|
||||
`utf-8`
|
||||
)
|
||||
).version;
|
||||
).version
|
||||
|
||||
monorepoPKGjson.dependencies[
|
||||
packageThatWillBePublished
|
||||
] = `${currentVersion}-dev-${versionPostFix}`;
|
||||
] = `${currentVersion}-dev-${versionPostFix}`
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const temporaryMonorepoPKGjsonString = JSON.stringify(monorepoPKGjson);
|
||||
const temporaryMonorepoPKGjsonString = JSON.stringify(monorepoPKGjson)
|
||||
|
||||
const unignorePackageJSONChanges = ignorePackageJSONChanges(packageName, [
|
||||
monorepoPKGjsonString,
|
||||
temporaryMonorepoPKGjsonString,
|
||||
]);
|
||||
])
|
||||
|
||||
// change version and dependency versions
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, temporaryMonorepoPKGjsonString);
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, temporaryMonorepoPKGjsonString)
|
||||
|
||||
return {
|
||||
newPackageVersion: monorepoPKGjson.version,
|
||||
unadjustPackageJson: registerCleanupTask(() => {
|
||||
// restore original package.json
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, monorepoPKGjsonString);
|
||||
unignorePackageJSONChanges();
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, monorepoPKGjsonString)
|
||||
unignorePackageJSONChanges()
|
||||
}),
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymous publishing require dummy .npmrc
|
||||
@@ -88,38 +88,38 @@ const adjustPackageJson = ({
|
||||
* This is not verdaccio restriction.
|
||||
*/
|
||||
const createTemporaryNPMRC = ({ pathToPackage }) => {
|
||||
const NPMRCPath = path.join(pathToPackage, `.npmrc`);
|
||||
fs.outputFileSync(NPMRCPath, NPMRCContent);
|
||||
const NPMRCPath = path.join(pathToPackage, `.npmrc`)
|
||||
fs.outputFileSync(NPMRCPath, NPMRCContent)
|
||||
|
||||
return registerCleanupTask(() => {
|
||||
fs.removeSync(NPMRCPath);
|
||||
});
|
||||
};
|
||||
fs.removeSync(NPMRCPath)
|
||||
})
|
||||
}
|
||||
|
||||
const publishPackage = async ({
|
||||
packageName,
|
||||
packagesToPublish,
|
||||
root,
|
||||
versionPostFix,
|
||||
ignorePackageJSONChanges,
|
||||
packageNameToPath,
|
||||
}) => {
|
||||
const monoRepoPackageJsonPath = getMonorepoPackageJsonPath({
|
||||
packageName,
|
||||
root,
|
||||
});
|
||||
packageNameToPath,
|
||||
})
|
||||
|
||||
const { unadjustPackageJson, newPackageVersion } = adjustPackageJson({
|
||||
monoRepoPackageJsonPath,
|
||||
packageName,
|
||||
root,
|
||||
packageNameToPath,
|
||||
versionPostFix,
|
||||
packagesToPublish,
|
||||
ignorePackageJSONChanges,
|
||||
});
|
||||
})
|
||||
|
||||
const pathToPackage = path.dirname(monoRepoPackageJsonPath);
|
||||
const pathToPackage = path.dirname(monoRepoPackageJsonPath)
|
||||
|
||||
const uncreateTemporaryNPMRC = createTemporaryNPMRC({ pathToPackage });
|
||||
const uncreateTemporaryNPMRC = createTemporaryNPMRC({ pathToPackage })
|
||||
|
||||
// npm publish
|
||||
const publishCmd = [
|
||||
@@ -128,26 +128,26 @@ const publishPackage = async ({
|
||||
{
|
||||
cwd: pathToPackage,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
console.log(
|
||||
`Publishing ${packageName}@${newPackageVersion} to local registry`
|
||||
);
|
||||
)
|
||||
try {
|
||||
await promisifiedSpawn(publishCmd);
|
||||
await promisifiedSpawn(publishCmd)
|
||||
|
||||
console.log(
|
||||
`Published ${packageName}@${newPackageVersion} to local registry`
|
||||
);
|
||||
)
|
||||
} catch (e) {
|
||||
console.error(`Failed to publish ${packageName}@${newPackageVersion}`, e);
|
||||
process.exit(1);
|
||||
console.error(`Failed to publish ${packageName}@${newPackageVersion}`, e)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
uncreateTemporaryNPMRC();
|
||||
unadjustPackageJson();
|
||||
uncreateTemporaryNPMRC()
|
||||
unadjustPackageJson()
|
||||
|
||||
return newPackageVersion;
|
||||
};
|
||||
return newPackageVersion
|
||||
}
|
||||
|
||||
exports.publishPackage = publishPackage;
|
||||
exports.publishPackage = publishPackage
|
||||
@@ -1,5 +1,15 @@
|
||||
const { getDependantPackages } = require(`../get-dependant-packages`)
|
||||
|
||||
function createMockPackageNameToPath(packageNames) {
|
||||
const packageNameToPath = new Map()
|
||||
|
||||
for (const packageName of packageNames) {
|
||||
packageNameToPath.set(packageName, `/test/${packageName}`)
|
||||
}
|
||||
|
||||
return packageNameToPath
|
||||
}
|
||||
|
||||
describe(`getDependantPackages`, () => {
|
||||
it(`handles deep dependency chains`, () => {
|
||||
const packagesToPublish = getDependantPackages({
|
||||
@@ -9,6 +19,13 @@ describe(`getDependantPackages`, () => {
|
||||
"package-a-dep1-dep1": new Set([`package-a-dep1`]),
|
||||
"not-related": new Set([`also-not-related`]),
|
||||
},
|
||||
packageNameToPath: createMockPackageNameToPath([
|
||||
`package-a`,
|
||||
`package-a-dep1`,
|
||||
`package-a-dep1-dep1`,
|
||||
`not-related`,
|
||||
`also-not-related`,
|
||||
]),
|
||||
})
|
||||
|
||||
expect(packagesToPublish).toEqual(
|
||||
@@ -23,6 +40,10 @@ describe(`getDependantPackages`, () => {
|
||||
"package-a": new Set([`package-b`]),
|
||||
"package-b": new Set([`package-a`]),
|
||||
},
|
||||
packageNameToPath: createMockPackageNameToPath([
|
||||
`package-a`,
|
||||
`package-b`,
|
||||
]),
|
||||
})
|
||||
expect(packagesToPublish).toEqual(new Set([`package-a`, `package-b`]))
|
||||
})
|
||||
|
||||
@@ -43,15 +43,25 @@ jest.doMock(
|
||||
|
||||
describe(`traversePackageDeps`, () => {
|
||||
it(`handles deep dependency chains`, () => {
|
||||
const monoRepoPackages = [
|
||||
`package-a`,
|
||||
`package-a-dep1`,
|
||||
`package-a-dep1-dep1`,
|
||||
`package-not-used`,
|
||||
]
|
||||
const packageNameToPath = new Map()
|
||||
for (const packageName of monoRepoPackages) {
|
||||
packageNameToPath.set(
|
||||
packageName,
|
||||
path.join(...`<monorepo-path>/packages/${packageName}`.split(`/`))
|
||||
)
|
||||
}
|
||||
|
||||
const { seenPackages, depTree } = traversePackagesDeps({
|
||||
root: `<monorepo-path>`,
|
||||
packages: [`package-a`, `doesnt-exist`],
|
||||
monoRepoPackages: [
|
||||
`package-a`,
|
||||
`package-a-dep1`,
|
||||
`package-a-dep1-dep1`,
|
||||
`package-not-used`,
|
||||
],
|
||||
monoRepoPackages,
|
||||
packageNameToPath,
|
||||
})
|
||||
|
||||
expect(seenPackages).toEqual([
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const fs = require(`fs-extra`);
|
||||
const _ = require(`lodash`);
|
||||
const fs = require(`fs-extra`)
|
||||
const _ = require(`lodash`)
|
||||
const {
|
||||
getMonorepoPackageJsonPath,
|
||||
} = require(`./get-monorepo-package-json-path`);
|
||||
const got = require(`got`);
|
||||
} = require(`./get-monorepo-package-json-path`)
|
||||
const got = require(`got`)
|
||||
|
||||
function difference(object, base) {
|
||||
function changes(object, base) {
|
||||
@@ -12,11 +12,11 @@ function difference(object, base) {
|
||||
result[key] =
|
||||
_.isObject(value) && _.isObject(base[key])
|
||||
? changes(value, base[key])
|
||||
: value;
|
||||
: value
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
return changes(object, base);
|
||||
return changes(object, base)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,33 +24,33 @@ function difference(object, base) {
|
||||
* It will skip dependencies that are removed in monorepo package.
|
||||
*
|
||||
* If local package is not installed, it will check unpkg.com.
|
||||
* This allow medusa-dev to skip publishing unnecesairly and
|
||||
* This allow gatsby-dev to skip publishing unnecesairly and
|
||||
* let install packages from public npm repository if nothing changed.
|
||||
*/
|
||||
exports.checkDepsChanges = async ({
|
||||
newPath,
|
||||
packageName,
|
||||
monoRepoPackages,
|
||||
root,
|
||||
isInitialScan,
|
||||
ignoredPackageJSON,
|
||||
packageNameToPath,
|
||||
}) => {
|
||||
let localPKGjson;
|
||||
let packageNotInstalled = false;
|
||||
let localPKGjson
|
||||
let packageNotInstalled = false
|
||||
try {
|
||||
localPKGjson = JSON.parse(fs.readFileSync(newPath, `utf-8`));
|
||||
localPKGjson = JSON.parse(fs.readFileSync(newPath, `utf-8`))
|
||||
} catch {
|
||||
packageNotInstalled = true;
|
||||
packageNotInstalled = true
|
||||
// there is no local package - so we still need to install deps
|
||||
// this is nice because devs won't need to do initial package installation - we can handle this.
|
||||
if (!isInitialScan) {
|
||||
console.log(
|
||||
`'${packageName}' doesn't seem to be installed. Restart medusa-dev to publish it`
|
||||
);
|
||||
`'${packageName}' doesn't seem to be installed. Restart gatsby-dev to publish it`
|
||||
)
|
||||
return {
|
||||
didDepsChanged: false,
|
||||
packageNotInstalled,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// if package is not installed, we will do http GET request to
|
||||
@@ -60,37 +60,33 @@ exports.checkDepsChanges = async ({
|
||||
// this allow us to not publish to local repository
|
||||
// and save some time/work
|
||||
try {
|
||||
const response = await got(
|
||||
`https://unpkg.com/${packageName}/package.json`
|
||||
);
|
||||
const version = getPackageVersion(packageName)
|
||||
const url = `https://unpkg.com/${packageName}@${version}/package.json`
|
||||
const response = await got(url)
|
||||
if (response?.statusCode !== 200) {
|
||||
throw new Error(`No response or non 200 code`);
|
||||
throw new Error(`No response or non 200 code for ${url}`)
|
||||
}
|
||||
localPKGjson = JSON.parse(response.body);
|
||||
} catch {
|
||||
localPKGjson = JSON.parse(response.body)
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`'${packageName}' doesn't seem to be installed and is not published on NPM.`
|
||||
);
|
||||
`'${packageName}' doesn't seem to be installed and is not published on NPM. Error: ${e.message}`
|
||||
)
|
||||
return {
|
||||
didDepsChanged: true,
|
||||
packageNotInstalled,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const monoDir = packageName.startsWith("@medusajs")
|
||||
? packageName.split("/")[1]
|
||||
: packageName;
|
||||
|
||||
const monoRepoPackageJsonPath = getMonorepoPackageJsonPath({
|
||||
packageName: monoDir,
|
||||
root,
|
||||
});
|
||||
packageName,
|
||||
packageNameToPath,
|
||||
})
|
||||
const monorepoPKGjsonString = fs.readFileSync(
|
||||
monoRepoPackageJsonPath,
|
||||
`utf-8`
|
||||
);
|
||||
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString);
|
||||
)
|
||||
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString)
|
||||
if (ignoredPackageJSON.has(packageName)) {
|
||||
if (ignoredPackageJSON.get(packageName).includes(monorepoPKGjsonString)) {
|
||||
// we are in middle of publishing and content of package.json is one set during publish process,
|
||||
@@ -98,44 +94,44 @@ exports.checkDepsChanges = async ({
|
||||
return {
|
||||
didDepsChanged: false,
|
||||
packageNotInstalled,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!monorepoPKGjson.dependencies) monorepoPKGjson.dependencies = {};
|
||||
if (!localPKGjson.dependencies) localPKGjson.dependencies = {};
|
||||
if (!monorepoPKGjson.dependencies) monorepoPKGjson.dependencies = {}
|
||||
if (!localPKGjson.dependencies) localPKGjson.dependencies = {}
|
||||
|
||||
const areDepsEqual = _.isEqual(
|
||||
monorepoPKGjson.dependencies,
|
||||
localPKGjson.dependencies
|
||||
);
|
||||
)
|
||||
|
||||
if (!areDepsEqual) {
|
||||
const diff = difference(
|
||||
monorepoPKGjson.dependencies,
|
||||
localPKGjson.dependencies
|
||||
);
|
||||
)
|
||||
|
||||
const diff2 = difference(
|
||||
localPKGjson.dependencies,
|
||||
monorepoPKGjson.dependencies
|
||||
);
|
||||
)
|
||||
|
||||
let needPublishing = false;
|
||||
let isPublishing = false;
|
||||
let needPublishing = false
|
||||
let isPublishing = false
|
||||
const depChangeLog = _.uniq(Object.keys({ ...diff, ...diff2 }))
|
||||
.reduce((acc, key) => {
|
||||
if (monorepoPKGjson.dependencies[key] === `medusa-dev`) {
|
||||
if (monorepoPKGjson.dependencies[key] === `gatsby-dev`) {
|
||||
// if we are in middle of publishing to local repository - ignore
|
||||
isPublishing = true;
|
||||
return acc;
|
||||
isPublishing = true
|
||||
return acc
|
||||
}
|
||||
|
||||
if (localPKGjson.dependencies[key] === `medusa-dev`) {
|
||||
if (localPKGjson.dependencies[key] === `gatsby-dev`) {
|
||||
// monorepo packages will restore version, but after installation
|
||||
// in local site - it will use `medusa-dev` dist tag - we need
|
||||
// in local site - it will use `gatsby-dev` dist tag - we need
|
||||
// to ignore changes that
|
||||
return acc;
|
||||
return acc
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -143,48 +139,55 @@ exports.checkDepsChanges = async ({
|
||||
monorepoPKGjson.dependencies[key]
|
||||
) {
|
||||
// Check only for version changes in packages
|
||||
// that are not from medusa repo.
|
||||
// Changes in medusa packages will be copied over
|
||||
// that are not from gatsby repo.
|
||||
// Changes in gatsby packages will be copied over
|
||||
// from monorepo - and if those contain other dependency
|
||||
// changes - they will be covered
|
||||
if (!monoRepoPackages.includes(key)) {
|
||||
acc.push(
|
||||
` - '${key}' changed version from ${localPKGjson.dependencies[key]} to ${monorepoPKGjson.dependencies[key]}`
|
||||
);
|
||||
needPublishing = true;
|
||||
)
|
||||
needPublishing = true
|
||||
}
|
||||
} else if (monorepoPKGjson.dependencies[key]) {
|
||||
acc.push(
|
||||
` - '${key}@${monorepoPKGjson.dependencies[key]}' was added`
|
||||
);
|
||||
needPublishing = true;
|
||||
acc.push(` - '${key}@${monorepoPKGjson.dependencies[key]}' was added`)
|
||||
needPublishing = true
|
||||
} else {
|
||||
acc.push(` - '${key}@${localPKGjson.dependencies[key]}' was removed`);
|
||||
acc.push(` - '${key}@${localPKGjson.dependencies[key]}' was removed`)
|
||||
// this doesn't need publishing really, so will skip this
|
||||
}
|
||||
return acc;
|
||||
return acc
|
||||
}, [])
|
||||
.join(`\n`);
|
||||
.join(`\n`)
|
||||
|
||||
if (!isPublishing && depChangeLog.length > 0) {
|
||||
console.log(`Dependencies of '${packageName}' changed:\n${depChangeLog}`);
|
||||
console.log(`Dependencies of '${packageName}' changed:\n${depChangeLog}`)
|
||||
if (isInitialScan) {
|
||||
console.log(
|
||||
`Will ${!needPublishing ? `not ` : ``}publish to local npm registry.`
|
||||
);
|
||||
)
|
||||
} else {
|
||||
console.warn(
|
||||
`Installation of dependencies after initial scan is not implemented`
|
||||
);
|
||||
)
|
||||
}
|
||||
return {
|
||||
didDepsChanged: needPublishing,
|
||||
packageNotInstalled,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
didDepsChanged: false,
|
||||
packageNotInstalled,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getPackageVersion(packageName) {
|
||||
const projectPackageJson = JSON.parse(
|
||||
fs.readFileSync(`./package.json`, `utf-8`)
|
||||
)
|
||||
const { dependencies = {}, devDependencies = {} } = projectPackageJson
|
||||
const version = dependencies[packageName] || devDependencies[packageName]
|
||||
return version || `latest`
|
||||
}
|
||||
@@ -1,11 +1,4 @@
|
||||
const path = require(`path`);
|
||||
const path = require(`path`)
|
||||
|
||||
exports.getMonorepoPackageJsonPath = ({ packageName, root }) => {
|
||||
let dirName = packageName;
|
||||
if (packageName.startsWith("@medusajs")) {
|
||||
const [, directory] = packageName.split("/");
|
||||
dirName = directory;
|
||||
}
|
||||
|
||||
return path.join(root, `packages`, dirName, `package.json`);
|
||||
};
|
||||
exports.getMonorepoPackageJsonPath = ({ packageName, packageNameToPath }) =>
|
||||
path.join(packageNameToPath.get(packageName), `package.json`)
|
||||
@@ -1,10 +1,17 @@
|
||||
const _ = require(`lodash`);
|
||||
const path = require(`path`);
|
||||
const _ = require(`lodash`)
|
||||
const path = require(`path`)
|
||||
|
||||
/**
|
||||
* @typedef {Object} TraversePackagesDepsReturn
|
||||
* @property {Object} depTree Lookup table to check dependants for given package.
|
||||
* Used to determine which packages need to be published.
|
||||
* @example
|
||||
* ```
|
||||
* {
|
||||
* "medusa-cli": Set(["medusa"]),
|
||||
* "medusa-telemetry": Set(["medusa", "medusa-cli"]),
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -24,53 +31,58 @@ const path = require(`path`);
|
||||
* @return {TraversePackagesDepsReturn}
|
||||
*/
|
||||
const traversePackagesDeps = ({
|
||||
root,
|
||||
packages,
|
||||
monoRepoPackages,
|
||||
seenPackages = [...packages],
|
||||
depTree = {},
|
||||
packageNameToPath,
|
||||
}) => {
|
||||
packages.forEach((p) => {
|
||||
if (p.startsWith("@medusajs")) {
|
||||
p = p.split("/")[1];
|
||||
}
|
||||
let pkgJson;
|
||||
let pkgJson
|
||||
try {
|
||||
pkgJson = require(path.join(root, `packages`, p, `package.json`));
|
||||
} catch {
|
||||
console.error(`"${p}" package doesn't exist in monorepo.`);
|
||||
const packageRoot = packageNameToPath.get(p)
|
||||
if (packageRoot) {
|
||||
pkgJson = require(path.join(packageRoot, `package.json`))
|
||||
} else {
|
||||
console.error(`"${p}" package doesn't exist in monorepo.`)
|
||||
// remove from seenPackages
|
||||
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p)
|
||||
return
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`"${p}" package doesn't exist in monorepo.`, e)
|
||||
// remove from seenPackages
|
||||
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p);
|
||||
return;
|
||||
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p)
|
||||
return
|
||||
}
|
||||
|
||||
const fromMonoRepo = _.intersection(
|
||||
Object.keys({ ...pkgJson.dependencies }),
|
||||
monoRepoPackages
|
||||
);
|
||||
)
|
||||
|
||||
fromMonoRepo.forEach((pkgName) => {
|
||||
depTree[pkgName] = (depTree[pkgName] || new Set()).add(p);
|
||||
});
|
||||
depTree[pkgName] = (depTree[pkgName] || new Set()).add(p)
|
||||
})
|
||||
|
||||
// only traverse not yet seen packages to avoid infinite loops
|
||||
const newPackages = _.difference(fromMonoRepo, seenPackages);
|
||||
const newPackages = _.difference(fromMonoRepo, seenPackages)
|
||||
|
||||
if (newPackages.length) {
|
||||
newPackages.forEach((depFromMonorepo) => {
|
||||
seenPackages.push(depFromMonorepo);
|
||||
});
|
||||
seenPackages.push(depFromMonorepo)
|
||||
})
|
||||
|
||||
traversePackagesDeps({
|
||||
root,
|
||||
packages: fromMonoRepo,
|
||||
monoRepoPackages,
|
||||
seenPackages,
|
||||
depTree,
|
||||
});
|
||||
packageNameToPath,
|
||||
})
|
||||
}
|
||||
});
|
||||
return { seenPackages, depTree };
|
||||
};
|
||||
})
|
||||
return { seenPackages, depTree }
|
||||
}
|
||||
|
||||
exports.traversePackagesDeps = traversePackagesDeps;
|
||||
exports.traversePackagesDeps = traversePackagesDeps
|
||||
@@ -1,27 +1,27 @@
|
||||
const chokidar = require(`chokidar`);
|
||||
const _ = require(`lodash`);
|
||||
const del = require(`del`);
|
||||
const fs = require(`fs-extra`);
|
||||
const path = require(`path`);
|
||||
const findWorkspaceRoot = require(`find-yarn-workspace-root`);
|
||||
const chokidar = require(`chokidar`)
|
||||
const _ = require(`lodash`)
|
||||
const del = require(`del`)
|
||||
const fs = require(`fs-extra`)
|
||||
const path = require(`path`)
|
||||
const findWorkspaceRoot = require(`find-yarn-workspace-root`)
|
||||
|
||||
const { publishPackagesLocallyAndInstall } = require(`./local-npm-registry`);
|
||||
const { checkDepsChanges } = require(`./utils/check-deps-changes`);
|
||||
const { getDependantPackages } = require(`./utils/get-dependant-packages`);
|
||||
const { publishPackagesLocallyAndInstall } = require(`./local-npm-registry`)
|
||||
const { checkDepsChanges } = require(`./utils/check-deps-changes`)
|
||||
const { getDependantPackages } = require(`./utils/get-dependant-packages`)
|
||||
const {
|
||||
setDefaultSpawnStdio,
|
||||
promisifiedSpawn,
|
||||
} = require(`./utils/promisified-spawn`);
|
||||
const { traversePackagesDeps } = require(`./utils/traverse-package-deps`);
|
||||
} = require(`./utils/promisified-spawn`)
|
||||
const { traversePackagesDeps } = require(`./utils/traverse-package-deps`)
|
||||
|
||||
let numCopied = 0;
|
||||
let numCopied = 0
|
||||
|
||||
const quit = () => {
|
||||
console.log(`Copied ${numCopied} files`);
|
||||
process.exit();
|
||||
};
|
||||
console.log(`Copied ${numCopied} files`)
|
||||
process.exit()
|
||||
}
|
||||
|
||||
const MAX_COPY_RETRIES = 3;
|
||||
const MAX_COPY_RETRIES = 3
|
||||
|
||||
/*
|
||||
* non-existent packages break on('ready')
|
||||
@@ -30,76 +30,89 @@ const MAX_COPY_RETRIES = 3;
|
||||
async function watch(
|
||||
root,
|
||||
packages,
|
||||
{ scanOnce, quiet, forceInstall, monoRepoPackages, localPackages }
|
||||
{
|
||||
scanOnce,
|
||||
quiet,
|
||||
forceInstall,
|
||||
monoRepoPackages,
|
||||
localPackages,
|
||||
packageNameToPath,
|
||||
externalRegistry,
|
||||
}
|
||||
) {
|
||||
setDefaultSpawnStdio(quiet ? `ignore` : `inherit`);
|
||||
setDefaultSpawnStdio(quiet ? `ignore` : `inherit`)
|
||||
// determine if in yarn workspace - if in workspace, force using verdaccio
|
||||
// as current logic of copying files will not work correctly.
|
||||
const yarnWorkspaceRoot = findWorkspaceRoot();
|
||||
const yarnWorkspaceRoot = findWorkspaceRoot()
|
||||
if (yarnWorkspaceRoot && process.env.NODE_ENV !== `test`) {
|
||||
console.log(`Yarn workspace found.`);
|
||||
forceInstall = true;
|
||||
console.log(`Yarn workspace found.`)
|
||||
forceInstall = true
|
||||
}
|
||||
|
||||
let afterPackageInstallation = false;
|
||||
let queuedCopies = [];
|
||||
let afterPackageInstallation = false
|
||||
let queuedCopies = []
|
||||
|
||||
const realCopyPath = (arg) => {
|
||||
const { oldPath, newPath, quiet, resolve, reject, retry = 0 } = arg;
|
||||
const { oldPath, newPath, quiet, resolve, reject, retry = 0 } = arg
|
||||
fs.copy(oldPath, newPath, (err) => {
|
||||
if (err) {
|
||||
if (retry >= MAX_COPY_RETRIES) {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
return;
|
||||
console.error(err)
|
||||
reject(err)
|
||||
return
|
||||
} else {
|
||||
setTimeout(
|
||||
() => realCopyPath({ ...arg, retry: retry + 1 }),
|
||||
500 * Math.pow(2, retry)
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// When the medusa binary is copied over, it is not setup with the executable
|
||||
// permissions that it is given when installed via yarn.
|
||||
// This fixes the issue where after running meduas-dev, running `yarn medusa develop`
|
||||
// This fixes the issue where after running medusa-dev, running `yarn medusa develop`
|
||||
// fails with a permission issue.
|
||||
if (/(bin\/meduas.js|medusa(-cli)?\/cli.js)$/.test(newPath)) {
|
||||
fs.chmodSync(newPath, `0755`);
|
||||
// @fixes https://github.com/medusajs/medusa/issues/18809
|
||||
// Binary files we target:
|
||||
// - medusa/bin/medusa.js
|
||||
// -medusa/cli.js
|
||||
// -medusa-cli/cli.js
|
||||
if (/(bin\/medusa.js|medusa(-cli)?\/cli.js)$/.test(newPath)) {
|
||||
fs.chmodSync(newPath, `0755`)
|
||||
}
|
||||
|
||||
numCopied += 1;
|
||||
numCopied += 1
|
||||
if (!quiet) {
|
||||
console.log(`Copied ${oldPath} to ${newPath}`);
|
||||
console.log(`Copied ${oldPath} to ${newPath}`)
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
const copyPath = (oldPath, newPath, quiet, packageName) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const argObj = { oldPath, newPath, quiet, packageName, resolve, reject };
|
||||
const argObj = { oldPath, newPath, quiet, packageName, resolve, reject }
|
||||
if (afterPackageInstallation) {
|
||||
realCopyPath(argObj);
|
||||
realCopyPath(argObj)
|
||||
} else {
|
||||
queuedCopies.push(argObj);
|
||||
queuedCopies.push(argObj)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const runQueuedCopies = () => {
|
||||
afterPackageInstallation = true;
|
||||
queuedCopies.forEach((argObj) => realCopyPath(argObj));
|
||||
queuedCopies = [];
|
||||
};
|
||||
afterPackageInstallation = true
|
||||
queuedCopies.forEach((argObj) => realCopyPath(argObj))
|
||||
queuedCopies = []
|
||||
}
|
||||
|
||||
const clearJSFilesFromNodeModules = async () => {
|
||||
const packagesToClear = queuedCopies.reduce((acc, { packageName }) => {
|
||||
if (packageName) {
|
||||
acc.add(packageName);
|
||||
acc.add(packageName)
|
||||
}
|
||||
return acc;
|
||||
}, new Set());
|
||||
return acc
|
||||
}, new Set())
|
||||
|
||||
await Promise.all(
|
||||
[...packagesToClear].map(
|
||||
@@ -110,65 +123,64 @@ async function watch(
|
||||
`!node_modules/${packageToClear}/src/**/*.{js,js.map}`,
|
||||
])
|
||||
)
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
// check packages deps and if they depend on other packages from monorepo
|
||||
// add them to packages list
|
||||
const { seenPackages, depTree } = traversePackagesDeps({
|
||||
root,
|
||||
packages: _.uniq(localPackages),
|
||||
monoRepoPackages,
|
||||
});
|
||||
packageNameToPath,
|
||||
})
|
||||
|
||||
const allPackagesToWatch = packages
|
||||
? _.intersection(packages, seenPackages)
|
||||
: seenPackages;
|
||||
: seenPackages
|
||||
|
||||
const ignoredPackageJSON = new Map();
|
||||
const ignoredPackageJSON = new Map()
|
||||
const ignorePackageJSONChanges = (packageName, contentArray) => {
|
||||
ignoredPackageJSON.set(packageName, contentArray);
|
||||
ignoredPackageJSON.set(packageName, contentArray)
|
||||
|
||||
return () => {
|
||||
ignoredPackageJSON.delete(packageName);
|
||||
};
|
||||
};
|
||||
ignoredPackageJSON.delete(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
if (forceInstall) {
|
||||
try {
|
||||
if (allPackagesToWatch.length > 0) {
|
||||
await publishPackagesLocallyAndInstall({
|
||||
packagesToPublish: allPackagesToWatch,
|
||||
root,
|
||||
packageNameToPath,
|
||||
localPackages,
|
||||
ignorePackageJSONChanges,
|
||||
yarnWorkspaceRoot,
|
||||
});
|
||||
externalRegistry,
|
||||
})
|
||||
} else {
|
||||
// run `yarn`
|
||||
const yarnInstallCmd = [`yarn`];
|
||||
const yarnInstallCmd = [`yarn`]
|
||||
|
||||
console.log(`Installing packages from public NPM registry`);
|
||||
await promisifiedSpawn(yarnInstallCmd);
|
||||
console.log(`Installation complete`);
|
||||
console.log(`Installing packages from public NPM registry`)
|
||||
await promisifiedSpawn(yarnInstallCmd)
|
||||
console.log(`Installation complete`)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
process.exit();
|
||||
process.exit()
|
||||
}
|
||||
|
||||
if (allPackagesToWatch.length === 0) {
|
||||
console.error(`There are no packages to watch.`);
|
||||
return;
|
||||
console.error(`There are no packages to watch.`)
|
||||
return
|
||||
}
|
||||
|
||||
const cleanToWatch = allPackagesToWatch.map((pkgName) => {
|
||||
if (pkgName.startsWith(`@medusajs`)) {
|
||||
return pkgName.split("/")[1];
|
||||
}
|
||||
return pkgName;
|
||||
});
|
||||
const allPackagesIgnoringThemesToWatch = allPackagesToWatch.filter(
|
||||
(pkgName) => !pkgName.startsWith(`medusa-theme`)
|
||||
)
|
||||
|
||||
const ignored = [
|
||||
/[/\\]node_modules[/\\]/i,
|
||||
@@ -178,63 +190,70 @@ async function watch(
|
||||
/[/\\]__mocks__[/\\]/i,
|
||||
/\.npmrc/i,
|
||||
].concat(
|
||||
cleanToWatch.map((p) => new RegExp(`${p}[\\/\\\\]src[\\/\\\\]`, `i`))
|
||||
);
|
||||
allPackagesIgnoringThemesToWatch.map(
|
||||
(p) => new RegExp(`${p}[\\/\\\\]src[\\/\\\\]`, `i`)
|
||||
)
|
||||
)
|
||||
const watchers = _.uniq(
|
||||
cleanToWatch
|
||||
.map((p) => path.join(root, `/packages/`, p))
|
||||
allPackagesToWatch
|
||||
.map((p) => path.join(packageNameToPath.get(p)))
|
||||
.filter((p) => fs.existsSync(p))
|
||||
);
|
||||
)
|
||||
|
||||
let allCopies = [];
|
||||
const packagesToPublish = new Set();
|
||||
let isInitialScan = true;
|
||||
let isPublishing = false;
|
||||
let allCopies = []
|
||||
const packagesToPublish = new Set()
|
||||
let isInitialScan = true
|
||||
let isPublishing = false
|
||||
|
||||
const waitFor = new Set();
|
||||
let anyPackageNotInstalled = false;
|
||||
|
||||
const watchEvents = [`change`, `add`];
|
||||
const waitFor = new Set()
|
||||
let anyPackageNotInstalled = false
|
||||
|
||||
const watchEvents = [`change`, `add`]
|
||||
const packagePathMatchingEntries = Array.from(packageNameToPath.entries())
|
||||
chokidar
|
||||
.watch(watchers, {
|
||||
ignored: [(filePath) => _.some(ignored, (reg) => reg.test(filePath))],
|
||||
})
|
||||
.on(`all`, async (event, filePath) => {
|
||||
if (!watchEvents.includes(event)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const [pack] = filePath
|
||||
.split(/packages[/\\]/)
|
||||
.pop()
|
||||
.split(/[/\\]/);
|
||||
// match against paths
|
||||
let packageName
|
||||
|
||||
const sourcePkg = JSON.parse(
|
||||
fs.readFileSync(path.join(root, `/packages/`, pack, `package.json`))
|
||||
);
|
||||
const packageName = sourcePkg.name;
|
||||
for (const [_packageName, packagePath] of packagePathMatchingEntries) {
|
||||
const relativeToThisPackage = path.relative(packagePath, filePath)
|
||||
if (!relativeToThisPackage.startsWith(`..`)) {
|
||||
packageName = _packageName
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const prefix = path.join(root, `/packages/`, pack);
|
||||
if (!packageName) {
|
||||
return
|
||||
}
|
||||
|
||||
const prefix = packageNameToPath.get(packageName)
|
||||
|
||||
// Copy it over local version.
|
||||
// Don't copy over the medusa bin file as that breaks the NPM symlink.
|
||||
if (_.includes(filePath, `dist/medusa-cli.js`)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const relativePackageFile = path.relative(prefix, filePath);
|
||||
const relativePackageFile = path.relative(prefix, filePath)
|
||||
|
||||
const newPath = path.join(
|
||||
`./node_modules/${packageName}`,
|
||||
relativePackageFile
|
||||
);
|
||||
)
|
||||
|
||||
if (relativePackageFile === `package.json`) {
|
||||
// package.json files will change during publish to adjust version of package (and dependencies), so ignore
|
||||
// changes during this process
|
||||
if (isPublishing) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
// Compare dependencies with local version
|
||||
@@ -243,10 +262,10 @@ async function watch(
|
||||
newPath,
|
||||
packageName,
|
||||
monoRepoPackages,
|
||||
root,
|
||||
packageNameToPath,
|
||||
isInitialScan,
|
||||
ignoredPackageJSON,
|
||||
});
|
||||
})
|
||||
|
||||
if (isInitialScan) {
|
||||
// normally checkDepsChanges would be sync,
|
||||
@@ -255,21 +274,19 @@ async function watch(
|
||||
// keep track of it to make sure all of it
|
||||
// finish before installing
|
||||
|
||||
waitFor.add(didDepsChangedPromise);
|
||||
waitFor.add(didDepsChangedPromise)
|
||||
}
|
||||
|
||||
const {
|
||||
didDepsChanged,
|
||||
packageNotInstalled,
|
||||
} = await didDepsChangedPromise;
|
||||
const { didDepsChanged, packageNotInstalled } =
|
||||
await didDepsChangedPromise
|
||||
|
||||
if (packageNotInstalled) {
|
||||
anyPackageNotInstalled = true;
|
||||
anyPackageNotInstalled = true
|
||||
}
|
||||
|
||||
if (didDepsChanged) {
|
||||
if (isInitialScan) {
|
||||
waitFor.delete(didDepsChangedPromise);
|
||||
waitFor.delete(didDepsChangedPromise)
|
||||
// handle dependency change only in initial scan - this is for sure doable to
|
||||
// handle this in watching mode correctly - but for the sake of shipping
|
||||
// this I limit more work/time consuming edge cases.
|
||||
@@ -287,66 +304,67 @@ async function watch(
|
||||
}).forEach((packageToPublish) => {
|
||||
// scheduling publish - we will publish when `ready` is emitted
|
||||
// as we can do single publish then
|
||||
packagesToPublish.add(packageToPublish);
|
||||
});
|
||||
packagesToPublish.add(packageToPublish)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// don't ever copy package.json as this will mess up any future dependency
|
||||
// changes checks
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const localCopies = [copyPath(filePath, newPath, quiet, packageName)];
|
||||
const localCopies = [copyPath(filePath, newPath, quiet, packageName)]
|
||||
|
||||
// If this is from "cache-dir" also copy it into the site's .cache
|
||||
if (_.includes(filePath, `cache-dir`)) {
|
||||
const newCachePath = path.join(
|
||||
`.cache/`,
|
||||
path.relative(path.join(prefix, `cache-dir`), filePath)
|
||||
);
|
||||
localCopies.push(copyPath(filePath, newCachePath, quiet));
|
||||
)
|
||||
localCopies.push(copyPath(filePath, newCachePath, quiet))
|
||||
}
|
||||
|
||||
allCopies = allCopies.concat(localCopies);
|
||||
allCopies = allCopies.concat(localCopies)
|
||||
})
|
||||
.on(`ready`, async () => {
|
||||
// wait for all async work needed to be done
|
||||
// before publishing / installing
|
||||
await Promise.all(Array.from(waitFor));
|
||||
await Promise.all(Array.from(waitFor))
|
||||
|
||||
if (isInitialScan) {
|
||||
isInitialScan = false;
|
||||
isInitialScan = false
|
||||
if (packagesToPublish.size > 0) {
|
||||
isPublishing = true;
|
||||
isPublishing = true
|
||||
await publishPackagesLocallyAndInstall({
|
||||
packagesToPublish: Array.from(packagesToPublish),
|
||||
root,
|
||||
packageNameToPath,
|
||||
localPackages,
|
||||
ignorePackageJSONChanges,
|
||||
});
|
||||
packagesToPublish.clear();
|
||||
isPublishing = false;
|
||||
externalRegistry,
|
||||
})
|
||||
packagesToPublish.clear()
|
||||
isPublishing = false
|
||||
} else if (anyPackageNotInstalled) {
|
||||
// run `yarn`
|
||||
const yarnInstallCmd = [`yarn`];
|
||||
const yarnInstallCmd = [`yarn`]
|
||||
|
||||
console.log(`Installing packages from public NPM registry`);
|
||||
await promisifiedSpawn(yarnInstallCmd);
|
||||
console.log(`Installation complete`);
|
||||
console.log(`Installing packages from public NPM registry`)
|
||||
await promisifiedSpawn(yarnInstallCmd)
|
||||
console.log(`Installation complete`)
|
||||
}
|
||||
|
||||
await clearJSFilesFromNodeModules();
|
||||
runQueuedCopies();
|
||||
await clearJSFilesFromNodeModules()
|
||||
runQueuedCopies()
|
||||
}
|
||||
|
||||
// all files watched, quit once all files are copied if necessary
|
||||
Promise.all(allCopies).then(() => {
|
||||
if (scanOnce) {
|
||||
quit();
|
||||
quit()
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = watch;
|
||||
module.exports = watch
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.0.7](https://github.com/medusajs/medusa/compare/medusa-file-minio@1.0.6...medusa-file-minio@1.0.7) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **medusa-file-spaces,medusa-file-s3,medusa-file-minio:** Add options to super call in file plugins ([#1714](https://github.com/medusajs/medusa/issues/1714)) ([a5f717b](https://github.com/medusajs/medusa/commit/a5f717be5ae1954f3dbf1e7b2edb35d11088a8c8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **medusa:** Delete and download url endpoints ([#1705](https://github.com/medusajs/medusa/issues/1705)) ([cc29b64](https://github.com/medusajs/medusa/commit/cc29b641c9358415b46179371988e7ddc11d2664))
|
||||
* **medusa:** Extend file-service interface + move to core ([#1577](https://github.com/medusajs/medusa/issues/1577)) ([8e42d37](https://github.com/medusajs/medusa/commit/8e42d37e84e80c003b9c0311117ab8a8871aa61b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.0.6](https://github.com/medusajs/medusa/compare/medusa-file-minio@1.0.4...medusa-file-minio@1.0.6) (2022-06-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-file-minio
|
||||
|
||||
@@ -13,4 +13,4 @@ Learn more about how you can use this plugin in the [documentation](https://docs
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
}
|
||||
```
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-file-minio",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"description": "MinIO server file connector for Medusa",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import fs from "fs"
|
||||
import { AbstractFileService } from '@medusajs/medusa'
|
||||
import aws from "aws-sdk"
|
||||
import { FileService } from "medusa-interfaces"
|
||||
import fs from "fs"
|
||||
|
||||
class MinioService extends FileService {
|
||||
class MinioService extends AbstractFileService {
|
||||
|
||||
constructor({}, options) {
|
||||
super()
|
||||
super({}, options)
|
||||
|
||||
this.bucket_ = options.bucket
|
||||
this.accessKeyId_ = options.access_key_id
|
||||
@@ -15,14 +16,14 @@ class MinioService extends FileService {
|
||||
}
|
||||
|
||||
upload(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.setPromisesDependency(null)
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
endpoint: this.endpoint_,
|
||||
s3ForcePathStyle: this.s3ForcePathStyle_,
|
||||
signatureVersion: this.signatureVersion_,
|
||||
})
|
||||
}, true)
|
||||
|
||||
const s3 = new aws.S3()
|
||||
const params = {
|
||||
@@ -46,14 +47,14 @@ class MinioService extends FileService {
|
||||
}
|
||||
|
||||
delete(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.setPromisesDependency(null)
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
endpoint: this.endpoint_,
|
||||
s3ForcePathStyle: this.s3ForcePathStyle_,
|
||||
signatureVersion: this.signatureVersion_,
|
||||
})
|
||||
}, true)
|
||||
|
||||
const s3 = new aws.S3()
|
||||
const params = {
|
||||
@@ -71,6 +72,18 @@ class MinioService extends FileService {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async getUploadStreamDescriptor(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
async getDownloadStream(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
async getPresignedDownloadUrl(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
export default MinioService
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.1.3](https://github.com/medusajs/medusa/compare/medusa-file-s3@1.1.2...medusa-file-s3@1.1.3) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **medusa-file-spaces,medusa-file-s3,medusa-file-minio:** Add options to super call in file plugins ([#1714](https://github.com/medusajs/medusa/issues/1714)) ([a5f717b](https://github.com/medusajs/medusa/commit/a5f717be5ae1954f3dbf1e7b2edb35d11088a8c8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **medusa:** Extend file-service interface + move to core ([#1577](https://github.com/medusajs/medusa/issues/1577)) ([8e42d37](https://github.com/medusajs/medusa/commit/8e42d37e84e80c003b9c0311117ab8a8871aa61b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.2](https://github.com/medusajs/medusa/compare/medusa-file-s3@1.1.0...medusa-file-s3@1.1.2) (2022-06-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-file-s3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-file-s3",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "AWS s3 file connector for Medusa",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import fs from "fs"
|
||||
import aws from "aws-sdk"
|
||||
import { FileService } from "medusa-interfaces"
|
||||
import { AbstractFileService } from '@medusajs/medusa'
|
||||
|
||||
class S3Service extends FileService {
|
||||
class S3Service extends AbstractFileService {
|
||||
constructor({}, options) {
|
||||
super()
|
||||
super({}, options)
|
||||
|
||||
this.bucket_ = options.bucket
|
||||
this.s3Url_ = options.s3_url
|
||||
@@ -15,13 +15,13 @@ class S3Service extends FileService {
|
||||
}
|
||||
|
||||
upload(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.setPromisesDependency(null)
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
}, true)
|
||||
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
@@ -44,13 +44,13 @@ class S3Service extends FileService {
|
||||
}
|
||||
|
||||
delete(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.setPromisesDependency(null)
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
}, true)
|
||||
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
@@ -68,6 +68,18 @@ class S3Service extends FileService {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async getUploadStreamDescriptor(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
async getDownloadStream(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
async getPresignedDownloadUrl(fileData) {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
export default S3Service
|
||||
@@ -3,6 +3,24 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.2.3](https://github.com/medusajs/medusa/compare/medusa-file-spaces@1.2.2...medusa-file-spaces@1.2.3) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **medusa-file-spaces,medusa-file-s3,medusa-file-minio:** Add options to super call in file plugins ([#1714](https://github.com/medusajs/medusa/issues/1714)) ([a5f717b](https://github.com/medusajs/medusa/commit/a5f717be5ae1954f3dbf1e7b2edb35d11088a8c8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **medusa:** Add batch strategy for order exports ([#1603](https://github.com/medusajs/medusa/issues/1603)) ([bf47d1a](https://github.com/medusajs/medusa/commit/bf47d1aecd74f4489667609444a8b09393e894d3))
|
||||
* **medusa:** Extend file-service interface + move to core ([#1577](https://github.com/medusajs/medusa/issues/1577)) ([8e42d37](https://github.com/medusajs/medusa/commit/8e42d37e84e80c003b9c0311117ab8a8871aa61b))
|
||||
* **medusa-file-spaces:** DigitalOcean fileservice streaming ([#1585](https://github.com/medusajs/medusa/issues/1585)) ([abaf10b](https://github.com/medusajs/medusa/commit/abaf10b31d1e9a60710da87cac5c9c869195660d)), closes [#1583](https://github.com/medusajs/medusa/issues/1583) [#1580](https://github.com/medusajs/medusa/issues/1580) [#1582](https://github.com/medusajs/medusa/issues/1582) [#1583](https://github.com/medusajs/medusa/issues/1583) [#1580](https://github.com/medusajs/medusa/issues/1580) [#1582](https://github.com/medusajs/medusa/issues/1582)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.2.2](https://github.com/medusajs/medusa/compare/medusa-file-spaces@1.2.0...medusa-file-spaces@1.2.2) (2022-06-19)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-file-spaces",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Digital Ocean Spaces file connector for Medusa",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import fs from "fs"
|
||||
import { AbstractFileService } from "@medusajs/medusa"
|
||||
import aws from "aws-sdk"
|
||||
import fs from "fs"
|
||||
import { parse } from "path"
|
||||
import { FileService } from "medusa-interfaces"
|
||||
import stream from "stream"
|
||||
|
||||
class DigitalOceanService extends FileService {
|
||||
class DigitalOceanService extends AbstractFileService {
|
||||
constructor({}, options) {
|
||||
super()
|
||||
super({}, options)
|
||||
|
||||
this.bucket_ = options.bucket
|
||||
this.spacesUrl_ = options.spaces_url?.replace(/\/$/, "")
|
||||
@@ -16,18 +17,12 @@ class DigitalOceanService extends FileService {
|
||||
}
|
||||
|
||||
upload(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
this.updateAwsConfig()
|
||||
|
||||
const parsedFilename = parse(file.originalname)
|
||||
const fileKey = `${parsedFilename.name}-${Date.now()}${parsedFilename.ext}`
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
const params = {
|
||||
ACL: "public-read",
|
||||
Bucket: this.bucket_,
|
||||
Body: fs.createReadStream(file.path),
|
||||
@@ -51,16 +46,10 @@ class DigitalOceanService extends FileService {
|
||||
}
|
||||
|
||||
delete(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
this.updateAwsConfig()
|
||||
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
const params = {
|
||||
Bucket: this.bucket_,
|
||||
Key: `${file}`,
|
||||
}
|
||||
@@ -75,6 +64,71 @@ class DigitalOceanService extends FileService {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async getUploadStreamDescriptor(fileData) {
|
||||
this.updateAwsConfig()
|
||||
|
||||
const pass = new stream.PassThrough()
|
||||
|
||||
const fileKey = `${fileData.name}.${fileData.ext}`
|
||||
const params = {
|
||||
ACL: fileData.acl ?? "private",
|
||||
Bucket: this.bucket_,
|
||||
Body: pass,
|
||||
Key: fileKey,
|
||||
}
|
||||
|
||||
const s3 = new aws.S3()
|
||||
return {
|
||||
writeStream: pass,
|
||||
promise: s3.upload(params).promise(),
|
||||
url: `${this.spacesUrl_}/${fileKey}`,
|
||||
fileKey,
|
||||
}
|
||||
}
|
||||
|
||||
async getDownloadStream(fileData) {
|
||||
this.updateAwsConfig()
|
||||
|
||||
const s3 = new aws.S3()
|
||||
|
||||
const params = {
|
||||
Bucket: this.bucket_,
|
||||
Key: `${fileData.fileKey}`,
|
||||
}
|
||||
|
||||
return s3.getObject(params).createReadStream()
|
||||
}
|
||||
|
||||
async getPresignedDownloadUrl(fileData) {
|
||||
this.updateAwsConfig({
|
||||
signatureVersion: "v4",
|
||||
})
|
||||
|
||||
const s3 = new aws.S3()
|
||||
|
||||
const params = {
|
||||
Bucket: this.bucket_,
|
||||
Key: `${fileData.fileKey}`,
|
||||
Expires: 60, // 60 seconds
|
||||
}
|
||||
|
||||
return await s3.getSignedUrlPromise("getObject", params)
|
||||
}
|
||||
|
||||
updateAwsConfig(additionalConfiguration = {}) {
|
||||
aws.config.setPromisesDependency(null)
|
||||
aws.config.update(
|
||||
{
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
...additionalConfiguration,
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default DigitalOceanService
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.3.3](https://github.com/medusajs/medusa/compare/medusa-fulfillment-webshipper@1.3.2...medusa-fulfillment-webshipper@1.3.3) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **webshipper:** allow cancelling WS orders with error status ([#1755](https://github.com/medusajs/medusa/issues/1755)) ([1d3032d](https://github.com/medusajs/medusa/commit/1d3032dc671b477654afd13a218caa772454bde0))
|
||||
* **webshipper:** only add invoices if invoice generator produces a file ([#1749](https://github.com/medusajs/medusa/issues/1749)) ([c0e18d4](https://github.com/medusajs/medusa/commit/c0e18d473c050d143f67ed2c76fa9ec9414daf1a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.3.2](https://github.com/medusajs/medusa/compare/medusa-fulfillment-webshipper@1.3.0...medusa-fulfillment-webshipper@1.3.2) (2022-06-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-fulfillment-webshipper
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# medusa-fulfillment-webshipper
|
||||
|
||||
Adds Webshipper as a fulfilment provider in Medusa Commerce.
|
||||
Adds Webshipper as a fulfilment provider in Medusa Commerce.
|
||||
|
||||
On each new fulfillment an order is created in Webshipper. The plugin listens for shipment events and updated the shipment accordingly.
|
||||
A webhook listener is exposed at `/webshipper/shipments` to listen for shipment creations. You must create this webhook in Webshipper to have Medusa listen for shipment events.
|
||||
@@ -13,4 +13,5 @@ A webhook listener is exposed at `/webshipper/shipments` to listen for shipment
|
||||
order_channel_id: [the channel id to register orders on] (required)
|
||||
webhook_secret: [the webhook secret used to listen for shipments] (required)
|
||||
coo_countries: [an array of countries in which a Certificate of Origin will be attached] (default: "all")
|
||||
delete_on_cancel [determines whether Webshipper orders are deleted when a Medusa fulfillment is canceled] (default: false)
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-fulfillment-webshipper",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3",
|
||||
"description": "Webshipper Fulfillment provider for Medusa",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -18,7 +18,7 @@
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.5",
|
||||
"@babel/runtime": "^7.9.6",
|
||||
"@medusajs/medusa": "^1.3.2",
|
||||
"@medusajs/medusa": "^1.3.3",
|
||||
"client-sessions": "^0.8.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.8.0",
|
||||
|
||||
@@ -287,19 +287,21 @@ class WebshipperFulfillmentService extends FulfillmentService {
|
||||
fulfillmentItems
|
||||
)
|
||||
|
||||
invoice = await this.client_.documents
|
||||
.create({
|
||||
type: "documents",
|
||||
attributes: {
|
||||
document_size: this.options_.document_size || "A4",
|
||||
document_format: "PDF",
|
||||
base64: base64Invoice,
|
||||
document_type: "invoice",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
throw err
|
||||
})
|
||||
if (base64Invoice) {
|
||||
invoice = await this.client_.documents
|
||||
.create({
|
||||
type: "documents",
|
||||
attributes: {
|
||||
document_size: this.options_.document_size || "A4",
|
||||
document_format: "PDF",
|
||||
base64: base64Invoice,
|
||||
document_type: "invoice",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
const cooCountries = this.options_.coo_countries
|
||||
if (
|
||||
@@ -621,19 +623,17 @@ class WebshipperFulfillmentService extends FulfillmentService {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (order) {
|
||||
if (
|
||||
order.data.attributes.status !== "pending" &&
|
||||
order.data.attributes.status !== "missing_rate"
|
||||
) {
|
||||
if (order.data.attributes.status === "cancelled") {
|
||||
return Promise.resolve(order)
|
||||
}
|
||||
throw new Error("Cannot cancel order")
|
||||
}
|
||||
if (this.options_.delete_on_cancel) {
|
||||
return await this.client_.orders.delete(data.id)
|
||||
}
|
||||
|
||||
return this.client_.orders.delete(data.id)
|
||||
return await this.client_.orders.update(data.id, {
|
||||
id: data.id,
|
||||
type: "orders",
|
||||
attributes: {
|
||||
status: "cancelled",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,16 @@ class Webshipper {
|
||||
},
|
||||
}).then(({ data }) => data)
|
||||
},
|
||||
update: async (id, data) => {
|
||||
const path = `/v2/orders/${id}`
|
||||
return this.client_({
|
||||
method: "PATCH",
|
||||
url: path,
|
||||
data: {
|
||||
data,
|
||||
},
|
||||
}).then(({ data }) => data)
|
||||
},
|
||||
delete: async (id) => {
|
||||
const path = `/v2/orders/${id}`
|
||||
return this.client_({
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.3.1](https://github.com/medusajs/medusa/compare/medusa-interfaces@1.3.0...medusa-interfaces@1.3.1) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **medusa:** Remove deps `mongoose` + `mongodb` ([#1218](https://github.com/medusajs/medusa/issues/1218)) ([c76e23e](https://github.com/medusajs/medusa/commit/c76e23e84dd8cb08c3c709f9f95c4c17b9685439))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.3.0](https://github.com/medusajs/medusa/compare/medusa-interfaces@1.2.1...medusa-interfaces@1.3.0) (2022-05-01)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-interfaces",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"description": "Core interfaces for Medusa",
|
||||
"main": "dist/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import mongoose from "mongoose"
|
||||
|
||||
/**
|
||||
* Interface for data models. The default data layer uses an internal mongoose
|
||||
* model and is as such compatible with MongoDB.
|
||||
* @interface
|
||||
*/
|
||||
class BaseModel {
|
||||
constructor() {
|
||||
/** @const the underlying mongoose model used for queries */
|
||||
this.mongooseModel_ = this.createMongooseModel_()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model schema. The child class must implement the static schema
|
||||
* property.
|
||||
* @return {string} the models schema
|
||||
*/
|
||||
getSchema() {
|
||||
if (!this.constructor.schema) {
|
||||
throw new Error("Schema not defined")
|
||||
}
|
||||
return this.constructor.schema
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model name. The child class must implement the static modelName
|
||||
* property.
|
||||
* @return {string} the name of the model
|
||||
*/
|
||||
getModelName() {
|
||||
if (!this.constructor.modelName) {
|
||||
throw new Error("Every model must have a static modelName property")
|
||||
}
|
||||
return this.constructor.modelName
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the schema options defined in child class.
|
||||
* @return {object} the schema options
|
||||
*/
|
||||
getSchemaOptions() {
|
||||
if (!this.constructor.schemaOptions) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return this.constructor.schemaOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates a mongoose model based on schema, schema options and model name.
|
||||
* @return {Mongooose.Model} the mongoose model
|
||||
*/
|
||||
createMongooseModel_() {
|
||||
const schema = this.getSchema()
|
||||
const options = this.getSchemaOptions()
|
||||
|
||||
const mongooseSchema = new mongoose.Schema(schema, options)
|
||||
|
||||
return mongoose.model(this.getModelName(), mongooseSchema)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
startSession() {
|
||||
return this.mongooseModel_.startSession()
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the mongoose model via the mongoose's findOne.
|
||||
* @param query {object} a mongoose selector query
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {?mongoose.Document} the retreived mongoose document or null.
|
||||
*/
|
||||
findOne(query, options = {}) {
|
||||
return this.mongooseModel_.findOne(query, options).lean()
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the mongoose model via the mongoose's find.
|
||||
* @param query {object} a mongoose selector query
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {Array<mongoose.Document>} the retreived mongoose documents or
|
||||
* an empty array
|
||||
*/
|
||||
find(query, options, offset, limit) {
|
||||
return this.mongooseModel_
|
||||
.find(query, options)
|
||||
.skip(offset)
|
||||
.limit(limit)
|
||||
.lean()
|
||||
}
|
||||
|
||||
count() {
|
||||
return this.mongooseModel_.count({})
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a model via the mongoose model's updateOne.
|
||||
* @param query {object} a mongoose selector query
|
||||
* @param update {object} mongoose update object
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {object} mongoose result
|
||||
*/
|
||||
updateOne(query, update, options = {}) {
|
||||
options.new = true
|
||||
return this.mongooseModel_.findOneAndUpdate(query, update, options).lean()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a model via the mongoose model's update.
|
||||
* @param query {object} a mongoose selector query
|
||||
* @param update {object} mongoose update object
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {object} mongoose result
|
||||
*/
|
||||
update(query, update, options) {
|
||||
return this.mongooseModel_.update(query, update, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a document in the mongoose model's collection via create.
|
||||
* @param object {object} the value of the document to be created
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {object} mongoose result
|
||||
*/
|
||||
create(object, options) {
|
||||
return this.mongooseModel_.create(object, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a document in the mongoose model's collection
|
||||
* @param query {object} the value of the document to be created
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {object} mongoose result
|
||||
*/
|
||||
deleteOne(query, options) {
|
||||
return this.mongooseModel_.deleteOne(query, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes many document in the mongoose model's collection
|
||||
* @param query {object} the value of the document to be created
|
||||
* @param options {?object=} mongoose options
|
||||
* @return {object} mongoose result
|
||||
*/
|
||||
delete(query, options) {
|
||||
return this.mongooseModel_.deleteMany(query, options)
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseModel
|
||||
@@ -1,8 +1,7 @@
|
||||
export { default as BaseService } from "./base-service"
|
||||
export { default as BaseModel } from "./base-model"
|
||||
export { default as PaymentService } from "./payment-service"
|
||||
export { default as FulfillmentService } from "./fulfillment-service"
|
||||
export { default as FileService } from "./file-service"
|
||||
export { default as FulfillmentService } from "./fulfillment-service"
|
||||
export { default as NotificationService } from "./notification-service"
|
||||
export { default as OauthService } from "./oauth-service"
|
||||
export { default as PaymentService } from "./payment-service"
|
||||
export { default as SearchService } from "./search-service"
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.2.3](https://github.com/medusajs/medusa/compare/@medusajs/medusa-js@1.2.2...@medusajs/medusa-js@1.2.3) (2022-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **medusa-js:** Fix `stringifyNullProperties` util ([#1766](https://github.com/medusajs/medusa/issues/1766)) ([7bee57f](https://github.com/medusajs/medusa/commit/7bee57f7c55e15b6a6c847dfda433e67f258ef8e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **medusa-js:** Create utils to stringify null values and respect object types ([#1748](https://github.com/medusajs/medusa/issues/1748)) ([fc1cbe7](https://github.com/medusajs/medusa/commit/fc1cbe72c7b0cd2879a8b112a6f63fa94c728a19))
|
||||
* **medusa,medusa-js,medusa-react:** Add BatchJob API support in `medusa-js` + `medusa-react` ([#1704](https://github.com/medusajs/medusa/issues/1704)) ([7302d76](https://github.com/medusajs/medusa/commit/7302d76e12683c989f340d2fcfaf4338dca6554a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.2.2](https://github.com/medusajs/medusa/compare/@medusajs/medusa-js@1.2.0...@medusajs/medusa-js@1.2.2) (2022-06-19)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@medusajs/medusa-js",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Client for Medusa Commerce Rest API",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -15,7 +15,7 @@
|
||||
"author": "Oliver Juhl",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@medusajs/medusa": "^1.3.2",
|
||||
"@medusajs/medusa": "^1.3.3",
|
||||
"axios": "^0.24.0",
|
||||
"form-data": "^4.0.0",
|
||||
"qs": "^6.10.3",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
AdminBatchJobListRes,
|
||||
AdminBatchJobRes,
|
||||
AdminGetBatchParams,
|
||||
AdminPostBatchesReq,
|
||||
} from "@medusajs/medusa"
|
||||
import qs from "qs"
|
||||
import { ResponsePromise } from "../../typings"
|
||||
import BaseResource from "../base"
|
||||
import { stringifyNullProperties } from "../../utils"
|
||||
|
||||
class AdminBatchJobsResource extends BaseResource {
|
||||
create(
|
||||
payload: AdminPostBatchesReq,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminBatchJobRes> {
|
||||
const path = `/admin/batch-jobs`
|
||||
return this.client.request("POST", path, payload, {}, customHeaders)
|
||||
}
|
||||
|
||||
list(
|
||||
query?: AdminGetBatchParams,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminBatchJobListRes> {
|
||||
let path = `/admin/batch-jobs`
|
||||
|
||||
if (query) {
|
||||
const queryString = qs.stringify(stringifyNullProperties(query))
|
||||
path = `/admin/batch-jobs?${queryString}`
|
||||
}
|
||||
|
||||
return this.client.request("GET", path, {}, {}, customHeaders)
|
||||
}
|
||||
|
||||
cancel(
|
||||
batchJobId: string,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminBatchJobRes> {
|
||||
const path = `/admin/batch-jobs/${batchJobId}/cancel`
|
||||
return this.client.request("POST", path, {}, {}, customHeaders)
|
||||
}
|
||||
|
||||
confirm(
|
||||
batchJobId: string,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminBatchJobRes> {
|
||||
const path = `/admin/batch-jobs/${batchJobId}/confirm`
|
||||
return this.client.request("POST", path, {}, {}, customHeaders)
|
||||
}
|
||||
|
||||
retrieve(
|
||||
batchJobId: string,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminBatchJobRes> {
|
||||
const path = `/admin/batch-jobs/${batchJobId}`
|
||||
return this.client.request("GET", path, {}, {}, customHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminBatchJobsResource
|
||||
@@ -1,33 +1,35 @@
|
||||
import BaseResource from "../base"
|
||||
import AdminAuthResource from "./auth"
|
||||
import AdminCustomersResource from "./customers"
|
||||
import AdminCustomerGroupsResource from "./customer-groups"
|
||||
import AdminDiscountsResource from "./discounts"
|
||||
import AdminBatchJobsResource from "./batch-jobs"
|
||||
import CollectionsResource from "./collections"
|
||||
import AdminCustomerGroupsResource from "./customer-groups"
|
||||
import AdminCustomersResource from "./customers"
|
||||
import AdminDiscountsResource from "./discounts"
|
||||
import AdminDraftOrdersResource from "./draft-orders"
|
||||
import AdminGiftCardsResource from "./gift-cards"
|
||||
import AdminInvitesResource from "./invites"
|
||||
import AdminNotesResource from "./notes"
|
||||
import AdminProductsResource from "./products"
|
||||
import AdminProductTypesResource from "./product-types"
|
||||
import AdminUsersResource from "./users"
|
||||
import AdminReturnsResource from "./returns"
|
||||
import AdminNotificationsResource from "./notifications"
|
||||
import AdminOrdersResource from "./orders"
|
||||
import AdminPriceListResource from "./price-lists"
|
||||
import AdminProductTagsResource from "./product-tags"
|
||||
import AdminProductTypesResource from "./product-types"
|
||||
import AdminProductsResource from "./products"
|
||||
import AdminRegionsResource from "./regions"
|
||||
import AdminReturnReasonsResource from "./return-reasons"
|
||||
import AdminVariantsResource from "./variants"
|
||||
import AdminSwapsResource from "./swaps"
|
||||
import AdminTaxRatesResource from "./tax-rates"
|
||||
import AdminReturnsResource from "./returns"
|
||||
import AdminShippingOptionsResource from "./shipping-options"
|
||||
import AdminShippingProfilesResource from "./shipping-profiles"
|
||||
import AdminStoresResource from "./store"
|
||||
import AdminShippingOptionsResource from "./shipping-options"
|
||||
import AdminRegionsResource from "./regions"
|
||||
import AdminNotificationsResource from "./notifications"
|
||||
import AdminSwapsResource from "./swaps"
|
||||
import AdminTaxRatesResource from "./tax-rates"
|
||||
import AdminUploadsResource from "./uploads"
|
||||
import AdminProductTagsResource from "./product-tags"
|
||||
import AdminPriceListResource from "./price-lists"
|
||||
import AdminUsersResource from "./users"
|
||||
import AdminVariantsResource from "./variants"
|
||||
|
||||
class Admin extends BaseResource {
|
||||
public auth = new AdminAuthResource(this.client)
|
||||
public batchJobs = new AdminBatchJobsResource(this.client)
|
||||
public customers = new AdminCustomersResource(this.client)
|
||||
public customerGroups = new AdminCustomerGroupsResource(this.client)
|
||||
public discounts = new AdminDiscountsResource(this.client)
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import { AdminUploadRes, IAdminPostUploadsFile } from "@medusajs/medusa"
|
||||
import {
|
||||
AdminDeleteUploadsReq,
|
||||
IAdminPostUploadsFileReq,
|
||||
AdminDeleteUploadsRes,
|
||||
AdminPostUploadsDownloadUrlReq,
|
||||
AdminUploadsDownloadUrlRes,
|
||||
AdminUploadsRes,
|
||||
} from "@medusajs/medusa"
|
||||
import FormData from "form-data"
|
||||
import { ResponsePromise } from "../../typings"
|
||||
import BaseResource from "../base"
|
||||
import FormData from "form-data"
|
||||
|
||||
class AdminUploadsResource extends BaseResource {
|
||||
private headers = {
|
||||
"Content-Type": "multipart/form-data",
|
||||
}
|
||||
|
||||
create(file: IAdminPostUploadsFile): ResponsePromise<AdminUploadRes> {
|
||||
create(file: IAdminPostUploadsFileReq): ResponsePromise<AdminUploadsRes> {
|
||||
const path = `/admin/uploads`
|
||||
|
||||
const payload = new FormData()
|
||||
@@ -16,6 +23,24 @@ class AdminUploadsResource extends BaseResource {
|
||||
|
||||
return this.client.request("POST", path, payload, {}, this.headers)
|
||||
}
|
||||
|
||||
delete(
|
||||
payload: AdminDeleteUploadsReq,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminDeleteUploadsRes> {
|
||||
const path = `/admin/uploads`
|
||||
|
||||
return this.client.request("DELETE", path, payload, {}, customHeaders)
|
||||
}
|
||||
|
||||
getPresignedDownloadUrl(
|
||||
payload: AdminPostUploadsDownloadUrlReq,
|
||||
customHeaders: Record<string, any> = {}
|
||||
): ResponsePromise<AdminUploadsDownloadUrlRes> {
|
||||
const path = `/admin/uploads/download-url`
|
||||
|
||||
return this.client.request("POST", path, payload, {}, customHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminUploadsResource
|
||||
@@ -0,0 +1,21 @@
|
||||
export function stringifyNullProperties<T extends object>(input: T): T {
|
||||
const convertProperties = (obj: T) => {
|
||||
const res = {} as T
|
||||
|
||||
Object.keys(obj).reduce((acc: T, key: string) => {
|
||||
if (obj[key] === null) {
|
||||
acc[key] = "null"
|
||||
} else if (typeof obj[key] === "object") {
|
||||
acc[key] = convertProperties(obj[key])
|
||||
} else {
|
||||
acc[key] = obj[key]
|
||||
}
|
||||
|
||||
return acc
|
||||
}, res)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
return convertProperties(input)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { stringifyNullProperties } from "../../src/utils"
|
||||
|
||||
describe("stringifyNullProperties", () => {
|
||||
test("returns empty object on no props", () => {
|
||||
const result = stringifyNullProperties({})
|
||||
expect(result).toEqual({})
|
||||
})
|
||||
|
||||
test("successfully stringifies null property", () => {
|
||||
const result = stringifyNullProperties({ test: null })
|
||||
expect(result).toEqual({ test: "null" })
|
||||
})
|
||||
|
||||
test("successfully stringifies nested null property", () => {
|
||||
const result = stringifyNullProperties({
|
||||
test: { test_2: { test_3: null } },
|
||||
another_test: "test",
|
||||
})
|
||||
expect(result).toEqual({
|
||||
test: { test_2: { test_3: "null" } },
|
||||
another_test: "test",
|
||||
})
|
||||
})
|
||||
|
||||
test("successfully stringifies string property", () => {
|
||||
const result = stringifyNullProperties({
|
||||
test: "test",
|
||||
})
|
||||
expect(result).toEqual({ test: "test" })
|
||||
})
|
||||
})
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.2.3](https://github.com/medusajs/medusa/compare/medusa-payment-paypal@1.2.2...medusa-payment-paypal@1.2.3) (2022-07-05)
|
||||
|
||||
**Note:** Version bump only for package medusa-payment-paypal
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.2.2](https://github.com/medusajs/medusa/compare/medusa-payment-paypal@1.2.0...medusa-payment-paypal@1.2.2) (2022-06-19)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-payment-paypal",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Paypal Payment provider for Meduas Commerce",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.8.0",
|
||||
"jest": "^25.5.2",
|
||||
"medusa-interfaces": "^1.3.0",
|
||||
"medusa-interfaces": "^1.3.1",
|
||||
"medusa-test-utils": "^1.1.37"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.1.41](https://github.com/medusajs/medusa/compare/medusa-payment-stripe@1.1.40...medusa-payment-stripe@1.1.41) (2022-07-05)
|
||||
|
||||
**Note:** Version bump only for package medusa-payment-stripe
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.40](https://github.com/medusajs/medusa/compare/medusa-payment-stripe@1.1.38...medusa-payment-stripe@1.1.40) (2022-06-19)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "medusa-payment-stripe",
|
||||
"version": "1.1.40",
|
||||
"version": "1.1.41",
|
||||
"description": "Stripe Payment provider for Meduas Commerce",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-transform-instanceof",
|
||||
"@babel/plugin-transform-classes"
|
||||
],
|
||||
"presets": ["@babel/preset-env"],
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": ["@babel/plugin-transform-runtime"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/lib
|
||||
node_modules
|
||||
.DS_store
|
||||
.env*
|
||||
/*.js
|
||||
!index.js
|
||||
|
||||
/dist
|
||||
|
||||
/api
|
||||
/services
|
||||
/models
|
||||
/subscribers
|
||||
/loaders
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/lib
|
||||
node_modules
|
||||
.DS_store
|
||||
.env*
|
||||
/*.js
|
||||
!index.js
|
||||
yarn.lock
|
||||
/src
|
||||
@@ -1,222 +0,0 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.2.0](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.37...medusa-plugin-add-ons@1.2.0) (2022-05-01)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.37](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.36...medusa-plugin-add-ons@1.1.37) (2022-01-11)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.36](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.35...medusa-plugin-add-ons@1.1.36) (2021-12-29)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.35](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.34...medusa-plugin-add-ons@1.1.35) (2021-12-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.34](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.33...medusa-plugin-add-ons@1.1.34) (2021-12-08)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.33](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.32...medusa-plugin-add-ons@1.1.33) (2021-11-23)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.32](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.31...medusa-plugin-add-ons@1.1.32) (2021-11-22)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.31](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.30...medusa-plugin-add-ons@1.1.31) (2021-11-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.30](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.29...medusa-plugin-add-ons@1.1.30) (2021-11-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.29](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.28...medusa-plugin-add-ons@1.1.29) (2021-10-18)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.28](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.27...medusa-plugin-add-ons@1.1.28) (2021-10-18)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.27](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.25...medusa-plugin-add-ons@1.1.27) (2021-10-18)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.26](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.25...medusa-plugin-add-ons@1.1.26) (2021-10-18)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.25](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.24...medusa-plugin-add-ons@1.1.25) (2021-09-15)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.24](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.23...medusa-plugin-add-ons@1.1.24) (2021-09-14)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.23](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.22...medusa-plugin-add-ons@1.1.23) (2021-08-05)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.22](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.21...medusa-plugin-add-ons@1.1.22) (2021-07-26)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.19...medusa-plugin-add-ons@1.1.21) (2021-07-15)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.19...medusa-plugin-add-ons@1.1.20) (2021-07-15)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.18...medusa-plugin-add-ons@1.1.19) (2021-07-02)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.18](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.17...medusa-plugin-add-ons@1.1.18) (2021-06-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- release assist ([668e8a7](https://github.com/medusajs/medusa/commit/668e8a740200847fc2a41c91d2979097f1392532))
|
||||
|
||||
## [1.1.17](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.16...medusa-plugin-add-ons@1.1.17) (2021-06-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.16](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.15...medusa-plugin-add-ons@1.1.16) (2021-06-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.15](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.14...medusa-plugin-add-ons@1.1.15) (2021-06-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.14](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.13...medusa-plugin-add-ons@1.1.14) (2021-06-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.13](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.12...medusa-plugin-add-ons@1.1.13) (2021-06-08)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.12](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.9...medusa-plugin-add-ons@1.1.12) (2021-04-28)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.11](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.10...medusa-plugin-add-ons@1.1.11) (2021-04-20)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.10](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.9...medusa-plugin-add-ons@1.1.10) (2021-04-20)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.9](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.8...medusa-plugin-add-ons@1.1.9) (2021-04-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- merge develop ([2982a8e](https://github.com/medusajs/medusa/commit/2982a8e682e90beb4549d969d9d3b04d78a46a2d))
|
||||
- merge develop ([a468c45](https://github.com/medusajs/medusa/commit/a468c451e82c68f41b5005a2e480057f6124aaa6))
|
||||
|
||||
## [1.1.8](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.7...medusa-plugin-add-ons@1.1.8) (2021-04-13)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.7](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.6...medusa-plugin-add-ons@1.1.7) (2021-03-30)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.6](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.5...medusa-plugin-add-ons@1.1.6) (2021-03-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.5](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.3...medusa-plugin-add-ons@1.1.5) (2021-03-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.4](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.3...medusa-plugin-add-ons@1.1.4) (2021-03-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.3](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.2...medusa-plugin-add-ons@1.1.3) (2021-02-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.2](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.1...medusa-plugin-add-ons@1.1.2) (2021-02-03)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.1.1](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.0...medusa-plugin-add-ons@1.1.1) (2021-01-27)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
# [1.1.0](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.8...medusa-plugin-add-ons@1.1.0) (2021-01-26)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.8](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.7...medusa-plugin-add-ons@1.0.8) (2020-12-17)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.7](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.6...medusa-plugin-add-ons@1.0.7) (2020-11-24)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.6](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.5...medusa-plugin-add-ons@1.0.6) (2020-10-19)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.5](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.4...medusa-plugin-add-ons@1.0.5) (2020-10-12)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.4](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.3...medusa-plugin-add-ons@1.0.4) (2020-10-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.3](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.2...medusa-plugin-add-ons@1.0.3) (2020-10-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **medusa-plugin-add-ons:** fixes add-on decorator ([5071f36](https://github.com/medusajs/medusa/commit/5071f362e4e140d11a1342a5058e8ad2efaa1ed4))
|
||||
- **medusa-plugin-addon:** Fixes admin endpoints, Adds flag to avoid merging add-on line-items ([d8483cd](https://github.com/medusajs/medusa/commit/d8483cd1352ecc587112723786b7c31882f9416e))
|
||||
|
||||
## [1.0.2](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.1...medusa-plugin-add-ons@1.0.2) (2020-09-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
## [1.0.1](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.0.0...medusa-plugin-add-ons@1.0.1) (2020-09-09)
|
||||
|
||||
**Note:** Version bump only for package medusa-plugin-add-ons
|
||||
|
||||
# 1.0.0 (2020-09-09)
|
||||
|
||||
### Features
|
||||
|
||||
- **plugins:** Adds add-on plugin ([3de1e6d](https://github.com/medusajs/medusa/commit/3de1e6dd4ad4a2a48d4d8116ebdd011efce2b22a))
|
||||
@@ -1 +0,0 @@
|
||||
// noop
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "medusa-plugin-add-ons",
|
||||
"version": "1.2.0",
|
||||
"description": "Add-on plugin for Medusa Commerce",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
"directory": "packages/medusa-plugin-add-ons"
|
||||
},
|
||||
"author": "Oliver Juhl",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.7.5",
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/node": "^7.7.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||
"@babel/plugin-transform-classes": "^7.9.5",
|
||||
"@babel/plugin-transform-instanceof": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.5",
|
||||
"@babel/register": "^7.7.4",
|
||||
"@babel/runtime": "^7.9.6",
|
||||
"client-sessions": "^0.8.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"eslint": "^6.8.0",
|
||||
"jest": "^25.5.2",
|
||||
"medusa-test-utils": "^1.1.37"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src -d . --ignore **/__tests__",
|
||||
"prepare": "cross-env NODE_ENV=production npm run build",
|
||||
"watch": "babel -w src --out-dir . --ignore **/__tests__",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"medusa-core-utils": "^1.1.31",
|
||||
"redis": "^3.0.2"
|
||||
},
|
||||
"gitHead": "81a7ff73d012fda722f6e9ef0bd9ba0232d37808"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Router } from "express"
|
||||
import admin from "./routes/admin"
|
||||
import store from "./routes/store"
|
||||
|
||||
export default (rootDirectory) => {
|
||||
const app = Router()
|
||||
|
||||
store(app, rootDirectory)
|
||||
admin(app, rootDirectory)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export default (fn) => (...args) => fn(...args).catch(args[2])
|
||||
@@ -1,5 +0,0 @@
|
||||
import { default as wrap } from "./await-middleware"
|
||||
|
||||
export default {
|
||||
wrap,
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
name: Validator.string().required(),
|
||||
prices: Validator.array()
|
||||
.items({
|
||||
currency_code: Validator.string(),
|
||||
amount: Validator.number(),
|
||||
})
|
||||
.required(),
|
||||
valid_for: Validator.array().items(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
try {
|
||||
const addOnService = req.scope.resolve("addOnService")
|
||||
|
||||
const addOn = await addOnService.create(value)
|
||||
|
||||
res.status(200).json({ addOn })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const addOnService = req.scope.resolve("addOnService")
|
||||
try {
|
||||
await addOnService.delete(id)
|
||||
|
||||
res.status(200).send({
|
||||
id,
|
||||
object: "addOn",
|
||||
deleted: true,
|
||||
})
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
Loaded 100 of 400 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user