Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for fullPath on methods. #1200

Merged
merged 1 commit into from
Jul 28, 2021
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
9 changes: 8 additions & 1 deletion lib/StripeMethod.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const makeAutoPaginationMethods = require('./autoPagination')
* @param [spec.method='GET'] Request Method (POST, GET, DELETE, PUT)
* @param [spec.path=''] Path to be appended to the API BASE_PATH, joined with
* the instance's path (e.g. 'charges' or 'customers')
* @param [spec.fullPath=''] Fully qualified path to the method (eg. /v1/a/b/c).
* If this is specified, path should not be specified.
* @param [spec.urlParams=[]] Array of required arguments in the order that they
* must be passed by the consumer of the API. Subsequent optional arguments are
* optionally passed through a hash (Object) as the penultimate argument
Expand All @@ -20,11 +22,16 @@ const makeAutoPaginationMethods = require('./autoPagination')
* @param [spec.host] Hostname for the request.
*/
function stripeMethod(spec) {
if (spec.path !== undefined && spec.fullPath !== undefined) {
throw new Error(
`Method spec specified both a 'path' (${spec.path}) and a 'fullPath' (${spec.fullPath}).`
);
}
return function(...args) {
const callback = typeof args[args.length - 1] == 'function' && args.pop();

spec.urlParams = utils.extractUrlParams(
this.createResourcePathWithSymbols(spec.path || '')
spec.fullPath || this.createResourcePathWithSymbols(spec.path || '')
);

const requestPromise = utils.callbackifyPromiseWithTimeout(
Expand Down
19 changes: 16 additions & 3 deletions lib/makeRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@ const utils = require('./utils');

function getRequestOpts(self, requestArgs, spec, overrideData) {
// Extract spec values with defaults.
const commandPath = utils.makeURLInterpolator(spec.path || '');
const requestMethod = (spec.method || 'GET').toUpperCase();
const urlParams = spec.urlParams || [];
const encode = spec.encode || ((data) => data);
const path = self.createResourcePathWithSymbols(spec.path);

const isUsingFullPath = !!spec.fullPath;
const commandPath = utils.makeURLInterpolator(
isUsingFullPath ? spec.fullPath : spec.path || ''
);

// When using fullPath, we ignore the resource path as it should already be
// fully qualified.
const path = isUsingFullPath
? spec.fullPath
: self.createResourcePathWithSymbols(spec.path);

// Don't mutate args externally.
const args = [].slice.call(requestArgs);
Expand Down Expand Up @@ -39,7 +48,11 @@ function getRequestOpts(self, requestArgs, spec, overrideData) {
);
}

const requestPath = self.createFullPath(commandPath, urlData);
// When using full path, we can just invoke the URL interpolator directly
// as we don't need to use the resource to create a full path.
const requestPath = isUsingFullPath
? commandPath(urlData)
: self.createFullPath(commandPath, urlData);
const headers = Object.assign(options.headers, spec.headers);

if (spec.validator) {
Expand Down
32 changes: 32 additions & 0 deletions test/StripeResource.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,38 @@ describe('StripeResource', () => {
});
});

describe('method with fullPath', () => {
it('interpolates in parameters', (callback) => {
const handleRequest = (req, res) => {
expect(req.url).to.equal('/v1/parent/hello/child/world');

// Write back JSON to close out the server.
res.write('{}');
res.end();
};

testUtils.getTestServerStripe(
{},
handleRequest,
(err, stripe, closeServer) => {
const resource = new (StripeResource.extend({
test: stripeMethod({
method: 'GET',
fullPath: '/v1/parent/{param1}/child/{param2}',
}),
}))(stripe);

return resource.test('hello', 'world', (err, res) => {
closeServer();
// Spot check that we received a response.
expect(res).to.deep.equal({});
return callback(err);
});
}
);
});
});

describe('streaming', () => {
/**
* Defines a fake resource with a `pdf` method
Expand Down
39 changes: 39 additions & 0 deletions test/makeRequest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require('../testUtils');

const makeRequest = require('../lib/makeRequest');
const utils = require('../lib/utils');
const expect = require('chai').expect;

describe('makeRequest', () => {
Expand All @@ -26,4 +27,42 @@ describe('makeRequest', () => {
]);
});
});

describe('makeRequest with fullPath', () => {
it('handles urlData', async () => {
const args = ['hello', 'world'];

const fullPath = '/v1/parent/{param1}/child/{param2}';
const spec = {
fullPath,
urlParams: utils.extractUrlParams(fullPath),
};

let actualPath;
const mockSelf = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

// These two methods shouldn't be called when using a fullPath, as they
// don't rely on the resource path.
createResourcePathWithSymbols: () => {
throw new Error('Unexpected call to createResourcePathWithSymbols.');
},
createFullPath: () => {
throw new Error('Unexpected call to createFullPath.');
},
_request: (
_method,
_host,
path,
_body,
_auth,
_headers,
requestCallback
) => {
actualPath = path;
requestCallback(null, 'response');
},
};
await makeRequest(mockSelf, args, spec, {});
expect(actualPath).to.equal('/v1/parent/hello/child/world');
});
});
});
3 changes: 2 additions & 1 deletion types/lib.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ declare module 'stripe' {
>(spec: T): StripeResource & T;
static method(spec: {
method: string;
path: string;
path?: string;
fullPath?: string;
methodType?: 'list';
}): (...args: any[]) => object; //eslint-disable-line @typescript-eslint/no-explicit-any
static BASIC_METHODS: {
Expand Down
4 changes: 4 additions & 0 deletions types/test/typescriptTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ Stripe.StripeResource.extend({
method: 'create',
path: 'foo',
}),
fooFullPath: Stripe.StripeResource.method({
method: 'create',
fullPath: '/v1/full/path',
}),
});

const maxBufferedRequestMetrics: number =
Expand Down