join command with wildcard does not collect matching files
Describe the bug
When using the join command with a file wildcard the following error is always returned:
At least 2 apis should be provided.
To Reproduce Steps to reproduce the behavior:
- have a folder with several yaml files
- run this command:
npx --yes @redocly/cli@latest join ./*.yaml -o ./OpenAPI.yaml - See error:
At least 2 apis should be provided.
Expected behavior
the files matching the wildcard should be used for joining. When using the following command (non wildcard) the join works correctly:
npx --yes @redocly/cli@latest join .\Identity-OpenAPI.yaml .\Shopping-OpenAPI.yaml -o ./OpenAPI.yaml
success: ./OpenAPI.yaml: join processed in 49ms
Redocly Version(s) 1.0.0 on win10
Node.js Version(s)
v19.9.0
Hello!
Let us check this.
Hi @vip32,
We've attempted to replicate this matter on both Mac and Windows machines, but unfortunately, we haven't been able to encounter the same issue.
Thus, could you please consider sharing with us a sample project that demonstrates this issue? This would enable us to conduct a more in-depth investigation from our side.
Thanks for taking time for this, interesting it works in your sample though. I extracted the files and created a small repo with only the yaml files: https://github.com/vip32/openapi_tmp
executing npx --yes @redocly/cli@latest join ./*.yaml -o ./OpenAPI.yaml on it gives the error.
Thanks for reporting @vip32!
I believe this is specific to Windows command line. We will check if it could be fixed a bit later. Meanwhile, as a workaround, you can use Git Bash.
with docker (on windows) the result is the same
docker run --rm -v .:/spec redocly/cli:latest join ./*.yaml -o .\OpenAPI.yaml >> At least 2 apis should be provided.
In Windows shells the wildcard is resolved to first match only. Fix proposed in yargs: https://github.com/yargs/yargs/issues/50#issuecomment-54087619 .
The issues is in miscellaneous.ts, the expandGlobsInEntrypoints function. The glob does not have __promisify__ function. To fix this you can pretty much do this:
return glob.hasMagic(aliasOrPath) && !isAbsoluteUrl(aliasOrPath)
? (await require("util").promisify(glob)(aliasOrPath)).map((g: string) => getAliasOrPath(config, g))
: getAliasOrPath(config, aliasOrPath);
Or just use the newer glob.
Do you want me to create a PR for this?
In Windows shells the wildcard is resolved to first match only. Fix proposed in
yargs: yargs/yargs#50 (comment) .
That's not entirely accurate. In Windows the wildcards are not resolved by the system when passed as part of an argument. Instead commands or apps resolve wildcards themselves (in case of Node.js application they usually use glob). In Linux, however, the system tries to resolve wildcards in command line and converts a single string with wildcards into a list of space separated existing paths that match the wildcard.
The redocly-cli attempts to handle it correctly, but it relies on glob object to have __promisify__ function, which is missing. For some dumb reason the __promisify__ function is present in @types/glob but is actually missing from the glob itself.
I will try to create a PR to fix this when I have the time this week. My Windows build isn't working because if this, and I am stuck with Ubuntu WSL, which I am not particularly fond of :D