├── .babelrc.js
├── .dockerignore
├── .env.template
├── .github
└── workflows
│ └── npm-publish.yml
├── .gitignore
├── .npmignore
├── README.md
├── data
└── seed.json
├── docker-compose.yml
├── index.js
├── package-lock.json
├── package.json
├── src
├── loaders
│ └── index.ts
├── services
│ ├── README.md
│ ├── magento-category.ts
│ ├── magento-client.ts
│ └── magento-product.ts
└── strategies
│ └── import.ts
├── tsconfig.json
└── yarn.lock
/.babelrc.js:
--------------------------------------------------------------------------------
1 | let ignore = [`**/dist`];
2 |
3 | // Jest needs to compile this code, but generally we don't want this copied
4 | // to output folders
5 | if (process.env.NODE_ENV !== `test`) {
6 | ignore.push(`**/__tests__`);
7 | }
8 |
9 | module.exports = {
10 | presets: [["babel-preset-medusa-package"], ["@babel/preset-typescript", {
11 | allowDeclareFields: true
12 | }]],
13 | ignore,
14 | };
15 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 |
4 | npm-debug.log
5 |
--------------------------------------------------------------------------------
/.env.template:
--------------------------------------------------------------------------------
1 | JWT_SECRET=something
2 | COOKIE_SECRET=something
3 | STRIPE_API_KEY=
4 | STRIPE_WEBHOOK_SECRET=
5 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3 |
4 | name: Node.js Package
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 | - uses: actions/setup-node@v3
16 | with:
17 | node-version: 16
18 | - run: npm ci
19 | - run: npm test
20 |
21 | publish-npm:
22 | needs: build
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v3
26 | - uses: actions/setup-node@v3
27 | with:
28 | node-version: 16
29 | registry-url: https://registry.npmjs.org/
30 | - run: npm ci
31 | - run: npm publish
32 | env:
33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}}
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | .env
3 | .DS_Store
4 | /uploads
5 | /node_modules
6 | yarn-error.log
7 | /.idea
8 |
9 | medusa-config.js
10 | Dockerfile
11 | medusa-db.sql
12 | develop.sh
13 | /loaders
14 | /services
15 | /strategies
16 | /data
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /lib
2 | node_modules
3 | .DS_store
4 | .env*
5 | /*.js
6 | !index.js
7 | yarn.lock
8 | src
9 | .gitignore
10 | .eslintrc
11 | .babelrc
12 | .prettierrc
13 |
14 | #These are files that are included in a
15 | #Medusa project and can be removed from a
16 | #plugin project
17 | medusa-config.js
18 | Dockerfile
19 | medusa-db.sql
20 | develop.sh
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Magento Source Plugin for Medusa
8 |
9 |
10 | A Medusa plugin that imports categories and products from Magento into Medusa.
11 |
12 |
13 | ## Description
14 |
15 | This plugin imports Magento categories and products into Medusa. It creates categories and products that don't exist, and updates those that have been imported previously.
16 |
17 | ### Limitations
18 |
19 | Magento has 6 product types. As some of those types don't exist in Medusa, only the Configurable and Simple products can be imported.
20 |
21 | ## Prerequisites
22 |
23 | ### Medusa Setup
24 |
25 | You must have a [Medusa server installed](https://docs.medusajs.com/quickstart/quick-start) before installing this plugin.
26 |
27 | Furthermore, the Medusa server should have [PostgreSQL](https://docs.medusajs.com/tutorial/set-up-your-development-environment#postgresql) and [Redis](https://docs.medusajs.com/tutorial/set-up-your-development-environment#redis) installed and configured on your Medusa server.
28 |
29 | ### Magento Setup
30 |
31 | On your Magento admin, go to System -> Integrations -> Add New Integrations.
32 |
33 | You need to give the integration the access to the following resources:
34 |
35 | - Catalog (with its child resources).
36 | - Stores -> Settings (with its child resources).
37 | - Stores -> Attributes (with its child resources).
38 |
39 | After creating the integration, activate it from the Integrations listing page. Once you activate it, you'll receive four keys: Consumer Key, Consumer Secret, Access Token, and Access Token Secret. Copy them as you'll need them for the plugin's options.
40 |
41 | ## Installing Plugin
42 |
43 | To install the plugin run the following command on your Medusa server:
44 |
45 | ```bash
46 | npm install medusa-source-magento
47 | ```
48 |
49 | ## Plugin Configurations
50 |
51 | Add the plugin and its options into the `plugins` array in `medusa-config.js`:
52 |
53 | ```js
54 | const plugins = [
55 | //...
56 | {
57 | resolve: `medusa-source-magento`,
58 | //if your plugin has configurations
59 | options: {
60 | magento_url: '',
61 | consumer_key: '',
62 | consumer_secret: '',
63 | access_token: '',
64 | access_token_secret: '',
65 | image_prefix: '' // optional
66 | },
67 | },
68 | ];
69 | ```
70 |
71 | ### Options
72 |
73 | | Name | Description | Required | Default Value|
74 | -------|-------------|----------|--------------|
75 | | `magento_url` | The URL of your Medusa server. It shouldn't end with a backslash. | true | |
76 | | `consumer_key` | The Consumer Key of the integration. | true | |
77 | | `consumer_secret` | The Consumer Secret of the integration. | true | |
78 | | `access_token` | The Access Token of the integration. | true | |
79 | | `access_token_secret` | The Access Token Secret of the integration | true | |
80 | | `image_prefix` | The URL prefix of media files. This is necessary if you don't use Magento's default storage for product images (for example, if you use S3) | false | The URL will be retrieved from Magento. |
81 |
82 | ## Use the Plugin
83 |
84 | ### Server Startup
85 |
86 | To use the plugin, just start the Medusa server:
87 |
88 | ```bash
89 | npm start
90 | ```
91 |
92 | The import process will run in the background of the server. Based on how many products you have, it can take some time the first time running it.
93 |
94 | ### As a Batch Job
95 |
96 | You can trigger the import by creating a new batch job using the Create Batch Job API endpoint. You can pass the following in the payload:
97 |
98 | ```json
99 | {
100 | "type": "import-magento",
101 | "context": { },
102 | "dry_run": false
103 | }
104 | ```
105 |
106 | This will trigger the import process.
--------------------------------------------------------------------------------
/data/seed.json:
--------------------------------------------------------------------------------
1 | {
2 | "store": {
3 | "currencies": ["eur", "usd"]
4 | },
5 | "users": [
6 | {
7 | "email": "admin@medusa-test.com",
8 | "password": "supersecret"
9 | }
10 | ],
11 | "regions": [
12 | {
13 | "id": "test-region-eu",
14 | "name": "EU",
15 | "currency_code": "eur",
16 | "tax_rate": 0,
17 | "payment_providers": ["manual"],
18 | "fulfillment_providers": ["manual"],
19 | "countries": ["gb", "de", "dk", "se", "fr", "es", "it"]
20 | },
21 | {
22 | "id": "test-region-na",
23 | "name": "NA",
24 | "currency_code": "usd",
25 | "tax_rate": 0,
26 | "payment_providers": ["manual"],
27 | "fulfillment_providers": ["manual"],
28 | "countries": ["us", "ca"]
29 | }
30 | ],
31 | "shipping_options": [
32 | {
33 | "name": "PostFake Standard",
34 | "region_id": "test-region-eu",
35 | "provider_id": "manual",
36 | "data": {
37 | "id": "manual-fulfillment"
38 | },
39 | "price_type": "flat_rate",
40 | "amount": 1000
41 | },
42 | {
43 | "name": "PostFake Express",
44 | "region_id": "test-region-eu",
45 | "provider_id": "manual",
46 | "data": {
47 | "id": "manual-fulfillment"
48 | },
49 | "price_type": "flat_rate",
50 | "amount": 1500
51 | },
52 | {
53 | "name": "PostFake Return",
54 | "region_id": "test-region-eu",
55 | "provider_id": "manual",
56 | "data": {
57 | "id": "manual-fulfillment"
58 | },
59 | "price_type": "flat_rate",
60 | "is_return": true,
61 | "amount": 1000
62 | },
63 | {
64 | "name": "I want to return it myself",
65 | "region_id": "test-region-eu",
66 | "provider_id": "manual",
67 | "data": {
68 | "id": "manual-fulfillment"
69 | },
70 | "price_type": "flat_rate",
71 | "is_return": true,
72 | "amount": 0
73 | },
74 | {
75 | "name": "FakeEx Standard",
76 | "region_id": "test-region-na",
77 | "provider_id": "manual",
78 | "data": {
79 | "id": "manual-fulfillment"
80 | },
81 | "price_type": "flat_rate",
82 | "amount": 800
83 | },
84 | {
85 | "name": "FakeEx Express",
86 | "region_id": "test-region-na",
87 | "provider_id": "manual",
88 | "data": {
89 | "id": "manual-fulfillment"
90 | },
91 | "price_type": "flat_rate",
92 | "amount": 1200
93 | },
94 | {
95 | "name": "FakeEx Return",
96 | "region_id": "test-region-na",
97 | "provider_id": "manual",
98 | "data": {
99 | "id": "manual-fulfillment"
100 | },
101 | "price_type": "flat_rate",
102 | "is_return": true,
103 | "amount": 800
104 | },
105 | {
106 | "name": "I want to return it myself",
107 | "region_id": "test-region-na",
108 | "provider_id": "manual",
109 | "data": {
110 | "id": "manual-fulfillment"
111 | },
112 | "price_type": "flat_rate",
113 | "is_return": true,
114 | "amount": 0
115 | }
116 | ],
117 | "products": [
118 | {
119 | "title": "Medusa T-Shirt",
120 | "subtitle": null,
121 | "description": "Reimagine the feeling of a classic T-shirt. With our cotton T-shirts, everyday essentials no longer have to be ordinary.",
122 | "handle": "t-shirt",
123 | "is_giftcard": false,
124 | "weight": 400,
125 | "images": [
126 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/tee-black-front.png",
127 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/tee-black-back.png",
128 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/tee-white-front.png",
129 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/tee-white-back.png"
130 | ],
131 | "options": [
132 | {
133 | "title": "Size",
134 | "values": ["S", "M", "L", "XL"]
135 | },
136 | {
137 | "title": "Color",
138 | "values": ["Black", "White"]
139 | }
140 | ],
141 | "variants": [
142 | {
143 | "title": "S / Black",
144 | "prices": [
145 | {
146 | "currency_code": "eur",
147 | "amount": 1950
148 | },
149 | {
150 | "currency_code": "usd",
151 | "amount": 2200
152 | }
153 | ],
154 | "options": [
155 | {
156 | "value": "S"
157 | },
158 | {
159 | "value": "Black"
160 | }
161 | ],
162 | "inventory_quantity": 100,
163 | "manage_inventory": true
164 | },
165 | {
166 | "title": "S / White",
167 | "prices": [
168 | {
169 | "currency_code": "eur",
170 | "amount": 1950
171 | },
172 | {
173 | "currency_code": "usd",
174 | "amount": 2200
175 | }
176 | ],
177 | "options": [
178 | {
179 | "value": "S"
180 | },
181 | {
182 | "value": "White"
183 | }
184 | ],
185 | "inventory_quantity": 100,
186 | "manage_inventory": true
187 | },
188 | {
189 | "title": "M / Black",
190 | "prices": [
191 | {
192 | "currency_code": "eur",
193 | "amount": 1950
194 | },
195 | {
196 | "currency_code": "usd",
197 | "amount": 2200
198 | }
199 | ],
200 | "options": [
201 | {
202 | "value": "M"
203 | },
204 | {
205 | "value": "Black"
206 | }
207 | ],
208 | "inventory_quantity": 100,
209 | "manage_inventory": true
210 | },
211 | {
212 | "title": "M / White",
213 | "prices": [
214 | {
215 | "currency_code": "eur",
216 | "amount": 1950
217 | },
218 | {
219 | "currency_code": "usd",
220 | "amount": 2200
221 | }
222 | ],
223 | "options": [
224 | {
225 | "value": "M"
226 | },
227 | {
228 | "value": "White"
229 | }
230 | ],
231 | "inventory_quantity": 100,
232 | "manage_inventory": true
233 | },
234 | {
235 | "title": "L / Black",
236 | "prices": [
237 | {
238 | "currency_code": "eur",
239 | "amount": 1950
240 | },
241 | {
242 | "currency_code": "usd",
243 | "amount": 2200
244 | }
245 | ],
246 | "options": [
247 | {
248 | "value": "L"
249 | },
250 | {
251 | "value": "Black"
252 | }
253 | ],
254 | "inventory_quantity": 100,
255 | "manage_inventory": true
256 | },
257 | {
258 | "title": "L / White",
259 | "prices": [
260 | {
261 | "currency_code": "eur",
262 | "amount": 1950
263 | },
264 | {
265 | "currency_code": "usd",
266 | "amount": 2200
267 | }
268 | ],
269 | "options": [
270 | {
271 | "value": "L"
272 | },
273 | {
274 | "value": "White"
275 | }
276 | ],
277 | "inventory_quantity": 100,
278 | "manage_inventory": true
279 | },
280 | {
281 | "title": "XL / Black",
282 | "prices": [
283 | {
284 | "currency_code": "eur",
285 | "amount": 1950
286 | },
287 | {
288 | "currency_code": "usd",
289 | "amount": 2200
290 | }
291 | ],
292 | "options": [
293 | {
294 | "value": "XL"
295 | },
296 | {
297 | "value": "Black"
298 | }
299 | ],
300 | "inventory_quantity": 100,
301 | "manage_inventory": true
302 | },
303 | {
304 | "title": "XL / White",
305 | "prices": [
306 | {
307 | "currency_code": "eur",
308 | "amount": 1950
309 | },
310 | {
311 | "currency_code": "usd",
312 | "amount": 2200
313 | }
314 | ],
315 | "options": [
316 | {
317 | "value": "XL"
318 | },
319 | {
320 | "value": "White"
321 | }
322 | ],
323 | "inventory_quantity": 100,
324 | "manage_inventory": true
325 | }
326 | ]
327 | },
328 | {
329 | "title": "Medusa Sweatshirt",
330 | "subtitle": null,
331 | "description": "Reimagine the feeling of a classic sweatshirt. With our cotton sweatshirt, everyday essentials no longer have to be ordinary.",
332 | "handle": "sweatshirt",
333 | "is_giftcard": false,
334 | "weight": 400,
335 | "images": [
336 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatshirt-vintage-front.png",
337 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatshirt-vintage-back.png"
338 | ],
339 | "options": [
340 | {
341 | "title": "Size",
342 | "values": ["S", "M", "L", "XL"]
343 | }
344 | ],
345 | "variants": [
346 | {
347 | "title": "S",
348 | "prices": [
349 | {
350 | "currency_code": "eur",
351 | "amount": 2950
352 | },
353 | {
354 | "currency_code": "usd",
355 | "amount": 3350
356 | }
357 | ],
358 | "options": [
359 | {
360 | "value": "S"
361 | }
362 | ],
363 | "inventory_quantity": 100,
364 | "manage_inventory": true
365 | },
366 | {
367 | "title": "M",
368 | "prices": [
369 | {
370 | "currency_code": "eur",
371 | "amount": 2950
372 | },
373 | {
374 | "currency_code": "usd",
375 | "amount": 3350
376 | }
377 | ],
378 | "options": [
379 | {
380 | "value": "M"
381 | }
382 | ],
383 | "inventory_quantity": 100,
384 | "manage_inventory": true
385 | },
386 | {
387 | "title": "L",
388 | "prices": [
389 | {
390 | "currency_code": "eur",
391 | "amount": 2950
392 | },
393 | {
394 | "currency_code": "usd",
395 | "amount": 3350
396 | }
397 | ],
398 | "options": [
399 | {
400 | "value": "L"
401 | }
402 | ],
403 | "inventory_quantity": 100,
404 | "manage_inventory": true
405 | },
406 | {
407 | "title": "XL",
408 | "prices": [
409 | {
410 | "currency_code": "eur",
411 | "amount": 2950
412 | },
413 | {
414 | "currency_code": "usd",
415 | "amount": 3350
416 | }
417 | ],
418 | "options": [
419 | {
420 | "value": "XL"
421 | }
422 | ],
423 | "inventory_quantity": 100,
424 | "manage_inventory": true
425 | }
426 | ]
427 | },
428 | {
429 | "title": "Medusa Sweatpants",
430 | "subtitle": null,
431 | "description": "Reimagine the feeling of classic sweatpants. With our cotton sweatpants, everyday essentials no longer have to be ordinary.",
432 | "handle": "sweatpants",
433 | "is_giftcard": false,
434 | "weight": 400,
435 | "images": [
436 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png",
437 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-back.png"
438 | ],
439 | "options": [
440 | {
441 | "title": "Size",
442 | "values": ["S", "M", "L", "XL"]
443 | }
444 | ],
445 | "variants": [
446 | {
447 | "title": "S",
448 | "prices": [
449 | {
450 | "currency_code": "eur",
451 | "amount": 2950
452 | },
453 | {
454 | "currency_code": "usd",
455 | "amount": 3350
456 | }
457 | ],
458 | "options": [
459 | {
460 | "value": "S"
461 | }
462 | ],
463 | "inventory_quantity": 100,
464 | "manage_inventory": true
465 | },
466 | {
467 | "title": "M",
468 | "prices": [
469 | {
470 | "currency_code": "eur",
471 | "amount": 2950
472 | },
473 | {
474 | "currency_code": "usd",
475 | "amount": 3350
476 | }
477 | ],
478 | "options": [
479 | {
480 | "value": "M"
481 | }
482 | ],
483 | "inventory_quantity": 100,
484 | "manage_inventory": true
485 | },
486 | {
487 | "title": "L",
488 | "prices": [
489 | {
490 | "currency_code": "eur",
491 | "amount": 2950
492 | },
493 | {
494 | "currency_code": "usd",
495 | "amount": 3350
496 | }
497 | ],
498 | "options": [
499 | {
500 | "value": "L"
501 | }
502 | ],
503 | "inventory_quantity": 100,
504 | "manage_inventory": true
505 | },
506 | {
507 | "title": "XL",
508 | "prices": [
509 | {
510 | "currency_code": "eur",
511 | "amount": 2950
512 | },
513 | {
514 | "currency_code": "usd",
515 | "amount": 3350
516 | }
517 | ],
518 | "options": [
519 | {
520 | "value": "XL"
521 | }
522 | ],
523 | "inventory_quantity": 100,
524 | "manage_inventory": true
525 | }
526 | ]
527 | },
528 | {
529 | "title": "Medusa Shorts",
530 | "subtitle": null,
531 | "description": "Reimagine the feeling of classic shorts. With our cotton shorts, everyday essentials no longer have to be ordinary.",
532 | "handle": "shorts",
533 | "is_giftcard": false,
534 | "weight": 400,
535 | "images": [
536 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/shorts-vintage-front.png",
537 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/shorts-vintage-back.png"
538 | ],
539 | "options": [
540 | {
541 | "title": "Size",
542 | "values": ["S", "M", "L", "XL"]
543 | }
544 | ],
545 | "variants": [
546 | {
547 | "title": "S",
548 | "prices": [
549 | {
550 | "currency_code": "eur",
551 | "amount": 2500
552 | },
553 | {
554 | "currency_code": "usd",
555 | "amount": 2850
556 | }
557 | ],
558 | "options": [
559 | {
560 | "value": "S"
561 | }
562 | ],
563 | "inventory_quantity": 100,
564 | "manage_inventory": true
565 | },
566 | {
567 | "title": "M",
568 | "prices": [
569 | {
570 | "currency_code": "eur",
571 | "amount": 2500
572 | },
573 | {
574 | "currency_code": "usd",
575 | "amount": 2850
576 | }
577 | ],
578 | "options": [
579 | {
580 | "value": "M"
581 | }
582 | ],
583 | "inventory_quantity": 100,
584 | "manage_inventory": true
585 | },
586 | {
587 | "title": "L",
588 | "prices": [
589 | {
590 | "currency_code": "eur",
591 | "amount": 2500
592 | },
593 | {
594 | "currency_code": "usd",
595 | "amount": 2850
596 | }
597 | ],
598 | "options": [
599 | {
600 | "value": "L"
601 | }
602 | ],
603 | "inventory_quantity": 100,
604 | "manage_inventory": true
605 | },
606 | {
607 | "title": "XL",
608 | "prices": [
609 | {
610 | "currency_code": "eur",
611 | "amount": 2500
612 | },
613 | {
614 | "currency_code": "usd",
615 | "amount": 2850
616 | }
617 | ],
618 | "options": [
619 | {
620 | "value": "XL"
621 | }
622 | ],
623 | "inventory_quantity": 100,
624 | "manage_inventory": true
625 | }
626 | ]
627 | },
628 | {
629 | "title": "Medusa Hoodie",
630 | "subtitle": null,
631 | "description": "Reimagine the feeling of a classic hoodie. With our cotton hoodie, everyday essentials no longer have to be ordinary.",
632 | "handle": "hoodie",
633 | "is_giftcard": false,
634 | "weight": 400,
635 | "images": [
636 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/black_hoodie_front.png",
637 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/black_hoodie_back.png"
638 | ],
639 | "options": [
640 | {
641 | "title": "Size",
642 | "values": ["S", "M", "L", "XL"]
643 | }
644 | ],
645 | "variants": [
646 | {
647 | "title": "S",
648 | "prices": [
649 | {
650 | "currency_code": "eur",
651 | "amount": 3650
652 | },
653 | {
654 | "currency_code": "usd",
655 | "amount": 4150
656 | }
657 | ],
658 | "options": [
659 | {
660 | "value": "S"
661 | }
662 | ],
663 | "inventory_quantity": 100,
664 | "manage_inventory": true
665 | },
666 | {
667 | "title": "M",
668 | "prices": [
669 | {
670 | "currency_code": "eur",
671 | "amount": 3650
672 | },
673 | {
674 | "currency_code": "usd",
675 | "amount": 4150
676 | }
677 | ],
678 | "options": [
679 | {
680 | "value": "M"
681 | }
682 | ],
683 | "inventory_quantity": 100,
684 | "manage_inventory": true
685 | },
686 | {
687 | "title": "L",
688 | "prices": [
689 | {
690 | "currency_code": "eur",
691 | "amount": 3650
692 | },
693 | {
694 | "currency_code": "usd",
695 | "amount": 4150
696 | }
697 | ],
698 | "options": [
699 | {
700 | "value": "L"
701 | }
702 | ],
703 | "inventory_quantity": 100,
704 | "manage_inventory": true
705 | },
706 | {
707 | "title": "XL",
708 | "prices": [
709 | {
710 | "currency_code": "eur",
711 | "amount": 3650
712 | },
713 | {
714 | "currency_code": "usd",
715 | "amount": 4150
716 | }
717 | ],
718 | "options": [
719 | {
720 | "value": "XL"
721 | }
722 | ],
723 | "inventory_quantity": 100,
724 | "manage_inventory": true
725 | }
726 | ]
727 | },
728 | {
729 | "title": "Medusa Longsleeve",
730 | "subtitle": null,
731 | "description": "Reimagine the feeling of a classic longsleeve. With our cotton longsleeve, everyday essentials no longer have to be ordinary.",
732 | "handle": "longsleeve",
733 | "is_giftcard": false,
734 | "weight": 400,
735 | "images": [
736 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/ls-black-front.png",
737 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/ls-black-back.png"
738 | ],
739 | "options": [
740 | {
741 | "title": "Size",
742 | "values": ["S", "M", "L", "XL"]
743 | }
744 | ],
745 | "variants": [
746 | {
747 | "title": "S",
748 | "prices": [
749 | {
750 | "currency_code": "eur",
751 | "amount": 3650
752 | },
753 | {
754 | "currency_code": "usd",
755 | "amount": 4150
756 | }
757 | ],
758 | "options": [
759 | {
760 | "value": "S"
761 | }
762 | ],
763 | "inventory_quantity": 100,
764 | "manage_inventory": true
765 | },
766 | {
767 | "title": "M",
768 | "prices": [
769 | {
770 | "currency_code": "eur",
771 | "amount": 3650
772 | },
773 | {
774 | "currency_code": "usd",
775 | "amount": 4150
776 | }
777 | ],
778 | "options": [
779 | {
780 | "value": "M"
781 | }
782 | ],
783 | "inventory_quantity": 100,
784 | "manage_inventory": true
785 | },
786 | {
787 | "title": "L",
788 | "prices": [
789 | {
790 | "currency_code": "eur",
791 | "amount": 3650
792 | },
793 | {
794 | "currency_code": "usd",
795 | "amount": 4150
796 | }
797 | ],
798 | "options": [
799 | {
800 | "value": "L"
801 | }
802 | ],
803 | "inventory_quantity": 100,
804 | "manage_inventory": true
805 | },
806 | {
807 | "title": "XL",
808 | "prices": [
809 | {
810 | "currency_code": "eur",
811 | "amount": 3650
812 | },
813 | {
814 | "currency_code": "usd",
815 | "amount": 4150
816 | }
817 | ],
818 | "options": [
819 | {
820 | "value": "XL"
821 | }
822 | ],
823 | "inventory_quantity": 100,
824 | "manage_inventory": true
825 | }
826 | ]
827 | },
828 | {
829 | "title": "Medusa Coffee Mug",
830 | "subtitle": null,
831 | "description": "Every programmer's best friend.",
832 | "handle": "coffee-mug",
833 | "is_giftcard": false,
834 | "weight": 400,
835 | "images": [
836 | "https://medusa-public-images.s3.eu-west-1.amazonaws.com/coffee-mug.png"
837 | ],
838 | "options": [
839 | {
840 | "title": "Size",
841 | "values": ["One Size"]
842 | }
843 | ],
844 | "variants": [
845 | {
846 | "title": "One Size",
847 | "prices": [
848 | {
849 | "currency_code": "eur",
850 | "amount": 1000
851 | },
852 | {
853 | "currency_code": "usd",
854 | "amount": 1200
855 | }
856 | ],
857 | "options": [
858 | {
859 | "value": "One Size"
860 | }
861 | ],
862 | "inventory_quantity": 100,
863 | "manage_inventory": true
864 | }
865 | ]
866 | }
867 | ]
868 | }
869 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 | backend:
4 | build:
5 | context: .
6 | dockerfile: Dockerfile
7 | image: backend:starter
8 | container_name: medusa-server-default
9 | depends_on:
10 | - postgres
11 | - redis
12 | environment:
13 | DATABASE_URL: postgres://postgres:postgres@postgres:5432/medusa-docker
14 | REDIS_URL: redis://redis
15 | NODE_ENV: development
16 | JWT_SECRET: something
17 | COOKIE_SECRET: something
18 | PORT: 9000
19 | ports:
20 | - "9000:9000"
21 | volumes:
22 | - .:/app/medusa
23 | - node_modules:/app/medusa/node_modules
24 |
25 | postgres:
26 | image: postgres:10.4
27 | ports:
28 | - "5432:5432"
29 | environment:
30 | POSTGRES_USER: postgres
31 | POSTGRES_PASSWORD: postgres
32 | POSTGRES_DB: medusa-docker
33 |
34 | redis:
35 | image: redis
36 | expose:
37 | - 6379
38 |
39 | volumes:
40 | node_modules:
41 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // noop
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "medusa-source-magento",
3 | "version": "0.0.9",
4 | "description": "Source plugins that allows users to import data from a Magento store to Medusa",
5 | "author": "Shahed Nasser ",
6 | "license": "MIT",
7 | "main": "index.js",
8 | "scripts": {
9 | "seed": "medusa seed -f ./data/seed.json",
10 | "build": "babel src --out-dir . --ignore **/__tests__ --extensions \".ts,.js\"",
11 | "start": "medusa develop",
12 | "watch": "babel -w src --out-dir . --ignore **/__tests__ --extensions \".ts,.js\"",
13 | "prepare": "cross-env NODE_ENV=production npm run build"
14 | },
15 | "peerDependencies": {
16 | "@medusajs/medusa": "^1.5.0",
17 | "axios": "^1.1.2",
18 | "medusa-interfaces": "^1.3.0",
19 | "typeorm": "^0.2.36",
20 | "medusa-core-utils": "^1.1.33"
21 | },
22 | "devDependencies": {
23 | "@babel/cli": "^7.14.3",
24 | "@babel/core": "^7.14.3",
25 | "@babel/preset-typescript": "^7.14.5",
26 | "babel-preset-medusa-package": "^1.1.19",
27 | "cross-env": "^7.0.3"
28 | },
29 | "repository": "https://github.com/shahednasser/medusa-source-magento",
30 | "keywords": [
31 | "medusa-plugin",
32 | "medusa-plugin-source"
33 | ],
34 | "dependencies": {
35 | "axios-oauth-1.0a": "^0.3.6"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/loaders/index.ts:
--------------------------------------------------------------------------------
1 | import { BatchJobService } from '@medusajs/medusa'
2 |
3 | export default async (container, options) => {
4 | try {
5 | const batchJobService: BatchJobService = container.resolve("batchJobService")
6 | console.log("Creating batch job to import magento products...")
7 | await batchJobService.create({
8 | type: 'import-magento',
9 | context: {
10 | options
11 | },
12 | dry_run: false,
13 | created_by: null
14 | })
15 | } catch (err) {
16 | console.log(err)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/services/README.md:
--------------------------------------------------------------------------------
1 | # Custom services
2 |
3 | You may define custom services that will be registered on the global container by creating files in the `/services` directory that export an instance of `BaseService`.
4 |
5 | ```js
6 | // my.js
7 |
8 | import { BaseService } from "medusa-interfaces";
9 |
10 | class MyService extends BaseService {
11 | constructor({ productService }) {
12 | super();
13 |
14 | this.productService_ = productService
15 | }
16 |
17 | async getProductMessage() {
18 | const [product] = await this.productService_.list({}, { take: 1 })
19 |
20 | return `Welcome to ${product.title}!`
21 | }
22 | }
23 |
24 | export default MyService;
25 | ```
26 |
27 | The first argument to the `constructor` is the global giving you access to easy dependency injection. The container holds all registered services from the core, installed plugins and from other files in the `/services` directory. The registration name is a camelCased version of the file name with the type appended i.e.: `my.js` is registered as `myService`, `custom-thing.js` is registered as `customThingService`.
28 |
29 | You may use the services you define here in custom endpoints by resolving the services defined.
30 |
31 | ```js
32 | import { Router } from "express"
33 |
34 | export default () => {
35 | const router = Router()
36 |
37 | router.get("/hello-product", async (req, res) => {
38 | const myService = req.scope.resolve("myService")
39 |
40 | res.json({
41 | message: await myService.getProductMessage()
42 | })
43 | })
44 |
45 | return router;
46 | }
47 | ```
48 |
--------------------------------------------------------------------------------
/src/services/magento-category.ts:
--------------------------------------------------------------------------------
1 | import MagentoClientService, { PluginOptions } from './magento-client';
2 | import { ProductCollection, ProductCollectionService, TransactionBaseService } from '@medusajs/medusa';
3 |
4 | import { EntityManager } from 'typeorm';
5 |
6 | type InjectedDependencies = {
7 | magentoClientService: MagentoClientService;
8 | productCollectionService: ProductCollectionService;
9 | manager: EntityManager;
10 | }
11 |
12 | class MagentoCategoryService extends TransactionBaseService {
13 | declare protected manager_: EntityManager;
14 | declare protected transactionManager_: EntityManager;
15 | protected magentoClientService_: MagentoClientService;
16 | protected productCollectionService_: ProductCollectionService;
17 |
18 | constructor(container: InjectedDependencies, options: PluginOptions) {
19 | super(container);
20 |
21 | this.manager_ = container.manager;
22 | this.magentoClientService_ = container.magentoClientService;
23 | this.productCollectionService_ = container.productCollectionService;
24 | }
25 |
26 | async create (category: any): Promise {
27 | return this.atomicPhase_(async (manager) => {
28 | //check if a collection exists for the category
29 | const existingCollection = await this.productCollectionService_
30 | .withTransaction(manager)
31 | .retrieveByHandle(this.getHandle(category))
32 | .catch(() => undefined);
33 |
34 | if (existingCollection) {
35 | return this.update(category, existingCollection)
36 | }
37 |
38 | //create collection
39 | const collectionData = this.normalizeCollection(category);
40 |
41 | await this.productCollectionService_
42 | .withTransaction(manager)
43 | .create(collectionData)
44 | })
45 | }
46 |
47 | async update (category: any, existingCollection: ProductCollection): Promise {
48 | return this.atomicPhase_(async (manager) => {
49 | const collectionData = this.normalizeCollection(category);
50 |
51 | const update = {}
52 |
53 | for (const key of Object.keys(collectionData)) {
54 | if (collectionData[key] !== existingCollection[key]) {
55 | update[key] = collectionData[key]
56 | }
57 | }
58 |
59 | if (Object.values(update).length) {
60 | await this.productCollectionService_
61 | .withTransaction(manager)
62 | .update(existingCollection.id, update)
63 | }
64 | })
65 | }
66 |
67 | normalizeCollection (category: any): any {
68 | return {
69 | title: category.name,
70 | handle: category.custom_attributes.find((attribute) => attribute.attribute_code === 'url_key')?.value,
71 | metadata: {
72 | magento_id: category.id
73 | }
74 | }
75 | }
76 |
77 | getHandle(category: any): string {
78 | return category.custom_attributes.find((attribute) => attribute.attribute_code === 'url_key')?.value || ''
79 | }
80 | }
81 |
82 | export default MagentoCategoryService;
--------------------------------------------------------------------------------
/src/services/magento-client.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance, AxiosResponse, Method } from 'axios';
2 |
3 | import { EntityManager } from 'typeorm';
4 | import { Logger } from '@medusajs/medusa/dist/types/global';
5 | import { MedusaError } from 'medusa-core-utils';
6 | import { TransactionBaseService } from '@medusajs/medusa';
7 | import addOAuthInterceptor from 'axios-oauth-1.0a';
8 |
9 | export type PluginOptions = {
10 | magento_url: string;
11 | consumer_key: string;
12 | consumer_secret: string;
13 | access_token: string;
14 | access_token_secret: string;
15 | image_prefix?: string;
16 | }
17 |
18 | type InjectedDependencies = {
19 | manager: EntityManager;
20 | logger: Logger;
21 | }
22 |
23 | export type MagentoFilters = {
24 | field: string;
25 | value: string;
26 | condition_type?: string;
27 | }
28 |
29 | type SearchCriteria = {
30 | currentPage: number;
31 | filterGroups?: MagentoFilters[][];
32 | storeId?: string;
33 | currencyCode?: string;
34 | }
35 |
36 | export enum MagentoProductTypes {
37 | CONFIGURABLE = 'configurable',
38 | SIMPLE = 'simple'
39 | }
40 |
41 | class MagentoClientService extends TransactionBaseService {
42 | declare protected manager_: EntityManager;
43 | declare protected transactionManager_: EntityManager;
44 | protected logger_: Logger;
45 | protected apiBaseUrl_: string;
46 | protected options_: PluginOptions;
47 | protected client_: AxiosInstance;
48 | protected defaultStoreId_: string;
49 | protected defaultCurrencyCode_: string;
50 | protected defaultImagePrefix_: string;
51 |
52 | constructor(container: InjectedDependencies, options: PluginOptions) {
53 | super(container);
54 | this.manager_ = container.manager
55 | this.logger_ = container.logger;
56 | this.options_ = options;
57 | this.apiBaseUrl_ = `${options.magento_url}/rest/default/V1`
58 |
59 | this.client_ = axios.create({
60 | headers: {
61 | 'Accept': 'application/json'
62 | }
63 | });
64 |
65 | addOAuthInterceptor(this.client_, {
66 | algorithm: 'HMAC-SHA256',
67 | key: options.consumer_key,
68 | secret: options.consumer_secret,
69 | token: options.access_token,
70 | tokenSecret: options.access_token_secret
71 | });
72 |
73 | this.client_.interceptors.request.use(null, (error) => {
74 | console.log(error);
75 | throw new MedusaError(
76 | MedusaError.Types.UNEXPECTED_STATE,
77 | error.response?.data?.message || error.request?.data?.message || error.message || "An error occurred while sending the request."
78 | )
79 | })
80 |
81 | this.client_.interceptors.response.use(null, (error) => {
82 | console.log(error);
83 | throw new MedusaError(
84 | MedusaError.Types.UNEXPECTED_STATE,
85 | error.response?.data?.message || error.request?.data?.message || error.message || "An error occurred while sending the request."
86 | )
87 | })
88 |
89 | this.defaultImagePrefix_ = options.image_prefix
90 | }
91 |
92 | async retrieveProducts(type?: MagentoProductTypes, lastUpdatedTime?: string, filters?: MagentoFilters[][]) : Promise[]> {
93 | const searchCriteria: SearchCriteria = {
94 | currentPage: 1,
95 | filterGroups: []
96 | }
97 |
98 | if (type) {
99 | searchCriteria.filterGroups.push([
100 | {
101 | field: 'type_id',
102 | value: type,
103 | condition_type: 'eq'
104 | }
105 | ])
106 | }
107 |
108 | if (lastUpdatedTime) {
109 | searchCriteria.filterGroups.push([
110 | {
111 | field: 'updated_at',
112 | value: lastUpdatedTime,
113 | condition_type: 'gt'
114 | }
115 | ])
116 | }
117 |
118 | if (filters) {
119 | filters.forEach((filterGroup) => {
120 | const newFilterGroup: MagentoFilters[] = filterGroup.map((filter) => ({
121 | field: filter.field,
122 | value: filter.value,
123 | condition_type: filter.condition_type || 'eq'
124 | }));
125 |
126 | searchCriteria.filterGroups.push(newFilterGroup)
127 | })
128 | }
129 |
130 | return this.sendRequest(`/products?${this.formatSearchCriteriaQuery(searchCriteria)}`)
131 | .then(async ({ data }) => {
132 | await this.retrieveDefaultConfigs();
133 | let options;
134 |
135 | if (type === MagentoProductTypes.CONFIGURABLE) {
136 | options = await this.retrieveOptions();
137 | }
138 |
139 | for (let i = 0; i < data.items.length; i++) {
140 | data.items[i].media_gallery_entries = data.items[i].media_gallery_entries?.map((entry) => {
141 | entry.url = `${this.defaultImagePrefix_}${entry.file}`
142 |
143 | return entry
144 | })
145 |
146 | if (data.items[i].extension_attributes?.configurable_product_options) {
147 | data.items[i].extension_attributes?.configurable_product_options.forEach((option) => {
148 | option.values = options.find((o) => o.attribute_id == option.attribute_id)?.options || []
149 | })
150 | }
151 |
152 | if (type === MagentoProductTypes.SIMPLE) {
153 | const response = await this.retrieveInventoryData(data.items[i].sku)
154 | data.items[i].stockData = response.data;
155 | }
156 | }
157 |
158 | return data.items;
159 | })
160 | }
161 |
162 | async retrieveProductImages(items: Record[]): Promise[]> {
163 | if (!this.defaultStoreId_ || !this.defaultCurrencyCode_) {
164 | throw new MedusaError(
165 | MedusaError.Types.INVALID_DATA,
166 | "Default Store ID and Default Currency Code must be set first."
167 | )
168 | }
169 |
170 | const { data } = await this.sendRequest(`/products-render-info?${this.formatSearchCriteriaQuery({
171 | currentPage: 1,
172 | filterGroups: [
173 | [
174 | {
175 | field: 'entity_id',
176 | value: items.map((item) => item.id).join(','),
177 | condition_type: 'in'
178 | }
179 | ]
180 | ],
181 | storeId: this.defaultStoreId_,
182 | currencyCode: this.defaultCurrencyCode_
183 | })}`)
184 |
185 | return items.map((item) => {
186 | const itemData = data.items.find((i) => i.id == item.id)
187 | if (itemData) {
188 | item.images = itemData.images || []
189 | }
190 |
191 | return item;
192 | });
193 | }
194 |
195 | async retrieveDefaultConfigs() {
196 | if (this.defaultImagePrefix_) {
197 | return;
198 | }
199 |
200 | const { data } = await this.sendRequest(`/store/storeConfigs`)
201 |
202 | const defaultStore = data.length ? data.find((store) => store.code === 'default') : data
203 |
204 | if (!this.defaultImagePrefix_) {
205 | this.defaultImagePrefix_ = `${defaultStore.base_media_url}catalog/product`
206 | }
207 | }
208 |
209 | async retrieveOptionValues (title: string) : Promise[]> {
210 | return this.sendRequest(`/products/attributes/${title}`)
211 | .then(({ data }) => {
212 | return data.options.filter((values) => values.value.length > 0);
213 | })
214 | }
215 |
216 | async retrieveOptions () : Promise[]> {
217 | const searchCriteria: SearchCriteria = {
218 | currentPage: 1
219 | }
220 |
221 | return this.sendRequest(`/products/attributes?${this.formatSearchCriteriaQuery(searchCriteria)}`)
222 | .then(({ data }) => {
223 | return data.items;
224 | })
225 | }
226 |
227 | async retrieveInventoryData (sku: string) : Promise> {
228 | return this.sendRequest(`/stockItems/${encodeURIComponent(sku)}`);
229 | }
230 |
231 | async retrieveSimpleProductsAsVariants (productIds: string[]) : Promise[]> {
232 | return this.retrieveProducts(MagentoProductTypes.SIMPLE, null, [
233 | [
234 | {
235 | field: 'entity_id',
236 | value: productIds.join(','),
237 | condition_type: 'in'
238 | }
239 | ]
240 | ])
241 | .then(async (products) => {
242 | return await Promise.all(products.map(async (variant) => {
243 | //get stock item of that variant
244 | const { data } = await this.retrieveInventoryData(variant.sku)
245 |
246 | return {
247 | ...variant,
248 | stockData: data
249 | }
250 | }))
251 | })
252 | }
253 |
254 | async retrieveCategories (lastUpdatedTime?: string) : Promise> {
255 | const searchCriteria: SearchCriteria = {
256 | currentPage: 1,
257 | filterGroups: [
258 | [
259 | {
260 | field: 'name',
261 | value: 'Root Catalog,Default Category',
262 | condition_type: 'nin'
263 | }
264 | ]
265 | ]
266 | }
267 |
268 | if (lastUpdatedTime) {
269 | searchCriteria.filterGroups.push([
270 | {
271 | field: 'updated_at',
272 | value: lastUpdatedTime,
273 | condition_type: 'gt'
274 | }
275 | ])
276 | }
277 |
278 | return this.sendRequest(`/categories/list?${this.formatSearchCriteriaQuery(searchCriteria)}`)
279 | }
280 |
281 | async sendRequest (path: string, method: Method = 'GET', data?: Record) : Promise> {
282 | return this.client_.request({
283 | url: `${this.apiBaseUrl_}${path}`,
284 | method,
285 | data
286 | })
287 | }
288 |
289 | formatSearchCriteriaQuery (searchCriteria: SearchCriteria): string {
290 | let query = `searchCriteria[currentPage]=${searchCriteria.currentPage}`;
291 |
292 | if (searchCriteria.filterGroups?.length) {
293 | searchCriteria.filterGroups.map((filterGroup, index) => {
294 | filterGroup.map((filter, filterIndex) => {
295 | query += `&searchCriteria[filterGroups][${index}][filters][${filterIndex}][field]=${filter.field}&searchCriteria[filterGroups][${index}][filters][${filterIndex}][value]=${filter.value}&searchCriteria[filterGroups][${index}][filters][${filterIndex}][condition_type]=${filter.condition_type}`;
296 | })
297 | })
298 | }
299 |
300 | if (searchCriteria.storeId) {
301 | query += `&storeId=${searchCriteria.storeId}`
302 | }
303 |
304 | if (searchCriteria.currencyCode) {
305 | query += `¤cyCode=${searchCriteria.currencyCode}`
306 | }
307 |
308 | return query;
309 | }
310 | }
311 |
312 | export default MagentoClientService
313 |
--------------------------------------------------------------------------------
/src/services/magento-product.ts:
--------------------------------------------------------------------------------
1 | import { CurrencyService, Product, ProductCollectionService, ProductService, ProductStatus, ProductVariantService, ShippingProfileService, Store, StoreService, TransactionBaseService, ProductVariant } from '@medusajs/medusa';
2 | import MagentoClientService, { MagentoProductTypes, PluginOptions } from './magento-client';
3 |
4 | import { EntityManager } from 'typeorm';
5 | import { CreateProductVariantInput } from '@medusajs/medusa/dist/types/product-variant';
6 |
7 | type InjectedDependencies = {
8 | productService: ProductService;
9 | magentoClientService: MagentoClientService;
10 | currencyService: CurrencyService;
11 | productVariantService: ProductVariantService;
12 | productCollectionService: ProductCollectionService;
13 | shippingProfileService: ShippingProfileService;
14 | storeService: StoreService;
15 | manager: EntityManager;
16 | }
17 |
18 | class MagentoProductService extends TransactionBaseService {
19 | declare protected manager_: EntityManager;
20 | declare protected transactionManager_: EntityManager;
21 | protected options_: PluginOptions;
22 | protected productService_: ProductService;
23 | protected magentoClientService_: MagentoClientService;
24 | protected currencyService_: CurrencyService;
25 | protected productVariantService_: ProductVariantService;
26 | protected productCollectionService_: ProductCollectionService;
27 | protected shippingProfileService_: ShippingProfileService;
28 | protected storeServices_: StoreService;
29 | protected currencies: string[];
30 | protected defaultShippingProfileId: string;
31 |
32 | constructor(container: InjectedDependencies, options: PluginOptions) {
33 | super(container);
34 | this.manager_ = container.manager;
35 | this.options_ = options;
36 | this.productService_ = container.productService;
37 | this.magentoClientService_ = container.magentoClientService;
38 | this.currencyService_ = container.currencyService;
39 | this.productVariantService_ = container.productVariantService;
40 | this.productCollectionService_ = container.productCollectionService;
41 | this.shippingProfileService_ = container.shippingProfileService;
42 | this.storeServices_ = container.storeService;
43 |
44 | this.currencies = [];
45 | this.defaultShippingProfileId = "";
46 | }
47 |
48 | async create (productData: any): Promise {
49 | return this.atomicPhase_(async (manager) => {
50 |
51 | //check if product exists
52 | const existingProduct: Product = await this.productService_
53 | .withTransaction(manager)
54 | .retrieveByExternalId(productData.id, {
55 | relations: ["variants", "options", "images"],
56 | })
57 | .catch(() => undefined);
58 |
59 | if (existingProduct) {
60 | //update the product instead
61 | return this.update(productData, existingProduct);
62 | } else {
63 | //check if it's a variant
64 | const existingVariant: ProductVariant = await this.productVariantService_
65 | .withTransaction(manager)
66 | .retrieveBySKU(productData.sku)
67 | .catch(() => undefined)
68 |
69 | if (existingVariant) {
70 | return this.updateVariant(productData, existingVariant);
71 | }
72 | }
73 |
74 | //retrieve store's currencies
75 | await this.getCurrencies();
76 |
77 | const normalizedProduct = this.normalizeProduct(productData);
78 | normalizedProduct.profile_id = await this.getDefaultShippingProfile();
79 |
80 | if (productData.extension_attributes?.category_links) {
81 | await this.setCategory(productData.extension_attributes?.category_links, normalizedProduct, manager)
82 | }
83 |
84 | if (productData.extension_attributes?.configurable_product_options) {
85 | //retrieve options
86 | productData.extension_attributes?.configurable_product_options.map((item) => {
87 | normalizedProduct.options.push(this.normalizeOption(item))
88 | })
89 | }
90 |
91 | let productImages = normalizedProduct.images;
92 | delete normalizedProduct.images;
93 |
94 | //create product
95 | let product = await this.productService_
96 | .withTransaction(manager)
97 | .create(normalizedProduct);
98 |
99 | if (productData.extension_attributes?.configurable_product_links) {
100 | //insert the configurable product's simple products as variants
101 | //re-retrieve product with options
102 | product = await this.productService_
103 | .withTransaction(manager)
104 | .retrieve(product.id, {
105 | relations: ['options']
106 | });
107 |
108 | //attached option id to normalized options
109 | normalizedProduct.options = normalizedProduct.options.map((option) => {
110 | const productOption = product.options.find((o) => o.title === option.title);
111 |
112 | return {
113 | ...option,
114 | id: productOption.id
115 | }
116 | })
117 |
118 | //retrieve simple products as variants
119 | const variants = await this.magentoClientService_
120 | .retrieveSimpleProductsAsVariants(productData.extension_attributes?.configurable_product_links);
121 |
122 | for (let v of variants) {
123 | const variantData = this.normalizeVariant(v, normalizedProduct.options)
124 | await this.productVariantService_
125 | .withTransaction(manager)
126 | .create(product.id, variantData as CreateProductVariantInput)
127 |
128 | if (v.media_gallery_entries) {
129 | //update products images with variant's images
130 | productImages.push(...v.media_gallery_entries.map((entry) => entry.url));
131 | }
132 | }
133 |
134 | } else {
135 | //insert a default variant for a simple product
136 |
137 | const variantData = this.normalizeVariant(productData, []);
138 |
139 | await this.productVariantService_
140 | .withTransaction(manager)
141 | .create(product.id, variantData as CreateProductVariantInput)
142 |
143 | }
144 |
145 | //insert product images
146 | productImages = [...new Set(productImages)];
147 |
148 | await this.productService_
149 | .withTransaction(manager)
150 | .update(product.id, {
151 | images: productImages
152 | })
153 | })
154 | }
155 |
156 | async update (productData: any, existingProduct: Product): Promise {
157 | return this.atomicPhase_(async (manager) => {
158 |
159 | //retrieve store's currencies
160 | await this.getCurrencies();
161 |
162 | const normalizedProduct = this.normalizeProduct(productData);
163 | let productOptions = existingProduct.options;
164 |
165 | if (productData.extension_attributes?.category_links) {
166 | await this.setCategory(productData.extension_attributes?.category_links, normalizedProduct, manager)
167 | }
168 |
169 | if (productData.extension_attributes?.configurable_product_options) {
170 | //retrieve options
171 | productData.extension_attributes.configurable_product_options.forEach(async (item) => {
172 | const existingOption = productOptions.find((o) => o.metadata.magento_id == item.id)
173 |
174 | if (!existingOption) {
175 | //add option
176 | await this.productService_
177 | .withTransaction(manager)
178 | .addOption(existingProduct.id, item.label)
179 | }
180 |
181 | //update option and its values
182 | const normalizedOption = this.normalizeOption(item)
183 | delete normalizedOption.values
184 |
185 | await this.productService_
186 | .withTransaction(manager)
187 | .updateOption(existingProduct.id, existingOption.id, normalizedOption)
188 | })
189 |
190 | //check if there are options that should be deleted
191 | const optionsToDelete = productOptions.filter(
192 | (o) => !productData.extension_attributes?.configurable_product_options.find((magento_option) => magento_option.id == o.metadata.magento_id))
193 |
194 | optionsToDelete.forEach(async (option) => {
195 | await this.productService_
196 | .withTransaction(manager)
197 | .deleteOption(existingProduct.id, option.id)
198 | })
199 |
200 | //re-retrieve product options
201 | productOptions = (await this.productService_
202 | .withTransaction(manager)
203 | .retrieveByExternalId(productData.id, {
204 | relations: ["options", "options.values"],
205 | })).options;
206 | }
207 |
208 | let productImages = existingProduct.images.map((image) => image.url)
209 |
210 | if (productData.extension_attributes?.configurable_product_links) {
211 | //attach values to the options
212 | productOptions = productOptions.map((productOption) => {
213 | const productDataOption = productData.options.find((o) => productOption.metadata.magento_id == o.id)
214 | if (productDataOption) {
215 | productOption.values = this.normalizeOption(productDataOption).values
216 | }
217 |
218 | return productOption;
219 | })
220 |
221 | //retrieve simple products as variants
222 | const variants = await this.magentoClientService_
223 | .retrieveSimpleProductsAsVariants(productData.extension_attributes.configurable_product_links);
224 |
225 | for (let v of variants) {
226 | const variantData = await this.normalizeVariant(v, productOptions)
227 |
228 | //check if variant exists
229 | const existingVariant = existingProduct.variants.find((variant) => variant.metadata.magento_id === v.id)
230 | if (existingVariant) {
231 | //update variant
232 | await this.productVariantService_
233 | .withTransaction(manager)
234 | .update(existingVariant.id, variantData)
235 | } else {
236 | //create variant
237 | await this.productVariantService_
238 | .withTransaction(manager)
239 | .create(existingProduct.id, variantData as CreateProductVariantInput)
240 | }
241 |
242 | if (v.media_gallery_entries) {
243 | productImages.push(...v.media_gallery_entries.map((entry) => entry.url))
244 | }
245 | }
246 |
247 | //check if any variants should be deleted
248 | const variantsToDelete = existingProduct.variants.filter(
249 | (v) => productData.extension_attributes.configurable_product_links.indexOf(v.metadata.magento_id) === -1
250 | )
251 |
252 | variantsToDelete.forEach(async (variant) => {
253 | await this.productVariantService_
254 | .withTransaction(manager)
255 | .delete(variant.id)
256 | })
257 | } else {
258 | //insert or update a default variant for a simple product
259 |
260 | const variantData = await this.normalizeVariant(productData, []);
261 |
262 | if (existingProduct.variants.length) {
263 | await this.productVariantService_
264 | .withTransaction(manager)
265 | .update(existingProduct.variants[0].id, variantData)
266 | } else {
267 | await this.productVariantService_
268 | .withTransaction(manager)
269 | .create(existingProduct.id, variantData as CreateProductVariantInput)
270 | }
271 | }
272 |
273 | productImages = [...new Set(productImages)];
274 |
275 | //update product
276 | delete normalizedProduct.options
277 | delete normalizedProduct.images
278 |
279 | const update = {}
280 |
281 | for (const key of Object.keys(normalizedProduct)) {
282 | if (normalizedProduct[key] !== existingProduct[key]) {
283 | update[key] = normalizedProduct[key]
284 | }
285 | }
286 |
287 | normalizedProduct.images = productImages
288 |
289 | if (Object.values(update).length) {
290 | await this.productService_
291 | .withTransaction(manager)
292 | .update(existingProduct.id, update)
293 | }
294 | })
295 | }
296 |
297 | async updateVariant (productData: any, existingVariant: ProductVariant): Promise {
298 | return this.atomicPhase_(async (manager: EntityManager) => {
299 |
300 | //retrieve store's currencies
301 | await this.getCurrencies();
302 |
303 | const variantData = await this.normalizeVariant(productData, []);
304 | delete variantData.options
305 | delete variantData.magento_id
306 |
307 | const update = {}
308 |
309 | for (const key of Object.keys(variantData)) {
310 | if (variantData[key] !== existingVariant[key]) {
311 | update[key] = variantData[key]
312 | }
313 | }
314 |
315 | if (Object.values(update).length) {
316 | await this.productVariantService_
317 | .withTransaction(manager)
318 | .update(existingVariant.id, variantData)
319 | }
320 | })
321 | }
322 |
323 | async getCurrencies () {
324 | if (this.currencies.length) {
325 | return;
326 | }
327 |
328 | const defaultStore: Store = await this.storeServices_.retrieve({ relations: ['currencies', 'default_currency'] });
329 | this.currencies = []
330 |
331 | this.currencies.push(...defaultStore.currencies?.map((currency) => currency.code) || [])
332 | this.currencies.push(defaultStore.default_currency?.code)
333 | }
334 |
335 | async getDefaultShippingProfile (): Promise {
336 | if (!this.defaultShippingProfileId.length) {
337 | this.defaultShippingProfileId = (await this.shippingProfileService_.retrieveDefault()).id;
338 | }
339 |
340 | return this.defaultShippingProfileId;
341 | }
342 |
343 | async setCategory (categories: Record[], product: Record, manager: EntityManager) {
344 | //Magento supports multiple categories for a product
345 | //since Medusa supports only one collection for a product, we'll
346 | //use the category with the highest position
347 |
348 | categories.sort((a, b) => {
349 | if (a.position > b.position) {
350 | return 1;
351 | }
352 |
353 | return a.position < b.position ? -1 : 0;
354 | })
355 |
356 | //retrieve Medusa collection using magento ID
357 | const [_, count] = await this.productCollectionService_
358 | .withTransaction(manager)
359 | .listAndCount()
360 |
361 | const existingCollections = await this.productCollectionService_
362 | .withTransaction(manager)
363 | .list({}, {
364 | skip: 0,
365 | take: count
366 | });
367 |
368 | if (existingCollections.length) {
369 | product.collection_id = existingCollections.find((collection) => {
370 | for (let category of categories) {
371 | if (collection.metadata.magento_id == category.category_id) {
372 | return true;
373 | }
374 | }
375 |
376 | return false;
377 | })?.id
378 | }
379 |
380 | return product;
381 | }
382 |
383 | normalizeProduct(product: Record): any {
384 | return {
385 | title: product.name,
386 | handle: product.custom_attributes?.find((attribute) => attribute.attribute_code === 'url_key')?.value,
387 | description: this.removeHtmlTags(product.custom_attributes?.find((attribute) => attribute.attribute_code === 'description')?.value || ''),
388 | type: {
389 | value: product.type_id
390 | },
391 | external_id: product.id,
392 | status: product.status == 1 ? ProductStatus.PUBLISHED : ProductStatus.DRAFT,
393 | images: product.media_gallery_entries?.map((img) => img.url) || [],
394 | thumbnail: product.media_gallery_entries?.find((img) => img.types.includes('thumbnail'))?.url,
395 | options: [],
396 | collection_id: null
397 | };
398 | }
399 |
400 | normalizeVariant (variant: Record, options?: Record[]): Record {
401 | return {
402 | title: variant.name,
403 | prices: this.currencies.map((currency) => ({
404 | amount: this.parsePrice(variant.price),
405 | currency_code: currency
406 | })),
407 | sku: variant.sku,
408 | inventory_quantity: variant.stockData.qty,
409 | allow_backorder: variant.stockData.backorders > 0,
410 | manage_inventory: variant.stockData.manage_stock,
411 | weight: variant.weight || 0,
412 | options: options?.map((option) => {
413 | const variantOption = variant.custom_attributes?.find((attribute) => attribute.attribute_code.toLowerCase() === option.title.toLowerCase())
414 | if (variantOption) {
415 | return {
416 | option_id: option.id,
417 | value: option.values.find((value) => value.metadata?.magento_value === variantOption.value)?.value
418 | }
419 | }
420 | }),
421 | metadata: {
422 | magento_id: variant.id
423 | }
424 | }
425 | }
426 |
427 | normalizeOption (option: Record): any {
428 | return {
429 | title: option.label,
430 | values: option.values.map((value) => ({
431 | value: value.label,
432 | metadata: {
433 | magento_value: value.value,
434 | }
435 | })),
436 | metadata: {
437 | magento_id: option.id
438 | }
439 | }
440 | }
441 |
442 | parsePrice(price: any): number {
443 | return parseInt((parseFloat(Number(price).toFixed(2)) * 100).toString());
444 | }
445 |
446 | removeHtmlTags(str: string): string {
447 | if ((str===null) || (str==='')) {
448 | return '';
449 | }
450 |
451 | str = str.toString();
452 |
453 | // Regular expression to identify HTML tags in
454 | // the input string. Replacing the identified
455 | // HTML tag with a null string.
456 | return str.replace( /(<([^>]+)>)/ig, '');
457 | }
458 | }
459 |
460 | export default MagentoProductService
--------------------------------------------------------------------------------
/src/strategies/import.ts:
--------------------------------------------------------------------------------
1 | import { AbstractBatchJobStrategy, BatchJob, BatchJobService, ProductVariantService, Store, StoreService } from '@medusajs/medusa'
2 | import MagentoClientService, { MagentoProductTypes } from '../services/magento-client';
3 |
4 | import { EntityManager } from 'typeorm'
5 | import { Logger } from '@medusajs/medusa/dist/types/global';
6 | import MagentoCategoryService from '../services/magento-category';
7 | import MagentoProductService from '../services/magento-product';
8 |
9 | type InjectedDependencies = {
10 | storeService: StoreService;
11 | magentoProductService: MagentoProductService;
12 | magentoClientService: MagentoClientService;
13 | magentoCategoryService: MagentoCategoryService;
14 | productVariantService: ProductVariantService;
15 | logger: Logger;
16 | manager: EntityManager;
17 | batchJobService: BatchJobService;
18 | }
19 |
20 | class ImportStrategy extends AbstractBatchJobStrategy {
21 | static identifier = 'import-magento-strategy'
22 | static batchType = 'import-magento'
23 |
24 | protected batchJobService_: BatchJobService
25 | protected storeService_: StoreService;
26 | protected magentoProductService_: MagentoProductService;
27 | protected magentoClientService_: MagentoClientService;
28 | protected magentoCategoryService_: MagentoCategoryService;
29 | protected productVariantService: ProductVariantService;
30 | protected logger_: Logger;
31 |
32 | constructor(container: InjectedDependencies) {
33 | super(container);
34 |
35 | this.manager_ = container.manager;
36 | this.storeService_ = container.storeService;
37 | this.magentoProductService_ = container.magentoProductService;
38 | this.magentoClientService_ = container.magentoClientService;
39 | this.magentoCategoryService_ = container.magentoCategoryService;
40 | this.productVariantService = container.productVariantService;
41 | this.logger_ = container.logger;
42 | this.batchJobService_ = container.batchJobService;
43 | }
44 |
45 | async preProcessBatchJob(batchJobId: string): Promise {
46 | return await this.atomicPhase_(async (transactionManager) => {
47 | const batchJob = (await this.batchJobService_
48 | .withTransaction(transactionManager)
49 | .retrieve(batchJobId))
50 |
51 | await this.batchJobService_
52 | .withTransaction(transactionManager)
53 | .update(batchJob, {
54 | result: {
55 | progress: 0
56 | }
57 | })
58 | })
59 | }
60 |
61 | async processJob(batchJobId: string): Promise {
62 | const batchJob = (await this.batchJobService_
63 | .retrieve(batchJobId))
64 |
65 | let store: Store
66 |
67 | try {
68 | store = await this.storeService_.retrieve();
69 | } catch (e) {
70 | this.logger_.info('Skipping Magento import since no store is created in Medusa.');
71 | return;
72 | }
73 |
74 | this.logger_.info('Importing categories from Magento...')
75 | const lastUpdatedTime = await this.getBuildTime(store)
76 |
77 | //retrieve categories
78 | const { data } = await this.magentoClientService_.retrieveCategories(lastUpdatedTime);
79 |
80 | data.items.map(async (category) => {
81 | return this.magentoCategoryService_
82 | .create(category);
83 | })
84 |
85 | if (data.items.length) {
86 | this.logger_.info(`${data.items.length} categories have been imported or updated successfully.`)
87 | } else {
88 | this.logger_.info(`No categories have been imported or updated.`)
89 | }
90 |
91 | this.logger_.info('Importing products from Magento...')
92 |
93 | //retrieve configurable products
94 | const products = await this.magentoClientService_.retrieveProducts(MagentoProductTypes.CONFIGURABLE, lastUpdatedTime);
95 |
96 | for (let product of products) {
97 | await this.magentoProductService_
98 | .create(product);
99 | }
100 |
101 | //retrieve simple products to insert those that don't belong to a configurable product
102 | const simpleProducts = await this.magentoClientService_.retrieveProducts(MagentoProductTypes.SIMPLE, lastUpdatedTime);
103 |
104 | for (let product of simpleProducts) {
105 | await this.magentoProductService_
106 | .create(product);
107 | }
108 |
109 | if (products.length || simpleProducts.length) {
110 | this.logger_.info(`${products.length + simpleProducts.length} products have been imported or updated successfully.`)
111 | } else {
112 | this.logger_.info(`No products have been imported or updated.`)
113 | }
114 |
115 | await this.updateBuildTime(store);
116 | }
117 |
118 | async getBuildTime(store?: Store|null): Promise {
119 | let buildtime = null
120 |
121 | try {
122 | if (!store) {
123 | store = await this.storeService_.retrieve()
124 | }
125 | } catch {
126 | return null
127 | }
128 |
129 | if (store.metadata?.source_magento_bt) {
130 | buildtime = store.metadata.source_magento_bt
131 | }
132 |
133 | if (!buildtime) {
134 | return null
135 | }
136 |
137 | return buildtime
138 | }
139 |
140 | async updateBuildTime (store?: Store|null): Promise {
141 | try {
142 | if (!store) {
143 | store = await this.storeService_.retrieve()
144 | }
145 | } catch {
146 | return null
147 | }
148 |
149 | const payload = {
150 | metadata: {
151 | source_magento_bt: new Date().toISOString(),
152 | },
153 | }
154 |
155 | await this.storeService_.update(payload)
156 | }
157 |
158 | protected async shouldRetryOnProcessingError(batchJob: BatchJob, err: unknown): Promise {
159 | return true
160 | }
161 |
162 | buildTemplate(): Promise {
163 | throw new Error('Method not implemented.')
164 | }
165 | declare protected manager_: EntityManager
166 | declare protected transactionManager_: EntityManager
167 |
168 | }
169 |
170 | export default ImportStrategy
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["es5", "es6"],
4 | "target": "esnext",
5 | "allowJs": true,
6 | "esModuleInterop": true,
7 | "module": "commonjs",
8 | "moduleResolution": "node",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "skipLibCheck": true,
12 | "skipDefaultLibCheck": true,
13 | "declaration": false,
14 | "sourceMap": false,
15 | "outDir": "./dist",
16 | "rootDir": "src",
17 | "baseUrl": "src"
18 | },
19 | "include": ["src"],
20 | "exclude": [
21 | "**/__tests__",
22 | "**/__fixtures__",
23 | "node_modules"
24 | ]
25 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@ampproject/remapping@^2.1.0":
6 | version "2.2.0"
7 | resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz"
8 | dependencies:
9 | "@jridgewell/gen-mapping" "^0.1.0"
10 | "@jridgewell/trace-mapping" "^0.3.9"
11 |
12 | "@babel/cli@^7.14.3":
13 | version "7.19.3"
14 | resolved "https://registry.npmjs.org/@babel/cli/-/cli-7.19.3.tgz"
15 | dependencies:
16 | "@jridgewell/trace-mapping" "^0.3.8"
17 | commander "^4.0.1"
18 | convert-source-map "^1.1.0"
19 | fs-readdir-recursive "^1.1.0"
20 | glob "^7.2.0"
21 | make-dir "^2.1.0"
22 | slash "^2.0.0"
23 | optionalDependencies:
24 | "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3"
25 | chokidar "^3.4.0"
26 |
27 | "@babel/code-frame@^7.18.6":
28 | version "7.18.6"
29 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz"
30 | dependencies:
31 | "@babel/highlight" "^7.18.6"
32 |
33 | "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.19.3", "@babel/compat-data@^7.19.4":
34 | version "7.19.4"
35 | resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz"
36 |
37 | "@babel/core@^7.14.3":
38 | version "7.19.3"
39 | resolved "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz"
40 | dependencies:
41 | "@ampproject/remapping" "^2.1.0"
42 | "@babel/code-frame" "^7.18.6"
43 | "@babel/generator" "^7.19.3"
44 | "@babel/helper-compilation-targets" "^7.19.3"
45 | "@babel/helper-module-transforms" "^7.19.0"
46 | "@babel/helpers" "^7.19.0"
47 | "@babel/parser" "^7.19.3"
48 | "@babel/template" "^7.18.10"
49 | "@babel/traverse" "^7.19.3"
50 | "@babel/types" "^7.19.3"
51 | convert-source-map "^1.7.0"
52 | debug "^4.1.0"
53 | gensync "^1.0.0-beta.2"
54 | json5 "^2.2.1"
55 | semver "^6.3.0"
56 |
57 | "@babel/generator@^7.19.3", "@babel/generator@^7.19.4":
58 | version "7.19.5"
59 | resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz"
60 | dependencies:
61 | "@babel/types" "^7.19.4"
62 | "@jridgewell/gen-mapping" "^0.3.2"
63 | jsesc "^2.5.1"
64 |
65 | "@babel/helper-annotate-as-pure@^7.18.6":
66 | version "7.18.6"
67 | resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz"
68 | dependencies:
69 | "@babel/types" "^7.18.6"
70 |
71 | "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6":
72 | version "7.18.9"
73 | resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz"
74 | dependencies:
75 | "@babel/helper-explode-assignable-expression" "^7.18.6"
76 | "@babel/types" "^7.18.9"
77 |
78 | "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.3":
79 | version "7.19.3"
80 | resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz"
81 | dependencies:
82 | "@babel/compat-data" "^7.19.3"
83 | "@babel/helper-validator-option" "^7.18.6"
84 | browserslist "^4.21.3"
85 | semver "^6.3.0"
86 |
87 | "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.19.0":
88 | version "7.19.0"
89 | resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz"
90 | dependencies:
91 | "@babel/helper-annotate-as-pure" "^7.18.6"
92 | "@babel/helper-environment-visitor" "^7.18.9"
93 | "@babel/helper-function-name" "^7.19.0"
94 | "@babel/helper-member-expression-to-functions" "^7.18.9"
95 | "@babel/helper-optimise-call-expression" "^7.18.6"
96 | "@babel/helper-replace-supers" "^7.18.9"
97 | "@babel/helper-split-export-declaration" "^7.18.6"
98 |
99 | "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0":
100 | version "7.19.0"
101 | resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz"
102 | dependencies:
103 | "@babel/helper-annotate-as-pure" "^7.18.6"
104 | regexpu-core "^5.1.0"
105 |
106 | "@babel/helper-define-polyfill-provider@^0.3.3":
107 | version "0.3.3"
108 | resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz"
109 | dependencies:
110 | "@babel/helper-compilation-targets" "^7.17.7"
111 | "@babel/helper-plugin-utils" "^7.16.7"
112 | debug "^4.1.1"
113 | lodash.debounce "^4.0.8"
114 | resolve "^1.14.2"
115 | semver "^6.1.2"
116 |
117 | "@babel/helper-environment-visitor@^7.18.9":
118 | version "7.18.9"
119 | resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz"
120 |
121 | "@babel/helper-explode-assignable-expression@^7.18.6":
122 | version "7.18.6"
123 | resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz"
124 | dependencies:
125 | "@babel/types" "^7.18.6"
126 |
127 | "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0":
128 | version "7.19.0"
129 | resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz"
130 | dependencies:
131 | "@babel/template" "^7.18.10"
132 | "@babel/types" "^7.19.0"
133 |
134 | "@babel/helper-hoist-variables@^7.18.6":
135 | version "7.18.6"
136 | resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz"
137 | dependencies:
138 | "@babel/types" "^7.18.6"
139 |
140 | "@babel/helper-member-expression-to-functions@^7.18.9":
141 | version "7.18.9"
142 | resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz"
143 | dependencies:
144 | "@babel/types" "^7.18.9"
145 |
146 | "@babel/helper-module-imports@^7.18.6":
147 | version "7.18.6"
148 | resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz"
149 | dependencies:
150 | "@babel/types" "^7.18.6"
151 |
152 | "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0":
153 | version "7.19.0"
154 | resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz"
155 | dependencies:
156 | "@babel/helper-environment-visitor" "^7.18.9"
157 | "@babel/helper-module-imports" "^7.18.6"
158 | "@babel/helper-simple-access" "^7.18.6"
159 | "@babel/helper-split-export-declaration" "^7.18.6"
160 | "@babel/helper-validator-identifier" "^7.18.6"
161 | "@babel/template" "^7.18.10"
162 | "@babel/traverse" "^7.19.0"
163 | "@babel/types" "^7.19.0"
164 |
165 | "@babel/helper-optimise-call-expression@^7.18.6":
166 | version "7.18.6"
167 | resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz"
168 | dependencies:
169 | "@babel/types" "^7.18.6"
170 |
171 | "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
172 | version "7.19.0"
173 | resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz"
174 |
175 | "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9":
176 | version "7.18.9"
177 | resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz"
178 | dependencies:
179 | "@babel/helper-annotate-as-pure" "^7.18.6"
180 | "@babel/helper-environment-visitor" "^7.18.9"
181 | "@babel/helper-wrap-function" "^7.18.9"
182 | "@babel/types" "^7.18.9"
183 |
184 | "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9", "@babel/helper-replace-supers@^7.19.1":
185 | version "7.19.1"
186 | resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz"
187 | dependencies:
188 | "@babel/helper-environment-visitor" "^7.18.9"
189 | "@babel/helper-member-expression-to-functions" "^7.18.9"
190 | "@babel/helper-optimise-call-expression" "^7.18.6"
191 | "@babel/traverse" "^7.19.1"
192 | "@babel/types" "^7.19.0"
193 |
194 | "@babel/helper-simple-access@^7.18.6":
195 | version "7.19.4"
196 | resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz"
197 | dependencies:
198 | "@babel/types" "^7.19.4"
199 |
200 | "@babel/helper-skip-transparent-expression-wrappers@^7.18.9":
201 | version "7.18.9"
202 | resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz"
203 | dependencies:
204 | "@babel/types" "^7.18.9"
205 |
206 | "@babel/helper-split-export-declaration@^7.18.6":
207 | version "7.18.6"
208 | resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz"
209 | dependencies:
210 | "@babel/types" "^7.18.6"
211 |
212 | "@babel/helper-string-parser@^7.19.4":
213 | version "7.19.4"
214 | resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz"
215 |
216 | "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
217 | version "7.19.1"
218 | resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz"
219 |
220 | "@babel/helper-validator-option@^7.18.6":
221 | version "7.18.6"
222 | resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz"
223 |
224 | "@babel/helper-wrap-function@^7.18.9":
225 | version "7.19.0"
226 | resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz"
227 | dependencies:
228 | "@babel/helper-function-name" "^7.19.0"
229 | "@babel/template" "^7.18.10"
230 | "@babel/traverse" "^7.19.0"
231 | "@babel/types" "^7.19.0"
232 |
233 | "@babel/helpers@^7.19.0":
234 | version "7.19.4"
235 | resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz"
236 | dependencies:
237 | "@babel/template" "^7.18.10"
238 | "@babel/traverse" "^7.19.4"
239 | "@babel/types" "^7.19.4"
240 |
241 | "@babel/highlight@^7.18.6":
242 | version "7.18.6"
243 | resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz"
244 | dependencies:
245 | "@babel/helper-validator-identifier" "^7.18.6"
246 | chalk "^2.0.0"
247 | js-tokens "^4.0.0"
248 |
249 | "@babel/parser@^7.18.10", "@babel/parser@^7.19.3", "@babel/parser@^7.19.4":
250 | version "7.19.4"
251 | resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz"
252 |
253 | "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
254 | version "7.18.6"
255 | resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz"
256 | dependencies:
257 | "@babel/helper-plugin-utils" "^7.18.6"
258 |
259 | "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9":
260 | version "7.18.9"
261 | resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz"
262 | dependencies:
263 | "@babel/helper-plugin-utils" "^7.18.9"
264 | "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
265 | "@babel/plugin-proposal-optional-chaining" "^7.18.9"
266 |
267 | "@babel/plugin-proposal-async-generator-functions@^7.19.1":
268 | version "7.19.1"
269 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz"
270 | dependencies:
271 | "@babel/helper-environment-visitor" "^7.18.9"
272 | "@babel/helper-plugin-utils" "^7.19.0"
273 | "@babel/helper-remap-async-to-generator" "^7.18.9"
274 | "@babel/plugin-syntax-async-generators" "^7.8.4"
275 |
276 | "@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.18.6":
277 | version "7.18.6"
278 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz"
279 | dependencies:
280 | "@babel/helper-create-class-features-plugin" "^7.18.6"
281 | "@babel/helper-plugin-utils" "^7.18.6"
282 |
283 | "@babel/plugin-proposal-class-static-block@^7.18.6":
284 | version "7.18.6"
285 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz"
286 | dependencies:
287 | "@babel/helper-create-class-features-plugin" "^7.18.6"
288 | "@babel/helper-plugin-utils" "^7.18.6"
289 | "@babel/plugin-syntax-class-static-block" "^7.14.5"
290 |
291 | "@babel/plugin-proposal-decorators@^7.12.1":
292 | version "7.19.3"
293 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.19.3.tgz"
294 | dependencies:
295 | "@babel/helper-create-class-features-plugin" "^7.19.0"
296 | "@babel/helper-plugin-utils" "^7.19.0"
297 | "@babel/helper-replace-supers" "^7.19.1"
298 | "@babel/helper-split-export-declaration" "^7.18.6"
299 | "@babel/plugin-syntax-decorators" "^7.19.0"
300 |
301 | "@babel/plugin-proposal-dynamic-import@^7.18.6":
302 | version "7.18.6"
303 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz"
304 | dependencies:
305 | "@babel/helper-plugin-utils" "^7.18.6"
306 | "@babel/plugin-syntax-dynamic-import" "^7.8.3"
307 |
308 | "@babel/plugin-proposal-export-namespace-from@^7.18.9":
309 | version "7.18.9"
310 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz"
311 | dependencies:
312 | "@babel/helper-plugin-utils" "^7.18.9"
313 | "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
314 |
315 | "@babel/plugin-proposal-json-strings@^7.18.6":
316 | version "7.18.6"
317 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz"
318 | dependencies:
319 | "@babel/helper-plugin-utils" "^7.18.6"
320 | "@babel/plugin-syntax-json-strings" "^7.8.3"
321 |
322 | "@babel/plugin-proposal-logical-assignment-operators@^7.18.9":
323 | version "7.18.9"
324 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz"
325 | dependencies:
326 | "@babel/helper-plugin-utils" "^7.18.9"
327 | "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
328 |
329 | "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
330 | version "7.18.6"
331 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz"
332 | dependencies:
333 | "@babel/helper-plugin-utils" "^7.18.6"
334 | "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
335 |
336 | "@babel/plugin-proposal-numeric-separator@^7.18.6":
337 | version "7.18.6"
338 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz"
339 | dependencies:
340 | "@babel/helper-plugin-utils" "^7.18.6"
341 | "@babel/plugin-syntax-numeric-separator" "^7.10.4"
342 |
343 | "@babel/plugin-proposal-object-rest-spread@^7.19.4":
344 | version "7.19.4"
345 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.19.4.tgz"
346 | dependencies:
347 | "@babel/compat-data" "^7.19.4"
348 | "@babel/helper-compilation-targets" "^7.19.3"
349 | "@babel/helper-plugin-utils" "^7.19.0"
350 | "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
351 | "@babel/plugin-transform-parameters" "^7.18.8"
352 |
353 | "@babel/plugin-proposal-optional-catch-binding@^7.18.6":
354 | version "7.18.6"
355 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz"
356 | dependencies:
357 | "@babel/helper-plugin-utils" "^7.18.6"
358 | "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
359 |
360 | "@babel/plugin-proposal-optional-chaining@^7.14.2", "@babel/plugin-proposal-optional-chaining@^7.18.9":
361 | version "7.18.9"
362 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz"
363 | dependencies:
364 | "@babel/helper-plugin-utils" "^7.18.9"
365 | "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
366 | "@babel/plugin-syntax-optional-chaining" "^7.8.3"
367 |
368 | "@babel/plugin-proposal-private-methods@^7.18.6":
369 | version "7.18.6"
370 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz"
371 | dependencies:
372 | "@babel/helper-create-class-features-plugin" "^7.18.6"
373 | "@babel/helper-plugin-utils" "^7.18.6"
374 |
375 | "@babel/plugin-proposal-private-property-in-object@^7.18.6":
376 | version "7.18.6"
377 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz"
378 | dependencies:
379 | "@babel/helper-annotate-as-pure" "^7.18.6"
380 | "@babel/helper-create-class-features-plugin" "^7.18.6"
381 | "@babel/helper-plugin-utils" "^7.18.6"
382 | "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
383 |
384 | "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
385 | version "7.18.6"
386 | resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz"
387 | dependencies:
388 | "@babel/helper-create-regexp-features-plugin" "^7.18.6"
389 | "@babel/helper-plugin-utils" "^7.18.6"
390 |
391 | "@babel/plugin-syntax-async-generators@^7.8.4":
392 | version "7.8.4"
393 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz"
394 | dependencies:
395 | "@babel/helper-plugin-utils" "^7.8.0"
396 |
397 | "@babel/plugin-syntax-class-properties@^7.12.13":
398 | version "7.12.13"
399 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz"
400 | dependencies:
401 | "@babel/helper-plugin-utils" "^7.12.13"
402 |
403 | "@babel/plugin-syntax-class-static-block@^7.14.5":
404 | version "7.14.5"
405 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz"
406 | dependencies:
407 | "@babel/helper-plugin-utils" "^7.14.5"
408 |
409 | "@babel/plugin-syntax-decorators@^7.19.0":
410 | version "7.19.0"
411 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.19.0.tgz"
412 | dependencies:
413 | "@babel/helper-plugin-utils" "^7.19.0"
414 |
415 | "@babel/plugin-syntax-dynamic-import@^7.8.3":
416 | version "7.8.3"
417 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz"
418 | dependencies:
419 | "@babel/helper-plugin-utils" "^7.8.0"
420 |
421 | "@babel/plugin-syntax-export-namespace-from@^7.8.3":
422 | version "7.8.3"
423 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz"
424 | dependencies:
425 | "@babel/helper-plugin-utils" "^7.8.3"
426 |
427 | "@babel/plugin-syntax-import-assertions@^7.18.6":
428 | version "7.18.6"
429 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz"
430 | dependencies:
431 | "@babel/helper-plugin-utils" "^7.18.6"
432 |
433 | "@babel/plugin-syntax-json-strings@^7.8.3":
434 | version "7.8.3"
435 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz"
436 | dependencies:
437 | "@babel/helper-plugin-utils" "^7.8.0"
438 |
439 | "@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
440 | version "7.10.4"
441 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz"
442 | dependencies:
443 | "@babel/helper-plugin-utils" "^7.10.4"
444 |
445 | "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
446 | version "7.8.3"
447 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz"
448 | dependencies:
449 | "@babel/helper-plugin-utils" "^7.8.0"
450 |
451 | "@babel/plugin-syntax-numeric-separator@^7.10.4":
452 | version "7.10.4"
453 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz"
454 | dependencies:
455 | "@babel/helper-plugin-utils" "^7.10.4"
456 |
457 | "@babel/plugin-syntax-object-rest-spread@^7.8.3":
458 | version "7.8.3"
459 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz"
460 | dependencies:
461 | "@babel/helper-plugin-utils" "^7.8.0"
462 |
463 | "@babel/plugin-syntax-optional-catch-binding@^7.8.3":
464 | version "7.8.3"
465 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz"
466 | dependencies:
467 | "@babel/helper-plugin-utils" "^7.8.0"
468 |
469 | "@babel/plugin-syntax-optional-chaining@^7.8.3":
470 | version "7.8.3"
471 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz"
472 | dependencies:
473 | "@babel/helper-plugin-utils" "^7.8.0"
474 |
475 | "@babel/plugin-syntax-private-property-in-object@^7.14.5":
476 | version "7.14.5"
477 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz"
478 | dependencies:
479 | "@babel/helper-plugin-utils" "^7.14.5"
480 |
481 | "@babel/plugin-syntax-top-level-await@^7.14.5":
482 | version "7.14.5"
483 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz"
484 | dependencies:
485 | "@babel/helper-plugin-utils" "^7.14.5"
486 |
487 | "@babel/plugin-syntax-typescript@^7.18.6":
488 | version "7.18.6"
489 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz"
490 | dependencies:
491 | "@babel/helper-plugin-utils" "^7.18.6"
492 |
493 | "@babel/plugin-transform-arrow-functions@^7.18.6":
494 | version "7.18.6"
495 | resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz"
496 | dependencies:
497 | "@babel/helper-plugin-utils" "^7.18.6"
498 |
499 | "@babel/plugin-transform-async-to-generator@^7.18.6":
500 | version "7.18.6"
501 | resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz"
502 | dependencies:
503 | "@babel/helper-module-imports" "^7.18.6"
504 | "@babel/helper-plugin-utils" "^7.18.6"
505 | "@babel/helper-remap-async-to-generator" "^7.18.6"
506 |
507 | "@babel/plugin-transform-block-scoped-functions@^7.18.6":
508 | version "7.18.6"
509 | resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz"
510 | dependencies:
511 | "@babel/helper-plugin-utils" "^7.18.6"
512 |
513 | "@babel/plugin-transform-block-scoping@^7.19.4":
514 | version "7.19.4"
515 | resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.19.4.tgz"
516 | dependencies:
517 | "@babel/helper-plugin-utils" "^7.19.0"
518 |
519 | "@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.19.0":
520 | version "7.19.0"
521 | resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz"
522 | dependencies:
523 | "@babel/helper-annotate-as-pure" "^7.18.6"
524 | "@babel/helper-compilation-targets" "^7.19.0"
525 | "@babel/helper-environment-visitor" "^7.18.9"
526 | "@babel/helper-function-name" "^7.19.0"
527 | "@babel/helper-optimise-call-expression" "^7.18.6"
528 | "@babel/helper-plugin-utils" "^7.19.0"
529 | "@babel/helper-replace-supers" "^7.18.9"
530 | "@babel/helper-split-export-declaration" "^7.18.6"
531 | globals "^11.1.0"
532 |
533 | "@babel/plugin-transform-computed-properties@^7.18.9":
534 | version "7.18.9"
535 | resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz"
536 | dependencies:
537 | "@babel/helper-plugin-utils" "^7.18.9"
538 |
539 | "@babel/plugin-transform-destructuring@^7.19.4":
540 | version "7.19.4"
541 | resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.19.4.tgz"
542 | dependencies:
543 | "@babel/helper-plugin-utils" "^7.19.0"
544 |
545 | "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4":
546 | version "7.18.6"
547 | resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz"
548 | dependencies:
549 | "@babel/helper-create-regexp-features-plugin" "^7.18.6"
550 | "@babel/helper-plugin-utils" "^7.18.6"
551 |
552 | "@babel/plugin-transform-duplicate-keys@^7.18.9":
553 | version "7.18.9"
554 | resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz"
555 | dependencies:
556 | "@babel/helper-plugin-utils" "^7.18.9"
557 |
558 | "@babel/plugin-transform-exponentiation-operator@^7.18.6":
559 | version "7.18.6"
560 | resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz"
561 | dependencies:
562 | "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6"
563 | "@babel/helper-plugin-utils" "^7.18.6"
564 |
565 | "@babel/plugin-transform-for-of@^7.18.8":
566 | version "7.18.8"
567 | resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz"
568 | dependencies:
569 | "@babel/helper-plugin-utils" "^7.18.6"
570 |
571 | "@babel/plugin-transform-function-name@^7.18.9":
572 | version "7.18.9"
573 | resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz"
574 | dependencies:
575 | "@babel/helper-compilation-targets" "^7.18.9"
576 | "@babel/helper-function-name" "^7.18.9"
577 | "@babel/helper-plugin-utils" "^7.18.9"
578 |
579 | "@babel/plugin-transform-instanceof@^7.12.1":
580 | version "7.18.9"
581 | resolved "https://registry.npmjs.org/@babel/plugin-transform-instanceof/-/plugin-transform-instanceof-7.18.9.tgz"
582 | dependencies:
583 | "@babel/helper-plugin-utils" "^7.18.9"
584 |
585 | "@babel/plugin-transform-literals@^7.18.9":
586 | version "7.18.9"
587 | resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz"
588 | dependencies:
589 | "@babel/helper-plugin-utils" "^7.18.9"
590 |
591 | "@babel/plugin-transform-member-expression-literals@^7.18.6":
592 | version "7.18.6"
593 | resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz"
594 | dependencies:
595 | "@babel/helper-plugin-utils" "^7.18.6"
596 |
597 | "@babel/plugin-transform-modules-amd@^7.18.6":
598 | version "7.18.6"
599 | resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz"
600 | dependencies:
601 | "@babel/helper-module-transforms" "^7.18.6"
602 | "@babel/helper-plugin-utils" "^7.18.6"
603 | babel-plugin-dynamic-import-node "^2.3.3"
604 |
605 | "@babel/plugin-transform-modules-commonjs@^7.18.6":
606 | version "7.18.6"
607 | resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz"
608 | dependencies:
609 | "@babel/helper-module-transforms" "^7.18.6"
610 | "@babel/helper-plugin-utils" "^7.18.6"
611 | "@babel/helper-simple-access" "^7.18.6"
612 | babel-plugin-dynamic-import-node "^2.3.3"
613 |
614 | "@babel/plugin-transform-modules-systemjs@^7.19.0":
615 | version "7.19.0"
616 | resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz"
617 | dependencies:
618 | "@babel/helper-hoist-variables" "^7.18.6"
619 | "@babel/helper-module-transforms" "^7.19.0"
620 | "@babel/helper-plugin-utils" "^7.19.0"
621 | "@babel/helper-validator-identifier" "^7.18.6"
622 | babel-plugin-dynamic-import-node "^2.3.3"
623 |
624 | "@babel/plugin-transform-modules-umd@^7.18.6":
625 | version "7.18.6"
626 | resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz"
627 | dependencies:
628 | "@babel/helper-module-transforms" "^7.18.6"
629 | "@babel/helper-plugin-utils" "^7.18.6"
630 |
631 | "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1":
632 | version "7.19.1"
633 | resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz"
634 | dependencies:
635 | "@babel/helper-create-regexp-features-plugin" "^7.19.0"
636 | "@babel/helper-plugin-utils" "^7.19.0"
637 |
638 | "@babel/plugin-transform-new-target@^7.18.6":
639 | version "7.18.6"
640 | resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz"
641 | dependencies:
642 | "@babel/helper-plugin-utils" "^7.18.6"
643 |
644 | "@babel/plugin-transform-object-super@^7.18.6":
645 | version "7.18.6"
646 | resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz"
647 | dependencies:
648 | "@babel/helper-plugin-utils" "^7.18.6"
649 | "@babel/helper-replace-supers" "^7.18.6"
650 |
651 | "@babel/plugin-transform-parameters@^7.18.8":
652 | version "7.18.8"
653 | resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz"
654 | dependencies:
655 | "@babel/helper-plugin-utils" "^7.18.6"
656 |
657 | "@babel/plugin-transform-property-literals@^7.18.6":
658 | version "7.18.6"
659 | resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz"
660 | dependencies:
661 | "@babel/helper-plugin-utils" "^7.18.6"
662 |
663 | "@babel/plugin-transform-regenerator@^7.18.6":
664 | version "7.18.6"
665 | resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz"
666 | dependencies:
667 | "@babel/helper-plugin-utils" "^7.18.6"
668 | regenerator-transform "^0.15.0"
669 |
670 | "@babel/plugin-transform-reserved-words@^7.18.6":
671 | version "7.18.6"
672 | resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz"
673 | dependencies:
674 | "@babel/helper-plugin-utils" "^7.18.6"
675 |
676 | "@babel/plugin-transform-runtime@^7.12.1":
677 | version "7.19.1"
678 | resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.1.tgz"
679 | dependencies:
680 | "@babel/helper-module-imports" "^7.18.6"
681 | "@babel/helper-plugin-utils" "^7.19.0"
682 | babel-plugin-polyfill-corejs2 "^0.3.3"
683 | babel-plugin-polyfill-corejs3 "^0.6.0"
684 | babel-plugin-polyfill-regenerator "^0.4.1"
685 | semver "^6.3.0"
686 |
687 | "@babel/plugin-transform-shorthand-properties@^7.18.6":
688 | version "7.18.6"
689 | resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz"
690 | dependencies:
691 | "@babel/helper-plugin-utils" "^7.18.6"
692 |
693 | "@babel/plugin-transform-spread@^7.19.0":
694 | version "7.19.0"
695 | resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz"
696 | dependencies:
697 | "@babel/helper-plugin-utils" "^7.19.0"
698 | "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
699 |
700 | "@babel/plugin-transform-sticky-regex@^7.18.6":
701 | version "7.18.6"
702 | resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz"
703 | dependencies:
704 | "@babel/helper-plugin-utils" "^7.18.6"
705 |
706 | "@babel/plugin-transform-template-literals@^7.18.9":
707 | version "7.18.9"
708 | resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz"
709 | dependencies:
710 | "@babel/helper-plugin-utils" "^7.18.9"
711 |
712 | "@babel/plugin-transform-typeof-symbol@^7.18.9":
713 | version "7.18.9"
714 | resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz"
715 | dependencies:
716 | "@babel/helper-plugin-utils" "^7.18.9"
717 |
718 | "@babel/plugin-transform-typescript@^7.18.6":
719 | version "7.19.3"
720 | resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz"
721 | dependencies:
722 | "@babel/helper-create-class-features-plugin" "^7.19.0"
723 | "@babel/helper-plugin-utils" "^7.19.0"
724 | "@babel/plugin-syntax-typescript" "^7.18.6"
725 |
726 | "@babel/plugin-transform-unicode-escapes@^7.18.10":
727 | version "7.18.10"
728 | resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz"
729 | dependencies:
730 | "@babel/helper-plugin-utils" "^7.18.9"
731 |
732 | "@babel/plugin-transform-unicode-regex@^7.18.6":
733 | version "7.18.6"
734 | resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz"
735 | dependencies:
736 | "@babel/helper-create-regexp-features-plugin" "^7.18.6"
737 | "@babel/helper-plugin-utils" "^7.18.6"
738 |
739 | "@babel/preset-env@^7.12.7":
740 | version "7.19.4"
741 | resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.4.tgz"
742 | dependencies:
743 | "@babel/compat-data" "^7.19.4"
744 | "@babel/helper-compilation-targets" "^7.19.3"
745 | "@babel/helper-plugin-utils" "^7.19.0"
746 | "@babel/helper-validator-option" "^7.18.6"
747 | "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6"
748 | "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9"
749 | "@babel/plugin-proposal-async-generator-functions" "^7.19.1"
750 | "@babel/plugin-proposal-class-properties" "^7.18.6"
751 | "@babel/plugin-proposal-class-static-block" "^7.18.6"
752 | "@babel/plugin-proposal-dynamic-import" "^7.18.6"
753 | "@babel/plugin-proposal-export-namespace-from" "^7.18.9"
754 | "@babel/plugin-proposal-json-strings" "^7.18.6"
755 | "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9"
756 | "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6"
757 | "@babel/plugin-proposal-numeric-separator" "^7.18.6"
758 | "@babel/plugin-proposal-object-rest-spread" "^7.19.4"
759 | "@babel/plugin-proposal-optional-catch-binding" "^7.18.6"
760 | "@babel/plugin-proposal-optional-chaining" "^7.18.9"
761 | "@babel/plugin-proposal-private-methods" "^7.18.6"
762 | "@babel/plugin-proposal-private-property-in-object" "^7.18.6"
763 | "@babel/plugin-proposal-unicode-property-regex" "^7.18.6"
764 | "@babel/plugin-syntax-async-generators" "^7.8.4"
765 | "@babel/plugin-syntax-class-properties" "^7.12.13"
766 | "@babel/plugin-syntax-class-static-block" "^7.14.5"
767 | "@babel/plugin-syntax-dynamic-import" "^7.8.3"
768 | "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
769 | "@babel/plugin-syntax-import-assertions" "^7.18.6"
770 | "@babel/plugin-syntax-json-strings" "^7.8.3"
771 | "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
772 | "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
773 | "@babel/plugin-syntax-numeric-separator" "^7.10.4"
774 | "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
775 | "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
776 | "@babel/plugin-syntax-optional-chaining" "^7.8.3"
777 | "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
778 | "@babel/plugin-syntax-top-level-await" "^7.14.5"
779 | "@babel/plugin-transform-arrow-functions" "^7.18.6"
780 | "@babel/plugin-transform-async-to-generator" "^7.18.6"
781 | "@babel/plugin-transform-block-scoped-functions" "^7.18.6"
782 | "@babel/plugin-transform-block-scoping" "^7.19.4"
783 | "@babel/plugin-transform-classes" "^7.19.0"
784 | "@babel/plugin-transform-computed-properties" "^7.18.9"
785 | "@babel/plugin-transform-destructuring" "^7.19.4"
786 | "@babel/plugin-transform-dotall-regex" "^7.18.6"
787 | "@babel/plugin-transform-duplicate-keys" "^7.18.9"
788 | "@babel/plugin-transform-exponentiation-operator" "^7.18.6"
789 | "@babel/plugin-transform-for-of" "^7.18.8"
790 | "@babel/plugin-transform-function-name" "^7.18.9"
791 | "@babel/plugin-transform-literals" "^7.18.9"
792 | "@babel/plugin-transform-member-expression-literals" "^7.18.6"
793 | "@babel/plugin-transform-modules-amd" "^7.18.6"
794 | "@babel/plugin-transform-modules-commonjs" "^7.18.6"
795 | "@babel/plugin-transform-modules-systemjs" "^7.19.0"
796 | "@babel/plugin-transform-modules-umd" "^7.18.6"
797 | "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1"
798 | "@babel/plugin-transform-new-target" "^7.18.6"
799 | "@babel/plugin-transform-object-super" "^7.18.6"
800 | "@babel/plugin-transform-parameters" "^7.18.8"
801 | "@babel/plugin-transform-property-literals" "^7.18.6"
802 | "@babel/plugin-transform-regenerator" "^7.18.6"
803 | "@babel/plugin-transform-reserved-words" "^7.18.6"
804 | "@babel/plugin-transform-shorthand-properties" "^7.18.6"
805 | "@babel/plugin-transform-spread" "^7.19.0"
806 | "@babel/plugin-transform-sticky-regex" "^7.18.6"
807 | "@babel/plugin-transform-template-literals" "^7.18.9"
808 | "@babel/plugin-transform-typeof-symbol" "^7.18.9"
809 | "@babel/plugin-transform-unicode-escapes" "^7.18.10"
810 | "@babel/plugin-transform-unicode-regex" "^7.18.6"
811 | "@babel/preset-modules" "^0.1.5"
812 | "@babel/types" "^7.19.4"
813 | babel-plugin-polyfill-corejs2 "^0.3.3"
814 | babel-plugin-polyfill-corejs3 "^0.6.0"
815 | babel-plugin-polyfill-regenerator "^0.4.1"
816 | core-js-compat "^3.25.1"
817 | semver "^6.3.0"
818 |
819 | "@babel/preset-modules@^0.1.5":
820 | version "0.1.5"
821 | resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz"
822 | dependencies:
823 | "@babel/helper-plugin-utils" "^7.0.0"
824 | "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
825 | "@babel/plugin-transform-dotall-regex" "^7.4.4"
826 | "@babel/types" "^7.4.4"
827 | esutils "^2.0.2"
828 |
829 | "@babel/preset-typescript@^7.14.5", "@babel/preset-typescript@^7.16.0":
830 | version "7.18.6"
831 | resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz"
832 | dependencies:
833 | "@babel/helper-plugin-utils" "^7.18.6"
834 | "@babel/helper-validator-option" "^7.18.6"
835 | "@babel/plugin-transform-typescript" "^7.18.6"
836 |
837 | "@babel/runtime@^7.8.4":
838 | version "7.19.4"
839 | resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz"
840 | dependencies:
841 | regenerator-runtime "^0.13.4"
842 |
843 | "@babel/template@^7.18.10":
844 | version "7.18.10"
845 | resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz"
846 | dependencies:
847 | "@babel/code-frame" "^7.18.6"
848 | "@babel/parser" "^7.18.10"
849 | "@babel/types" "^7.18.10"
850 |
851 | "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.19.3", "@babel/traverse@^7.19.4":
852 | version "7.19.4"
853 | resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz"
854 | dependencies:
855 | "@babel/code-frame" "^7.18.6"
856 | "@babel/generator" "^7.19.4"
857 | "@babel/helper-environment-visitor" "^7.18.9"
858 | "@babel/helper-function-name" "^7.19.0"
859 | "@babel/helper-hoist-variables" "^7.18.6"
860 | "@babel/helper-split-export-declaration" "^7.18.6"
861 | "@babel/parser" "^7.19.4"
862 | "@babel/types" "^7.19.4"
863 | debug "^4.1.0"
864 | globals "^11.1.0"
865 |
866 | "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.19.4", "@babel/types@^7.4.4":
867 | version "7.19.4"
868 | resolved "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz"
869 | dependencies:
870 | "@babel/helper-string-parser" "^7.19.4"
871 | "@babel/helper-validator-identifier" "^7.19.1"
872 | to-fast-properties "^2.0.0"
873 |
874 | "@jridgewell/gen-mapping@^0.1.0":
875 | version "0.1.1"
876 | resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz"
877 | dependencies:
878 | "@jridgewell/set-array" "^1.0.0"
879 | "@jridgewell/sourcemap-codec" "^1.4.10"
880 |
881 | "@jridgewell/gen-mapping@^0.3.2":
882 | version "0.3.2"
883 | resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz"
884 | dependencies:
885 | "@jridgewell/set-array" "^1.0.1"
886 | "@jridgewell/sourcemap-codec" "^1.4.10"
887 | "@jridgewell/trace-mapping" "^0.3.9"
888 |
889 | "@jridgewell/resolve-uri@3.1.0":
890 | version "3.1.0"
891 | resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz"
892 |
893 | "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
894 | version "1.1.2"
895 | resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz"
896 |
897 | "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
898 | version "1.4.14"
899 | resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz"
900 |
901 | "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9":
902 | version "0.3.17"
903 | resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz"
904 | dependencies:
905 | "@jridgewell/resolve-uri" "3.1.0"
906 | "@jridgewell/sourcemap-codec" "1.4.14"
907 |
908 | "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3":
909 | version "2.1.8-no-fsevents.3"
910 | resolved "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz"
911 |
912 | ansi-styles@^3.2.1:
913 | version "3.2.1"
914 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
915 | dependencies:
916 | color-convert "^1.9.0"
917 |
918 | anymatch@~3.1.2:
919 | version "3.1.2"
920 | resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz"
921 | dependencies:
922 | normalize-path "^3.0.0"
923 | picomatch "^2.0.4"
924 |
925 | axios-oauth-1.0a@^0.3.6:
926 | version "0.3.6"
927 | resolved "https://registry.npmjs.org/axios-oauth-1.0a/-/axios-oauth-1.0a-0.3.6.tgz"
928 | dependencies:
929 | oauth-sign "^0.9.0"
930 |
931 | babel-plugin-dynamic-import-node@^2.3.3:
932 | version "2.3.3"
933 | resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz"
934 | dependencies:
935 | object.assign "^4.1.0"
936 |
937 | babel-plugin-polyfill-corejs2@^0.3.3:
938 | version "0.3.3"
939 | resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz"
940 | dependencies:
941 | "@babel/compat-data" "^7.17.7"
942 | "@babel/helper-define-polyfill-provider" "^0.3.3"
943 | semver "^6.1.1"
944 |
945 | babel-plugin-polyfill-corejs3@^0.6.0:
946 | version "0.6.0"
947 | resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz"
948 | dependencies:
949 | "@babel/helper-define-polyfill-provider" "^0.3.3"
950 | core-js-compat "^3.25.1"
951 |
952 | babel-plugin-polyfill-regenerator@^0.4.1:
953 | version "0.4.1"
954 | resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz"
955 | dependencies:
956 | "@babel/helper-define-polyfill-provider" "^0.3.3"
957 |
958 | babel-plugin-transform-typescript-metadata@^0.3.1:
959 | version "0.3.2"
960 | resolved "https://registry.npmjs.org/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz"
961 | dependencies:
962 | "@babel/helper-plugin-utils" "^7.0.0"
963 |
964 | babel-preset-medusa-package@^1.1.19:
965 | version "1.1.19"
966 | resolved "https://registry.npmjs.org/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.19.tgz"
967 | dependencies:
968 | "@babel/plugin-proposal-class-properties" "^7.12.1"
969 | "@babel/plugin-proposal-decorators" "^7.12.1"
970 | "@babel/plugin-proposal-optional-chaining" "^7.14.2"
971 | "@babel/plugin-transform-classes" "^7.12.1"
972 | "@babel/plugin-transform-instanceof" "^7.12.1"
973 | "@babel/plugin-transform-runtime" "^7.12.1"
974 | "@babel/preset-env" "^7.12.7"
975 | "@babel/preset-typescript" "^7.16.0"
976 | babel-plugin-transform-typescript-metadata "^0.3.1"
977 | core-js "^3.7.0"
978 |
979 | balanced-match@^1.0.0:
980 | version "1.0.2"
981 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
982 |
983 | binary-extensions@^2.0.0:
984 | version "2.2.0"
985 | resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
986 |
987 | brace-expansion@^1.1.7:
988 | version "1.1.11"
989 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
990 | dependencies:
991 | balanced-match "^1.0.0"
992 | concat-map "0.0.1"
993 |
994 | braces@~3.0.2:
995 | version "3.0.2"
996 | resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
997 | dependencies:
998 | fill-range "^7.0.1"
999 |
1000 | browserslist@^4.21.3, browserslist@^4.21.4:
1001 | version "4.21.4"
1002 | resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz"
1003 | dependencies:
1004 | caniuse-lite "^1.0.30001400"
1005 | electron-to-chromium "^1.4.251"
1006 | node-releases "^2.0.6"
1007 | update-browserslist-db "^1.0.9"
1008 |
1009 | call-bind@^1.0.2:
1010 | version "1.0.2"
1011 | resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz"
1012 | dependencies:
1013 | function-bind "^1.1.1"
1014 | get-intrinsic "^1.0.2"
1015 |
1016 | caniuse-lite@^1.0.30001400:
1017 | version "1.0.30001419"
1018 | resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001419.tgz"
1019 |
1020 | chalk@^2.0.0:
1021 | version "2.4.2"
1022 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
1023 | dependencies:
1024 | ansi-styles "^3.2.1"
1025 | escape-string-regexp "^1.0.5"
1026 | supports-color "^5.3.0"
1027 |
1028 | chokidar@^3.4.0:
1029 | version "3.5.3"
1030 | resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
1031 | dependencies:
1032 | anymatch "~3.1.2"
1033 | braces "~3.0.2"
1034 | glob-parent "~5.1.2"
1035 | is-binary-path "~2.1.0"
1036 | is-glob "~4.0.1"
1037 | normalize-path "~3.0.0"
1038 | readdirp "~3.6.0"
1039 | optionalDependencies:
1040 | fsevents "~2.3.2"
1041 |
1042 | color-convert@^1.9.0:
1043 | version "1.9.3"
1044 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
1045 | dependencies:
1046 | color-name "1.1.3"
1047 |
1048 | color-name@1.1.3:
1049 | version "1.1.3"
1050 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
1051 |
1052 | commander@^4.0.1:
1053 | version "4.1.1"
1054 | resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
1055 |
1056 | concat-map@0.0.1:
1057 | version "0.0.1"
1058 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
1059 |
1060 | convert-source-map@^1.1.0, convert-source-map@^1.7.0:
1061 | version "1.9.0"
1062 | resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
1063 |
1064 | core-js-compat@^3.25.1:
1065 | version "3.25.5"
1066 | resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.5.tgz"
1067 | dependencies:
1068 | browserslist "^4.21.4"
1069 |
1070 | core-js@^3.7.0:
1071 | version "3.25.5"
1072 | resolved "https://registry.npmjs.org/core-js/-/core-js-3.25.5.tgz"
1073 |
1074 | cross-env@^7.0.3:
1075 | version "7.0.3"
1076 | resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz"
1077 | dependencies:
1078 | cross-spawn "^7.0.1"
1079 |
1080 | cross-spawn@^7.0.1:
1081 | version "7.0.3"
1082 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
1083 | dependencies:
1084 | path-key "^3.1.0"
1085 | shebang-command "^2.0.0"
1086 | which "^2.0.1"
1087 |
1088 | debug@^4.1.0, debug@^4.1.1:
1089 | version "4.3.4"
1090 | resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
1091 | dependencies:
1092 | ms "2.1.2"
1093 |
1094 | define-properties@^1.1.4:
1095 | version "1.1.4"
1096 | resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz"
1097 | dependencies:
1098 | has-property-descriptors "^1.0.0"
1099 | object-keys "^1.1.1"
1100 |
1101 | electron-to-chromium@^1.4.251:
1102 | version "1.4.282"
1103 | resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.282.tgz"
1104 |
1105 | escalade@^3.1.1:
1106 | version "3.1.1"
1107 | resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
1108 |
1109 | escape-string-regexp@^1.0.5:
1110 | version "1.0.5"
1111 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
1112 |
1113 | esutils@^2.0.2:
1114 | version "2.0.3"
1115 | resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
1116 |
1117 | fill-range@^7.0.1:
1118 | version "7.0.1"
1119 | resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
1120 | dependencies:
1121 | to-regex-range "^5.0.1"
1122 |
1123 | fs-readdir-recursive@^1.1.0:
1124 | version "1.1.0"
1125 | resolved "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz"
1126 |
1127 | fs.realpath@^1.0.0:
1128 | version "1.0.0"
1129 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
1130 |
1131 | fsevents@~2.3.2:
1132 | version "2.3.2"
1133 | resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
1134 |
1135 | function-bind@^1.1.1:
1136 | version "1.1.1"
1137 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
1138 |
1139 | gensync@^1.0.0-beta.2:
1140 | version "1.0.0-beta.2"
1141 | resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz"
1142 |
1143 | get-intrinsic@^1.0.2, get-intrinsic@^1.1.1:
1144 | version "1.1.3"
1145 | resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz"
1146 | dependencies:
1147 | function-bind "^1.1.1"
1148 | has "^1.0.3"
1149 | has-symbols "^1.0.3"
1150 |
1151 | glob-parent@~5.1.2:
1152 | version "5.1.2"
1153 | resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
1154 | dependencies:
1155 | is-glob "^4.0.1"
1156 |
1157 | glob@^7.2.0:
1158 | version "7.2.3"
1159 | resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
1160 | dependencies:
1161 | fs.realpath "^1.0.0"
1162 | inflight "^1.0.4"
1163 | inherits "2"
1164 | minimatch "^3.1.1"
1165 | once "^1.3.0"
1166 | path-is-absolute "^1.0.0"
1167 |
1168 | globals@^11.1.0:
1169 | version "11.12.0"
1170 | resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
1171 |
1172 | has-flag@^3.0.0:
1173 | version "3.0.0"
1174 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
1175 |
1176 | has-property-descriptors@^1.0.0:
1177 | version "1.0.0"
1178 | resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz"
1179 | dependencies:
1180 | get-intrinsic "^1.1.1"
1181 |
1182 | has-symbols@^1.0.3:
1183 | version "1.0.3"
1184 | resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz"
1185 |
1186 | has@^1.0.3:
1187 | version "1.0.3"
1188 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
1189 | dependencies:
1190 | function-bind "^1.1.1"
1191 |
1192 | inflight@^1.0.4:
1193 | version "1.0.6"
1194 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
1195 | dependencies:
1196 | once "^1.3.0"
1197 | wrappy "1"
1198 |
1199 | inherits@2:
1200 | version "2.0.4"
1201 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
1202 |
1203 | is-binary-path@~2.1.0:
1204 | version "2.1.0"
1205 | resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
1206 | dependencies:
1207 | binary-extensions "^2.0.0"
1208 |
1209 | is-core-module@^2.9.0:
1210 | version "2.10.0"
1211 | resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz"
1212 | dependencies:
1213 | has "^1.0.3"
1214 |
1215 | is-extglob@^2.1.1:
1216 | version "2.1.1"
1217 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
1218 |
1219 | is-glob@^4.0.1, is-glob@~4.0.1:
1220 | version "4.0.3"
1221 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
1222 | dependencies:
1223 | is-extglob "^2.1.1"
1224 |
1225 | is-number@^7.0.0:
1226 | version "7.0.0"
1227 | resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
1228 |
1229 | isexe@^2.0.0:
1230 | version "2.0.0"
1231 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
1232 |
1233 | js-tokens@^4.0.0:
1234 | version "4.0.0"
1235 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
1236 |
1237 | jsesc@^2.5.1:
1238 | version "2.5.2"
1239 | resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
1240 |
1241 | jsesc@~0.5.0:
1242 | version "0.5.0"
1243 | resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz"
1244 |
1245 | json5@^2.2.1:
1246 | version "2.2.3"
1247 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
1248 |
1249 | lodash.debounce@^4.0.8:
1250 | version "4.0.8"
1251 | resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
1252 |
1253 | make-dir@^2.1.0:
1254 | version "2.1.0"
1255 | resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz"
1256 | dependencies:
1257 | pify "^4.0.1"
1258 | semver "^5.6.0"
1259 |
1260 | minimatch@^3.1.1:
1261 | version "3.1.2"
1262 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
1263 | dependencies:
1264 | brace-expansion "^1.1.7"
1265 |
1266 | ms@2.1.2:
1267 | version "2.1.2"
1268 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
1269 |
1270 | node-releases@^2.0.6:
1271 | version "2.0.6"
1272 | resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz"
1273 |
1274 | normalize-path@^3.0.0, normalize-path@~3.0.0:
1275 | version "3.0.0"
1276 | resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
1277 |
1278 | oauth-sign@^0.9.0:
1279 | version "0.9.0"
1280 | resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz"
1281 |
1282 | object-keys@^1.1.1:
1283 | version "1.1.1"
1284 | resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz"
1285 |
1286 | object.assign@^4.1.0:
1287 | version "4.1.4"
1288 | resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz"
1289 | dependencies:
1290 | call-bind "^1.0.2"
1291 | define-properties "^1.1.4"
1292 | has-symbols "^1.0.3"
1293 | object-keys "^1.1.1"
1294 |
1295 | once@^1.3.0:
1296 | version "1.4.0"
1297 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
1298 | dependencies:
1299 | wrappy "1"
1300 |
1301 | path-is-absolute@^1.0.0:
1302 | version "1.0.1"
1303 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
1304 |
1305 | path-key@^3.1.0:
1306 | version "3.1.1"
1307 | resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
1308 |
1309 | path-parse@^1.0.7:
1310 | version "1.0.7"
1311 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
1312 |
1313 | picocolors@^1.0.0:
1314 | version "1.0.0"
1315 | resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
1316 |
1317 | picomatch@^2.0.4, picomatch@^2.2.1:
1318 | version "2.3.1"
1319 | resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
1320 |
1321 | pify@^4.0.1:
1322 | version "4.0.1"
1323 | resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz"
1324 |
1325 | readdirp@~3.6.0:
1326 | version "3.6.0"
1327 | resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
1328 | dependencies:
1329 | picomatch "^2.2.1"
1330 |
1331 | regenerate-unicode-properties@^10.1.0:
1332 | version "10.1.0"
1333 | resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz"
1334 | dependencies:
1335 | regenerate "^1.4.2"
1336 |
1337 | regenerate@^1.4.2:
1338 | version "1.4.2"
1339 | resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz"
1340 |
1341 | regenerator-runtime@^0.13.4:
1342 | version "0.13.10"
1343 | resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz"
1344 |
1345 | regenerator-transform@^0.15.0:
1346 | version "0.15.0"
1347 | resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz"
1348 | dependencies:
1349 | "@babel/runtime" "^7.8.4"
1350 |
1351 | regexpu-core@^5.1.0:
1352 | version "5.2.1"
1353 | resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz"
1354 | dependencies:
1355 | regenerate "^1.4.2"
1356 | regenerate-unicode-properties "^10.1.0"
1357 | regjsgen "^0.7.1"
1358 | regjsparser "^0.9.1"
1359 | unicode-match-property-ecmascript "^2.0.0"
1360 | unicode-match-property-value-ecmascript "^2.0.0"
1361 |
1362 | regjsgen@^0.7.1:
1363 | version "0.7.1"
1364 | resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz"
1365 |
1366 | regjsparser@^0.9.1:
1367 | version "0.9.1"
1368 | resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz"
1369 | dependencies:
1370 | jsesc "~0.5.0"
1371 |
1372 | resolve@^1.14.2:
1373 | version "1.22.1"
1374 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz"
1375 | dependencies:
1376 | is-core-module "^2.9.0"
1377 | path-parse "^1.0.7"
1378 | supports-preserve-symlinks-flag "^1.0.0"
1379 |
1380 | semver@^5.6.0:
1381 | version "5.7.1"
1382 | resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
1383 |
1384 | semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
1385 | version "6.3.0"
1386 | resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz"
1387 |
1388 | shebang-command@^2.0.0:
1389 | version "2.0.0"
1390 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
1391 | dependencies:
1392 | shebang-regex "^3.0.0"
1393 |
1394 | shebang-regex@^3.0.0:
1395 | version "3.0.0"
1396 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
1397 |
1398 | slash@^2.0.0:
1399 | version "2.0.0"
1400 | resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz"
1401 |
1402 | supports-color@^5.3.0:
1403 | version "5.5.0"
1404 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
1405 | dependencies:
1406 | has-flag "^3.0.0"
1407 |
1408 | supports-preserve-symlinks-flag@^1.0.0:
1409 | version "1.0.0"
1410 | resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
1411 |
1412 | to-fast-properties@^2.0.0:
1413 | version "2.0.0"
1414 | resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
1415 |
1416 | to-regex-range@^5.0.1:
1417 | version "5.0.1"
1418 | resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
1419 | dependencies:
1420 | is-number "^7.0.0"
1421 |
1422 | unicode-canonical-property-names-ecmascript@^2.0.0:
1423 | version "2.0.0"
1424 | resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz"
1425 |
1426 | unicode-match-property-ecmascript@^2.0.0:
1427 | version "2.0.0"
1428 | resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz"
1429 | dependencies:
1430 | unicode-canonical-property-names-ecmascript "^2.0.0"
1431 | unicode-property-aliases-ecmascript "^2.0.0"
1432 |
1433 | unicode-match-property-value-ecmascript@^2.0.0:
1434 | version "2.0.0"
1435 | resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz"
1436 |
1437 | unicode-property-aliases-ecmascript@^2.0.0:
1438 | version "2.1.0"
1439 | resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz"
1440 |
1441 | update-browserslist-db@^1.0.9:
1442 | version "1.0.10"
1443 | resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz"
1444 | dependencies:
1445 | escalade "^3.1.1"
1446 | picocolors "^1.0.0"
1447 |
1448 | which@^2.0.1:
1449 | version "2.0.2"
1450 | resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"
1451 | dependencies:
1452 | isexe "^2.0.0"
1453 |
1454 | wrappy@1:
1455 | version "1.0.2"
1456 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
1457 |
--------------------------------------------------------------------------------