Skip to content

Commit

Permalink
Merge pull request #339 from oslabs-beta/master
Browse files Browse the repository at this point in the history
Official Swell-1.15.0
  • Loading branch information
nqnguyen1 authored Jul 6, 2023
2 parents 0ac050b + b9bbbbc commit d3df136
Show file tree
Hide file tree
Showing 37 changed files with 1,170 additions and 533 deletions.
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ Swell is a one-stop shop for sending and monitoring your API requests:
<!-- -TODO --- This needs to be updated -->
<img src="./ReadMeGifs/Gifs/gRPC.gif" style="display: block; margin: 10px auto 30px;" />

- _tRPC_: Swell includes full support for all methods of TypeScript Remote Procedure Calls including batch call support for queries and mutations as well as subscription
<img src="./ReadMeGifs/Gifs/trpc.gif" style="display: block; margin: 10px auto 30px;" />
<!-- <img src="./ReadMeGifs/Gifs/tRPC-subscription.gif" style="display: block; margin: 10px auto 30px;" /> -->

Calls are currently being made using by using http get and post request using TRPC's http RPC specification (See [RPC docs](https://trpc.io/docs/rpc)). TLDR- inputs for query procedures will be turn into uri-encoded json string and send as query param while inputs for mutate procedures will be store inside of the body.

Batch requests can be made by adding multiple procedures before sending out the request, all query procedures will get batch together into one singular get request and all mutate procedures will get batch together into one singular put request, if there are mixture of query and mutate procedures call in one request, the app will send out both a post and get request concurrently and combine the response into one response.

Nested endpoint must follow the general format parentEndpoint.childEndpoint.grandchildEndpoint. For example:

```js
client.user.update.mutate({ userId: '1', name: 'Luke' });
```

A request to the above endpoint must have the mutate option selected from the drop down menu, must have an endpoint of .user.update and a input body of {"userId": "1","name": "Luke"}

