Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
a2cc18a434
|
|||
|
58e6157f40
|
|||
|
2bf9345f69
|
|||
|
e5dad3f2d6
|
|||
|
47930b010f
|
|||
|
5666702ccc
|
|||
|
771fe4931a
|
|||
|
c6bdcfe7cc
|
|||
|
60cad4b501
|
|||
|
01d29ee023
|
|||
|
3c1871ce1f
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
/nbproject
|
||||
|
||||
.phpunit.result.cache
|
||||
.phpunit.cache
|
||||
|
||||
151
README.md
151
README.md
@@ -8,14 +8,17 @@ Without 3rd-party dependencies.
|
||||
|
||||
These formats are supported for now: `http`, `curl`, `wget`.
|
||||
|
||||
> This project was quickly written in my spare time to solve one exact problem in one NDA-project, so it may
|
||||
> contain stupid errors and (for sure) doesn't cover all possible cases according to collection schema.
|
||||
> So feel free to propose your improvements.
|
||||
> This project has been started and quickly written in my spare time to solve one exact problem in one NDA-project,
|
||||
> so it may contain stupid errors and (for sure) doesn't cover all possible cases according to collection schema.
|
||||
> Feel free to propose your improvements.
|
||||
|
||||
Versions older than the latest are not supported, only current one is.
|
||||
If you found an error in old version please ensure if an error you found has been fixed in latest version.
|
||||
So please always use the latest version of `pm-convert`.
|
||||
|
||||
## Supported features
|
||||
|
||||
* [collection schema **v2.1**](https://schema.postman.com/json/collection/v2.1.0/collection.json);
|
||||
* `Bearer` auth;
|
||||
* collection schemas [**v2.1**](https://schema.postman.com/json/collection/v2.1.0/collection.json) and [**v2.0**](https://schema.postman.com/json/collection/v2.0.0/collection.json);
|
||||
* replace vars in requests by stored in collection and environment file;
|
||||
* export one or several collections (or even whole directories) into one or all of formats supported at the same time;
|
||||
* all headers (including disabled for `http`-format);
|
||||
@@ -24,10 +27,9 @@ These formats are supported for now: `http`, `curl`, `wget`.
|
||||
|
||||
## Planned features
|
||||
|
||||
- conversion between postman schema v2.1 <-> v2.0 (#11);
|
||||
- support as many as possible/necessary of authentication kinds (_currently only `Bearer` supported_);
|
||||
- support as many as possible/necessary of body formats (_currently only `json` and `formdata`_);
|
||||
- documentation generation support (markdown) with responce examples (if present) (#6);
|
||||
- support as many as possible/necessary of body formats (_currently only `json` and `formdata` supported_);
|
||||
- documentation generation support (markdown) with response examples (if present) (#6);
|
||||
- maybe some another convert formats (like httpie or something...);
|
||||
- better logging;
|
||||
- 90%+ test coverage, phpcs, psalm, etc.;
|
||||
@@ -65,10 +67,10 @@ Possible ARGUMENTS:
|
||||
-o, --output - a directory OUTPUT_PATH to put results in
|
||||
-e, --env - use environment file with variables to replace in requests
|
||||
--var "NAME=VALUE" - force replace specified env variable called NAME with custom VALUE
|
||||
(see interpolation notes below)
|
||||
-p, --preserve - do not delete OUTPUT_PATH (if exists)
|
||||
--dump - convert provided arguments into settings file in `pwd`
|
||||
-h, --help - show this help message and exit
|
||||
-v, --version - show version info and exit
|
||||
--version - show version info and exit
|
||||
|
||||
If no ARGUMENTS passed then --help implied.
|
||||
If both -f and -d are specified then only unique set of files from both arguments will be converted.
|
||||
@@ -78,32 +80,26 @@ OUTPUT_PATH must be a valid path to writeable directory.
|
||||
If -o or -e was specified several times then only last one will be used.
|
||||
|
||||
Possible FORMATS:
|
||||
--http - generate raw *.http files (default)
|
||||
--curl - generate shell scripts with curl command
|
||||
--wget - generate shell scripts with wget command
|
||||
--http - generate raw *.http files (default)
|
||||
--curl - generate shell scripts with curl command
|
||||
--wget - generate shell scripts with wget command
|
||||
--v2.0 - convert from Postman Collection Schema v2.1 into v2.0
|
||||
--v2.1 - convert from Postman Collection Schema v2.0 into v2.1
|
||||
-a, --all - convert to all of formats listed above
|
||||
|
||||
If no FORMATS specified then --http implied.
|
||||
Any of FORMATS can be specified at the same time.
|
||||
|
||||
Notes about variable interpolation:
|
||||
1. You can use -e to tell where to find variables to replace in requests.
|
||||
2. You can use one or several --var to replace specific env variables to your own value.
|
||||
3. Correct syntax is `--var "NAME=VALUE". NAME may be in curly braces like {{NAME}}.
|
||||
4. Since -e is optional, a bunch of --var will emulate an environment. Also it does not
|
||||
matter if there is --var in environment file you provided or not.
|
||||
5. Even if you (not) provided -e and/or --var, any of variable may still be overridden
|
||||
from collection (if any), so last ones has top priority.
|
||||
Any of FORMATS can be specified at the same time or replaced by --all.
|
||||
|
||||
Example:
|
||||
./pm-convert \
|
||||
-f ~/dir1/first.postman_collection.json \
|
||||
--directory ~/team \
|
||||
--file ~/dir2/second.postman_collection.json \
|
||||
--env ~/localhost.postman_environment.json \
|
||||
-d ~/personal \
|
||||
--var "myvar=some value" \
|
||||
-o ~/postman_export
|
||||
|
||||
./pm-convert \
|
||||
-f ~/dir1/first.postman_collection.json \
|
||||
--directory ~/team \
|
||||
--file ~/dir2/second.postman_collection.json \
|
||||
--env ~/localhost.postman_environment.json \
|
||||
-d ~/personal \
|
||||
--var "myvar=some value" \
|
||||
-o ~/postman_export \
|
||||
--all
|
||||
```
|
||||
|
||||
### Notices
|
||||
@@ -116,12 +112,95 @@ Example:
|
||||
If not, you can rename them in Postman or convert collections with similar names into different directories.
|
||||
Otherwise any generated file may be accidently overwritten by another one.
|
||||
|
||||
## Notes about variable interpolation
|
||||
|
||||
1. You can use -e to tell where to find variables to replace in requests.
|
||||
2. You can use one or several --var to replace specific env variables to your own value.
|
||||
3. Correct syntax is `--var "NAME=VALUE"`. `NAME` may be in curly braces like `{{NAME}}`.
|
||||
4. Since -e is optional, a bunch of `--var` will emulate an environment. Also it does not matter if there is `--var` in environment file you provided or not.
|
||||
5. Even if you (not) provided -e and/or `--var`, any of variable may still be overridden from collection (if any), so last ones has top priority.
|
||||
|
||||
### Notes about conversion between Postman Schemas
|
||||
|
||||
You can use `--v2.1` to convert v2.1 into v2.1 (and this is not a typo).
|
||||
Same applies to `--v2.0`.
|
||||
|
||||
There is a case when a collection has been exported via Postman API.
|
||||
In such case collection itself places in single root object called `collection` like this:
|
||||
|
||||
```
|
||||
{
|
||||
"collection": {
|
||||
// your actual collection here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
So, pm-convert will just raise actual data up on top level and write into disk.
|
||||
|
||||
## Settings file
|
||||
|
||||
You may want to specify parameters once and just use them everytime without explicit defining arguments to `pm-convert`.
|
||||
|
||||
This might be done in several ways.
|
||||
|
||||
1. Save this file as `pm-convert-settings.json` in your project directory:
|
||||
|
||||
```json
|
||||
{
|
||||
"directories": [],
|
||||
"files": [],
|
||||
"environment": "",
|
||||
"output": "",
|
||||
"preserveOutput": false,
|
||||
"formats": [],
|
||||
"vars": {}
|
||||
}
|
||||
```
|
||||
|
||||
Fill it with values you need.
|
||||
|
||||
2. Add `--dump` at the end of your command and all arguments you provided will be converted and saved as
|
||||
`pm-convert-settings.json` in your curent working directory. For example in `--help` file will contain this:
|
||||
|
||||
```json
|
||||
{
|
||||
"directories": [
|
||||
"~/team",
|
||||
"~/personal"
|
||||
],
|
||||
"files": [
|
||||
"~/dir1/first.postman_collection.json",
|
||||
"~/dir2/second.postman_collection.json"
|
||||
],
|
||||
"environment": "~/localhost.postman_environment.json",
|
||||
"output": "~/postman_export",
|
||||
"preserveOutput": false,
|
||||
"formats": [
|
||||
"http",
|
||||
"curl",
|
||||
"wget",
|
||||
"v2.0",
|
||||
"v2.1"
|
||||
],
|
||||
"vars": {
|
||||
"myvar": "some value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If settings file already exists then you will be asked what to do: overwrite it, back it up or exit.
|
||||
|
||||
Once settings file saved in current you can just run `pm-convert`.
|
||||
Settings will be applied like if you pass them explicitly via arguments.
|
||||
|
||||
## How to implement a new format
|
||||
|
||||
1. Create new namespace in `./src/Converters` and name it according to format of your choice
|
||||
2. Create two classes for converter and request object which extends `Converters\Abstract\Abstract{Converter, Request}` respectively
|
||||
3. Change constants values in your new request class according to format you want to implement
|
||||
4. Write your own logic in converter's `__toString()` method, write new methods and override abstract ones
|
||||
1. Create new namespace in `./src/Converters` and name it according to format of your choice.
|
||||
2. Create two classes for converter and request object which extends `Converters\Abstract\Abstract{Converter, Request}` respectively.
|
||||
3. Change constants values in your new request class according to format you want to implement.
|
||||
4. Add your converter class name in `Converters\ConvertFormat`.
|
||||
5. Write your own logic in converter, write new methods and override abstract ones.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
],
|
||||
"keywords": ["postman", "collection", "converter", "http", "wget", "curl", "api", "convert"],
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-json": "*"
|
||||
"php": "^8.2",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-readline": "*"
|
||||
},
|
||||
"bin": ["pm-convert"],
|
||||
"autoload": {
|
||||
|
||||
269
composer.lock
generated
269
composer.lock
generated
@@ -4,21 +4,21 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7d1dfd3f8475dd697f5d4bdab92776a2",
|
||||
"content-hash": "d11deb8a29c512e733d7b130e0943d96",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.11.1",
|
||||
"version": "1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
|
||||
"reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
|
||||
"reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
|
||||
"reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -26,11 +26,12 @@
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/collections": "<1.6.8",
|
||||
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
|
||||
"doctrine/common": "<2.13.3 || >=3 <3.2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/collections": "^1.6.8",
|
||||
"doctrine/common": "^2.13.3 || ^3.2.2",
|
||||
"phpspec/prophecy": "^1.10",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -56,7 +57,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -64,29 +65,31 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-03-08T13:26:56+00:00"
|
||||
"time": "2024-06-12T14:39:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.17.1",
|
||||
"version": "v5.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
|
||||
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=7.0"
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ircmaxell/php-yacc": "^0.0.7",
|
||||
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/php-parse"
|
||||
@@ -94,7 +97,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.9-dev"
|
||||
"dev-master": "5.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -118,26 +121,27 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0"
|
||||
},
|
||||
"time": "2023-08-13T19:53:39+00:00"
|
||||
"time": "2024-07-01T20:03:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phar-io/manifest.git",
|
||||
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
|
||||
"reference": "54750ef60c58e43759730615a392c31c80e23176"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
|
||||
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
|
||||
"url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
|
||||
"reference": "54750ef60c58e43759730615a392c31c80e23176",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"phar-io/version": "^3.0.1",
|
||||
@@ -178,9 +182,15 @@
|
||||
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
||||
"support": {
|
||||
"issues": "https://github.com/phar-io/manifest/issues",
|
||||
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
|
||||
"source": "https://github.com/phar-io/manifest/tree/2.0.4"
|
||||
},
|
||||
"time": "2021-07-20T11:28:43+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/theseer",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-03T12:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/version",
|
||||
@@ -235,23 +245,23 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "10.1.3",
|
||||
"version": "10.1.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "be1fe461fdc917de2a29a452ccf2657d325b443d"
|
||||
"reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d",
|
||||
"reference": "be1fe461fdc917de2a29a452ccf2657d325b443d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
|
||||
"reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"nikic/php-parser": "^4.15",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
@@ -301,7 +311,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -309,20 +319,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-26T13:45:28+00:00"
|
||||
"time": "2024-06-29T08:25:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "4.0.2",
|
||||
"version": "4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "5647d65443818959172645e7ed999217360654b6"
|
||||
"reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6",
|
||||
"reference": "5647d65443818959172645e7ed999217360654b6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
|
||||
"reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -362,7 +372,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -370,7 +380,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-07T09:13:23+00:00"
|
||||
"time": "2023-08-31T06:24:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-invoker",
|
||||
@@ -437,16 +447,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
||||
"reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d"
|
||||
"reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
|
||||
"reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
|
||||
"reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -484,7 +494,8 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -492,7 +503,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T06:56:46+00:00"
|
||||
"time": "2023-08-31T14:07:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-timer",
|
||||
@@ -555,16 +566,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.3.3",
|
||||
"version": "10.5.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "241ed4dd0db1c096984e62d414c4e1ac8d5dbff4"
|
||||
"reference": "8e9e80872b4e8064401788ee8a32d40b4455318f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/241ed4dd0db1c096984e62d414c4e1ac8d5dbff4",
|
||||
"reference": "241ed4dd0db1c096984e62d414c4e1ac8d5dbff4",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f",
|
||||
"reference": "8e9e80872b4e8064401788ee8a32d40b4455318f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -574,26 +585,26 @@
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.10.1",
|
||||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"myclabs/deep-copy": "^1.12.0",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-code-coverage": "^10.1.1",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-invoker": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
"phpunit/php-timer": "^6.0",
|
||||
"sebastian/cli-parser": "^2.0",
|
||||
"sebastian/code-unit": "^2.0",
|
||||
"sebastian/comparator": "^5.0",
|
||||
"sebastian/diff": "^5.0",
|
||||
"sebastian/environment": "^6.0",
|
||||
"sebastian/exporter": "^5.0",
|
||||
"sebastian/global-state": "^6.0.1",
|
||||
"sebastian/object-enumerator": "^5.0",
|
||||
"sebastian/recursion-context": "^5.0",
|
||||
"sebastian/type": "^4.0",
|
||||
"sebastian/version": "^4.0"
|
||||
"phpunit/php-code-coverage": "^10.1.15",
|
||||
"phpunit/php-file-iterator": "^4.1.0",
|
||||
"phpunit/php-invoker": "^4.0.0",
|
||||
"phpunit/php-text-template": "^3.0.1",
|
||||
"phpunit/php-timer": "^6.0.0",
|
||||
"sebastian/cli-parser": "^2.0.1",
|
||||
"sebastian/code-unit": "^2.0.0",
|
||||
"sebastian/comparator": "^5.0.1",
|
||||
"sebastian/diff": "^5.1.1",
|
||||
"sebastian/environment": "^6.1.0",
|
||||
"sebastian/exporter": "^5.1.2",
|
||||
"sebastian/global-state": "^6.0.2",
|
||||
"sebastian/object-enumerator": "^5.0.0",
|
||||
"sebastian/recursion-context": "^5.0.0",
|
||||
"sebastian/type": "^4.0.0",
|
||||
"sebastian/version": "^4.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-soap": "To be able to generate mocks based on WSDL files"
|
||||
@@ -604,7 +615,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "10.3-dev"
|
||||
"dev-main": "10.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -636,7 +647,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.3"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -652,20 +663,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-09-05T04:34:51+00:00"
|
||||
"time": "2024-07-30T11:08:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/cli-parser.git",
|
||||
"reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae"
|
||||
"reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae",
|
||||
"reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
|
||||
"reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -700,7 +711,8 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/cli-parser",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
|
||||
"source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -708,7 +720,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T06:58:15+00:00"
|
||||
"time": "2024-03-02T07:12:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/code-unit",
|
||||
@@ -900,20 +912,20 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
"version": "3.0.0",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/complexity.git",
|
||||
"reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6"
|
||||
"reference": "68ff824baeae169ec9f2137158ee529584553799"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
|
||||
"reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
|
||||
"reference": "68ff824baeae169ec9f2137158ee529584553799",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^4.10",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -922,7 +934,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.0-dev"
|
||||
"dev-main": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -945,7 +957,8 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/complexity",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/complexity/issues",
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -953,20 +966,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T06:59:47+00:00"
|
||||
"time": "2023-12-21T08:37:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "5.0.3",
|
||||
"version": "5.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
|
||||
"reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
|
||||
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
|
||||
"reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -974,12 +987,12 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"symfony/process": "^4.2 || ^5"
|
||||
"symfony/process": "^6.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "5.0-dev"
|
||||
"dev-main": "5.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1012,7 +1025,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/5.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1020,20 +1033,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-01T07:48:21+00:00"
|
||||
"time": "2024-03-02T07:15:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "6.0.1",
|
||||
"version": "6.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951"
|
||||
"reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951",
|
||||
"reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
|
||||
"reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1048,7 +1061,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "6.0-dev"
|
||||
"dev-main": "6.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1076,7 +1089,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
||||
"security": "https://github.com/sebastianbergmann/environment/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/6.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/6.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1084,20 +1097,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-11T05:39:26+00:00"
|
||||
"time": "2024-03-23T08:47:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "5.0.0",
|
||||
"version": "5.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0"
|
||||
"reference": "955288482d97c19a372d3f31006ab3f37da47adf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
|
||||
"reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf",
|
||||
"reference": "955288482d97c19a372d3f31006ab3f37da47adf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1111,7 +1124,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "5.0-dev"
|
||||
"dev-main": "5.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1153,7 +1166,8 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/exporter/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1161,20 +1175,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T07:06:49+00:00"
|
||||
"time": "2024-03-02T07:17:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
"version": "6.0.1",
|
||||
"version": "6.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/global-state.git",
|
||||
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4"
|
||||
"reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4",
|
||||
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
|
||||
"reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1208,14 +1222,14 @@
|
||||
}
|
||||
],
|
||||
"description": "Snapshotting of global state",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/global-state",
|
||||
"homepage": "https://www.github.com/sebastianbergmann/global-state",
|
||||
"keywords": [
|
||||
"global state"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/global-state/issues",
|
||||
"security": "https://github.com/sebastianbergmann/global-state/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1223,24 +1237,24 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-19T07:19:23+00:00"
|
||||
"time": "2024-03-02T07:19:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/lines-of-code",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
|
||||
"reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130"
|
||||
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130",
|
||||
"reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
|
||||
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^4.10",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -1272,7 +1286,8 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1280,7 +1295,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T07:08:02+00:00"
|
||||
"time": "2023-12-21T08:38:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/object-enumerator",
|
||||
@@ -1568,16 +1583,16 @@
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/theseer/tokenizer.git",
|
||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
|
||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1606,7 +1621,7 @@
|
||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||
"support": {
|
||||
"issues": "https://github.com/theseer/tokenizer/issues",
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1614,7 +1629,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-07-28T10:34:58+00:00"
|
||||
"time": "2024-03-03T12:36:25+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
@@ -1623,8 +1638,10 @@
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^8.1",
|
||||
"ext-json": "*"
|
||||
"php": "^8.2",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-readline": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
|
||||
21
pm-convert
21
pm-convert
@@ -3,7 +3,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PmConverter\Processor;
|
||||
use PmConverter\Handler;
|
||||
const EOL = PHP_EOL;
|
||||
const DS = DIRECTORY_SEPARATOR;
|
||||
|
||||
const PM_VERSION = '1.7';
|
||||
|
||||
$paths = [
|
||||
__DIR__ . '/../../autoload.php',
|
||||
@@ -20,14 +24,13 @@ foreach ($paths as $path) {
|
||||
|
||||
is_null($file) && throw new RuntimeException('Unable to locate autoload.php file.');
|
||||
|
||||
$processor = new Processor($argv);
|
||||
$handler = new Handler();
|
||||
$handler::printVersion();
|
||||
$handler::printCopyright();
|
||||
try {
|
||||
$processor->convert();
|
||||
} catch (InvalidArgumentException $e) {
|
||||
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), PHP_EOL));
|
||||
print(implode(PHP_EOL, $processor->usage()));
|
||||
die(1);
|
||||
$handler->init($argv);
|
||||
$handler->start();
|
||||
} catch (Exception $e) {
|
||||
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), PHP_EOL));
|
||||
die(1);
|
||||
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), EOL));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
178
src/ArgumentParser.php
Normal file
178
src/ArgumentParser.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PmConverter\Converters\ConvertFormat;
|
||||
use PmConverter\Enums\ArgumentNames as AN;
|
||||
|
||||
class ArgumentParser
|
||||
{
|
||||
/**
|
||||
* @var array Raw arguments passed from cli ($argv)
|
||||
*/
|
||||
protected readonly array $raw;
|
||||
|
||||
/**
|
||||
* @var array Parsed and ready to use
|
||||
*/
|
||||
protected array $parsed = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $argv Raw arguments passed from cli ($argv)
|
||||
*/
|
||||
public function __construct(array $argv)
|
||||
{
|
||||
$this->raw = array_slice($argv, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses raw arguments
|
||||
*
|
||||
* @return array Settings according to settings file format
|
||||
*/
|
||||
public function parse(): array
|
||||
{
|
||||
foreach ($this->raw as $idx => $arg) {
|
||||
switch ($arg) {
|
||||
case '-c':
|
||||
case '--config':
|
||||
if (empty($this->raw[$idx + 1])) {
|
||||
throw new InvalidArgumentException('a configuration file path is expected for -c (--config)');
|
||||
}
|
||||
if (isset($this->parsed[AN::Config])) {
|
||||
printf(
|
||||
"INFO: Config file is already set to '%s' and will be overwritten to '%s'",
|
||||
$this->parsed[AN::Config],
|
||||
$this->raw[$idx + 1],
|
||||
);
|
||||
}
|
||||
$this->parsed[AN::Config] = $this->raw[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-d':
|
||||
case '--dir':
|
||||
if (empty($this->raw[$idx + 1])) {
|
||||
throw new InvalidArgumentException('a directory path is expected for -d (--dir)');
|
||||
}
|
||||
$this->parsed[AN::Directories][] = $this->raw[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-f':
|
||||
case '--file':
|
||||
if (empty($this->raw[$idx + 1])) {
|
||||
throw new InvalidArgumentException('a directory path is expected for -f (--file)');
|
||||
}
|
||||
$this->parsed[AN::Files][] = $this->raw[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-e':
|
||||
case '--env':
|
||||
if (empty($this->raw[$idx + 1])) {
|
||||
throw new InvalidArgumentException('an environment file path is expected for -e (--env)');
|
||||
}
|
||||
$this->parsed[AN::Environment][] = $this->raw[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-o':
|
||||
case '--output':
|
||||
if (empty($this->raw[$idx + 1])) {
|
||||
throw new InvalidArgumentException('an output path is expected for -o (--output)');
|
||||
}
|
||||
$this->parsed[AN::Output][] = $this->raw[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-p':
|
||||
case '--preserve':
|
||||
$this->parsed[AN::PreserveOutput] = true;
|
||||
break;
|
||||
|
||||
case '--http':
|
||||
$this->parsed[AN::Formats][] = ConvertFormat::Http;
|
||||
break;
|
||||
|
||||
case '--curl':
|
||||
$this->parsed[AN::Formats][] = ConvertFormat::Curl;
|
||||
break;
|
||||
|
||||
case '--wget':
|
||||
$this->parsed[AN::Formats][] = ConvertFormat::Wget;
|
||||
break;
|
||||
|
||||
case '--v2.0':
|
||||
$this->parsed[AN::Formats][] = ConvertFormat::Postman20;
|
||||
break;
|
||||
|
||||
case '--v2.1':
|
||||
$this->parsed[AN::Formats][] = ConvertFormat::Postman21;
|
||||
break;
|
||||
|
||||
case '-a':
|
||||
case '--all':
|
||||
foreach (ConvertFormat::cases() as $format) {
|
||||
$this->parsed[AN::Formats][] = $format;
|
||||
}
|
||||
break;
|
||||
|
||||
case '--var':
|
||||
$definition = trim($this->raw[$idx + 1]);
|
||||
$name = strtok($definition, '='); // take first part before equal sign as var name
|
||||
$value = strtok(''); // take the rest of argument as var value
|
||||
if (isset($this->parsed[AN::Vars][$name])) {
|
||||
printf(
|
||||
"INFO: Variable '%s' is already set to '%s' and will be overwritten to '%s'",
|
||||
$name,
|
||||
$this->parsed[AN::Vars][$name],
|
||||
$value,
|
||||
);
|
||||
}
|
||||
$this->parsed[AN::Vars][$name] = $value;
|
||||
break;
|
||||
|
||||
case '--dev':
|
||||
$this->parsed[AN::DevMode] = true;
|
||||
break;
|
||||
|
||||
case '-v':
|
||||
case '--verbose':
|
||||
$this->parsed[AN::Verbose] = true;
|
||||
break;
|
||||
|
||||
case '--dump':
|
||||
$this->parsed[AN::Dump] = true;
|
||||
break;
|
||||
|
||||
case '--version':
|
||||
$this->parsed[AN::Version] = true;
|
||||
break;
|
||||
|
||||
case '-h':
|
||||
case '--help':
|
||||
$this->parsed[AN::Help] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ([AN::Directories, AN::Files, AN::Formats] as $field) {
|
||||
if (!empty($this->parsed[$field])) {
|
||||
$this->parsed[$field] = array_unique($this->parsed[$field] ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns parsed arguments (if set) or parses raw ones
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parsed(): array
|
||||
{
|
||||
return $this->parsed ??= $this->parse();
|
||||
}
|
||||
}
|
||||
170
src/Collection.php
Normal file
170
src/Collection.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
use Exception;
|
||||
use Generator;
|
||||
use JsonException;
|
||||
use PmConverter\Enums\CollectionVersion;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Class that describes a request collection
|
||||
*
|
||||
* @property array|object $item
|
||||
* @property object $info
|
||||
* @property object|null $variable
|
||||
*/
|
||||
class Collection implements Stringable
|
||||
{
|
||||
public readonly CollectionVersion $version;
|
||||
|
||||
/**
|
||||
* Closed constructor so that we could use factory methods
|
||||
*
|
||||
* @param object $json
|
||||
*/
|
||||
private function __construct(protected object $json)
|
||||
{
|
||||
// specific case when collection has been exported via postman api
|
||||
if (property_exists($json, 'collection')) {
|
||||
$json = $json->collection;
|
||||
}
|
||||
$this->json = $json;
|
||||
$this->version = $this->detectVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory that creates new Collection from content read from file path
|
||||
*
|
||||
* @param string $path
|
||||
* @return static
|
||||
* @throws JsonException
|
||||
*/
|
||||
public static function fromFile(string $path): static
|
||||
{
|
||||
$content = file_get_contents(FileSystem::normalizePath($path));
|
||||
$json = json_decode($content, flags: JSON_THROW_ON_ERROR);
|
||||
return new static($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return json_encode($this->json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns reference to the parsed json structure
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function &raw(): object
|
||||
{
|
||||
return $this->json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns reference to any part of the parsed json structure
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function &__get(string $name): mixed
|
||||
{
|
||||
return $this->json->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns collection name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return $this->json->info->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection version
|
||||
*
|
||||
* @return CollectionVersion
|
||||
*/
|
||||
protected function detectVersion(): CollectionVersion
|
||||
{
|
||||
return match (true) {
|
||||
str_contains($this->json->info->schema, '/v2.0.') => CollectionVersion::Version20,
|
||||
str_contains($this->json->info->schema, '/v2.1.') => CollectionVersion::Version21,
|
||||
default => CollectionVersion::Unknown
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection version from raw file
|
||||
*
|
||||
* @param string $filepath
|
||||
* @return CollectionVersion
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function detectFileVersion(string $filepath): CollectionVersion
|
||||
{
|
||||
$content = file_get_contents($filepath);
|
||||
|
||||
if ($content === false) {
|
||||
throw new Exception("cannot read file: $filepath");
|
||||
}
|
||||
|
||||
$json = json_decode($content, true);
|
||||
$schema = $json['info']['schema'] ?? '';
|
||||
|
||||
if (str_ends_with($schema, 'v2.0.0/collection.json')) {
|
||||
return CollectionVersion::Version20;
|
||||
}
|
||||
|
||||
if (str_ends_with($schema, 'v2.1.0/collection.json')) {
|
||||
return CollectionVersion::Version21;
|
||||
}
|
||||
|
||||
return CollectionVersion::Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over collection request items and returns item associated by its path in folder
|
||||
*
|
||||
* @param mixed|null $item
|
||||
* @return Generator
|
||||
*/
|
||||
public function iterate(mixed $item = null): Generator
|
||||
{
|
||||
$is_recursive = !is_null($item);
|
||||
$folder = $is_recursive ? $item : $this->json;
|
||||
static $dir_tree;
|
||||
$path = DS . ($is_recursive ? implode(DS, $dir_tree ?? []) : '');
|
||||
foreach ($folder->item as $subitem) {
|
||||
if ($this->isItemFolder($subitem)) {
|
||||
$dir_tree[] = $subitem->name;
|
||||
yield from $this->iterate($subitem);
|
||||
continue;
|
||||
}
|
||||
yield $path => $subitem;
|
||||
}
|
||||
$is_recursive && array_pop($dir_tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether item contains another items or not
|
||||
*
|
||||
* @param object $item
|
||||
* @return bool
|
||||
*/
|
||||
protected function isItemFolder(object $item): bool
|
||||
{
|
||||
return !empty($item->item)
|
||||
&& is_array($item->item)
|
||||
&& empty($item->request);
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,24 @@ declare(strict_types=1);
|
||||
namespace PmConverter\Converters\Abstract;
|
||||
|
||||
use Exception;
|
||||
use PmConverter\Converters\{
|
||||
ConverterContract,
|
||||
RequestContract};
|
||||
use Iterator;
|
||||
use PmConverter\Collection;
|
||||
use PmConverter\Converters\RequestContract;
|
||||
use PmConverter\Environment;
|
||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
||||
use PmConverter\FileSystem;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class AbstractConverter implements ConverterContract
|
||||
abstract class AbstractConverter
|
||||
{
|
||||
/**
|
||||
* @var object|null
|
||||
* @var Collection|null
|
||||
*/
|
||||
protected ?object $collection = null;
|
||||
protected ?Collection $collection = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@@ -28,35 +30,67 @@ abstract class AbstractConverter implements ConverterContract
|
||||
protected string $outputPath;
|
||||
|
||||
/**
|
||||
* @var Environment|null
|
||||
* @var RequestContract[] Converted requests
|
||||
*/
|
||||
protected ?Environment $env = null;
|
||||
protected array $requests = [];
|
||||
|
||||
/**
|
||||
* Sets an environment with vars
|
||||
* Sets output path
|
||||
*
|
||||
* @param Environment $env
|
||||
* @param string $outputPath
|
||||
* @return $this
|
||||
*/
|
||||
public function withEnv(Environment $env): static
|
||||
public function to(string $outputPath): self
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->outputPath = sprintf('%s%s%s', $outputPath, DS, static::OUTPUT_DIR);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts collection requests
|
||||
* Converts requests from collection
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return static
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function convert(Collection $collection): static
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->outputPath = FileSystem::makeDir($this->outputPath);
|
||||
$this->setCollectionVars();
|
||||
foreach ($collection->iterate() as $path => $item) {
|
||||
// $this->requests[$path][] = $this->makeRequest($item);
|
||||
$request = $this->makeRequest($item);
|
||||
$this->writeRequest($request, $path);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns converted requests
|
||||
*
|
||||
* @return Iterator<string, RequestContract>
|
||||
*/
|
||||
public function converted(): Iterator
|
||||
{
|
||||
foreach ($this->requests as $path => $requests) {
|
||||
foreach ($requests as $request) {
|
||||
yield $path => $request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes requests on disk
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function convert(object $collection, string $outputPath): void
|
||||
public function flush(): void
|
||||
{
|
||||
$outputPath = sprintf('%s%s%s', $outputPath, DIRECTORY_SEPARATOR, static::OUTPUT_DIR);
|
||||
$this->outputPath = FileSystem::makeDir($outputPath);
|
||||
$this->collection = $collection;
|
||||
$this->setVariables();
|
||||
foreach ($collection->item as $item) {
|
||||
$this->convertItem($item);
|
||||
foreach ($this->converted() as $path => $request) {
|
||||
$this->writeRequest($request, $path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,14 +99,12 @@ abstract class AbstractConverter implements ConverterContract
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function setVariables(): static
|
||||
protected function setCollectionVars(): static
|
||||
{
|
||||
empty($this->env) && $this->env = new Environment($this->collection?->variable);
|
||||
if (!empty($this->collection?->variable)) {
|
||||
foreach ($this->collection->variable as $var) {
|
||||
$this->env[$var->key] = $var->value;
|
||||
}
|
||||
foreach ($this->collection?->variable ?? [] as $var) {
|
||||
Environment::instance()->setCustomVar($var->key, $var->value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -94,31 +126,9 @@ abstract class AbstractConverter implements ConverterContract
|
||||
*/
|
||||
protected function isItemFolder(object $item): bool
|
||||
{
|
||||
return !empty($item->item) && empty($item->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an item to request object and writes it into file
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function convertItem(mixed $item): void
|
||||
{
|
||||
if ($this->isItemFolder($item)) {
|
||||
static $dir_tree;
|
||||
foreach ($item->item as $subitem) {
|
||||
$dir_tree[] = $item->name;
|
||||
$path = implode(DIRECTORY_SEPARATOR, $dir_tree);
|
||||
if ($this->isItemFolder($subitem)) {
|
||||
$this->convertItem($subitem);
|
||||
} else {
|
||||
$this->writeRequest($this->initRequest($subitem), $path);
|
||||
}
|
||||
array_pop($dir_tree);
|
||||
}
|
||||
} else {
|
||||
$this->writeRequest($this->initRequest($item));
|
||||
}
|
||||
return !empty($item->item)
|
||||
&& is_array($item->item)
|
||||
&& empty($item->request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,17 +138,18 @@ abstract class AbstractConverter implements ConverterContract
|
||||
* @return RequestContract
|
||||
* @throws InvalidHttpVersionException
|
||||
*/
|
||||
protected function initRequest(object $item): RequestContract
|
||||
protected function makeRequest(object $item): RequestContract
|
||||
{
|
||||
$request_class = static::REQUEST_CLASS;
|
||||
|
||||
/** @var RequestContract $request */
|
||||
$request = new $request_class();
|
||||
$request->setName($item->name);
|
||||
$request->setVersion($this->collection->version);
|
||||
$request->setHttpVersion(1.1); //TODO http version?
|
||||
$request->setDescription($item->request?->description ?? null);
|
||||
$request->setVerb($item->request->method);
|
||||
$request->setUrl($item->request->url->raw);
|
||||
$request->setUrl($item->request->url);
|
||||
$request->setHeaders($item->request->header);
|
||||
$request->setAuth($item->request?->auth ?? $this->collection?->auth ?? null);
|
||||
if ($item->request->method !== 'GET' && !empty($item->request->body)) {
|
||||
@@ -157,9 +168,9 @@ abstract class AbstractConverter implements ConverterContract
|
||||
*/
|
||||
protected function writeRequest(RequestContract $request, string $subpath = null): bool
|
||||
{
|
||||
$filedir = sprintf('%s%s%s', $this->outputPath, DIRECTORY_SEPARATOR, $subpath);
|
||||
$filedir = sprintf('%s%s%s', $this->outputPath, DS, $subpath);
|
||||
$filedir = FileSystem::makeDir($filedir);
|
||||
$filepath = sprintf('%s%s%s.%s', $filedir, DIRECTORY_SEPARATOR, $request->getName(), static::FILE_EXT);
|
||||
$filepath = sprintf('%s%s%s.%s', $filedir, DS, $request->getName(), static::FILE_EXT);
|
||||
$content = $this->interpolate((string)$request);
|
||||
return file_put_contents($filepath, $content) > 0;
|
||||
}
|
||||
@@ -172,18 +183,9 @@ abstract class AbstractConverter implements ConverterContract
|
||||
*/
|
||||
protected function interpolate(string $content): string
|
||||
{
|
||||
if (!$this->env?->hasVars()) {
|
||||
return $content;
|
||||
}
|
||||
$matches = [];
|
||||
if (preg_match_all('/\{\{.*}}/m', $content, $matches, PREG_PATTERN_ORDER) > 0) {
|
||||
foreach ($matches[0] as $key => $var) {
|
||||
if (str_contains($content, $var)) {
|
||||
$content = str_replace($var, $this->env[$var] ?: $var, $content);
|
||||
unset($matches[0][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
$replace = static fn ($a) => Environment::instance()->var($var = $a[0]) ?: $var;
|
||||
return Environment::instance()->hasVars()
|
||||
? preg_replace_callback('/\{\{.*}}/m', $replace, $content)
|
||||
: $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ declare(strict_types=1);
|
||||
namespace PmConverter\Converters\Abstract;
|
||||
|
||||
use PmConverter\Converters\RequestContract;
|
||||
use PmConverter\Exceptions\{
|
||||
EmptyHttpVerbException,
|
||||
InvalidHttpVersionException};
|
||||
use PmConverter\HttpVersions;
|
||||
use PmConverter\Enums\CollectionVersion;
|
||||
use PmConverter\Enums\HttpVersion;
|
||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
@@ -22,9 +22,9 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
protected string $verb;
|
||||
|
||||
/**
|
||||
* @var string URL where to send a request
|
||||
* @var object|string URL where to send a request
|
||||
*/
|
||||
protected string $url;
|
||||
protected object|string $url;
|
||||
|
||||
/**
|
||||
* @var float HTTP protocol version
|
||||
@@ -56,14 +56,23 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
*/
|
||||
protected string $bodymode = 'raw';
|
||||
|
||||
|
||||
protected CollectionVersion $version;
|
||||
|
||||
public function setVersion(CollectionVersion $version): static
|
||||
{
|
||||
$this->version = $version;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setHttpVersion(float $version): static
|
||||
{
|
||||
if (!in_array($version, HttpVersions::values())) {
|
||||
if (!in_array($version, HttpVersion::values())) {
|
||||
throw new InvalidHttpVersionException(
|
||||
'Only these HTTP versions are supported: ' . implode(', ', HttpVersions::values())
|
||||
'Only these HTTP versions are supported: ' . implode(', ', HttpVersion::values())
|
||||
);
|
||||
}
|
||||
$this->httpVersion = $version;
|
||||
@@ -92,7 +101,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return str_replace(DIRECTORY_SEPARATOR, '_', $this->name);
|
||||
return str_replace(DS, '_', $this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +142,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setUrl(string $url): static
|
||||
public function setUrl(object|string $url): static
|
||||
{
|
||||
$this->url = $url;
|
||||
return $this;
|
||||
@@ -142,9 +151,9 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getUrl(): string
|
||||
public function getRawUrl(): string
|
||||
{
|
||||
return $this->url ?: '<empty url>';
|
||||
return is_object($this->url) ? $this->url->raw : $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +195,11 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
||||
if (!empty($auth)) {
|
||||
switch ($auth->type) {
|
||||
case 'bearer':
|
||||
$this->setHeader('Authorization', 'Bearer ' . $auth->{$auth->type}[0]->value);
|
||||
$this->setHeader('Authorization', 'Bearer ' . match ($this->version) {
|
||||
CollectionVersion::Version20 => $auth->{$auth->type}->token,
|
||||
CollectionVersion::Version21 => $auth->{$auth->type}[0]->value,
|
||||
default => null
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -5,14 +5,39 @@ declare(strict_types=1);
|
||||
namespace PmConverter\Converters;
|
||||
|
||||
|
||||
use PmConverter\Converters\{
|
||||
Curl\CurlConverter,
|
||||
Http\HttpConverter,
|
||||
Wget\WgetConverter};
|
||||
use PmConverter\Converters\Curl\CurlConverter;
|
||||
use PmConverter\Converters\Http\HttpConverter;
|
||||
use PmConverter\Converters\Postman20\Postman20Converter;
|
||||
use PmConverter\Converters\Postman21\Postman21Converter;
|
||||
use PmConverter\Converters\Wget\WgetConverter;
|
||||
|
||||
enum ConvertFormat: string
|
||||
{
|
||||
case Http = HttpConverter::class;
|
||||
case Curl = CurlConverter::class;
|
||||
case Wget = WgetConverter::class;
|
||||
case Postman20 = Postman20Converter::class;
|
||||
case Postman21 = Postman21Converter::class;
|
||||
|
||||
public static function fromArg(string $arg): self
|
||||
{
|
||||
return match ($arg) {
|
||||
'http' => ConvertFormat::Http,
|
||||
'curl' => ConvertFormat::Curl,
|
||||
'wget' => ConvertFormat::Wget,
|
||||
'v2.0' => ConvertFormat::Postman20,
|
||||
'v2.1' => ConvertFormat::Postman21,
|
||||
};
|
||||
}
|
||||
|
||||
public function toArg(): string
|
||||
{
|
||||
return match ($this) {
|
||||
ConvertFormat::Http => 'http',
|
||||
ConvertFormat::Curl => 'curl',
|
||||
ConvertFormat::Wget => 'wget',
|
||||
ConvertFormat::Postman20 => 'v2.0',
|
||||
ConvertFormat::Postman21 => 'v2.1',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters;
|
||||
|
||||
use PmConverter\Collection;
|
||||
|
||||
interface ConverterContract
|
||||
{
|
||||
public function convert(object $collection, string $outputPath): void;
|
||||
public function convert(Collection $collection, string $outputPath): void;
|
||||
public function getOutputPath(): string;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters\Curl;
|
||||
|
||||
use PmConverter\Converters\{
|
||||
Abstract\AbstractConverter,
|
||||
ConverterContract};
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
|
||||
class CurlConverter extends AbstractConverter implements ConverterContract
|
||||
class CurlConverter extends AbstractConverter
|
||||
{
|
||||
protected const FILE_EXT = 'sh';
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ class CurlRequest extends AbstractRequest
|
||||
"curl \ ",
|
||||
"\t--http1.1 \ ", //TODO proto
|
||||
"\t--request $this->verb \ ",
|
||||
"\t--location $this->url \ ",
|
||||
"\t--location {$this->getRawUrl()} \ ",
|
||||
],
|
||||
$this->prepareHeaders(),
|
||||
$this->prepareBody()
|
||||
);
|
||||
$output[] = rtrim(array_pop($output), '\ ');
|
||||
return implode(PHP_EOL, array_merge($output, ['']));
|
||||
return implode(EOL, array_merge($output, ['']));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters\Http;
|
||||
|
||||
use PmConverter\Converters\{
|
||||
Abstract\AbstractConverter,
|
||||
ConverterContract};
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
|
||||
class HttpConverter extends AbstractConverter implements ConverterContract
|
||||
class HttpConverter extends AbstractConverter
|
||||
{
|
||||
protected const FILE_EXT = 'http';
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ declare(strict_types=1);
|
||||
namespace PmConverter\Converters\Http;
|
||||
|
||||
use PmConverter\Converters\Abstract\AbstractRequest;
|
||||
use PmConverter\Exceptions\{
|
||||
EmptyHttpVerbException};
|
||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
||||
|
||||
/**
|
||||
* Class to determine file content with http request format
|
||||
@@ -29,7 +28,7 @@ class HttpRequest extends AbstractRequest
|
||||
*/
|
||||
protected function prepareHeaders(): array
|
||||
{
|
||||
$output[] = sprintf('%s %s HTTP/%s', $this->getVerb(), $this->getUrl(), $this->getHttpVersion());
|
||||
$output[] = sprintf('%s %s HTTP/%s', $this->getVerb(), $this->getRawUrl(), $this->getHttpVersion());
|
||||
foreach ($this->headers as $name => $data) {
|
||||
$output[] = sprintf('%s%s: %s', $data['disabled'] ? '# ' : '', $name, $data['value']);
|
||||
}
|
||||
@@ -69,6 +68,6 @@ class HttpRequest extends AbstractRequest
|
||||
$this->prepareHeaders(),
|
||||
$this->prepareBody()
|
||||
);
|
||||
return implode(PHP_EOL, $output);
|
||||
return implode(EOL, $output);
|
||||
}
|
||||
}
|
||||
|
||||
135
src/Converters/Postman20/Postman20Converter.php
Normal file
135
src/Converters/Postman20/Postman20Converter.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters\Postman20;
|
||||
|
||||
use PmConverter\Collection;
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
use PmConverter\Enums\CollectionVersion;
|
||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
||||
use PmConverter\FileSystem;
|
||||
|
||||
/**
|
||||
* Converts Postman Collection v2.1 to v2.0
|
||||
*/
|
||||
class Postman20Converter extends AbstractConverter
|
||||
{
|
||||
protected const FILE_EXT = 'v20.postman_collection.json';
|
||||
|
||||
protected const OUTPUT_DIR = 'pm-v2.0';
|
||||
|
||||
/**
|
||||
* Converts collection requests
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return static
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
*/
|
||||
public function convert(Collection $collection): static
|
||||
{
|
||||
$this->collection = $collection;
|
||||
// if data was exported from API, here is already valid json to
|
||||
// just flush it in file, otherwise we need to convert it deeper
|
||||
if ($this->collection->version === CollectionVersion::Version21) {
|
||||
$this->collection->info->schema = str_replace('/v2.1.', '/v2.0.', $this->collection->info->schema);
|
||||
$this->convertAuth($this->collection->raw());
|
||||
foreach ($this->collection->item as $item) {
|
||||
$this->convertItem($item);
|
||||
}
|
||||
}
|
||||
$this->outputPath = FileSystem::makeDir($this->outputPath);
|
||||
$this->writeCollection();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes converted collection into file
|
||||
*
|
||||
* @return bool
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
*/
|
||||
protected function writeCollection(): bool
|
||||
{
|
||||
$filedir = FileSystem::makeDir($this->outputPath);
|
||||
$filepath = sprintf('%s%s%s.%s', $filedir, DS, $this->collection->name(), static::FILE_EXT);
|
||||
return file_put_contents($filepath, $this->collection) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes some requests fields in place
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return void
|
||||
*/
|
||||
protected function convertItem(mixed $item): void
|
||||
{
|
||||
if ($this->isItemFolder($item)) {
|
||||
foreach ($item->item as $subitem) {
|
||||
if ($this->isItemFolder($subitem)) {
|
||||
$this->convertItem($subitem);
|
||||
} else {
|
||||
$this->convertAuth($subitem->request);
|
||||
$this->convertRequestUrl($subitem->request);
|
||||
$this->convertResponseUrls($subitem->response);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->convertAuth($item->request);
|
||||
$this->convertRequestUrl($item->request);
|
||||
$this->convertResponseUrls($item->response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts auth object from v2.1 to v2.0
|
||||
*
|
||||
* @param object $request
|
||||
* @return void
|
||||
*/
|
||||
protected function convertAuth(object $request): void
|
||||
{
|
||||
if (empty($request->auth)) {
|
||||
return;
|
||||
}
|
||||
$auth = ['type' => 'noauth'];
|
||||
$type = strtolower($request->auth->type);
|
||||
if ($type !== 'noauth') {
|
||||
foreach ($request->auth->$type as $param) {
|
||||
$auth[$param->key] = $param->value ?? '';
|
||||
}
|
||||
$request->auth->$type = (object)$auth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts requests URLs from object v2.1 to string v2.0
|
||||
*
|
||||
* @param object $request
|
||||
* @return void
|
||||
*/
|
||||
protected function convertRequestUrl(object $request): void
|
||||
{
|
||||
if (is_object($request->url)) {
|
||||
$request->url = $request->url->raw;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts URLs response examples from object v2.1 to string v2.0
|
||||
*
|
||||
* @param array $responses
|
||||
* @return void
|
||||
*/
|
||||
protected function convertResponseUrls(array $responses): void
|
||||
{
|
||||
foreach ($responses as $response) {
|
||||
if (is_object($response->originalRequest->url)) {
|
||||
$response->originalRequest->url = $response->originalRequest->url->raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
src/Converters/Postman21/Postman21Converter.php
Normal file
167
src/Converters/Postman21/Postman21Converter.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters\Postman21;
|
||||
|
||||
use PmConverter\Collection;
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
use PmConverter\Enums\CollectionVersion;
|
||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
||||
use PmConverter\FileSystem;
|
||||
|
||||
/**
|
||||
* Converts Postman Collection v2.0 to v2.1
|
||||
*/
|
||||
class Postman21Converter extends AbstractConverter
|
||||
{
|
||||
protected const FILE_EXT = 'v21.postman_collection.json';
|
||||
|
||||
protected const OUTPUT_DIR = 'pm-v2.1';
|
||||
|
||||
/**
|
||||
* Converts collection requests
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return static
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
*/
|
||||
public function convert(Collection $collection): static
|
||||
{
|
||||
$this->collection = $collection;
|
||||
// if data was exported from API, here is already valid json to
|
||||
// just flush it in file, otherwise we need to convert it deeper
|
||||
if ($this->collection->version === CollectionVersion::Version20) {
|
||||
$this->collection->info->schema = str_replace('/v2.0.', '/v2.1.', $this->collection->info->schema);
|
||||
$this->convertAuth($this->collection->raw());
|
||||
foreach ($this->collection->item as $item) {
|
||||
$this->convertItem($item);
|
||||
}
|
||||
}
|
||||
$this->outputPath = FileSystem::makeDir($this->outputPath);
|
||||
$this->writeCollection();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes converted collection into file
|
||||
*
|
||||
* @return bool
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
*/
|
||||
protected function writeCollection(): bool
|
||||
{
|
||||
$filedir = FileSystem::makeDir($this->outputPath);
|
||||
$filepath = sprintf('%s%s%s.%s', $filedir, DS, $this->collection->name(), static::FILE_EXT);
|
||||
return file_put_contents($filepath, $this->collection) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes some requests fields in place
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return void
|
||||
*/
|
||||
protected function convertItem(mixed $item): void
|
||||
{
|
||||
if ($this->isItemFolder($item)) {
|
||||
foreach ($item->item as $subitem) {
|
||||
if ($this->isItemFolder($subitem)) {
|
||||
$this->convertItem($subitem);
|
||||
} else {
|
||||
$this->convertAuth($subitem->request);
|
||||
$this->convertRequestUrl($subitem->request);
|
||||
$this->convertResponseUrls($subitem->response);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->convertAuth($item->request);
|
||||
$this->convertRequestUrl($item->request);
|
||||
$this->convertResponseUrls($item->response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts auth object from v2.0 to v2.1
|
||||
*
|
||||
* @param object $request
|
||||
* @return void
|
||||
*/
|
||||
protected function convertAuth(object $request): void
|
||||
{
|
||||
if (empty($request->auth)) {
|
||||
return;
|
||||
}
|
||||
$type = $request->auth->type;
|
||||
if ($type !== 'noauth' && isset($request->auth->$type)) {
|
||||
$auth = [];
|
||||
foreach ($request->auth->$type as $key => $value) {
|
||||
$auth[] = (object)[
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'string',
|
||||
];
|
||||
}
|
||||
$request->auth->$type = $auth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts requests URLs from string v2.0 to object v2.1
|
||||
*
|
||||
* @param object $request
|
||||
* @return void
|
||||
*/
|
||||
protected function convertRequestUrl(object $request): void
|
||||
{
|
||||
if (is_string($request->url) && mb_strlen($request->url) > 0) {
|
||||
$data = array_values(array_filter(explode('/', $request->url))); //TODO URL parsing
|
||||
if (count($data) === 1) {
|
||||
$url = [
|
||||
'raw' => $request->url,
|
||||
'host' => [$data[0] ?? $request->url],
|
||||
];
|
||||
} else {
|
||||
$url = [
|
||||
'raw' => $request->url,
|
||||
'protocol' => str_replace(':', '', $data[0]),
|
||||
'host' => [$data[1] ?? $request->url],
|
||||
'path' => array_slice($data, 2),
|
||||
];
|
||||
}
|
||||
$request->url = (object)$url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts URLs response examples from string v2.0 to object v2.1
|
||||
*
|
||||
* @param array $responses
|
||||
* @return void
|
||||
*/
|
||||
protected function convertResponseUrls(array $responses): void
|
||||
{
|
||||
foreach ($responses as $response) {
|
||||
if (is_string($response->originalRequest->url)) {
|
||||
$data = array_values(array_filter(explode('/', $response->originalRequest->url))); //TODO URL parsing
|
||||
if (count($data) === 1) {
|
||||
$url = [
|
||||
'raw' => $response->originalRequest->url,
|
||||
'host' => [$data[0] ?? $response->originalRequest->url],
|
||||
];
|
||||
} else {
|
||||
$url = [
|
||||
'raw' => $response->originalRequest->url,
|
||||
'protocol' => str_replace(':', '', $data[0]),
|
||||
'host' => [$data[1] ?? $response->originalRequest->url],
|
||||
'path' => array_slice($data, 2),
|
||||
];
|
||||
}
|
||||
$response->originalRequest->url = (object)$url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ interface RequestContract
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): string;
|
||||
public function getRawUrl(): string;
|
||||
|
||||
/**
|
||||
* Sets headers from collection item to request object
|
||||
@@ -116,7 +116,7 @@ interface RequestContract
|
||||
/**
|
||||
* Sets authorization headers
|
||||
*
|
||||
* @param object|null $auth
|
||||
* @param object $auth
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuth(object $auth): static;
|
||||
|
||||
@@ -4,11 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Converters\Wget;
|
||||
|
||||
use PmConverter\Converters\{
|
||||
Abstract\AbstractConverter,
|
||||
ConverterContract};
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
|
||||
class WgetConverter extends AbstractConverter implements ConverterContract
|
||||
class WgetConverter extends AbstractConverter
|
||||
{
|
||||
protected const FILE_EXT = 'sh';
|
||||
|
||||
|
||||
@@ -77,18 +77,18 @@ class WgetRequest extends AbstractRequest
|
||||
if ($this->getBodymode() === 'formdata') {
|
||||
if ($this->getBody()) {
|
||||
if ($this->getVerb() === 'GET') {
|
||||
$output[] = sprintf("\t%s?%s", $this->getUrl(), http_build_query($this->prepareBody()));
|
||||
$output[] = sprintf("\t%s?%s", $this->getRawUrl(), http_build_query($this->prepareBody()));
|
||||
} else {
|
||||
$output[] = sprintf("\t--body-data '%s' \ ", http_build_query($this->prepareBody()));
|
||||
$output[] = sprintf("\t%s", $this->getUrl());
|
||||
$output[] = sprintf("\t%s", $this->getRawUrl());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->getVerb() !== 'GET') {
|
||||
$output[] = sprintf("\t--body-data '%s' \ ", implode("\n", $this->prepareBody()));
|
||||
$output[] = sprintf("\t%s", $this->getUrl());
|
||||
$output[] = sprintf("\t%s", $this->getRawUrl());
|
||||
}
|
||||
}
|
||||
return implode(PHP_EOL, array_merge($output, ['']));
|
||||
return implode(EOL, array_merge($output, ['']));
|
||||
}
|
||||
}
|
||||
|
||||
25
src/Enums/ArgumentNames.php
Normal file
25
src/Enums/ArgumentNames.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Enums;
|
||||
|
||||
/**
|
||||
* Argument names
|
||||
*/
|
||||
class ArgumentNames
|
||||
{
|
||||
public const Config = 'config';
|
||||
public const Directories = 'directories';
|
||||
public const Files = 'files';
|
||||
public const Environment = 'environment';
|
||||
public const Output = 'output';
|
||||
public const PreserveOutput = 'preserveOutput';
|
||||
public const Formats = 'formats';
|
||||
public const Vars = 'vars';
|
||||
public const DevMode = 'devMode';
|
||||
public const Verbose = 'verbose';
|
||||
public const Dump = 'dump';
|
||||
public const Version = 'version';
|
||||
public const Help = 'help';
|
||||
}
|
||||
12
src/Enums/CollectionVersion.php
Normal file
12
src/Enums/CollectionVersion.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Enums;
|
||||
|
||||
enum CollectionVersion: string
|
||||
{
|
||||
case Version20 = 'v2.0';
|
||||
case Version21 = 'v2.1';
|
||||
case Unknown = 'unknown';
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter;
|
||||
namespace PmConverter\Enums;
|
||||
|
||||
enum HttpVersions: string
|
||||
enum HttpVersion: string
|
||||
{
|
||||
case Version10 = '1.0';
|
||||
case Version11 = '1.1';
|
||||
@@ -4,21 +4,141 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
class Environment implements \ArrayAccess
|
||||
use ArrayAccess;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Environment implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var string Path to env file
|
||||
*/
|
||||
protected static string $filepath = '';
|
||||
|
||||
/**
|
||||
* @var Environment
|
||||
*/
|
||||
protected static Environment $instance;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $vars = [];
|
||||
protected array $ownVars = [];
|
||||
|
||||
/**
|
||||
* @param object $env
|
||||
* @var array
|
||||
*/
|
||||
public function __construct(protected object $env)
|
||||
protected array $customVars = [];
|
||||
|
||||
public static function instance(): static
|
||||
{
|
||||
foreach ($env->values as $var) {
|
||||
$this->vars[static::formatKey($var->key)] = $var->value;
|
||||
return static::$instance ??= new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $filepath
|
||||
* @return $this
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function readFromFile(?string $filepath): static
|
||||
{
|
||||
if (empty($filepath)) {
|
||||
return $this;
|
||||
}
|
||||
$content = file_get_contents(static::$filepath = $filepath);
|
||||
$content = json_decode($content, flags: JSON_THROW_ON_ERROR); //TODO try-catch
|
||||
$content || throw new JsonException("not a valid environment: $filepath");
|
||||
property_exists($content, 'environment') && $content = $content->environment;
|
||||
if (!property_exists($content, 'id') && !property_exists($content, 'name')) {
|
||||
throw new JsonException("not a valid environment: $filepath");
|
||||
}
|
||||
return $this->setOwnVars($content->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
* @return $this
|
||||
*/
|
||||
protected function setOwnVars(array $vars): static
|
||||
{
|
||||
foreach ($vars as $key => $value) {
|
||||
is_object($value) && [$key, $value] = [$value->key, $value->value];
|
||||
$this->setOwnVar($key, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value to some environment own variable
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
protected function setOwnVar(string $name, string $value): static
|
||||
{
|
||||
$this->ownVars[static::formatKey($name)] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomVars(array $vars): static
|
||||
{
|
||||
foreach ($vars as $key => $value) {
|
||||
is_object($value) && [$key, $value] = [$value->key, $value->value];
|
||||
$this->setCustomVar($key, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value to some environment own variable
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomVar(string $name, string $value): static
|
||||
{
|
||||
$this->customVars[static::formatKey($name)] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value of specific variable
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function var(string $name): mixed
|
||||
{
|
||||
$format_key = static::formatKey($name);
|
||||
return $this->ownVars[$format_key] ?? $this->customVars[$format_key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of own and custom variables
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function vars(): array
|
||||
{
|
||||
return array_merge($this->ownVars, $this->customVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of custom variables
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function customVars(): array
|
||||
{
|
||||
return $this->customVars;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,15 +148,35 @@ class Environment implements \ArrayAccess
|
||||
*/
|
||||
public function hasVars(): bool
|
||||
{
|
||||
return !empty($this->vars);
|
||||
return !empty($this->ownVars) && !empty($this->customVars);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Closed constructor
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return array_key_exists(static::formatKey($offset), $this->vars);
|
||||
return array_key_exists(static::formatKey($offset), $this->vars());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +184,7 @@ class Environment implements \ArrayAccess
|
||||
*/
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return $this->vars[static::formatKey($offset)] ?? null;
|
||||
return $this->var($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +192,7 @@ class Environment implements \ArrayAccess
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
$this->vars[static::formatKey($offset)] = $value;
|
||||
$this->customVars[static::formatKey($offset)] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +200,7 @@ class Environment implements \ArrayAccess
|
||||
*/
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
unset($this->vars[static::formatKey($offset)]);
|
||||
unset($this->customVars[static::formatKey($offset)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
11
src/Exceptions/IncorrectSettingsFileException.php
Normal file
11
src/Exceptions/IncorrectSettingsFileException.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class IncorrectSettingsFileException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -4,11 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
use PmConverter\Exceptions\{
|
||||
CannotCreateDirectoryException,
|
||||
DirectoryIsNotReadableException,
|
||||
DirectoryIsNotWriteableException,
|
||||
DirectoryNotExistsException};
|
||||
use Exception;
|
||||
use JsonException;
|
||||
use PmConverter\Enums\CollectionVersion;
|
||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotReadableException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
||||
use PmConverter\Exceptions\DirectoryNotExistsException;
|
||||
|
||||
/**
|
||||
* Helper class to work with files and directories
|
||||
@@ -23,8 +25,17 @@ class FileSystem
|
||||
*/
|
||||
public static function normalizePath(string $path): string
|
||||
{
|
||||
$path = str_replace('~', $_SERVER['HOME'], $path);
|
||||
return rtrim($path, DIRECTORY_SEPARATOR);
|
||||
$path = trim($path);
|
||||
|
||||
if (str_starts_with($path, '~' . DS)) {
|
||||
$path = str_replace('~' . DS, $_SERVER['HOME'] . DS, $path);
|
||||
} elseif (str_starts_with($path, '.' . DS)) {
|
||||
$path = str_replace('.' . DS, $_SERVER['PWD'] . DS, $path);
|
||||
} elseif (!str_starts_with($path, DS)) {
|
||||
$path = $_SERVER['PWD'] . DS . $path;
|
||||
}
|
||||
|
||||
return rtrim($path, DS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +111,7 @@ class FileSystem
|
||||
$path = static::normalizePath($path);
|
||||
$records = array_diff(@scandir($path) ?: [], ['.', '..']);
|
||||
foreach ($records as &$record) {
|
||||
$record = sprintf('%s%s%s', $path, DIRECTORY_SEPARATOR, $record);
|
||||
$record = sprintf('%s%s%s', $path, DS, $record);
|
||||
}
|
||||
return $records;
|
||||
}
|
||||
@@ -110,16 +121,17 @@ class FileSystem
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
* @throws JsonException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function isCollectionFile(string $path): bool
|
||||
{
|
||||
$path = static::normalizePath($path);
|
||||
return !empty($path = trim($path))
|
||||
return !empty($path)
|
||||
&& str_ends_with($path, '.postman_collection.json')
|
||||
&& file_exists($path)
|
||||
&& is_file($path)
|
||||
&& is_readable($path)
|
||||
&& ($json = json_decode(file_get_contents($path), true))
|
||||
&& json_last_error() === JSON_ERROR_NONE
|
||||
&& isset($json['collection']['info']['name']);
|
||||
&& Collection::detectFileVersion($path) !== CollectionVersion::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
238
src/Handler.php
Normal file
238
src/Handler.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
use JsonException;
|
||||
use PmConverter\Enums\ArgumentNames as AN;
|
||||
|
||||
class Handler
|
||||
{
|
||||
/**
|
||||
* @var array Ready to use arguments
|
||||
*/
|
||||
protected array $arguments;
|
||||
|
||||
/**
|
||||
* @var Settings Settings read from file and merged with provided in cli
|
||||
*/
|
||||
protected Settings $settings;
|
||||
|
||||
/**
|
||||
* @var Environment Environment laoded from file with custom vars provided
|
||||
*/
|
||||
protected Environment $env;
|
||||
|
||||
/**
|
||||
* @var Processor Object that do convertions according to settings
|
||||
*/
|
||||
protected Processor $processor;
|
||||
|
||||
/**
|
||||
* Initializes main flow
|
||||
*
|
||||
* @param array $argv Raw arguments passed from cli
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function init(array $argv): void
|
||||
{
|
||||
$this->arguments = (new ArgumentParser($argv))->parsed();
|
||||
|
||||
if (!empty($this->arguments[AN::Help])) {
|
||||
self::printHelp();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!empty($this->arguments[AN::Version])) {
|
||||
self::printVersion();
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->settings = new Settings();
|
||||
$this->settings->loadFromFile($this->arguments[AN::Config] ?? null);
|
||||
$this->settings->override($this->arguments);
|
||||
|
||||
if (empty($this->settings->collectionPaths())) {
|
||||
throw new \Exception('at least 1 collection file must be defined');
|
||||
}
|
||||
|
||||
if (!empty($arguments[AN::Dump])) {
|
||||
$this->handleSettingsDump();
|
||||
}
|
||||
|
||||
$this->env = Environment::instance()
|
||||
->readFromFile($this->settings->envFilepath())
|
||||
->setCustomVars($this->settings->vars());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts convertions
|
||||
*
|
||||
* @return void
|
||||
* @throws Exceptions\CannotCreateDirectoryException
|
||||
* @throws Exceptions\DirectoryIsNotReadableException
|
||||
* @throws Exceptions\DirectoryIsNotWriteableException
|
||||
* @throws Exceptions\DirectoryNotExistsException
|
||||
* @throws Exceptions\IncorrectSettingsFileException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function start(): void
|
||||
{
|
||||
$this->processor = new Processor($this->settings, $this->env);
|
||||
$this->processor->start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles settings file saving when requested by --dump
|
||||
*
|
||||
* @return never
|
||||
*/
|
||||
protected function handleSettingsDump(): never
|
||||
{
|
||||
$answer = 'o';
|
||||
|
||||
if ($this->settings->fileExists()) {
|
||||
echo 'Settings file already exists: ' . $this->settings->filePath() . EOL;
|
||||
echo 'Do you want to (o)verwrite it, (b)ackup it and create new one or (c)ancel (default)?' . EOL;
|
||||
$answer = strtolower(trim(readline('> ')));
|
||||
}
|
||||
|
||||
if (!in_array($answer, ['o', 'b'])) {
|
||||
die('Current settings file has not been changed' . EOL);
|
||||
}
|
||||
|
||||
if ($answer === 'b') {
|
||||
$filepath = $this->settings->backup();
|
||||
printf("Settings file has been backed up to file:%s\t%s%s", EOL, $filepath, EOL);
|
||||
}
|
||||
|
||||
$this->settings->dump();
|
||||
printf("Arguments has been converted into settings file:%s\t%s%s", EOL, $this->settings->filePath(), EOL);
|
||||
die('Review and edit it if needed.' . EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns usage help strings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function help(): array
|
||||
{
|
||||
return array_merge(self::version(), [
|
||||
'Usage:',
|
||||
"\t./pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\tphp pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\tcomposer pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\t./vendor/bin/pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
'',
|
||||
'Possible ARGUMENTS:',
|
||||
"\t-f, --file - a PATH to a single collection file to convert from",
|
||||
"\t-d, --dir - a PATH to a directory with collections to convert from",
|
||||
"\t-o, --output - a directory OUTPUT_PATH to put results in",
|
||||
"\t-e, --env - use environment file with variables to replace in requests",
|
||||
"\t--var \"NAME=VALUE\" - force replace specified env variable called NAME with custom VALUE",
|
||||
"\t-p, --preserve - do not delete OUTPUT_PATH (if exists)",
|
||||
"\t --dump - convert provided arguments into settings file in `pwd",
|
||||
"\t-h, --help - show this help message and exit",
|
||||
"\t-v, --version - show version info and exit",
|
||||
'',
|
||||
'If no ARGUMENTS passed then --help implied.',
|
||||
'If both -f and -d are specified then only unique set of files from both arguments will be converted.',
|
||||
'-f or -d are required to be specified at least once, but each may be specified multiple times.',
|
||||
'PATH must be a valid path to readable json-file or directory.',
|
||||
'OUTPUT_PATH must be a valid path to writeable directory.',
|
||||
'If -o or -e was specified several times then only last one will be used.',
|
||||
'',
|
||||
'Possible FORMATS:',
|
||||
"\t--http - generate raw *.http files (default)",
|
||||
"\t--curl - generate shell scripts with curl command",
|
||||
"\t--wget - generate shell scripts with wget command",
|
||||
"\t--v2.0 - convert from Postman Collection Schema v2.1 into v2.0",
|
||||
"\t--v2.1 - convert from Postman Collection Schema v2.0 into v2.1",
|
||||
"\t-a, --all - convert to all of formats listed above",
|
||||
'',
|
||||
'If no FORMATS specified then --http implied.',
|
||||
'Any of FORMATS can be specified at the same time or replaced by --all.',
|
||||
'',
|
||||
'Example:',
|
||||
" ./pm-convert \ ",
|
||||
" -f ~/dir1/first.postman_collection.json \ ",
|
||||
" --directory ~/team \ ",
|
||||
" --file ~/dir2/second.postman_collection.json \ ",
|
||||
" --env ~/localhost.postman_environment.json \ ",
|
||||
" -d ~/personal \ ",
|
||||
" --var \"myvar=some value\" \ ",
|
||||
" -o ~/postman_export \ ",
|
||||
" --all",
|
||||
"",
|
||||
], self::copyright());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints usage help message in stdout
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function printHelp(): void
|
||||
{
|
||||
self::printArray(self::help());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns version strings
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function version(): array
|
||||
{
|
||||
return ['Postman collection converter v' . PM_VERSION, ''];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints version message in stdout
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function printVersion(): void
|
||||
{
|
||||
self::printArray(self::version());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns copyright strings
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function copyright(): array
|
||||
{
|
||||
return [
|
||||
'Anthony Axenov (c) 2023 - ' . (int)date('Y') . ', MIT license',
|
||||
'https://git.axenov.dev/anthony/pm-convert',
|
||||
'',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints copyright message in stdout
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function printCopyright(): void
|
||||
{
|
||||
self::printArray(self::copyright());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an arrays of string to stdout
|
||||
*
|
||||
* @param ...$strings
|
||||
* @return void
|
||||
*/
|
||||
protected static function printArray(...$strings): void
|
||||
{
|
||||
fwrite(STDOUT, implode("\n", array_merge(...$strings)));
|
||||
}
|
||||
}
|
||||
@@ -5,180 +5,65 @@ declare(strict_types=1);
|
||||
namespace PmConverter;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Generator;
|
||||
use JsonException;
|
||||
use PmConverter\Converters\{
|
||||
ConverterContract,
|
||||
ConvertFormat};
|
||||
use PmConverter\Exceptions\{
|
||||
CannotCreateDirectoryException,
|
||||
DirectoryIsNotReadableException,
|
||||
DirectoryIsNotWriteableException,
|
||||
DirectoryNotExistsException};
|
||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
||||
use PmConverter\Converters\ConverterContract;
|
||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotReadableException;
|
||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
||||
use PmConverter\Exceptions\DirectoryNotExistsException;
|
||||
use PmConverter\Exceptions\IncorrectSettingsFileException;
|
||||
|
||||
/**
|
||||
* Processor class
|
||||
*/
|
||||
class Processor
|
||||
{
|
||||
/**
|
||||
* Converter version
|
||||
*/
|
||||
public const VERSION = '1.4.1';
|
||||
|
||||
/**
|
||||
* @var string[] Paths to collection files
|
||||
*/
|
||||
protected array $collectionPaths = [];
|
||||
|
||||
/**
|
||||
* @var string Output path where to put results in
|
||||
*/
|
||||
protected string $outputPath;
|
||||
|
||||
/**
|
||||
* @var bool Flag to remove output directories or not before conversion started
|
||||
*/
|
||||
protected bool $preserveOutput = false;
|
||||
|
||||
/**
|
||||
* @var string[] Additional variables
|
||||
*/
|
||||
protected array $vars;
|
||||
|
||||
/**
|
||||
* @var ConvertFormat[] Formats to convert a collections into
|
||||
*/
|
||||
protected array $formats;
|
||||
|
||||
/**
|
||||
* @var ConverterContract[] Converters will be used for conversion according to choosen formats
|
||||
*/
|
||||
protected array $converters = [];
|
||||
|
||||
/**
|
||||
* @var object[] Collections that will be converted into choosen formats
|
||||
*/
|
||||
protected array $collections = [];
|
||||
|
||||
/**
|
||||
* @var int Initial timestamp
|
||||
*/
|
||||
protected int $initTime;
|
||||
protected readonly int $initTime;
|
||||
|
||||
/**
|
||||
* @var int Initial RAM usage
|
||||
*/
|
||||
protected int $initRam;
|
||||
protected readonly int $initRam;
|
||||
|
||||
/**
|
||||
* @var string Path to environment file
|
||||
* @var ConverterContract[] Converters will be used for conversion according to chosen formats
|
||||
*/
|
||||
protected string $envFile;
|
||||
|
||||
/**
|
||||
* @var Environment
|
||||
*/
|
||||
protected Environment $env;
|
||||
protected array $converters = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $argv Arguments came from cli
|
||||
* @param Settings $settings Settings (lol)
|
||||
* @param Environment $env Environment
|
||||
*/
|
||||
public function __construct(protected array $argv)
|
||||
{
|
||||
public function __construct(
|
||||
protected Settings $settings,
|
||||
protected Environment $env,
|
||||
) {
|
||||
$this->initTime = hrtime(true);
|
||||
$this->initRam = memory_get_usage(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an array of arguments came from cli
|
||||
* Handles input command
|
||||
*
|
||||
* @return void
|
||||
* @throws CannotCreateDirectoryException
|
||||
* @throws DirectoryIsNotReadableException
|
||||
* @throws DirectoryIsNotWriteableException
|
||||
* @throws DirectoryNotExistsException
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function parseArgs(): void
|
||||
public function start(): void
|
||||
{
|
||||
if (count($this->argv) < 2) {
|
||||
die(implode(PHP_EOL, $this->usage()) . PHP_EOL);
|
||||
}
|
||||
foreach ($this->argv as $idx => $arg) {
|
||||
switch ($arg) {
|
||||
case '-f':
|
||||
case '--file':
|
||||
$rawpath = $this->argv[$idx + 1];
|
||||
$normpath = FileSystem::normalizePath($rawpath);
|
||||
if (!FileSystem::isCollectionFile($normpath)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf("this is not a valid collection file:%s\t%s %s", PHP_EOL, $arg, $rawpath)
|
||||
);
|
||||
}
|
||||
$this->collectionPaths[] = $this->argv[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-o':
|
||||
case '--output':
|
||||
if (empty($this->argv[$idx + 1])) {
|
||||
throw new InvalidArgumentException('-o is required');
|
||||
}
|
||||
$this->outputPath = $this->argv[$idx + 1];
|
||||
break;
|
||||
|
||||
case '-d':
|
||||
case '--dir':
|
||||
if (empty($this->argv[$idx + 1])) {
|
||||
throw new InvalidArgumentException('a directory path is expected for -d (--dir)');
|
||||
}
|
||||
$rawpath = $this->argv[$idx + 1];
|
||||
$files = array_filter(
|
||||
FileSystem::dirContents($rawpath),
|
||||
static fn($filename) => FileSystem::isCollectionFile($filename)
|
||||
);
|
||||
$this->collectionPaths = array_unique(array_merge($this?->collectionPaths ?? [], $files));
|
||||
break;
|
||||
|
||||
case '-e':
|
||||
case '--env':
|
||||
$this->envFile = FileSystem::normalizePath($this->argv[$idx + 1]);
|
||||
break;
|
||||
|
||||
case '-p':
|
||||
case '--preserve':
|
||||
$this->preserveOutput = true;
|
||||
break;
|
||||
|
||||
case '--http':
|
||||
$this->formats[ConvertFormat::Http->name] = ConvertFormat::Http;
|
||||
break;
|
||||
|
||||
case '--curl':
|
||||
$this->formats[ConvertFormat::Curl->name] = ConvertFormat::Curl;
|
||||
break;
|
||||
|
||||
case '--wget':
|
||||
$this->formats[ConvertFormat::Wget->name] = ConvertFormat::Wget;
|
||||
break;
|
||||
|
||||
case '--var':
|
||||
[$var, $value] = explode('=', trim($this->argv[$idx + 1]));
|
||||
$this->vars[$var] = $value;
|
||||
break;
|
||||
|
||||
case '-v':
|
||||
case '--version':
|
||||
die(implode(PHP_EOL, $this->version()) . PHP_EOL);
|
||||
|
||||
case '-h':
|
||||
case '--help':
|
||||
die(implode(PHP_EOL, $this->usage()) . PHP_EOL);
|
||||
}
|
||||
}
|
||||
if (empty($this->collectionPaths)) {
|
||||
throw new InvalidArgumentException('there are no collections to convert');
|
||||
}
|
||||
if (empty($this->outputPath)) {
|
||||
throw new InvalidArgumentException('-o is required');
|
||||
}
|
||||
if (empty($this->formats)) {
|
||||
$this->formats = [ConvertFormat::Http->name => ConvertFormat::Http];
|
||||
}
|
||||
$this->prepareOutputDirectory();
|
||||
$this->initConverters();
|
||||
$this->convert();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,100 +75,72 @@ class Processor
|
||||
* @throws DirectoryNotExistsException
|
||||
* @throws DirectoryIsNotReadableException
|
||||
*/
|
||||
protected function initOutputDirectory(): void
|
||||
protected function prepareOutputDirectory(): void
|
||||
{
|
||||
if (isset($this?->outputPath) && !$this->preserveOutput) {
|
||||
FileSystem::removeDir($this->outputPath);
|
||||
if (!$this->settings->isPreserveOutput()) {
|
||||
FileSystem::removeDir($this->settings->outputPath());
|
||||
}
|
||||
FileSystem::makeDir($this->outputPath);
|
||||
FileSystem::makeDir($this->settings->outputPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes converters according to choosen formats
|
||||
* Initializes converters according to chosen formats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function initConverters(): void
|
||||
{
|
||||
foreach ($this->formats as $type) {
|
||||
$this->converters[$type->name] = new $type->value($this->preserveOutput);
|
||||
foreach ($this->settings->formats() as $type) {
|
||||
$this->converters[$type->name] = new $type->value($this->settings->isPreserveOutput());
|
||||
}
|
||||
unset($this->formats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes collection objects
|
||||
* Generates collections from settings
|
||||
*
|
||||
* @return Generator<Collection>
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function initCollections(): void
|
||||
protected function nextCollection(): Generator
|
||||
{
|
||||
foreach ($this->collectionPaths as $collectionPath) {
|
||||
$content = file_get_contents(FileSystem::normalizePath($collectionPath));
|
||||
$content = json_decode($content, flags: JSON_THROW_ON_ERROR);
|
||||
if (!property_exists($content, 'collection') || empty($content?->collection)) {
|
||||
throw new JsonException("not a valid collection: $collectionPath");
|
||||
}
|
||||
$this->collections[$content->collection->info->name] = $content->collection;
|
||||
foreach ($this->settings->collectionPaths() as $collectionPath) {
|
||||
yield Collection::fromFile($collectionPath);
|
||||
}
|
||||
unset($this->collectionPaths, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes environment object
|
||||
*
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function initEnv(): void
|
||||
{
|
||||
if (!isset($this->envFile)) {
|
||||
return;
|
||||
}
|
||||
$content = file_get_contents(FileSystem::normalizePath($this->envFile));
|
||||
$content = json_decode($content, flags: JSON_THROW_ON_ERROR);
|
||||
if (!property_exists($content, 'environment') || empty($content?->environment)) {
|
||||
throw new JsonException("not a valid environment: $this->envFile");
|
||||
}
|
||||
$this->env = new Environment($content->environment);
|
||||
foreach ($this->vars as $var => $value) {
|
||||
$this->env[$var] = $value;
|
||||
}
|
||||
unset($this->vars, $this->envFile, $content, $var, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a conversion
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function convert(): void
|
||||
{
|
||||
$this->parseArgs();
|
||||
$this->initOutputDirectory();
|
||||
$this->initConverters();
|
||||
$this->initCollections();
|
||||
$this->initEnv();
|
||||
$count = count($this->collections);
|
||||
$current = 0;
|
||||
$success = 0;
|
||||
print(implode(PHP_EOL, array_merge($this->version(), $this->copyright())) . PHP_EOL . PHP_EOL);
|
||||
foreach ($this->collections as $collectionName => $collection) {
|
||||
$count = count($this->settings->collectionPaths());
|
||||
$current = $success = 0;
|
||||
foreach ($this->nextCollection() as $collection) {
|
||||
++$current;
|
||||
printf("Converting '%s' (%d/%d):%s", $collectionName, $current, $count, PHP_EOL);
|
||||
foreach ($this->converters as $type => $exporter) {
|
||||
printf('> %s%s', strtolower($type), PHP_EOL);
|
||||
$outputPath = sprintf('%s%s%s', $this->outputPath, DIRECTORY_SEPARATOR, $collectionName);
|
||||
if (!empty($this->env)) {
|
||||
$exporter->withEnv($this->env);
|
||||
printf("Converting '%s' (%d/%d):%s", $collection->name(), $current, $count, EOL);
|
||||
foreach ($this->converters as $type => $converter) {
|
||||
/** @var AbstractConverter $converter */
|
||||
printf('> %s%s', strtolower($type), EOL);
|
||||
$outputPath = sprintf('%s%s%s', $this->settings->outputPath(), DS, $collection->name());
|
||||
try {
|
||||
$converter = $converter->to($outputPath);
|
||||
$converter = $converter->convert($collection);
|
||||
$converter->flush();
|
||||
printf(' OK: %s%s', $converter->getOutputPath(), EOL);
|
||||
} catch (Exception $e) {
|
||||
printf(' ERROR %s: %s%s', $e->getCode(), $e->getMessage(), EOL);
|
||||
if ($this->settings->isDevMode()) {
|
||||
array_map(static fn (string $line) => printf(' %s%s', $line, EOL), $e->getTrace());
|
||||
}
|
||||
}
|
||||
$exporter->convert($collection, $outputPath);
|
||||
printf(' OK: %s%s', $exporter->getOutputPath(), PHP_EOL);
|
||||
}
|
||||
print(PHP_EOL);
|
||||
print(EOL);
|
||||
++$success;
|
||||
}
|
||||
unset($this->converters, $type, $exporter, $outputPath, $this->collections, $collectionName, $collection);
|
||||
unset($this->converters, $type, $converter, $outputPath, $this->collections, $collectionName, $collection);
|
||||
$this->printStats($success, $current);
|
||||
}
|
||||
|
||||
@@ -297,86 +154,12 @@ class Processor
|
||||
protected function printStats(int $success, int $count): void
|
||||
{
|
||||
$time = (hrtime(true) - $this->initTime) / 1_000_000;
|
||||
$timeFmt = 'ms';
|
||||
if ($time > 1000) {
|
||||
$time /= 1000;
|
||||
$timeFmt = 'sec';
|
||||
}
|
||||
$ram = (memory_get_peak_usage(true) - $this->initRam) / 1024 / 1024;
|
||||
printf('Converted %d of %d in %.3f ms using up to %.3f MiB RAM%s', $success, $count, $time, $ram, PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function version(): array
|
||||
{
|
||||
return ["Postman collection converter v" . self::VERSION];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function copyright(): array
|
||||
{
|
||||
return [
|
||||
'Anthony Axenov (c) ' . date('Y') . ", MIT license",
|
||||
'https://git.axenov.dev/anthony/pm-convert'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function usage(): array
|
||||
{
|
||||
return array_merge($this->version(), [
|
||||
'Usage:',
|
||||
"\t./pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\tphp pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\tcomposer pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
"\t./vendor/bin/pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]",
|
||||
'',
|
||||
'Possible ARGUMENTS:',
|
||||
"\t-f, --file - a PATH to a single collection file to convert from",
|
||||
"\t-d, --dir - a PATH to a directory with collections to convert from",
|
||||
"\t-o, --output - a directory OUTPUT_PATH to put results in",
|
||||
"\t-e, --env - use environment file with variables to replace in requests",
|
||||
"\t--var \"NAME=VALUE\" - force replace specified env variable called NAME with custom VALUE",
|
||||
"\t (see interpolation notes below)",
|
||||
"\t-p, --preserve - do not delete OUTPUT_PATH (if exists)",
|
||||
"\t-h, --help - show this help message and exit",
|
||||
"\t-v, --version - show version info and exit",
|
||||
'',
|
||||
'If no ARGUMENTS passed then --help implied.',
|
||||
'If both -f and -d are specified then only unique set of files from both arguments will be converted.',
|
||||
'-f or -d are required to be specified at least once, but each may be specified multiple times.',
|
||||
'PATH must be a valid path to readable json-file or directory.',
|
||||
'OUTPUT_PATH must be a valid path to writeable directory.',
|
||||
'If -o or -e was specified several times then only last one will be used.',
|
||||
'',
|
||||
'Possible FORMATS:',
|
||||
"\t--http - generate raw *.http files (default)",
|
||||
"\t--curl - generate shell scripts with curl command",
|
||||
"\t--wget - generate shell scripts with wget command",
|
||||
'',
|
||||
'If no FORMATS specified then --http implied.',
|
||||
'Any of FORMATS can be specified at the same time.',
|
||||
'',
|
||||
'Notes about variable interpolation:',
|
||||
"\t1. You can use -e to tell where to find variables to replace in requests.",
|
||||
"\t2. You can use one or several --var to replace specific env variables to your own value.",
|
||||
"\t3. Correct syntax is `--var \"NAME=VALUE\". NAME may be in curly braces like {{NAME}}.",
|
||||
"\t4. Since -e is optional, a bunch of --var will emulate an environment. Also it does not",
|
||||
"\t matter if there is --var in environment file you provided or not.",
|
||||
"\t5. Even if you (not) provided -e and/or --var, any of variable may still be overridden",
|
||||
"\t from collection (if any), so last ones has top priority.",
|
||||
'',
|
||||
'Example:',
|
||||
" ./pm-convert \ ",
|
||||
" -f ~/dir1/first.postman_collection.json \ ",
|
||||
" --directory ~/team \ ",
|
||||
" --file ~/dir2/second.postman_collection.json \ ",
|
||||
" --env ~/localhost.postman_environment.json \ ",
|
||||
" -d ~/personal \ ",
|
||||
" --var \"myvar=some value\" \ ",
|
||||
" -o ~/postman_export ",
|
||||
"",
|
||||
], $this->copyright());
|
||||
printf("Converted %d/%d in %.2f $timeFmt using up to %.2f MiB RAM%s", $success, $count, $time, $ram, EOL);
|
||||
}
|
||||
}
|
||||
|
||||
425
src/Settings.php
Normal file
425
src/Settings.php
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PmConverter;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use JsonException;
|
||||
use PmConverter\Converters\ConvertFormat;
|
||||
use PmConverter\Enums\ArgumentNames as AN;
|
||||
|
||||
/**
|
||||
* Class responsible for settings storage and dumping
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
/**
|
||||
* @var string|null Full path to settings file
|
||||
*/
|
||||
protected ?string $filePath = null;
|
||||
|
||||
/**
|
||||
* @var bool Flag to output some debug-specific messages
|
||||
*/
|
||||
protected bool $devMode = false;
|
||||
|
||||
/**
|
||||
* @var string[] Paths to collection directories
|
||||
*/
|
||||
protected array $dirPaths = [];
|
||||
|
||||
/**
|
||||
* @var string[] Paths to collection files
|
||||
*/
|
||||
protected array $collectionPaths = [];
|
||||
|
||||
/**
|
||||
* @var string|null Output path where to put results in
|
||||
*/
|
||||
protected ?string $outputPath;
|
||||
|
||||
/**
|
||||
* @var bool Flag to remove output directories or not before conversion started
|
||||
*/
|
||||
protected bool $preserveOutput;
|
||||
|
||||
/**
|
||||
* @var string[] Additional variables
|
||||
*/
|
||||
protected array $vars = [];
|
||||
|
||||
/**
|
||||
* @var ConvertFormat[] Formats to convert a collections into
|
||||
*/
|
||||
protected array $formats = [];
|
||||
|
||||
/**
|
||||
* @var string|null Path to environment file
|
||||
*/
|
||||
protected ?string $envFilePath = null;
|
||||
|
||||
/**
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->loadFromDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads settings from file
|
||||
*
|
||||
* @param string|null $filePath
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function loadFromFile(?string $filePath = null): void
|
||||
{
|
||||
if (is_null($filePath)) {
|
||||
$filePath = sprintf('%s%spm-convert-settings.json', $_SERVER['PWD'], DS);
|
||||
}
|
||||
|
||||
$filePath = trim($filePath);
|
||||
|
||||
if (!file_exists($filePath)) {
|
||||
throw new Exception("file does not exist: $filePath");
|
||||
}
|
||||
|
||||
if (!is_file($filePath)) {
|
||||
throw new Exception("not a file: $filePath");
|
||||
}
|
||||
|
||||
if (!is_readable($filePath)) {
|
||||
throw new Exception("file is not readable: $filePath");
|
||||
}
|
||||
|
||||
$content = file_get_contents($filePath);
|
||||
$settings = json_decode($content ?: '{}', true, JSON_THROW_ON_ERROR);
|
||||
|
||||
$this->setFromArray($settings);
|
||||
$this->filePath = $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites some defined settings with new values
|
||||
*
|
||||
* @param array $settings
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function override(array $settings): void
|
||||
{
|
||||
$settings = array_replace_recursive($this->__serialize(), $settings);
|
||||
$this->setFromArray($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads settings with default values
|
||||
*
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function loadFromDefaults(): void
|
||||
{
|
||||
$this->setFromArray(self::defaults());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default settings values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function defaults(?string $key = null): mixed
|
||||
{
|
||||
$values = [
|
||||
AN::Config => null,
|
||||
AN::Directories => [],
|
||||
AN::Files => [],
|
||||
AN::Environment => null,
|
||||
AN::Output => null,
|
||||
AN::PreserveOutput => false,
|
||||
AN::Formats => ['http'],
|
||||
AN::Vars => [],
|
||||
AN::DevMode => false,
|
||||
AN::Verbose => false,
|
||||
];
|
||||
|
||||
return $key ? $values[$key] : $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set settings from array
|
||||
*
|
||||
* @param array $settings
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
protected function setFromArray(array $settings): void
|
||||
{
|
||||
foreach ($settings[AN::Directories] ?? self::defaults(AN::Directories) as $path) {
|
||||
$this->addDirPath($path);
|
||||
}
|
||||
|
||||
foreach ($settings[AN::Files] ?? self::defaults(AN::Files) ?? [] as $path) {
|
||||
$this->addFilePath($path);
|
||||
}
|
||||
|
||||
$this->setEnvFilePath($settings[AN::Environment] ?? self::defaults(AN::Environment));
|
||||
$this->setOutputPath($settings[AN::Output] ?? self::defaults(AN::Output));
|
||||
$this->setPreserveOutput($settings[AN::PreserveOutput] ?? self::defaults(AN::PreserveOutput));
|
||||
|
||||
foreach ($settings[AN::Formats] ?? self::defaults(AN::Formats) as $format) {
|
||||
$this->addFormat(ConvertFormat::fromArg($format));
|
||||
}
|
||||
|
||||
$this->vars = $settings[AN::Vars] ?? self::defaults(AN::Vars);
|
||||
$this->setDevMode($settings[AN::DevMode] ?? self::defaults(AN::DevMode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks wether settings file exists or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function fileExists(): bool
|
||||
{
|
||||
return is_file($this->filePath)
|
||||
&& is_readable($this->filePath)
|
||||
&& is_writable($this->filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns full path to settings file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function filePath(): string
|
||||
{
|
||||
return $this->filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds directory path into current settings array and fills files array with its content
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function addDirPath(string $path): void
|
||||
{
|
||||
$this->dirPaths = array_unique(array_merge(
|
||||
$this->dirPaths ?? [],
|
||||
[FileSystem::normalizePath($path)]
|
||||
));
|
||||
|
||||
$files = array_filter(
|
||||
FileSystem::dirContents($path),
|
||||
static fn ($filename) => FileSystem::isCollectionFile($filename)
|
||||
);
|
||||
|
||||
$this->collectionPaths = array_unique(array_merge($this->collectionPaths ?? [], $files));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds collection file into current settings array
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function addFilePath(string $path): void
|
||||
{
|
||||
if (!FileSystem::isCollectionFile($path)) {
|
||||
throw new InvalidArgumentException("not a valid collection: $path");
|
||||
}
|
||||
|
||||
if (!in_array($path, $this->collectionPaths)) {
|
||||
$this->collectionPaths[] = FileSystem::normalizePath($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets output directory path
|
||||
*
|
||||
* @param string|null $outputPath
|
||||
* @return void
|
||||
*/
|
||||
public function setOutputPath(?string $outputPath): void
|
||||
{
|
||||
$this->outputPath = $outputPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets developer mode setting
|
||||
*
|
||||
* @param bool $devMode
|
||||
* @return void
|
||||
*/
|
||||
public function setDevMode(bool $devMode): void
|
||||
{
|
||||
$this->devMode = $devMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a format to convert to into current settings array
|
||||
*
|
||||
* @param ConvertFormat $format
|
||||
* @return void
|
||||
*/
|
||||
public function addFormat(ConvertFormat $format): void
|
||||
{
|
||||
$this->formats[$format->name] = $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of variables
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function vars(): array
|
||||
{
|
||||
return $this->vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a setting responsible for saving old convertion results
|
||||
*
|
||||
* @param bool $preserveOutput
|
||||
* @return void
|
||||
*/
|
||||
public function setPreserveOutput(bool $preserveOutput): void
|
||||
{
|
||||
$this->preserveOutput = $preserveOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets environment filepath setting
|
||||
*
|
||||
* @param string|null $filepath
|
||||
* @return void
|
||||
*/
|
||||
public function setEnvFilePath(?string $filepath): void
|
||||
{
|
||||
$this->envFilePath = is_string($filepath)
|
||||
? FileSystem::normalizePath($filepath)
|
||||
: $filepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current value of developer mode setting
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDevMode(): bool
|
||||
{
|
||||
return $this->devMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current value of collection files setting
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function collectionPaths(): array
|
||||
{
|
||||
return $this->collectionPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current value of output directory path setting
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function outputPath(): ?string
|
||||
{
|
||||
return $this->outputPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current value of preserve output setting
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPreserveOutput(): bool
|
||||
{
|
||||
return $this->preserveOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current convert formats
|
||||
*
|
||||
* @return ConvertFormat[]
|
||||
*/
|
||||
public function formats(): array
|
||||
{
|
||||
return $this->formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current value of environment filepath setting
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function envFilepath(): ?string
|
||||
{
|
||||
return $this->envFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines fieldset of settings JSON
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return [
|
||||
AN::DevMode => $this->isDevMode(),
|
||||
AN::Directories => $this->dirPaths,
|
||||
AN::Files => $this->collectionPaths(),
|
||||
AN::Environment => $this->envFilepath(),
|
||||
AN::Output => $this->outputPath(),
|
||||
AN::PreserveOutput => $this->isPreserveOutput(),
|
||||
AN::Formats => array_values(array_map(
|
||||
static fn (ConvertFormat $format) => $format->toArg(),
|
||||
$this->formats(),
|
||||
)),
|
||||
AN::Vars => $this->vars,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts settings into JSON format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return json_encode($this->__serialize(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes settings in JSON format into settings file
|
||||
*
|
||||
* @param array $vars
|
||||
* @return bool
|
||||
*/
|
||||
public function dump(array $vars = []): bool
|
||||
{
|
||||
count($vars) > 0 && $this->vars = $vars;
|
||||
return file_put_contents(self::$filepath, (string)$this) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a backup file of current settings file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backup(): string
|
||||
{
|
||||
$newFilePath = $this->filePath() . '.bak.' . time();
|
||||
copy($this->filePath(), $newFilePath);
|
||||
return $newFilePath;
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,14 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PmConverter\Exceptions\{
|
||||
EmptyHttpVerbException,
|
||||
InvalidHttpVersionException};
|
||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
||||
|
||||
class AbstractRequestTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||
* @covers PmConverter\HttpVersions
|
||||
* @covers \PmConverter\Enums\HttpVersion
|
||||
* @return void
|
||||
* @throws InvalidHttpVersionException
|
||||
*/
|
||||
@@ -26,7 +25,7 @@ class AbstractRequestTest extends TestCase
|
||||
/**
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getVerb()
|
||||
* @covers PmConverter\HttpVersions
|
||||
* @covers \PmConverter\Enums\HttpVersion
|
||||
* @return void
|
||||
* @throws InvalidHttpVersionException
|
||||
*/
|
||||
@@ -71,7 +70,7 @@ class AbstractRequestTest extends TestCase
|
||||
/**
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setUrl()
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getUrl()
|
||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getRawUrl()
|
||||
* @return void
|
||||
*/
|
||||
public function testUrl(): void
|
||||
@@ -79,7 +78,7 @@ class AbstractRequestTest extends TestCase
|
||||
$request = new \PmConverter\Converters\Http\HttpRequest();
|
||||
$request->setUrl('http://localhost');
|
||||
|
||||
$this->assertSame('http://localhost', $request->getUrl());
|
||||
$this->assertSame('http://localhost', $request->getRawUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
10
tests/pm-convert-settings.json
Normal file
10
tests/pm-convert-settings.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"files": [
|
||||
"collections/20-API Lifecycle.postman_collection.json"
|
||||
],
|
||||
"output": "converted",
|
||||
"preserveOutput": false,
|
||||
"formats": [
|
||||
"http"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user