v1.4.0 #12
31
README.md
31
README.md
@ -24,12 +24,13 @@ These formats are supported for now: `http`, `curl`, `wget`.
|
|||||||
|
|
||||||
## 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`_);
|
- support as many as possible/necessary of body formats (_currently only `json` and `formdata`_);
|
||||||
- documentation generation support (markdown) with responce examples (if present);
|
- 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;
|
||||||
- tests, phpcs, psalm, etc.;
|
- 90%+ test coverage, phpcs, psalm, etc.;
|
||||||
- web version.
|
- web version.
|
||||||
|
|
||||||
## Install and upgrade
|
## Install and upgrade
|
||||||
@ -59,30 +60,40 @@ Usage:
|
|||||||
./vendor/bin/pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]
|
./vendor/bin/pm-convert -f|-d PATH -o OUTPUT_PATH [ARGUMENTS] [FORMATS]
|
||||||
|
|
||||||
Possible ARGUMENTS:
|
Possible ARGUMENTS:
|
||||||
-f, --file - a PATH to single collection located in PATH to convert from
|
-f, --file - a PATH to a single collection file to convert from
|
||||||
-d, --dir - a directory with collections located in COLLECTION_FILEPATH to convert from
|
-d, --dir - a PATH to a directory with collections to convert from
|
||||||
-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 variable values to replace in request
|
-e, --env - use environment file with variables to replace in requests
|
||||||
|
--var "NAME=VALUE" - force replace specified env variable called NAME with custom VALUE
|
||||||
|
(see interpolation notes below)
|
||||||
-p, --preserve - do not delete OUTPUT_PATH (if exists)
|
-p, --preserve - do not delete OUTPUT_PATH (if exists)
|
||||||
-h, --help - show this help message and exit
|
-h, --help - show this help message and exit
|
||||||
-v, --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 will be converted.
|
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.
|
-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.
|
PATH must be a valid path to readable json-file or directory.
|
||||||
OUTPUT_PATH must be a valid path to writeable directory.
|
OUTPUT_PATH must be a valid path to writeable directory.
|
||||||
If -o is specified several times then only last one will be used.
|
If -o or -e was specified several times then only last one will be used.
|
||||||
If -e is specified several times then only last one will be used.
|
|
||||||
If -e is not specified then only collection vars will be replaced (if any).
|
|
||||||
|
|
||||||
Possible FORMATS:
|
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
|
||||||
|
|
||||||
If no FORMATS specified then --http implied.
|
If no FORMATS specified then --http implied.
|
||||||
Any of FORMATS can be specified at the same time.
|
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 \
|
||||||
-f ~/dir1/first.postman_collection.json \
|
-f ~/dir1/first.postman_collection.json \
|
||||||
@ -90,7 +101,9 @@ Example:
|
|||||||
--file ~/dir2/second.postman_collection.json \
|
--file ~/dir2/second.postman_collection.json \
|
||||||
--env ~/localhost.postman_environment.json \
|
--env ~/localhost.postman_environment.json \
|
||||||
-d ~/personal \
|
-d ~/personal \
|
||||||
|
--var "myvar=some value" \
|
||||||
-o ~/postman_export
|
-o ~/postman_export
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notices
|
### Notices
|
||||||
|
@ -27,11 +27,6 @@ abstract class AbstractConverter implements ConverterContract
|
|||||||
*/
|
*/
|
||||||
protected string $outputPath;
|
protected string $outputPath;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string[]
|
|
||||||
*/
|
|
||||||
protected array $vars = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Environment|null
|
* @var Environment|null
|
||||||
*/
|
*/
|
||||||
@ -72,9 +67,10 @@ abstract class AbstractConverter implements ConverterContract
|
|||||||
*/
|
*/
|
||||||
protected function setVariables(): static
|
protected function setVariables(): static
|
||||||
{
|
{
|
||||||
if (isset($this->collection?->variable)) {
|
empty($this->env) && $this->env = new Environment($this->collection?->variable);
|
||||||
|
if (!empty($this->collection?->variable)) {
|
||||||
foreach ($this->collection->variable as $var) {
|
foreach ($this->collection->variable as $var) {
|
||||||
$this->vars["{{{$var->key}}}"] = $var->value;
|
$this->env[$var->key] = $var->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
@ -176,21 +172,18 @@ abstract class AbstractConverter implements ConverterContract
|
|||||||
*/
|
*/
|
||||||
protected function interpolate(string $content): string
|
protected function interpolate(string $content): string
|
||||||
{
|
{
|
||||||
if (empty($this->vars) && !$this->env?->hasVars()) {
|
if (!$this->env?->hasVars()) {
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
$matches = [];
|
$matches = [];
|
||||||
if (preg_match_all('/\{\{[a-zA-Z][a-zA-Z0-9]*}}/m', $content, $matches, PREG_PATTERN_ORDER) > 0) {
|
if (preg_match_all('/\{\{.*}}/m', $content, $matches, PREG_PATTERN_ORDER) > 0) {
|
||||||
foreach ($matches[0] as $key => $var) {
|
foreach ($matches[0] as $key => $var) {
|
||||||
if (str_contains($content, $var)) {
|
if (str_contains($content, $var)) {
|
||||||
$content = str_replace($var, $this->vars[$var] ?? $this->env[$var] ?? $var, $content);
|
$content = str_replace($var, $this->env[$var] ?: $var, $content);
|
||||||
unset($matches[0][$key]);
|
unset($matches[0][$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (!empty($matches[0])) {
|
|
||||||
// fwrite(STDERR, sprintf(' No values found: %s%s', implode(', ', $matches[0]), PHP_EOL));
|
|
||||||
// }
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ class Environment implements \ArrayAccess
|
|||||||
public function __construct(protected object $env)
|
public function __construct(protected object $env)
|
||||||
{
|
{
|
||||||
foreach ($env->values as $var) {
|
foreach ($env->values as $var) {
|
||||||
$this->vars["{{{$var->key}}}"] = $var->value;
|
$this->vars[static::formatKey($var->key)] = $var->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class Environment implements \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetExists(mixed $offset): bool
|
public function offsetExists(mixed $offset): bool
|
||||||
{
|
{
|
||||||
return array_key_exists($offset, $this->vars);
|
return array_key_exists(static::formatKey($offset), $this->vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +44,7 @@ class Environment implements \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetGet(mixed $offset): mixed
|
public function offsetGet(mixed $offset): mixed
|
||||||
{
|
{
|
||||||
return $this->vars[$offset];
|
return $this->vars[static::formatKey($offset)] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ class Environment implements \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetSet(mixed $offset, mixed $value): void
|
public function offsetSet(mixed $offset, mixed $value): void
|
||||||
{
|
{
|
||||||
$this->vars[$offset] = $value;
|
$this->vars[static::formatKey($offset)] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,6 +60,17 @@ class Environment implements \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function offsetUnset(mixed $offset): void
|
public function offsetUnset(mixed $offset): void
|
||||||
{
|
{
|
||||||
unset($this->vars[$offset]);
|
unset($this->vars[static::formatKey($offset)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns correct variable {{name}}
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function formatKey(string $key): string
|
||||||
|
{
|
||||||
|
return sprintf('{{%s}}', str_replace(['{', '}'], '', $key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,11 @@ class Processor
|
|||||||
*/
|
*/
|
||||||
protected bool $preserveOutput = false;
|
protected bool $preserveOutput = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[] Additional variables
|
||||||
|
*/
|
||||||
|
protected array $vars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ConvertFormat[] Formats to convert a collections into
|
* @var ConvertFormat[] Formats to convert a collections into
|
||||||
*/
|
*/
|
||||||
@ -64,7 +69,7 @@ class Processor
|
|||||||
protected int $initRam;
|
protected int $initRam;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string Path to environment file
|
||||||
*/
|
*/
|
||||||
protected string $envFile;
|
protected string $envFile;
|
||||||
|
|
||||||
@ -151,6 +156,11 @@ class Processor
|
|||||||
$this->formats[ConvertFormat::Wget->name] = ConvertFormat::Wget;
|
$this->formats[ConvertFormat::Wget->name] = ConvertFormat::Wget;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '--var':
|
||||||
|
[$var, $value] = explode('=', trim($this->argv[$idx + 1]));
|
||||||
|
$this->vars[$var] = $value;
|
||||||
|
break;
|
||||||
|
|
||||||
case '-v':
|
case '-v':
|
||||||
case '--version':
|
case '--version':
|
||||||
die(implode(PHP_EOL, $this->version()) . PHP_EOL);
|
die(implode(PHP_EOL, $this->version()) . PHP_EOL);
|
||||||
@ -198,6 +208,7 @@ class Processor
|
|||||||
foreach ($this->formats as $type) {
|
foreach ($this->formats as $type) {
|
||||||
$this->converters[$type->name] = new $type->value($this->preserveOutput);
|
$this->converters[$type->name] = new $type->value($this->preserveOutput);
|
||||||
}
|
}
|
||||||
|
unset($this->formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -215,6 +226,7 @@ class Processor
|
|||||||
}
|
}
|
||||||
$this->collections[$content->collection->info->name] = $content->collection;
|
$this->collections[$content->collection->info->name] = $content->collection;
|
||||||
}
|
}
|
||||||
|
unset($this->collectionPaths, $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,6 +246,10 @@ class Processor
|
|||||||
throw new JsonException("not a valid environment: $this->envFile");
|
throw new JsonException("not a valid environment: $this->envFile");
|
||||||
}
|
}
|
||||||
$this->env = new Environment($content->environment);
|
$this->env = new Environment($content->environment);
|
||||||
|
foreach ($this->vars as $var => $value) {
|
||||||
|
$this->env[$var] = $value;
|
||||||
|
}
|
||||||
|
unset($this->vars, $this->envFile, $content, $var, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -267,6 +283,7 @@ class Processor
|
|||||||
print(PHP_EOL);
|
print(PHP_EOL);
|
||||||
++$success;
|
++$success;
|
||||||
}
|
}
|
||||||
|
unset($this->converters, $type, $exporter, $outputPath, $this->collections, $collectionName, $collection);
|
||||||
$this->printStats($success, $current);
|
$this->printStats($success, $current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +298,7 @@ class Processor
|
|||||||
{
|
{
|
||||||
$time = (hrtime(true) - $this->initTime) / 1_000_000;
|
$time = (hrtime(true) - $this->initTime) / 1_000_000;
|
||||||
$ram = (memory_get_peak_usage(true) - $this->initRam) / 1024 / 1024;
|
$ram = (memory_get_peak_usage(true) - $this->initRam) / 1024 / 1024;
|
||||||
printf('Converted %d of %d in %.3f ms using %.3f MiB RAM%s', $success, $count, $time, $ram, PHP_EOL);
|
printf('Converted %d of %d in %.3f ms using up to %.3f MiB RAM%s', $success, $count, $time, $ram, PHP_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -316,22 +333,22 @@ class Processor
|
|||||||
"\t./vendor/bin/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:',
|
'Possible ARGUMENTS:',
|
||||||
"\t-f, --file - a PATH to single collection located in PATH to convert from",
|
"\t-f, --file - a PATH to a single collection file to convert from",
|
||||||
"\t-d, --dir - a directory with collections located in PATH 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-o, --output - a directory OUTPUT_PATH to put results in",
|
||||||
"\t-e, --env - use environment file with variable values to replace in request",
|
"\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-p, --preserve - do not delete OUTPUT_PATH (if exists)",
|
||||||
"\t-h, --help - show this help message and exit",
|
"\t-h, --help - show this help message and exit",
|
||||||
"\t-v, --version - show version info and exit",
|
"\t-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 will be converted.',
|
'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.',
|
'-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.',
|
'PATH must be a valid path to readable json-file or directory.',
|
||||||
'OUTPUT_PATH must be a valid path to writeable directory.',
|
'OUTPUT_PATH must be a valid path to writeable directory.',
|
||||||
'If -o is specified several times then only last one will be used.',
|
'If -o or -e was specified several times then only last one will be used.',
|
||||||
'If -e is specified several times then only last one will be used.',
|
|
||||||
'If -e is not specified then only collection vars will be replaced (if any).',
|
|
||||||
'',
|
'',
|
||||||
'Possible FORMATS:',
|
'Possible FORMATS:',
|
||||||
"\t--http - generate raw *.http files (default)",
|
"\t--http - generate raw *.http files (default)",
|
||||||
@ -341,6 +358,15 @@ class Processor
|
|||||||
'If no FORMATS specified then --http implied.',
|
'If no FORMATS specified then --http implied.',
|
||||||
'Any of FORMATS can be specified at the same time.',
|
'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:',
|
'Example:',
|
||||||
" ./pm-convert \ ",
|
" ./pm-convert \ ",
|
||||||
" -f ~/dir1/first.postman_collection.json \ ",
|
" -f ~/dir1/first.postman_collection.json \ ",
|
||||||
@ -348,6 +374,7 @@ class Processor
|
|||||||
" --file ~/dir2/second.postman_collection.json \ ",
|
" --file ~/dir2/second.postman_collection.json \ ",
|
||||||
" --env ~/localhost.postman_environment.json \ ",
|
" --env ~/localhost.postman_environment.json \ ",
|
||||||
" -d ~/personal \ ",
|
" -d ~/personal \ ",
|
||||||
|
" --var \"myvar=some value\" \ ",
|
||||||
" -o ~/postman_export ",
|
" -o ~/postman_export ",
|
||||||
"",
|
"",
|
||||||
], $this->copyright());
|
], $this->copyright());
|
||||||
|
Loading…
Reference in New Issue
Block a user