Skip to content
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
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ sdk.updatePet({ name: 'Buster 2' }, { petId: 1234 }).then(...)

Since we've supplied two objects here, the SDK automatically knows that you're supplying both a `body` and `metadata`, and can make a PUT request against `/pets/1234` for you.

What about a `multipart/form-data` request? That works too, and you don't even have to worry about the fun of multipart boundaries!

```js
sdk.uploadFile({ file: '/path/to/a/file.txt' }).then(...)
```

You can also give it a stream and it'll handle all of the hard work for you.

```js
sdk.uploadFile({ file: fs.createReadStream('/path/to/a/file.txt') }).then(...)
```

### HTTP requests
If the API you're using doesn't have any documented operation IDs, you can make requests with HTTP verbs instead:

Expand Down Expand Up @@ -112,7 +124,7 @@ Not yet, unfortunately. For APIs that use OAuth 2, you'll need a fully-qualified
Not yet! This is something we're thinking about how to handle, but it's difficult with the simple nature of the `.auth()` method as it currently does not require the user to inform the SDK of what kind of authentication scheme the token they're supplying it should match up against.

#### Will this work in browsers?
Not sure! If you'd like to help us out in making this compatible with browsers we'd love to help you out on a pull request.
Not at the moment as the library requires some filesystem handling in order to manage its cache state, but it's something we're actively thinking about. If you'd like to help us out in making this compatible with browsers we'd love to help you out on a pull request.

#### Will this validate my data before it reaches the API?
Not yet! This is something we've got planned down the road.
Expand Down
14 changes: 13 additions & 1 deletion packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ sdk.updatePet({ name: 'Buster 2' }, { petId: 1234 }).then(...)

Since we've supplied two objects here, the SDK automatically knows that you're supplying both a `body` and `metadata`, and can make a PUT request against `/pets/1234` for you.

What about a `multipart/form-data` request? That works too, and you don't even have to worry about the fun of multipart boundaries!

```js
sdk.uploadFile({ file: '/path/to/a/file.txt' }).then(...)
```

You can also give it a stream and it'll handle all of the hard work for you.

```js
sdk.uploadFile({ file: fs.createReadStream('/path/to/a/file.txt') }).then(...)
```

### HTTP requests
If the API you're using doesn't have any documented operation IDs, you can make requests with HTTP verbs instead:

Expand Down Expand Up @@ -112,7 +124,7 @@ Not yet, unfortunately. For APIs that use OAuth 2, you'll need a fully-qualified
Not yet! This is something we're thinking about how to handle, but it's difficult with the simple nature of the `.auth()` method as it currently does not require the user to inform the SDK of what kind of authentication scheme the token they're supplying it should match up against.

#### Will this work in browsers?
Not sure! If you'd like to help us out in making this compatible with browsers we'd love to help you out on a pull request.
Not at the moment as the library requires some filesystem handling in order to manage its cache state, but it's something we're actively thinking about. If you'd like to help us out in making this compatible with browsers we'd love to help you out on a pull request.

#### Will this validate my data before it reaches the API?
Not yet! This is something we've got planned down the road.
Expand Down
Binary file added packages/api/__tests__/__fixtures__/owlbert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
113 changes: 74 additions & 39 deletions packages/api/__tests__/lib/prepareParams.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const fs = require('fs');
const Oas = require('@readme/oas-tooling');
const $RefParser = require('@apidevtools/json-schema-ref-parser');
const readmeExample = require('@readme/oas-examples/3.0/json/readme.json');
Expand Down Expand Up @@ -39,16 +40,16 @@ describe('#prepareParams', () => {
usptoSpec = new Oas(schema);
});

