Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83794a7464 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,8 +1,5 @@
|
|||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
/vendor
|
/vendor
|
||||||
/nbproject
|
|
||||||
/tmp
|
|
||||||
|
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
.phpunit.cache
|
.phpunit.cache
|
||||||
|
|||||||
131
README.md
131
README.md
@@ -8,17 +8,14 @@ Without 3rd-party dependencies.
|
|||||||
|
|
||||||
These formats are supported for now: `http`, `curl`, `wget`.
|
These formats are supported for now: `http`, `curl`, `wget`.
|
||||||
|
|
||||||
> This project has been started and quickly written in my spare time to solve one exact problem in one NDA-project,
|
> This project was quickly written in my spare time to solve one exact problem in one NDA-project, so it may
|
||||||
> so it may contain stupid errors and (for sure) doesn't cover all possible cases according to collection schema.
|
> contain stupid errors and (for sure) doesn't cover all possible cases according to collection schema.
|
||||||
> Feel free to propose your improvements.
|
> So 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
|
## Supported features
|
||||||
|
|
||||||
* 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);
|
* [collection schema **v2.1**](https://schema.postman.com/json/collection/v2.1.0/collection.json);
|
||||||
|
* `Bearer` auth;
|
||||||
* replace vars in requests by stored in collection and environment file;
|
* 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;
|
* 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);
|
* all headers (including disabled for `http`-format);
|
||||||
@@ -27,9 +24,10 @@ So please always use the latest version of `pm-convert`.
|
|||||||
|
|
||||||
## Planned features
|
## 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 authentication kinds (_currently only `Bearer` supported_);
|
||||||
- support as many as possible/necessary of body formats (_currently only `json` and `formdata` supported_);
|
- support as many as possible/necessary of body formats (_currently only `json` and `formdata`_);
|
||||||
- documentation generation support (markdown) with response examples (if present) (#6);
|
- documentation generation support (markdown) with responce examples (if present) (#6);
|
||||||
- maybe some another convert formats (like httpie or something...);
|
- maybe some another convert formats (like httpie or something...);
|
||||||
- better logging;
|
- better logging;
|
||||||
- 90%+ test coverage, phpcs, psalm, etc.;
|
- 90%+ test coverage, phpcs, psalm, etc.;
|
||||||
@@ -67,10 +65,10 @@ Possible ARGUMENTS:
|
|||||||
-o, --output - a directory OUTPUT_PATH to put results in
|
-o, --output - a directory OUTPUT_PATH to put results in
|
||||||
-e, --env - use environment file with variables to replace in requests
|
-e, --env - use environment file with variables to replace in requests
|
||||||
--var "NAME=VALUE" - force replace specified env variable called NAME with custom VALUE
|
--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)
|
-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
|
-h, --help - show this help message and exit
|
||||||
--version - show version info and exit
|
-v, --version - show version info and exit
|
||||||
|
|
||||||
If no ARGUMENTS passed then --help implied.
|
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.
|
If both -f and -d are specified then only unique set of files from both arguments will be converted.
|
||||||
@@ -83,12 +81,18 @@ Possible FORMATS:
|
|||||||
--http - generate raw *.http files (default)
|
--http - generate raw *.http files (default)
|
||||||
--curl - generate shell scripts with curl command
|
--curl - generate shell scripts with curl command
|
||||||
--wget - generate shell scripts with wget 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.
|
If no FORMATS specified then --http implied.
|
||||||
Any of FORMATS can be specified at the same time or replaced by --all.
|
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.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
./pm-convert \
|
./pm-convert \
|
||||||
@@ -98,8 +102,8 @@ Example:
|
|||||||
--env ~/localhost.postman_environment.json \
|
--env ~/localhost.postman_environment.json \
|
||||||
-d ~/personal \
|
-d ~/personal \
|
||||||
--var "myvar=some value" \
|
--var "myvar=some value" \
|
||||||
-o ~/postman_export \
|
-o ~/postman_export
|
||||||
--all
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notices
|
### Notices
|
||||||
@@ -112,95 +116,12 @@ Example:
|
|||||||
If not, you can rename them in Postman or convert collections with similar names into different directories.
|
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.
|
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
|
## How to implement a new format
|
||||||
|
|
||||||
1. Create new namespace in `./src/Converters` and name it according to format of your choice.
|
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.
|
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.
|
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`.
|
4. Write your own logic in converter's `__toString()` method, write new methods and override abstract ones
|
||||||
5. Write your own logic in converter, write new methods and override abstract ones.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,8 @@
|
|||||||
],
|
],
|
||||||
"keywords": ["postman", "collection", "converter", "http", "wget", "curl", "api", "convert"],
|
"keywords": ["postman", "collection", "converter", "http", "wget", "curl", "api", "convert"],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.4",
|
"php": "^8.1",
|
||||||
"ext-json": "*",
|
"ext-json": "*"
|
||||||
"ext-mbstring": "*",
|
|
||||||
"ext-readline": "*"
|
|
||||||
},
|
},
|
||||||
"bin": ["pm-convert"],
|
"bin": ["pm-convert"],
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -32,6 +30,6 @@
|
|||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^12.5"
|
"phpunit/phpunit": "^10.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
885
composer.lock
generated
885
composer.lock
generated
File diff suppressed because it is too large
Load Diff
21
pm-convert
21
pm-convert
@@ -3,11 +3,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use PmConverter\Handler;
|
use PmConverter\Processor;
|
||||||
const EOL = PHP_EOL;
|
|
||||||
const DS = DIRECTORY_SEPARATOR;
|
|
||||||
|
|
||||||
const PM_VERSION = '1.8';
|
|
||||||
|
|
||||||
$paths = [
|
$paths = [
|
||||||
__DIR__ . '/../../autoload.php',
|
__DIR__ . '/../../autoload.php',
|
||||||
@@ -24,13 +20,14 @@ foreach ($paths as $path) {
|
|||||||
|
|
||||||
is_null($file) && throw new RuntimeException('Unable to locate autoload.php file.');
|
is_null($file) && throw new RuntimeException('Unable to locate autoload.php file.');
|
||||||
|
|
||||||
$handler = new Handler();
|
$processor = new Processor($argv);
|
||||||
$handler::printVersion();
|
|
||||||
$handler::printCopyright();
|
|
||||||
try {
|
try {
|
||||||
$handler->init($argv);
|
$processor->convert();
|
||||||
$handler->start();
|
} catch (InvalidArgumentException $e) {
|
||||||
|
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), PHP_EOL));
|
||||||
|
print(implode(PHP_EOL, $processor->usage()));
|
||||||
|
die(1);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), EOL));
|
fwrite(STDERR, sprintf('ERROR: %s%s', $e->getMessage(), PHP_EOL));
|
||||||
exit(1);
|
die(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"directories": [
|
|
||||||
"tmp"
|
|
||||||
],
|
|
||||||
"output": "tmp/output",
|
|
||||||
"preserveOutput": false,
|
|
||||||
"formats": [
|
|
||||||
"opencollection"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
<?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 = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 '--openc':
|
|
||||||
case '--opencollection':
|
|
||||||
$this->parsed[AN::Formats][] = ConvertFormat::OpenCollection;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
<?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, flags: JSON_THROW_ON_ERROR);
|
|
||||||
$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,24 +5,22 @@ declare(strict_types=1);
|
|||||||
namespace PmConverter\Converters\Abstract;
|
namespace PmConverter\Converters\Abstract;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Iterator;
|
use PmConverter\Converters\{
|
||||||
use PmConverter\Collection;
|
ConverterContract,
|
||||||
use PmConverter\Converters\RequestContract;
|
RequestContract};
|
||||||
use PmConverter\Environment;
|
use PmConverter\Environment;
|
||||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
|
||||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
|
||||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
use PmConverter\Exceptions\InvalidHttpVersionException;
|
||||||
use PmConverter\FileSystem;
|
use PmConverter\FileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
abstract class AbstractConverter
|
abstract class AbstractConverter implements ConverterContract
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Collection|null
|
* @var object|null
|
||||||
*/
|
*/
|
||||||
protected ?Collection $collection = null;
|
protected ?object $collection = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
@@ -30,67 +28,35 @@ abstract class AbstractConverter
|
|||||||
protected string $outputPath;
|
protected string $outputPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var RequestContract[] Converted requests
|
* @var Environment|null
|
||||||
*/
|
*/
|
||||||
protected array $requests = [];
|
protected ?Environment $env = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets output path
|
* Sets an environment with vars
|
||||||
*
|
*
|
||||||
* @param string $outputPath
|
* @param Environment $env
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function to(string $outputPath): self
|
public function withEnv(Environment $env): static
|
||||||
{
|
{
|
||||||
$this->outputPath = sprintf('%s%s%s', $outputPath, DS, static::OUTPUT_DIR);
|
$this->env = $env;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts requests from collection
|
* Converts collection requests
|
||||||
*
|
*
|
||||||
* @param Collection $collection
|
|
||||||
* @return static
|
|
||||||
* @throws CannotCreateDirectoryException
|
|
||||||
* @throws DirectoryIsNotWriteableException
|
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function convert(Collection $collection): static
|
public function convert(object $collection, string $outputPath): void
|
||||||
{
|
{
|
||||||
|
$outputPath = sprintf('%s%s%s', $outputPath, DIRECTORY_SEPARATOR, static::OUTPUT_DIR);
|
||||||
|
$this->outputPath = FileSystem::makeDir($outputPath);
|
||||||
$this->collection = $collection;
|
$this->collection = $collection;
|
||||||
$this->outputPath = FileSystem::makeDir($this->outputPath);
|
$this->setVariables();
|
||||||
$this->setCollectionVars();
|
foreach ($collection->item as $item) {
|
||||||
foreach ($collection->iterate() as $path => $item) {
|
$this->convertItem($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 flush(): void
|
|
||||||
{
|
|
||||||
foreach ($this->converted() as $path => $request) {
|
|
||||||
$this->writeRequest($request, $path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +65,14 @@ abstract class AbstractConverter
|
|||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setCollectionVars(): static
|
protected function setVariables(): static
|
||||||
{
|
{
|
||||||
foreach ($this->collection?->variable ?? [] as $var) {
|
empty($this->env) && $this->env = new Environment($this->collection?->variable);
|
||||||
Environment::instance()->setCustomVar($var->key, $var->value);
|
if (!empty($this->collection?->variable)) {
|
||||||
|
foreach ($this->collection->variable as $var) {
|
||||||
|
$this->env[$var->key] = $var->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +94,31 @@ abstract class AbstractConverter
|
|||||||
*/
|
*/
|
||||||
protected function isItemFolder(object $item): bool
|
protected function isItemFolder(object $item): bool
|
||||||
{
|
{
|
||||||
return !empty($item->item)
|
return !empty($item->item) && empty($item->request);
|
||||||
&& is_array($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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,24 +128,23 @@ abstract class AbstractConverter
|
|||||||
* @return RequestContract
|
* @return RequestContract
|
||||||
* @throws InvalidHttpVersionException
|
* @throws InvalidHttpVersionException
|
||||||
*/
|
*/
|
||||||
protected function makeRequest(object $item): RequestContract
|
protected function initRequest(object $item): RequestContract
|
||||||
{
|
{
|
||||||
$request_class = static::REQUEST_CLASS;
|
$request_class = static::REQUEST_CLASS;
|
||||||
|
|
||||||
/** @var RequestContract $request */
|
/** @var RequestContract $result */
|
||||||
$request = new $request_class();
|
$result = new $request_class();
|
||||||
$request->setName($item->name);
|
$result->setName($item->name);
|
||||||
$request->setVersion($this->collection->version);
|
$result->setHttpVersion(1.1); //TODO http version?
|
||||||
$request->setHttpVersion(1.1); //TODO http version?
|
$result->setDescription($item->request?->description ?? null);
|
||||||
$request->setDescription($item->request?->description ?? null);
|
$result->setVerb($item->request->method);
|
||||||
$request->setVerb($item->request->method);
|
$result->setUrl($item->request->url->raw);
|
||||||
$request->setUrl($item->request->url);
|
$result->setHeaders($item->request->header);
|
||||||
$request->setHeaders($item->request->header);
|
$result->setAuth($item->request?->auth ?? $this->collection?->auth ?? null);
|
||||||
$request->setAuth($item->request?->auth ?? $this->collection?->auth ?? null);
|
|
||||||
if ($item->request->method !== 'GET' && !empty($item->request->body)) {
|
if ($item->request->method !== 'GET' && !empty($item->request->body)) {
|
||||||
$request->setBody($item->request->body);
|
$result->setBody($item->request->body);
|
||||||
}
|
}
|
||||||
return $request;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,9 +157,9 @@ abstract class AbstractConverter
|
|||||||
*/
|
*/
|
||||||
protected function writeRequest(RequestContract $request, string $subpath = null): bool
|
protected function writeRequest(RequestContract $request, string $subpath = null): bool
|
||||||
{
|
{
|
||||||
$filedir = sprintf('%s%s%s', $this->outputPath, DS, $subpath);
|
$filedir = sprintf('%s%s%s', $this->outputPath, DIRECTORY_SEPARATOR, $subpath);
|
||||||
$filedir = FileSystem::makeDir($filedir);
|
$filedir = FileSystem::makeDir($filedir);
|
||||||
$filepath = sprintf('%s%s%s.%s', $filedir, DS, $request->getName(), static::FILE_EXT);
|
$filepath = sprintf('%s%s%s.%s', $filedir, DIRECTORY_SEPARATOR, $request->getName(), static::FILE_EXT);
|
||||||
$content = $this->interpolate((string)$request);
|
$content = $this->interpolate((string)$request);
|
||||||
return file_put_contents($filepath, $content) > 0;
|
return file_put_contents($filepath, $content) > 0;
|
||||||
}
|
}
|
||||||
@@ -183,9 +172,18 @@ abstract class AbstractConverter
|
|||||||
*/
|
*/
|
||||||
protected function interpolate(string $content): string
|
protected function interpolate(string $content): string
|
||||||
{
|
{
|
||||||
$replace = static fn ($a) => Environment::instance()->var($var = $a[0]) ?: $var;
|
if (!$this->env?->hasVars()) {
|
||||||
return Environment::instance()->hasVars()
|
return $content;
|
||||||
? preg_replace_callback('/\{\{.*}}/m', $replace, $content)
|
}
|
||||||
: $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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ declare(strict_types=1);
|
|||||||
namespace PmConverter\Converters\Abstract;
|
namespace PmConverter\Converters\Abstract;
|
||||||
|
|
||||||
use PmConverter\Converters\RequestContract;
|
use PmConverter\Converters\RequestContract;
|
||||||
use PmConverter\Enums\CollectionVersion;
|
use PmConverter\Exceptions\{
|
||||||
use PmConverter\Enums\HttpVersion;
|
EmptyHttpVerbException,
|
||||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
InvalidHttpVersionException};
|
||||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
use PmConverter\HttpVersions;
|
||||||
use Stringable;
|
use Stringable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,9 +22,9 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
protected string $verb;
|
protected string $verb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var object|string URL where to send a request
|
* @var string URL where to send a request
|
||||||
*/
|
*/
|
||||||
protected object|string $url;
|
protected string $url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var float HTTP protocol version
|
* @var float HTTP protocol version
|
||||||
@@ -56,23 +56,14 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
*/
|
*/
|
||||||
protected string $bodymode = 'raw';
|
protected string $bodymode = 'raw';
|
||||||
|
|
||||||
|
|
||||||
protected CollectionVersion $version;
|
|
||||||
|
|
||||||
public function setVersion(CollectionVersion $version): static
|
|
||||||
{
|
|
||||||
$this->version = $version;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function setHttpVersion(float $version): static
|
public function setHttpVersion(float $version): static
|
||||||
{
|
{
|
||||||
if (!in_array($version, HttpVersion::values())) {
|
if (!in_array($version, HttpVersions::values())) {
|
||||||
throw new InvalidHttpVersionException(
|
throw new InvalidHttpVersionException(
|
||||||
'Only these HTTP versions are supported: ' . implode(', ', HttpVersion::values())
|
'Only these HTTP versions are supported: ' . implode(', ', HttpVersions::values())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->httpVersion = $version;
|
$this->httpVersion = $version;
|
||||||
@@ -101,7 +92,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
*/
|
*/
|
||||||
public function getName(): string
|
public function getName(): string
|
||||||
{
|
{
|
||||||
return str_replace(DS, '_', $this->name);
|
return str_replace(DIRECTORY_SEPARATOR, '_', $this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +133,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function setUrl(object|string $url): static
|
public function setUrl(string $url): static
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
return $this;
|
return $this;
|
||||||
@@ -151,9 +142,9 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function getRawUrl(): string
|
public function getUrl(): string
|
||||||
{
|
{
|
||||||
return is_object($this->url) ? $this->url->raw : $this->url;
|
return $this->url ?: '<empty url>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,11 +186,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
if (!empty($auth)) {
|
if (!empty($auth)) {
|
||||||
switch ($auth->type) {
|
switch ($auth->type) {
|
||||||
case 'bearer':
|
case 'bearer':
|
||||||
$this->setHeader('Authorization', 'Bearer ' . match ($this->version) {
|
$this->setHeader('Authorization', 'Bearer ' . $auth->{$auth->type}[0]->value);
|
||||||
CollectionVersion::Version20 => $auth->{$auth->type}->token,
|
|
||||||
CollectionVersion::Version21 => $auth->{$auth->type}[0]->value,
|
|
||||||
default => null
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -232,12 +219,11 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
{
|
{
|
||||||
$this->setBodymode($body->mode);
|
$this->setBodymode($body->mode);
|
||||||
if ($body->mode === 'formdata') {
|
if ($body->mode === 'formdata') {
|
||||||
$this->setHeader('Content-Type', 'multipart/form-data')->setFormdataBody($body);
|
$this->setHeader('Content-Type', 'multipart/form-data')
|
||||||
} elseif ($body->mode === 'raw') {
|
->setFormdataBody($body);
|
||||||
$this->setBodyAsIs($body);
|
} elseif (!empty($body->options) && $body->options->{$this->bodymode}->language === 'json') {
|
||||||
if (!empty($body->options) && $body->options->{$this->bodymode}->language === 'json') {
|
$this->setHeader('Content-Type', 'application/json')
|
||||||
$this->setHeader('Content-Type', 'application/json');
|
->setJsonBody($body);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -265,7 +251,7 @@ abstract class AbstractRequest implements Stringable, RequestContract
|
|||||||
* @param object $body
|
* @param object $body
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
protected function setBodyAsIs(object $body): static
|
protected function setJsonBody(object $body): static
|
||||||
{
|
{
|
||||||
$this->body = $body->{$this->getBodymode()};
|
$this->body = $body->{$this->getBodymode()};
|
||||||
return $this;
|
return $this;
|
||||||
|
|||||||
@@ -5,43 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace PmConverter\Converters;
|
namespace PmConverter\Converters;
|
||||||
|
|
||||||
|
|
||||||
use PmConverter\Converters\Curl\CurlConverter;
|
use PmConverter\Converters\{
|
||||||
use PmConverter\Converters\Http\HttpConverter;
|
Curl\CurlConverter,
|
||||||
use PmConverter\Converters\OpenCollection\OpenCollectionConverter;
|
Http\HttpConverter,
|
||||||
use PmConverter\Converters\Postman20\Postman20Converter;
|
Wget\WgetConverter};
|
||||||
use PmConverter\Converters\Postman21\Postman21Converter;
|
|
||||||
use PmConverter\Converters\Wget\WgetConverter;
|
|
||||||
|
|
||||||
enum ConvertFormat: string
|
enum ConvertFormat: string
|
||||||
{
|
{
|
||||||
case Http = HttpConverter::class;
|
case Http = HttpConverter::class;
|
||||||
case Curl = CurlConverter::class;
|
case Curl = CurlConverter::class;
|
||||||
case Wget = WgetConverter::class;
|
case Wget = WgetConverter::class;
|
||||||
case OpenCollection = OpenCollectionConverter::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,
|
|
||||||
'opencollection' => ConvertFormat::OpenCollection,
|
|
||||||
'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::OpenCollection => 'opencollection',
|
|
||||||
ConvertFormat::Postman20 => 'v2.0',
|
|
||||||
ConvertFormat::Postman21 => 'v2.1',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter\Converters;
|
namespace PmConverter\Converters;
|
||||||
|
|
||||||
use PmConverter\Collection;
|
|
||||||
|
|
||||||
interface ConverterContract
|
interface ConverterContract
|
||||||
{
|
{
|
||||||
public function convert(Collection $collection, string $outputPath): void;
|
public function convert(object $collection, string $outputPath): void;
|
||||||
public function getOutputPath(): string;
|
public function getOutputPath(): string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter\Converters\Curl;
|
namespace PmConverter\Converters\Curl;
|
||||||
|
|
||||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
use PmConverter\Converters\{
|
||||||
|
Abstract\AbstractConverter,
|
||||||
|
ConverterContract};
|
||||||
|
|
||||||
class CurlConverter extends AbstractConverter
|
class CurlConverter extends AbstractConverter implements ConverterContract
|
||||||
{
|
{
|
||||||
protected const FILE_EXT = 'sh';
|
protected const FILE_EXT = 'sh';
|
||||||
|
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ class CurlRequest extends AbstractRequest
|
|||||||
"curl \ ",
|
"curl \ ",
|
||||||
"\t--http1.1 \ ", //TODO proto
|
"\t--http1.1 \ ", //TODO proto
|
||||||
"\t--request $this->verb \ ",
|
"\t--request $this->verb \ ",
|
||||||
"\t--location {$this->getRawUrl()} \ ",
|
"\t--location $this->url \ ",
|
||||||
],
|
],
|
||||||
$this->prepareHeaders(),
|
$this->prepareHeaders(),
|
||||||
$this->prepareBody()
|
$this->prepareBody()
|
||||||
);
|
);
|
||||||
$output[] = rtrim(array_pop($output), '\ ');
|
$output[] = rtrim(array_pop($output), '\ ');
|
||||||
return implode(EOL, array_merge($output, ['']));
|
return implode(PHP_EOL, array_merge($output, ['']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter\Converters\Http;
|
namespace PmConverter\Converters\Http;
|
||||||
|
|
||||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
use PmConverter\Converters\{
|
||||||
|
Abstract\AbstractConverter,
|
||||||
|
ConverterContract};
|
||||||
|
|
||||||
class HttpConverter extends AbstractConverter
|
class HttpConverter extends AbstractConverter implements ConverterContract
|
||||||
{
|
{
|
||||||
protected const FILE_EXT = 'http';
|
protected const FILE_EXT = 'http';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace PmConverter\Converters\Http;
|
namespace PmConverter\Converters\Http;
|
||||||
|
|
||||||
use PmConverter\Converters\Abstract\AbstractRequest;
|
use PmConverter\Converters\Abstract\AbstractRequest;
|
||||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
use PmConverter\Exceptions\{
|
||||||
|
EmptyHttpVerbException};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to determine file content with http request format
|
* Class to determine file content with http request format
|
||||||
@@ -28,7 +29,7 @@ class HttpRequest extends AbstractRequest
|
|||||||
*/
|
*/
|
||||||
protected function prepareHeaders(): array
|
protected function prepareHeaders(): array
|
||||||
{
|
{
|
||||||
$output[] = sprintf('%s %s HTTP/%s', $this->getVerb(), $this->getRawUrl(), $this->getHttpVersion());
|
$output[] = sprintf('%s %s HTTP/%s', $this->getVerb(), $this->getUrl(), $this->getHttpVersion());
|
||||||
foreach ($this->headers as $name => $data) {
|
foreach ($this->headers as $name => $data) {
|
||||||
$output[] = sprintf('%s%s: %s', $data['disabled'] ? '# ' : '', $name, $data['value']);
|
$output[] = sprintf('%s%s: %s', $data['disabled'] ? '# ' : '', $name, $data['value']);
|
||||||
}
|
}
|
||||||
@@ -68,6 +69,6 @@ class HttpRequest extends AbstractRequest
|
|||||||
$this->prepareHeaders(),
|
$this->prepareHeaders(),
|
||||||
$this->prepareBody()
|
$this->prepareBody()
|
||||||
);
|
);
|
||||||
return implode(EOL, $output);
|
return implode(PHP_EOL, $output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PmConverter\Converters\OpenCollection;
|
|
||||||
|
|
||||||
use PmConverter\Collection;
|
|
||||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
|
||||||
use PmConverter\FileSystem;
|
|
||||||
|
|
||||||
class OpenCollectionConverter extends AbstractConverter
|
|
||||||
{
|
|
||||||
protected const FILE_EXT = 'yml';
|
|
||||||
|
|
||||||
protected const OUTPUT_DIR = 'opencollection';
|
|
||||||
|
|
||||||
protected const REQUEST_CLASS = OpenCollectionRequest::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function convert(Collection $collection): static
|
|
||||||
{
|
|
||||||
$this->collection = $collection;
|
|
||||||
$this->outputPath = FileSystem::makeDir($this->outputPath);
|
|
||||||
$this->setCollectionVars();
|
|
||||||
|
|
||||||
// Write main collection file
|
|
||||||
$this->writeCollectionFile($collection);
|
|
||||||
|
|
||||||
foreach ($collection->iterate() as $path => $item) {
|
|
||||||
$request = $this->makeRequest($item);
|
|
||||||
$this->writeRequest($request, $path);
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes main OpenCollection collection file
|
|
||||||
*
|
|
||||||
* @param Collection $collection
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function writeCollectionFile(Collection $collection): void
|
|
||||||
{
|
|
||||||
$filepath = sprintf('%s%scollection.%s', $this->outputPath, DS, static::FILE_EXT);
|
|
||||||
$content = $this->generateCollectionContent($collection);
|
|
||||||
file_put_contents($filepath, $content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates collection YAML content
|
|
||||||
*
|
|
||||||
* @param Collection $collection
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function generateCollectionContent(Collection $collection): string
|
|
||||||
{
|
|
||||||
$output = [
|
|
||||||
'name: ' . ($collection->name ?? 'Untitled Collection'),
|
|
||||||
'type: collection',
|
|
||||||
'',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!empty($collection->info?->description)) {
|
|
||||||
$output[] = 'description: |';
|
|
||||||
$output[] = ' ' . str_replace("\n", "\n ", $collection->info->description);
|
|
||||||
$output[] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$output[] = 'version: 1';
|
|
||||||
$output[] = '';
|
|
||||||
$output[] = 'baseVars: []';
|
|
||||||
$output[] = '';
|
|
||||||
$output[] = 'environments: []';
|
|
||||||
$output[] = '';
|
|
||||||
$output[] = 'requests:';
|
|
||||||
|
|
||||||
foreach ($collection->iterate() as $path => $item) {
|
|
||||||
$requestRef = str_replace(DS, '/', $path . '/' . $item->name);
|
|
||||||
$output[] = ' - $ref: ./' . $requestRef . '.yml';
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode("\n", $output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PmConverter\Converters\OpenCollection;
|
|
||||||
|
|
||||||
use PmConverter\Converters\Abstract\AbstractRequest;
|
|
||||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to determine file content with OpenCollection format
|
|
||||||
*/
|
|
||||||
class OpenCollectionRequest extends AbstractRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function prepareDescription(): array
|
|
||||||
{
|
|
||||||
return empty($this->description)
|
|
||||||
? []
|
|
||||||
: ['description: |', ' ' . str_replace("\n", "\n ", $this->description), ''];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @throws EmptyHttpVerbException
|
|
||||||
*/
|
|
||||||
protected function prepareHeaders(): array
|
|
||||||
{
|
|
||||||
$output = ['headers:'];
|
|
||||||
foreach ($this->headers as $name => $data) {
|
|
||||||
$prefix = $data['disabled'] ? '# ' : '';
|
|
||||||
$output[] = sprintf('%s %s: %s', $prefix, $name, $data['value']);
|
|
||||||
}
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function prepareBody(): array
|
|
||||||
{
|
|
||||||
$output = ['body:'];
|
|
||||||
|
|
||||||
switch ($this->getBodymode()) {
|
|
||||||
case 'formdata':
|
|
||||||
$output[] = ' type: formdata';
|
|
||||||
$output[] = ' files:';
|
|
||||||
foreach ($this->body as $key => $data) {
|
|
||||||
$disabled = $data['disabled'] ?? false;
|
|
||||||
$prefix = $disabled ? '# ' : ' ';
|
|
||||||
if ($data['type'] === 'file') {
|
|
||||||
$output[] = sprintf('%s- name: %s', $prefix, $key);
|
|
||||||
$output[] = sprintf('%s type: file', $prefix);
|
|
||||||
$output[] = sprintf('%s value: %s', $prefix, $data['value']);
|
|
||||||
} else {
|
|
||||||
$output[] = sprintf('%s- name: %s', $prefix, $key);
|
|
||||||
$output[] = sprintf('%s type: text', $prefix);
|
|
||||||
$output[] = sprintf('%s value: %s', $prefix, $data['value']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$output[] = ' type: raw';
|
|
||||||
if (!empty($this->body)) {
|
|
||||||
$output[] = ' content: |';
|
|
||||||
$bodyContent = is_string($this->body) ? $this->body : json_encode($this->body, JSON_PRETTY_PRINT);
|
|
||||||
foreach (explode("\n", $bodyContent) as $line) {
|
|
||||||
$output[] = ' ' . $line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
* @throws EmptyHttpVerbException
|
|
||||||
*/
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
$output = [
|
|
||||||
'name: ' . $this->getName(),
|
|
||||||
'type: request',
|
|
||||||
'',
|
|
||||||
];
|
|
||||||
|
|
||||||
$output[] = 'method: ' . strtolower($this->getVerb());
|
|
||||||
$output[] = '';
|
|
||||||
|
|
||||||
$url = $this->getRawUrl();
|
|
||||||
$output[] = 'url: ' . $url;
|
|
||||||
$output[] = '';
|
|
||||||
|
|
||||||
$output = array_merge($output, $this->prepareDescription());
|
|
||||||
|
|
||||||
if (!empty($this->headers)) {
|
|
||||||
$output = array_merge($output, $this->prepareHeaders());
|
|
||||||
$output[] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->verb !== 'GET' && !empty($this->body)) {
|
|
||||||
$output = array_merge($output, $this->prepareBody());
|
|
||||||
$output[] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode("\n", $output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
<?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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
<?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
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getRawUrl(): string;
|
public function getUrl(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets headers from collection item to request object
|
* Sets headers from collection item to request object
|
||||||
@@ -116,7 +116,7 @@ interface RequestContract
|
|||||||
/**
|
/**
|
||||||
* Sets authorization headers
|
* Sets authorization headers
|
||||||
*
|
*
|
||||||
* @param object $auth
|
* @param object|null $auth
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setAuth(object $auth): static;
|
public function setAuth(object $auth): static;
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter\Converters\Wget;
|
namespace PmConverter\Converters\Wget;
|
||||||
|
|
||||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
use PmConverter\Converters\{
|
||||||
|
Abstract\AbstractConverter,
|
||||||
|
ConverterContract};
|
||||||
|
|
||||||
class WgetConverter extends AbstractConverter
|
class WgetConverter extends AbstractConverter implements ConverterContract
|
||||||
{
|
{
|
||||||
protected const FILE_EXT = 'sh';
|
protected const FILE_EXT = 'sh';
|
||||||
|
|
||||||
|
|||||||
@@ -77,18 +77,18 @@ class WgetRequest extends AbstractRequest
|
|||||||
if ($this->getBodymode() === 'formdata') {
|
if ($this->getBodymode() === 'formdata') {
|
||||||
if ($this->getBody()) {
|
if ($this->getBody()) {
|
||||||
if ($this->getVerb() === 'GET') {
|
if ($this->getVerb() === 'GET') {
|
||||||
$output[] = sprintf("\t%s?%s", $this->getRawUrl(), http_build_query($this->prepareBody()));
|
$output[] = sprintf("\t%s?%s", $this->getUrl(), http_build_query($this->prepareBody()));
|
||||||
} else {
|
} else {
|
||||||
$output[] = sprintf("\t--body-data '%s' \ ", http_build_query($this->prepareBody()));
|
$output[] = sprintf("\t--body-data '%s' \ ", http_build_query($this->prepareBody()));
|
||||||
$output[] = sprintf("\t%s", $this->getRawUrl());
|
$output[] = sprintf("\t%s", $this->getUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($this->getVerb() !== 'GET') {
|
if ($this->getVerb() !== 'GET') {
|
||||||
$output[] = sprintf("\t--body-data '%s' \ ", implode("\n", $this->prepareBody()));
|
$output[] = sprintf("\t--body-data '%s' \ ", implode("\n", $this->prepareBody()));
|
||||||
$output[] = sprintf("\t%s", $this->getRawUrl());
|
$output[] = sprintf("\t%s", $this->getUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return implode(EOL, array_merge($output, ['']));
|
return implode(PHP_EOL, array_merge($output, ['']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
<?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';
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PmConverter\Enums;
|
|
||||||
|
|
||||||
enum CollectionVersion: string
|
|
||||||
{
|
|
||||||
case Version20 = 'v2.0';
|
|
||||||
case Version21 = 'v2.1';
|
|
||||||
case Unknown = 'unknown';
|
|
||||||
}
|
|
||||||
@@ -4,141 +4,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter;
|
namespace PmConverter;
|
||||||
|
|
||||||
use ArrayAccess;
|
class Environment implements \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
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected array $ownVars = [];
|
protected array $vars = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @param object $env
|
||||||
*/
|
*/
|
||||||
protected array $customVars = [];
|
public function __construct(protected object $env)
|
||||||
|
|
||||||
public static function instance(): static
|
|
||||||
{
|
{
|
||||||
return static::$instance ??= new static();
|
foreach ($env->values as $var) {
|
||||||
|
$this->vars[static::formatKey($var->key)] = $var->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,35 +28,15 @@ class Environment implements ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function hasVars(): bool
|
public function hasVars(): bool
|
||||||
{
|
{
|
||||||
return !empty($this->ownVars) && !empty($this->customVars);
|
return !empty($this->vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closed constructor
|
|
||||||
*/
|
|
||||||
protected function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public function offsetExists(mixed $offset): bool
|
public function offsetExists(mixed $offset): bool
|
||||||
{
|
{
|
||||||
return array_key_exists(static::formatKey($offset), $this->vars());
|
return array_key_exists(static::formatKey($offset), $this->vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -184,7 +44,7 @@ class Environment implements ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetGet(mixed $offset): mixed
|
public function offsetGet(mixed $offset): mixed
|
||||||
{
|
{
|
||||||
return $this->var($offset);
|
return $this->vars[static::formatKey($offset)] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,7 +52,7 @@ class Environment implements ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetSet(mixed $offset, mixed $value): void
|
public function offsetSet(mixed $offset, mixed $value): void
|
||||||
{
|
{
|
||||||
$this->customVars[static::formatKey($offset)] = $value;
|
$this->vars[static::formatKey($offset)] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,7 +60,7 @@ class Environment implements ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetUnset(mixed $offset): void
|
public function offsetUnset(mixed $offset): void
|
||||||
{
|
{
|
||||||
unset($this->customVars[static::formatKey($offset)]);
|
unset($this->vars[static::formatKey($offset)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PmConverter\Exceptions;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
class IncorrectSettingsFileException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -4,13 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace PmConverter;
|
namespace PmConverter;
|
||||||
|
|
||||||
use Exception;
|
use PmConverter\Exceptions\{
|
||||||
use JsonException;
|
CannotCreateDirectoryException,
|
||||||
use PmConverter\Enums\CollectionVersion;
|
DirectoryIsNotReadableException,
|
||||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
DirectoryIsNotWriteableException,
|
||||||
use PmConverter\Exceptions\DirectoryIsNotReadableException;
|
DirectoryNotExistsException};
|
||||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
|
||||||
use PmConverter\Exceptions\DirectoryNotExistsException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to work with files and directories
|
* Helper class to work with files and directories
|
||||||
@@ -25,17 +23,8 @@ class FileSystem
|
|||||||
*/
|
*/
|
||||||
public static function normalizePath(string $path): string
|
public static function normalizePath(string $path): string
|
||||||
{
|
{
|
||||||
$path = trim($path);
|
$path = str_replace('~', $_SERVER['HOME'], $path);
|
||||||
|
return rtrim($path, DIRECTORY_SEPARATOR);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +100,7 @@ class FileSystem
|
|||||||
$path = static::normalizePath($path);
|
$path = static::normalizePath($path);
|
||||||
$records = array_diff(@scandir($path) ?: [], ['.', '..']);
|
$records = array_diff(@scandir($path) ?: [], ['.', '..']);
|
||||||
foreach ($records as &$record) {
|
foreach ($records as &$record) {
|
||||||
$record = sprintf('%s%s%s', $path, DS, $record);
|
$record = sprintf('%s%s%s', $path, DIRECTORY_SEPARATOR, $record);
|
||||||
}
|
}
|
||||||
return $records;
|
return $records;
|
||||||
}
|
}
|
||||||
@@ -121,17 +110,16 @@ class FileSystem
|
|||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws JsonException
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public static function isCollectionFile(string $path): bool
|
public static function isCollectionFile(string $path): bool
|
||||||
{
|
{
|
||||||
$path = static::normalizePath($path);
|
$path = static::normalizePath($path);
|
||||||
return !empty($path)
|
return !empty($path = trim($path))
|
||||||
&& str_ends_with($path, '.postman_collection.json')
|
&& str_ends_with($path, '.postman_collection.json')
|
||||||
&& file_exists($path)
|
&& file_exists($path)
|
||||||
&& is_file($path)
|
|
||||||
&& is_readable($path)
|
&& is_readable($path)
|
||||||
&& Collection::detectFileVersion($path) !== CollectionVersion::Unknown;
|
&& ($json = json_decode(file_get_contents($path), true))
|
||||||
|
&& json_last_error() === JSON_ERROR_NONE
|
||||||
|
&& isset($json['collection']['info']['name']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
239
src/Handler.php
239
src/Handler.php
@@ -1,239 +0,0 @@
|
|||||||
<?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--opencollection - generate OpenCollection YAML files",
|
|
||||||
"\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)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace PmConverter\Enums;
|
namespace PmConverter;
|
||||||
|
|
||||||
enum HttpVersion: string
|
enum HttpVersions: string
|
||||||
{
|
{
|
||||||
case Version10 = '1.0';
|
case Version10 = '1.0';
|
||||||
case Version11 = '1.1';
|
case Version11 = '1.1';
|
||||||
@@ -5,65 +5,180 @@ declare(strict_types=1);
|
|||||||
namespace PmConverter;
|
namespace PmConverter;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Generator;
|
use InvalidArgumentException;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
use PmConverter\Converters\Abstract\AbstractConverter;
|
use PmConverter\Converters\{
|
||||||
use PmConverter\Converters\ConverterContract;
|
ConverterContract,
|
||||||
use PmConverter\Exceptions\CannotCreateDirectoryException;
|
ConvertFormat};
|
||||||
use PmConverter\Exceptions\DirectoryIsNotReadableException;
|
use PmConverter\Exceptions\{
|
||||||
use PmConverter\Exceptions\DirectoryIsNotWriteableException;
|
CannotCreateDirectoryException,
|
||||||
use PmConverter\Exceptions\DirectoryNotExistsException;
|
DirectoryIsNotReadableException,
|
||||||
use PmConverter\Exceptions\IncorrectSettingsFileException;
|
DirectoryIsNotWriteableException,
|
||||||
|
DirectoryNotExistsException};
|
||||||
|
|
||||||
/**
|
|
||||||
* Processor class
|
|
||||||
*/
|
|
||||||
class Processor
|
class Processor
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var int Initial timestamp
|
* Converter version
|
||||||
*/
|
*/
|
||||||
protected readonly int $initTime;
|
public const VERSION = '1.4.0';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int Initial RAM usage
|
* @var string[] Paths to collection files
|
||||||
*/
|
*/
|
||||||
protected readonly int $initRam;
|
protected array $collectionPaths = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ConverterContract[] Converters will be used for conversion according to chosen formats
|
* @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 = [];
|
protected array $converters = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var object[] Collections that will be converted into choosen formats
|
||||||
|
*/
|
||||||
|
protected array $collections = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Initial timestamp
|
||||||
|
*/
|
||||||
|
protected int $initTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Initial RAM usage
|
||||||
|
*/
|
||||||
|
protected int $initRam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Path to environment file
|
||||||
|
*/
|
||||||
|
protected string $envFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Environment
|
||||||
|
*/
|
||||||
|
protected Environment $env;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param Settings $settings Settings (lol)
|
* @param array $argv Arguments came from cli
|
||||||
* @param Environment $env Environment
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(protected array $argv)
|
||||||
protected Settings $settings,
|
{
|
||||||
protected Environment $env,
|
|
||||||
) {
|
|
||||||
$this->initTime = hrtime(true);
|
$this->initTime = hrtime(true);
|
||||||
$this->initRam = memory_get_usage(true);
|
$this->initRam = memory_get_usage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles input command
|
* Parses an array of arguments came from cli
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws CannotCreateDirectoryException
|
|
||||||
* @throws DirectoryIsNotReadableException
|
|
||||||
* @throws DirectoryIsNotWriteableException
|
|
||||||
* @throws DirectoryNotExistsException
|
|
||||||
* @throws JsonException
|
|
||||||
*/
|
*/
|
||||||
public function start(): void
|
protected function parseArgs(): void
|
||||||
{
|
{
|
||||||
$this->prepareOutputDirectory();
|
if (count($this->argv) < 2) {
|
||||||
$this->initConverters();
|
die(implode(PHP_EOL, $this->usage()) . PHP_EOL);
|
||||||
$this->convert();
|
}
|
||||||
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,72 +190,100 @@ class Processor
|
|||||||
* @throws DirectoryNotExistsException
|
* @throws DirectoryNotExistsException
|
||||||
* @throws DirectoryIsNotReadableException
|
* @throws DirectoryIsNotReadableException
|
||||||
*/
|
*/
|
||||||
protected function prepareOutputDirectory(): void
|
protected function initOutputDirectory(): void
|
||||||
{
|
{
|
||||||
if (!$this->settings->isPreserveOutput()) {
|
if (isset($this?->outputPath) && !$this->preserveOutput) {
|
||||||
FileSystem::removeDir($this->settings->outputPath());
|
FileSystem::removeDir($this->outputPath);
|
||||||
}
|
}
|
||||||
FileSystem::makeDir($this->settings->outputPath());
|
FileSystem::makeDir($this->outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes converters according to chosen formats
|
* Initializes converters according to choosen formats
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function initConverters(): void
|
protected function initConverters(): void
|
||||||
{
|
{
|
||||||
foreach ($this->settings->formats() as $type) {
|
foreach ($this->formats as $type) {
|
||||||
$this->converters[$type->name] = new $type->value($this->settings->isPreserveOutput());
|
$this->converters[$type->name] = new $type->value($this->preserveOutput);
|
||||||
}
|
}
|
||||||
unset($this->formats);
|
unset($this->formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates collections from settings
|
* Initializes collection objects
|
||||||
*
|
*
|
||||||
* @return Generator<Collection>
|
|
||||||
* @throws JsonException
|
* @throws JsonException
|
||||||
*/
|
*/
|
||||||
protected function nextCollection(): Generator
|
protected function initCollections(): void
|
||||||
{
|
{
|
||||||
foreach ($this->settings->collectionPaths() as $collectionPath) {
|
foreach ($this->collectionPaths as $collectionPath) {
|
||||||
yield Collection::fromFile($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;
|
||||||
|
}
|
||||||
|
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
|
* Begins a conversion
|
||||||
*
|
*
|
||||||
* @throws JsonException
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function convert(): void
|
public function convert(): void
|
||||||
{
|
{
|
||||||
$count = count($this->settings->collectionPaths());
|
$this->parseArgs();
|
||||||
$current = $success = 0;
|
$this->initOutputDirectory();
|
||||||
foreach ($this->nextCollection() as $collection) {
|
$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) {
|
||||||
++$current;
|
++$current;
|
||||||
printf("Converting '%s' (%d/%d):%s", $collection->name(), $current, $count, EOL);
|
printf("Converting '%s' (%d/%d):%s", $collectionName, $current, $count, PHP_EOL);
|
||||||
foreach ($this->converters as $type => $converter) {
|
foreach ($this->converters as $type => $exporter) {
|
||||||
/** @var AbstractConverter $converter */
|
printf('> %s%s', strtolower($type), PHP_EOL);
|
||||||
printf('> %s%s', strtolower($type), EOL);
|
$outputPath = sprintf('%s%s%s', $this->outputPath, DIRECTORY_SEPARATOR, $collectionName);
|
||||||
$outputPath = sprintf('%s%s%s', $this->settings->outputPath(), DS, $collection->name());
|
if (!empty($this->env)) {
|
||||||
try {
|
$exporter->withEnv($this->env);
|
||||||
$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;
|
++$success;
|
||||||
}
|
}
|
||||||
unset($this->converters, $type, $converter, $outputPath, $this->collections, $collectionName, $collection);
|
unset($this->converters, $type, $exporter, $outputPath, $this->collections, $collectionName, $collection);
|
||||||
$this->printStats($success, $current);
|
$this->printStats($success, $current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +297,86 @@ class Processor
|
|||||||
protected function printStats(int $success, int $count): void
|
protected function printStats(int $success, int $count): void
|
||||||
{
|
{
|
||||||
$time = (hrtime(true) - $this->initTime) / 1_000_000;
|
$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;
|
$ram = (memory_get_peak_usage(true) - $this->initRam) / 1024 / 1024;
|
||||||
printf("Converted %d/%d in %.2f $timeFmt using up to %.2f MiB RAM%s", $success, $count, $time, $ram, EOL);
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
416
src/Settings.php
416
src/Settings.php
@@ -1,416 +0,0 @@
|
|||||||
<?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);
|
|
||||||
file_exists($filePath) || throw new Exception("file does not exist: $filePath");
|
|
||||||
is_file($filePath) || throw new Exception("not a file: $filePath");
|
|
||||||
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,14 +3,15 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use PmConverter\Exceptions\EmptyHttpVerbException;
|
use PmConverter\Exceptions\{
|
||||||
use PmConverter\Exceptions\InvalidHttpVersionException;
|
EmptyHttpVerbException,
|
||||||
|
InvalidHttpVersionException};
|
||||||
|
|
||||||
class AbstractRequestTest extends TestCase
|
class AbstractRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||||
* @covers \PmConverter\Enums\HttpVersion
|
* @covers PmConverter\HttpVersions
|
||||||
* @return void
|
* @return void
|
||||||
* @throws InvalidHttpVersionException
|
* @throws InvalidHttpVersionException
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +26,7 @@ class AbstractRequestTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getVerb()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::getVerb()
|
||||||
* @covers \PmConverter\Enums\HttpVersion
|
* @covers PmConverter\HttpVersions
|
||||||
* @return void
|
* @return void
|
||||||
* @throws InvalidHttpVersionException
|
* @throws InvalidHttpVersionException
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +71,7 @@ class AbstractRequestTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
* @covers PmConverter\Converters\Abstract\AbstractRequest
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setUrl()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::setUrl()
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getRawUrl()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::getUrl()
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function testUrl(): void
|
public function testUrl(): void
|
||||||
@@ -78,7 +79,7 @@ class AbstractRequestTest extends TestCase
|
|||||||
$request = new \PmConverter\Converters\Http\HttpRequest();
|
$request = new \PmConverter\Converters\Http\HttpRequest();
|
||||||
$request->setUrl('http://localhost');
|
$request->setUrl('http://localhost');
|
||||||
|
|
||||||
$this->assertSame('http://localhost', $request->getRawUrl());
|
$this->assertSame('http://localhost', $request->getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,7 +215,7 @@ class AbstractRequestTest extends TestCase
|
|||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setBodymode()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::setBodymode()
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setHeader()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::setHeader()
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setBody()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::setBody()
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::setBodyAsIs()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::setJsonBody()
|
||||||
* @covers PmConverter\Converters\Abstract\AbstractRequest::getBody()
|
* @covers PmConverter\Converters\Abstract\AbstractRequest::getBody()
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [
|
|
||||||
"collections/20-API Lifecycle.postman_collection.json"
|
|
||||||
],
|
|
||||||
"output": "converted",
|
|
||||||
"preserveOutput": false,
|
|
||||||
"formats": [
|
|
||||||
"http"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user