See [tRPC docs](https://trpc.io/docs/) for more information on sending tRPC requests or setting up a tRPC server.

## Additional features

- _Stress testing for HTTP/2 and GraphQL_: Test your server backend with Swell's stress testing feature to ensure your server can manage expected and unexpected loads accordingly
Expand All @@ -70,20 +88,6 @@ Swell is a one-stop shop for sending and monitoring your API requests:
- _Mock Server_: Swell allows you to create your own HTTP/2 mock server to facilitate front-end development without depending on a fully built backend server.
<img src="./ReadMeGifs/Gifs/MockServer.gif" style="display: block; margin: 10px auto 30px;" />

- _tRPC_: Swell includes full support for all methods of TypeScript Remote Procedure Calls including batch call support for queries and mutations.
<img src="./ReadMeGifs/Gifs/tRPC.gif" style="display: block; margin: 10px auto 30px;" />
<!-- <img src="./ReadMeGifs/Gifs/tRPC-subscription.gif" style="display: block; margin: 10px auto 30px;" /> -->

Calls are currently being made using Swell's own TRPCProxyClient generated from the URL provided by the user.
Batch requests must be entered one request per line. Swell will treat each line of code entered into the editor as a separate request before batching and returning responses.
Each request must follow the general format client.procedure.querytype(). For example:

```js
client.getUser.query({ name: 'Luke Skywalker' });
```

See [tRPC docs](https://trpc.io/docs/) for more information on sending tRPC requests or setting up a tRPC server.

- _Webhooks_: Swell includes user-defined HTTP callback connection testing designed to test other server's connection to the web and ability to send data. The test insures that when an event occurs, the source site makes an HTTP request to the URL configured for the webhook.
<img src="./ReadMeGifs/Gifs/Webhook.gif" style="float: left; margin-right: 10px;margin-bottom : 30px; margin-top : 10px;" />

Expand Down
Binary file removed ReadMeGifs/Gifs/tRPC.gif
Binary file not shown.
Binary file added ReadMeGifs/Gifs/trpc.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '../../../toolkit-refactor/store';
import TextCodeArea from '../sharedComponents/TextCodeArea';
import { RootState } from './src/client/toolkit-refactor/store';
import TextCodeArea from './src/client/components/main/sharedComponents/TextCodeArea';

/**
* renders entry form for TRPC request
*/


const TRPCBodyEntryForm = (props: any) => {
const { newRequestBodySet } = props;
const dispatch = useDispatch();
Expand Down
6 changes: 4 additions & 2 deletions docs/DEV-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ From a functionality standpoint:
- Consistent UI/UX styling and color palette
- Make requests via HTTP/2
- Query, Mutation, Subscribe/unsubscribe to GraphQL endpoints
- Query, Mutation, Subscribe/unsubscribe to tRPC endpoints
- HTTP/2 stress testing with `GET` requests
- GraphQL stress testing with `Query`
- Mock server for HTTP/2 (`Express`)
Expand Down Expand Up @@ -110,7 +111,8 @@ For the following technologies - if you reference the gifs in `readme` and try t

<!-- - gRPC -->

- tRPC
<!-- - tRPC -->

- OpenAPI

If future groups have a desire to iteration on the above features, please ensure the basic functionality works as expected, update E2E testing in `./test/testSuite.js` before adding new features.
Expand Down Expand Up @@ -161,7 +163,7 @@ Continuous Integration has been implemented using GitHub Actions. If you would l
- Make any necessary adjustments to the workflow and continue testing it on ci-draft and ci-main until the workflow is functioning as intended
- Finally, open a pull request to merge the new workflow into the dev and/or main branches

The idea is to troubleshoot new workflows before applying them to the dev or main branches.
The idea is to troubleshoot new workflows before applying them to the dev or main branches.

A Continuous Deployment pipeline would be an advantageous addition, as its absence blocks the ability to automatically package and release new iterations of the application. The groundwork for it is there (see the “scripts” and “build” properties in package.json) but packaging for Linux will need some attention, as outlined in the next section.

Expand Down
17 changes: 7 additions & 10 deletions index-csp.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Swell</title>
</head>

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <link rel="stylesheet" href="./node_modules/chart.js/dist/Chart.min.css" /> -->
<title>Swell</title>
</head>

<body></body>

</html>
<body></body>
</html>
52 changes: 29 additions & 23 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
// ** Entry point for Electron **
const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');


const { autoUpdater } = require('electron-updater');
const {
default: installExtension,
Expand All @@ -60,7 +59,7 @@ require('./main_process/main_graphqlController')();
require('./main_process/main_grpcController.js')();
require('./main_process/main_wsController.js')();
require('./main_process/main_mockController.js')();

require('./main_process/main_trpcController.js')();

// require mac touchbar
const { touchBar } = require('./main_process/main_touchbar.js');
Expand Down Expand Up @@ -218,8 +217,6 @@ app.on('ready', () => {
}
});



// Quit when all windows are closed.
app.on('window-all-closed', () => {
if (mockServerProcess) {
Expand Down Expand Up @@ -427,9 +424,13 @@ ipcMain.on('import-proto', (event) => {
if (err) {
return console.log('import-proto error reading file : ', err);
}

protoParserFunc(importedProto).then((protoObj) => {
mainWindow.webContents.send('proto-info', JSON.stringify(importedProto), JSON.stringify(protoObj));
mainWindow.webContents.send(
'proto-info',
JSON.stringify(importedProto),
JSON.stringify(protoObj)
);
});
});
})
Expand All @@ -442,8 +443,11 @@ ipcMain.on('import-proto', (event) => {
// Runs the function and returns the value back to GRPCProtoEntryForm
ipcMain.on('protoParserFunc-request', async (event, data) => {
try {
const result = await protoParserFunc(data)
mainWindow.webContents.send('protoParserFunc-return', JSON.stringify(result));
const result = await protoParserFunc(data);
mainWindow.webContents.send(
'protoParserFunc-return',
JSON.stringify(result)
);
} catch (err) {
console.log('error in protoParserFunc-request:, ', err);
mainWindow.webContents.send('protoParserFunc-return', { error: err });
Expand All @@ -464,28 +468,30 @@ ipcMain.on('import-openapi', (event) => {
.then((filePaths) => {
if (!filePaths) return undefined;
// read uploaded document & save in the redux store
fs.readFile(filePaths.filePaths[0], 'utf-8', async (err, importedFile) => {
// handle read error
if (err) {
return console.log('import-openapi error reading file : ', err);
}

try {
const documentObj = await openapiParserFunc(importedFile);
// console.log('Main.js - Working here!',documentObj);
mainWindow.webContents.send('openapi-info', documentObj);
} catch (err) {
return console.log('import-openapi error reading file : ', err);
fs.readFile(
filePaths.filePaths[0],
'utf-8',
async (err, importedFile) => {
// handle read error
if (err) {
return console.log('import-openapi error reading file : ', err);
}

try {
const documentObj = await openapiParserFunc(importedFile);
// console.log('Main.js - Working here!',documentObj);
mainWindow.webContents.send('openapi-info', documentObj);
} catch (err) {
return console.log('import-openapi error reading file : ', err);
}
}

});
);
})
.catch((err) => {
console.log('error in import-openapi', err);
});
});


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// MOCK SERVER //////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
Expand Down
32 changes: 15 additions & 17 deletions main_process/main_httpController.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,13 @@ const httpController = {
reqResObj.connectionType = 'plain';
}

// FIXME: There is something wrong with the logic below.
// First, it is checking if the headers have a 'content-length'
// or 'Content-Length' property. If it does not, it sets the
// responseSize to null. It it does, it checks if the headers have
// a 'content-length' property. If it does, it sets the contentLength
// to 'content-length' or 'Content-Length'. This does not make sense.
// I think it should be setting contentLength to headers['content-length']
// FIXME: There is something wrong with the logic below.
// First, it is checking if the headers have a 'content-length'
// or 'Content-Length' property. If it does not, it sets the
// responseSize to null. It it does, it checks if the headers have
// a 'content-length' property. If it does, it sets the contentLength
// to 'content-length' or 'Content-Length'. This does not make sense.
// I think it should be setting contentLength to headers['content-length']
// or headers['Content-Length'].

// check if response comes with 'content-length' header
Expand All @@ -209,14 +209,14 @@ const httpController = {
? (contentLength = 'content-length')
: (contentLength = 'Content-Length');

// FIXME: A previous group used a conversion figure of 1023.89427 to
// convert octets to bytes. This is incorrect because both an octet
// and byte are exactly 8 bits in modern computing. There could, however,
// be some ambiguity because "bytes" may have a different meaning in legacy
// systems. Check out this link for more info: https://en.wikipedia.org/wiki/Octet_(computing).
// If the desired responseSize is in bytes, it is enough to simply assign the value
// FIXME: A previous group used a conversion figure of 1023.89427 to
// convert octets to bytes. This is incorrect because both an octet
// and byte are exactly 8 bits in modern computing. There could, however,
// be some ambiguity because "bytes" may have a different meaning in legacy
// systems. Check out this link for more info: https://en.wikipedia.org/wiki/Octet_(computing).
// If the desired responseSize is in bytes, it is enough to simply assign the value
// of the content-length header.

// Converting content length octets into bytes
const conversionFigure = 1023.89427;
const octetToByteConversion =
Expand Down Expand Up @@ -295,7 +295,6 @@ const httpController = {
const { method, headers, body } = args.options;
const response = await fetch(headers.url, { method, headers, body });
const headersResponse = response.headers.raw();

if (headersResponse['content-type'][0].includes('stream')) {
return {
headers: headersResponse,
Expand Down Expand Up @@ -334,7 +333,6 @@ const httpController = {
reqResObj.timeSent = Date.now();

const options = this.parseFetchOptionsFromReqRes(reqResObj);

//-----------------------------------------
// Check if the URL provided is a stream
//-----------------------------------------
Expand Down Expand Up @@ -404,7 +402,7 @@ const httpController = {
cookies.forEach((cookie) => {
const cookieString = `${cookie.key}=${cookie.value}`;
// attach to formattedHeaders so options object includes this
formattedHeaders.cookie = cookieString;
formattedHeaders.cookie = formattedHeaders.cookie + ';' + cookieString;
});
}

Expand Down
Loading

0 comments on commit d3df136

Please sign in to comment.