it('should prepare nothing if nothing was supplied', () => {
it('should prepare nothing if nothing was supplied', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');

expect(prepareParams(operation)).toStrictEqual({});
expect(prepareParams(operation, null, null)).toStrictEqual({});
expect(prepareParams(operation, [], [])).toStrictEqual({});
expect(prepareParams(operation, {}, {})).toStrictEqual({});
expect(await prepareParams(operation)).toStrictEqual({});
expect(await prepareParams(operation, null, null)).toStrictEqual({});
expect(await prepareParams(operation, [], [])).toStrictEqual({});
expect(await prepareParams(operation, {}, {})).toStrictEqual({});
});

it('should prepare body and metadata when both are supplied', () => {
it('should prepare body and metadata when both are supplied', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = {
spec: 'this is the contents of an api specification',
Expand All @@ -58,7 +59,7 @@ describe('#prepareParams', () => {
'x-readme-version': '1.0',
};

expect(prepareParams(operation, body, metadata)).toStrictEqual({
expect(await prepareParams(operation, body, metadata)).toStrictEqual({
body: {
spec: 'this is the contents of an api specification',
},
Expand All @@ -68,7 +69,7 @@ describe('#prepareParams', () => {
});
});

it('should prepare body if body is a primitive', () => {
it('should prepare body if body is a primitive', async () => {
const schema = createOas('put', '/', {
requestBody: {
content: {
Expand All @@ -84,89 +85,123 @@ describe('#prepareParams', () => {
const operation = new Oas(schema).operation('/', 'put');
const body = 'Brie cheeseburger ricotta.';

expect(prepareParams(operation, body, {})).toStrictEqual({
expect(await prepareParams(operation, body, {})).toStrictEqual({
body,
});
});

it('should prepare body if body is an array', () => {
it('should prepare body if body is an array', async () => {
const operation = new Oas(arraySchema).operation('/', 'put');
const body = [
{
name: 'Buster',
},
];

expect(prepareParams(operation, body, {})).toStrictEqual({
expect(await prepareParams(operation, body, {})).toStrictEqual({
body,
});
});

it('should handle bodies when the content type is application/x-www-form-urlencoded', () => {
const operation = usptoSpec.operation('/{dataset}/{version}/records', 'post');
const body = {
criteria: '*:*',
};

const metadata = {
dataset: 'v1',
version: 'oa_citations',
};
describe('content types', () => {
it('should handle bodies when the content type is `application/x-www-form-urlencoded`', async () => {
const operation = usptoSpec.operation('/{dataset}/{version}/records', 'post');
const body = {
criteria: '*:*',
};

expect(prepareParams(operation, body, metadata)).toStrictEqual({
path: {
const metadata = {
dataset: 'v1',
version: 'oa_citations',
},
formData: {
criteria: '*:*',
},
};

expect(await prepareParams(operation, body, metadata)).toStrictEqual({
path: {
dataset: 'v1',
version: 'oa_citations',
},
formData: {
criteria: '*:*',
},
});
});

describe('multipart/form-data', () => {
it('should handle a multipart body when a property is a file path', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = {
spec: require.resolve('@readme/oas-examples/3.0/json/readme.json'),
};

const params = await prepareParams(operation, body);
expect(params.body.spec).toContain('data:application/json;name=readme.json;base64,');
});

it('should handle when the file path is relative', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = {
spec: './__tests__/__fixtures__/owlbert.png',
};

const params = await prepareParams(operation, body);
expect(params.body.spec).toContain('data:image/png;name=owlbert.png;base64,');
});

it('should handle a multipart body when a property is a file stream', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = {
spec: fs.createReadStream(require.resolve('@readme/oas-examples/3.0/json/readme.json')),
};

const params = await prepareParams(operation, body);
expect(params.body.spec).toContain('data:application/json;name=readme.json;base64,');
});
});
});

describe('supplying just a body or metadata', () => {
it('should handle if supplied is a body', () => {
it('should handle if supplied is a body', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = {
spec: 'this is the contents of an api specification',
};

expect(prepareParams(operation, body)).toStrictEqual({
expect(await prepareParams(operation, body)).toStrictEqual({
body,
});
});

it('should prepare a body if supplied is primitive', () => {
it('should prepare a body if supplied is primitive', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const body = 'this is a primitive value';

expect(prepareParams(operation, body)).toStrictEqual({
expect(await prepareParams(operation, body)).toStrictEqual({
body,
});
});

it('should prepare just a body if supplied argument is an array', () => {
it('should prepare just a body if supplied argument is an array', async () => {
const operation = new Oas(arraySchema).operation('/', 'put');
const body = [
{
name: 'Buster',
},
];

expect(prepareParams(operation, body)).toStrictEqual({
expect(await prepareParams(operation, body)).toStrictEqual({
body,
});
});

it('should prepare metadata if more than 25% of the supplied argument lines up with known parameters', () => {
it('should prepare metadata if more than 25% of the supplied argument lines up with known parameters', async () => {
const operation = usptoSpec.operation('/{dataset}/{version}/records', 'post');
const body = {
version: 'v1',
dataset: 'oa_citations',
randomUnknownParameter: true,
};

expect(prepareParams(operation, body)).toStrictEqual({
expect(await prepareParams(operation, body)).toStrictEqual({
path: {
version: 'v1',
dataset: 'oa_citations',
Expand All @@ -179,7 +214,7 @@ describe('#prepareParams', () => {
});
});

it('should prepare metadata if less than 25% of the supplied argument lines up with known parameters', () => {
it('should prepare metadata if less than 25% of the supplied argument lines up with known parameters', async () => {
const operation = usptoSpec.operation('/{dataset}/{version}/records', 'post');
const body = {
version: 'v1', // This a known parameter, but the others aren't and should be treated as body payload data.
Expand All @@ -189,7 +224,7 @@ describe('#prepareParams', () => {
randomUnknownParameter4: true,
};

expect(prepareParams(operation, body)).toStrictEqual({
expect(await prepareParams(operation, body)).toStrictEqual({
formData: {
version: 'v1',
randomUnknownParameter: true,
Expand All @@ -200,13 +235,13 @@ describe('#prepareParams', () => {
});
});

it('should prepare just metadata if supplied is metadata', () => {
it('should prepare just metadata if supplied is metadata', async () => {
const operation = readmeSpec.operation('/api-specification', 'post');
const metadata = {
'x-readme-version': '1.0',
};

expect(prepareParams(operation, metadata)).toStrictEqual({
expect(await prepareParams(operation, metadata)).toStrictEqual({
header: {
'x-readme-version': '1.0',
},
Expand Down
Loading