Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

feat: --body supports reading from STDIN #23

Merged
merged 7 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ FLAGS
-X, --method=<option> [default: GET] The HTTP method for the request.
<options: GET|POST|PUT|PATCH|HEAD|DELETE|OPTIONS|TRACE>
-i, --include Include HTTP response status and headers in the output.
-o, --target-org=username (required) Username or alias of the target org.
--body=file The file to use as the body for the request.
-o, --target-org=username (required) Username or alias of the target org. Not required if the `target-org`
configuration variable is already set.
--body=file The file to use as the body for the request (use "-" to read from standard input).

DESCRIPTION
Makes an authenticated HTTP request to the Salesforce REST API and prints the response.
Expand Down
27 changes: 14 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,39 @@
"type": "module",
"bugs": "https://github.com/cristiand391/sf-plugin-api/issues",
"dependencies": {
"@oclif/core": "^3.10.1",
"@salesforce/core": "^5.3.17",
"@salesforce/sf-plugins-core": "^4.0.0",
"@oclif/core": "^3.18.1",
"@salesforce/core": "^6.5.0",
"@salesforce/sf-plugins-core": "^7.1.4",
"chalk": "^5.3.0",
"got": "^13.0.0",
"proxy-agent": "^6.3.1"
},
"devDependencies": {
"@oclif/plugin-command-snapshot": "^5.0.1",
"@oclif/plugin-command-snapshot": "^5.0.6",
"@types/chai": "^4.3.4",
"@types/inquirer": "^9.0.3",
"@types/mocha": "^10.0.1",
"@types/sinon": "^10.0.13",
"@typescript-eslint/eslint-plugin": "^6.9.0",
"@typescript-eslint/parser": "^6.9.0",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"chai": "^4.3.6",
"eslint": "^8.26.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-salesforce": "^2.0.2",
"eslint-config-salesforce-typescript": "^1.1.1",
"eslint-config-salesforce-typescript": "^3.0.16",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsdoc": "^46.4.6",
"eslint-plugin-sf-plugin": "^1.16.2",
"eslint-plugin-sf-plugin": "^1.17.1",
"eslint-plugin-unicorn": "^49.0.0",
"mocha": "^10.2.0",
"nock": "^13.3.0",
"oclif": "^3.11.3",
"oclif": "^4.3.9",
"prettier": "^3.0.1",
"shx": "0.3.4",
"sinon": "^15.0.3",
"strip-ansi": "^7.1.0",
"ts-node": "^10.9.1",
"typescript": "^5.2.2",
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"wireit": "^0.10.0"
},
"engines": {
Expand Down Expand Up @@ -135,7 +136,7 @@
]
},
"test:deprecation-policy": {
"command": "ts-node \"./bin/dev.js\" snapshot:compare",
"command": "node --loader ts-node/esm --no-warnings=ExperimentalWarning \"./bin/dev.js\" snapshot:compare",
"files": [
"src/**/*.ts"
],
Expand Down
37 changes: 23 additions & 14 deletions src/commands/org/api.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { readFile } from 'node:fs/promises';
import { EOL } from 'node:os';
import got, { Headers, Method } from 'got';
import got, { Headers } from 'got';
import chalk from 'chalk';
import { ProxyAgent } from 'proxy-agent';
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { SfError, Org } from '@salesforce/core';
import { Args, ux } from '@oclif/core';
import { readStdin } from '@oclif/core/lib/parser/parse.js';

export class OrgApi extends SfCommand<void> {
public static readonly summary =
Expand All @@ -31,17 +32,14 @@ export class OrgApi extends SfCommand<void> {
// summary is already set in the org flag.
// eslint-disable-next-line sf-plugin/flag-summary
'target-org': Flags.requiredOrg({
// TODO: this is already set in the org flag but getting a wrong type if not set here.
// Fix flag types in oclif.
required: true,
helpValue: 'username',
}),
include: Flags.boolean({
char: 'i',
summary: 'Include HTTP response status and headers in the output.',
default: false,
}),
method: Flags.custom<Method>({
method: Flags.option({
options: [
'GET',
'POST',
Expand All @@ -51,7 +49,7 @@ export class OrgApi extends SfCommand<void> {
'DELETE',
'OPTIONS',
'TRACE',
],
] as const,
summary: 'The HTTP method for the request.',
char: 'X',
default: 'GET',
Expand All @@ -62,8 +60,23 @@ export class OrgApi extends SfCommand<void> {
char: 'H',
multiple: true,
}),
body: Flags.file({
summary: 'The file to use as the body for the request.',
body: Flags.string({
summary:
'The file to use as the body for the request (use "-" to read from standard input).',
parse: async (input) => {
if (input === '-') {
const body = await readStdin();
if (body) {
return body.trim();
} else {
throw new Error(
'Unable to read body: `-` was provided but STDIN is empty.',
);
}
} else {
return readFile(input, 'utf8');
}
},
helpValue: 'file',
}),
};
Expand Down Expand Up @@ -113,13 +126,9 @@ export class OrgApi extends SfCommand<void> {
}`,
...(flags.header ? OrgApi.getHeaders(flags.header) : {}),
},
body:
flags.method === 'GET'
? undefined
: flags.body
? await readFile(flags.body)
: undefined,
body: flags.method === 'GET' ? undefined : flags.body,
throwHttpErrors: false,
followRedirect: false,
});

// Print HTTP response status and headers.
Expand Down
37 changes: 29 additions & 8 deletions test/commands/org/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import nock = require('nock');
import { TestContext, MockTestOrgData } from '@salesforce/core/lib/testSetup.js';
import {
TestContext,
MockTestOrgData,
} from '@salesforce/core/lib/testSetup.js';
import { SfError } from '@salesforce/core';
import { expect } from 'chai';
import stripAnsi from 'strip-ansi';
Expand All @@ -13,6 +16,13 @@ describe('org api', () => {

let stdoutSpy: sinon.SinonSpy;

const orgLimitsResponse = {
ActiveScratchOrgs: {
Max: 200,
Remaining: 199,
},
};

beforeEach(async () => {
await $$.stubAuths(testOrg);
stdoutSpy = $$.SANDBOX.stub(process.stdout, 'write');
Expand All @@ -23,13 +33,6 @@ describe('org api', () => {
});

it('should request org limits and default to "GET" HTTP method', async () => {
const orgLimitsResponse = {
ActiveScratchOrgs: {
Max: 200,
Remaining: 199,
},
};

nock(testOrg.instanceUrl)
.get('/services/data/v56.0/limits')
.reply(200, orgLimitsResponse);
Expand Down Expand Up @@ -98,4 +101,22 @@ describe('org api', () => {
);
}
});

it('should not follow redirects', async () => {
nock(testOrg.instanceUrl)
.get('/services/data/v56.0/limites')
.reply(301, orgLimitsResponse, {
location: `${testOrg.instanceUrl}/services/data/v56.0/limits`,
});

await OrgApi.run([
'services/data/v56.0/limites',
'--target-org',
'[email protected]',
]);

const output = stripAnsi(stdoutSpy.args.flat().join(''));

expect(JSON.parse(output)).to.deep.equal(orgLimitsResponse);
});
});
Loading
Loading