├── .eslintrc.json
├── .gitignore
├── .husky
└── pre-push
├── .prettierignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── .yarnrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── icons
└── icon.png
├── package.json
├── src
├── extension.ts
└── test
│ ├── runTest.ts
│ └── suite
│ ├── extension.test.ts
│ └── index.ts
├── tsconfig.json
├── webpack.config.js
├── webview
├── App.css
├── App.tsx
├── acquireVsCodeApi.d.ts
├── components
│ ├── RequestBar
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── RequestOptionsBar
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── RequestOptionsWindow
│ │ ├── index.tsx
│ │ └── styles.css
│ └── Response
│ │ ├── index.tsx
│ │ └── styles.css
├── constants
│ ├── request-options.ts
│ ├── response-options.ts
│ ├── response-views.ts
│ └── supported-langs.ts
├── features
│ ├── codeGen
│ │ ├── CodeSnippet
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── codeGenSlice.ts
│ ├── requestAuth
│ │ ├── BasicAuth
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── BearerToken
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── NoAuth
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── RequestAuth
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestAuthSlice.ts
│ ├── requestBody
│ │ ├── Binary
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── FormData
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── GraphQL
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── NoBody
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── Raw
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── RequestBody
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── UrlEncoded
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestBodySlice.ts
│ ├── requestHeader
│ │ ├── HeadersWindow
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestHeaderSlice.ts
│ ├── requestMethod
│ │ ├── RequestMethodSelector
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestMethodSlice.ts
│ ├── requestOptions
│ │ ├── RequestOptions
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestOptionsSlice.ts
│ ├── requestUrl
│ │ ├── RequestQueryParams
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ ├── RequestUrl
│ │ │ ├── index.tsx
│ │ │ └── styles.css
│ │ └── requestUrlSlice.ts
│ └── response
│ │ ├── ResponseBody
│ │ ├── index.tsx
│ │ └── styles.css
│ │ ├── ResponseHeaders
│ │ ├── index.tsx
│ │ └── styles.css
│ │ ├── ResponseTab
│ │ ├── index.tsx
│ │ └── styles.css
│ │ ├── ResponseWindow
│ │ ├── index.tsx
│ │ └── styles.css
│ │ └── responseSlice.ts
├── icons
│ └── package.svg
├── index.css
├── index.tsx
├── pages
│ └── Postcode
│ │ ├── index.tsx
│ │ └── styles.css
├── prerender.tsx
├── react-app-env.d.ts
├── redux
│ ├── hooks.ts
│ └── store.ts
├── shared
│ ├── Editor
│ │ ├── index.tsx
│ │ └── styles.css
│ └── KeyValueTable
│ │ ├── index.tsx
│ │ └── styles.css
└── vscode.ts
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true,
5 | "node": true
6 | },
7 | "extends": [
8 | "eslint:recommended",
9 | "plugin:react/recommended",
10 | "plugin:@typescript-eslint/recommended",
11 | "plugin:prettier/recommended"
12 | ],
13 | "parser": "@typescript-eslint/parser",
14 | "parserOptions": {
15 | "ecmaFeatures": {
16 | "jsx": true
17 | },
18 | "ecmaVersion": 12,
19 | "sourceType": "module"
20 | },
21 | "settings": {
22 | "react": {
23 | "version": "detect"
24 | }
25 | },
26 | "ignorePatterns": ["out", "dist", "**/*.d.ts"],
27 | "plugins": ["react", "@typescript-eslint"],
28 | "rules": {
29 | "@typescript-eslint/explicit-module-boundary-types": "off"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 |
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn lint
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
13 | "outFiles": ["${workspaceFolder}/dist/**/*.js"],
14 | "preLaunchTask": "${defaultBuildTask}"
15 | },
16 | {
17 | "name": "Extension Tests",
18 | "type": "extensionHost",
19 | "request": "launch",
20 | "args": [
21 | "--extensionDevelopmentPath=${workspaceFolder}",
22 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
23 | ],
24 | "outFiles": ["${workspaceFolder}/out/test/**/*.js"],
25 | "preLaunchTask": "npm: test-watch"
26 | }
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files
5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true, // set this to false to include "out" folder in search results
9 | "dist": true // set this to false to include "dist" folder in search results
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off"
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": ["$ts-webpack-watch", "$tslint-webpack-watch"],
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | },
19 | {
20 | "type": "npm",
21 | "script": "test-watch",
22 | "problemMatcher": "$tsc-watch",
23 | "isBackground": true,
24 | "presentation": {
25 | "reveal": "never"
26 | },
27 | "group": "build"
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | node_modules/**
5 | src/**
6 | .gitignore
7 | .yarnrc
8 | vsc-extension-quickstart.md
9 | **/tsconfig.json
10 | **/.eslintrc.json
11 | **/*.map
12 | **/*.ts
13 | dist/prerender.js
14 | dist/*.prerender.js
15 | dist/*.prerender.js.*
16 |
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | --ignore-engines true
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "postcode" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ### 1.3.9
8 |
9 | - automattically use http protocol if none is specified
10 | - make font size relative to vscode editor font size
11 |
12 | ### 1.3.8
13 |
14 | - display response time in response window
15 |
16 | ### 1.3.7
17 |
18 | - add request options for strict ssl
19 |
20 | ### 1.3.6
21 |
22 | - add beautify button for post body
23 |
24 | ### 1.3.5
25 |
26 | - fix basic auth functionality
27 |
28 | ### 1.3.4
29 |
30 | - Add headers tab for response
31 |
32 | ### 1.3.3
33 |
34 | - Improve load time by pre-rendering
35 |
36 | ### 1.3.2
37 |
38 | - Remove excess scroll
39 |
40 | ### 1.3.1
41 |
42 | - Add copy button to code editor
43 |
44 | ### 1.3.0
45 |
46 | - Support code-snippet generation
47 |
48 | ### 1.2.1
49 |
50 | - Clear error when response is updated
51 |
52 | ### 1.2.0
53 |
54 | - Support GraphQL requests
55 |
56 | ### 1.1.0
57 |
58 | - Support formating of responses based on language
59 |
60 | ### 1.0.0
61 |
62 | - Initial release
63 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Rohini Senthil
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Postcode
2 |
3 | API client for VS code 📦
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Postcode is a [Visual Studio Code](https://code.visualstudio.com/) [extension](https://marketplace.visualstudio.com/VSCode) that can be used to create and test simple and complex HTTP/s requests, as well as view responses. You can find the extension available [here](https://marketplace.visualstudio.com/items?itemName=rohinivsenthil.postcode).
13 |
14 |
15 |
16 |
17 |
18 | Release: 1.3.3
19 |
20 |
21 | ## Highlighted Features
22 |
23 | - **Intuitive UI/UX** similar to Postman fitting seamlessly with any VSCode theme
24 | - Supports **GraphQL** requests
25 | - Supports **code snippet generation** from requests
26 |
27 | ## Quick start
28 |
29 | **Step 1.** Install the Postcode extension for Visual Studio Code
30 | **Step 2.** Click on the Postcode icon in the side panel OR run the following command **Postcode: Create Request**
31 | **Step 3** Create or test your HTTP/s requests and hit Send to see the responses
32 |
33 | ## Commands
34 |
35 | | Command | Description |
36 | | ------------------------ | ---------------------------------------------------- |
37 | | Postcode: Create Request | Opens a new Postcode tab to create and test requests |
38 |
39 | ## Issues, feature requests, and contributions
40 |
41 | ### Issues
42 |
43 | - If you come across a problem with the extension, please file an [issue](https://github.com/rohinivsenthil/postcode/issues/new)
44 | - For list of known issues, please check the [issues tab](https://github.com/rohinivsenthil/postcode/issues/new)
45 |
46 | ### Feature requests
47 |
48 | - Find planned features for future releases marked as [feature](https://github.com/rohinivsenthil/postcode/issues?q=is%3Aissue+is%3Aopen+label%3Afeature) under issues tab.
49 | - For new feature requests, please file an [issue](https://github.com/rohinivsenthil/postcode/issues/new)
50 |
51 | ### Contributions
52 |
53 | Contributions are always welcome!
54 |
55 | #### Running the extension locally for development
56 |
57 | 1. Clone the repository and install dependencies by running `yarn install`
58 | 2. Press `F5` to open a new window with your extension loaded.
59 | 3. Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Postcode: Create Request`.
60 |
61 | #### Folder structure
62 |
63 | - **`package.json`** - this is the manifest file in which you declare your extension and command. The plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette.
64 | - **`webview`**: folder where you will find entire React code
65 | - **`src/extension.ts`**: this is the main file where you will provide the implementation of your command. The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
66 |
67 | #### Making changes
68 |
69 | - You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
70 | - You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
71 |
72 | ## Related
73 |
74 | - Read the [launch blog](https://rohinivsenthil.medium.com/postcode-vs-code-extension-alternative-to-postman-384816d4cf07) post on Medium
75 | - Featured #11 Product of the day on [Product Hunt](https://www.producthunt.com/posts/postcode)
76 | - Featured in **Trending this week** on Visual Studio Code Marketplace
77 |
--------------------------------------------------------------------------------
/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rohinivsenthil/postcode/824ff7d0c2d04f7204ad7461ffd1fb105cdcc14d/icons/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "postcode",
3 | "publisher": "rohinivsenthil",
4 | "displayName": "Postcode",
5 | "icon": "icons/icon.png",
6 | "description": "An API client to test and create HTTP/s requests",
7 | "version": "1.3.9",
8 | "license": "MIT",
9 | "bugs": {
10 | "url": "https://github.com/rohinivsenthil/postcode/issues"
11 | },
12 | "author": {
13 | "name": "Rohini Senthil",
14 | "email": "rohinivsenthil@gmail.com"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/rohinivsenthil/postcode"
19 | },
20 | "engines": {
21 | "vscode": "^1.56.0"
22 | },
23 | "categories": [
24 | "Programming Languages"
25 | ],
26 | "keywords": [
27 | "api-client",
28 | "postman",
29 | "REST",
30 | "graphql",
31 | "http"
32 | ],
33 | "activationEvents": [
34 | "onCommand:postcode.createRequest"
35 | ],
36 | "main": "./dist/extension.js",
37 | "contributes": {
38 | "commands": [
39 | {
40 | "command": "postcode.createRequest",
41 | "title": "Postcode: Create Request"
42 | }
43 | ],
44 | "viewsContainers": {
45 | "activitybar": [
46 | {
47 | "id": "postcode",
48 | "title": "Postcode",
49 | "icon": "webview/icons/package.svg"
50 | }
51 | ]
52 | },
53 | "views": {
54 | "postcode": [
55 | {
56 | "id": "postcode.request",
57 | "name": "Request"
58 | }
59 | ]
60 | },
61 | "viewsWelcome": [
62 | {
63 | "view": "postcode.request",
64 | "contents": "[Create Request](command:postcode.createRequest)"
65 | }
66 | ]
67 | },
68 | "scripts": {
69 | "vscode:prepublish": "yarn run package",
70 | "compile": "cross-env NODE_ENV=development webpack --progress",
71 | "watch": "cross-env NODE_ENV=development webpack --progress --watch",
72 | "package": "cross-env NODE_ENV=production webpack --progress",
73 | "test-compile": "tsc -p ./",
74 | "test-watch": "tsc -watch -p ./",
75 | "pretest": "yarn run test-compile && yarn run lint",
76 | "lint": "eslint src webview --ext .ts,.tsx",
77 | "lint:fix": "eslint --fix src webview --ext .ts,.tsx",
78 | "test": "node ./out/test/runTest.js",
79 | "prepare": "husky install"
80 | },
81 | "devDependencies": {
82 | "@svgr/webpack": "^5.5.0",
83 | "@types/glob": "^7.1.3",
84 | "@types/mocha": "^8.0.4",
85 | "@types/node": "^12.11.7",
86 | "@types/react": "^17.0.5",
87 | "@types/react-dom": "^17.0.4",
88 | "@types/react-redux": "^7.1.16",
89 | "@types/vscode": "^1.56.0",
90 | "@typescript-eslint/eslint-plugin": "^4.14.1",
91 | "@typescript-eslint/parser": "^4.14.1",
92 | "cross-env": "^7.0.3",
93 | "css-loader": "^5.2.4",
94 | "eslint": "^7.19.0",
95 | "eslint-config-prettier": "^8.3.0",
96 | "eslint-plugin-prettier": "^3.4.0",
97 | "eslint-plugin-react": "^7.23.2",
98 | "file-loader": "^6.2.0",
99 | "glob": "^7.1.6",
100 | "husky": "^7.0.1",
101 | "mini-css-extract-plugin": "^1.6.0",
102 | "mocha": "^8.2.1",
103 | "monaco-editor-webpack-plugin": "^3.1.0",
104 | "prettier": "2.3.0",
105 | "static-site-generator-webpack-plugin": "^3.4.2",
106 | "style-loader": "^2.0.0",
107 | "ts-loader": "^8.0.14",
108 | "typescript": "^4.1.3",
109 | "url-loader": "^4.1.1",
110 | "vscode-test": "^1.5.0",
111 | "webpack": "^5.19.0",
112 | "webpack-cli": "^4.4.0"
113 | },
114 | "dependencies": {
115 | "@reduxjs/toolkit": "^1.5.1",
116 | "axios": "^0.21.1",
117 | "buffer": "^6.0.3",
118 | "monaco-editor": "^0.24.0",
119 | "path-browserify": "^1.0.1",
120 | "postman-code-generators": "^1.1.5",
121 | "postman-collection": "^3.6.11",
122 | "react": "^17.0.2",
123 | "react-dom": "^17.0.2",
124 | "react-icons": "^4.2.0",
125 | "react-redux": "^7.2.4",
126 | "url": "^0.11.0"
127 | }
128 | }
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | // The module 'vscode' contains the VS Code extensibility API
2 | // Import the module and reference it with the alias vscode in your code below
3 | import * as vscode from "vscode";
4 | import * as fs from "fs";
5 | import axios from "axios";
6 | import * as https from "https";
7 | import { RequestOptions } from "../webview/features/requestOptions/requestOptionsSlice";
8 |
9 | // this method is called when your extension is activated
10 | // your extension is activated the very first time the command is executed
11 | export function activate(context: vscode.ExtensionContext) {
12 | const webviewContent = fs
13 | .readFileSync(
14 | vscode.Uri.joinPath(context.extensionUri, "dist/index.html").fsPath,
15 | { encoding: "utf-8" }
16 | )
17 | .replace(
18 | "styleUri",
19 | vscode.Uri.joinPath(context.extensionUri, "/dist/main.css")
20 | .with({ scheme: "vscode-resource" })
21 | .toString()
22 | )
23 | .replace(
24 | "scriptUri",
25 | vscode.Uri.joinPath(context.extensionUri, "/dist/webview.js")
26 | .with({ scheme: "vscode-resource" })
27 | .toString()
28 | );
29 |
30 | // The command has been defined in the package.json file
31 | // Now provide the implementation of the command with registerCommand
32 | // The commandId parameter must match the command field in package.json
33 | const disposable = vscode.commands.registerCommand(
34 | "postcode.createRequest",
35 | () => {
36 | // The code you place here will be executed every time your command is executed
37 |
38 | // Display a message box to the user
39 | vscode.window.showInformationMessage("Welcome to Postcode!");
40 |
41 | const panel = vscode.window.createWebviewPanel(
42 | "postcode",
43 | "Postcode",
44 | vscode.ViewColumn.One,
45 | {
46 | enableScripts: true,
47 | retainContextWhenHidden: true,
48 | localResourceRoots: [
49 | vscode.Uri.joinPath(context.extensionUri, "dist"),
50 | ],
51 | }
52 | );
53 |
54 | panel.webview.html = webviewContent;
55 | panel.iconPath = vscode.Uri.joinPath(
56 | context.extensionUri,
57 | "icons/icon.png"
58 | );
59 |
60 | panel.webview.onDidReceiveMessage(
61 | ({ method, url, headers, body, auth, options }) => {
62 | // Options Section
63 | const requestOptions = options as RequestOptions;
64 | let requestStartedAt, responseDuration;
65 |
66 | if (!url) {
67 | panel.webview.postMessage({
68 | type: "response",
69 | error: { message: "Request URL is empty" },
70 | });
71 | vscode.window.showInformationMessage("Request URL is empty");
72 | return;
73 | }
74 |
75 | const headersObj = {};
76 |
77 | if (auth.type === "bearer") {
78 | headersObj["Authorization"] = `Bearer ${auth.bearer.token}`;
79 | }
80 |
81 | headers.forEach(({ key, value, disabled }) => {
82 | if (!disabled) {
83 | headersObj[key] = value;
84 | }
85 | });
86 |
87 | let data = "";
88 | if (body.mode === "formdata") {
89 | const dataObj = new URLSearchParams();
90 | body.formdata.forEach(({ key, value, disabled }) => {
91 | if (!disabled) {
92 | dataObj.append(key, value);
93 | }
94 | });
95 | data = dataObj.toString();
96 | headersObj["Content-Type"] = "multipart/form-data";
97 | } else if (body.mode === "urlencoded") {
98 | const dataObj = new URLSearchParams();
99 | body.urlencoded.forEach(({ key, value, disabled }) => {
100 | if (!disabled) {
101 | dataObj.append(key, value);
102 | }
103 | });
104 | data = dataObj.toString();
105 | headersObj["Content-Type"] = "application/x-www-form-urlencoded";
106 | } else if (body.mode === "raw") {
107 | data = body.raw;
108 | headersObj["Content-Type"] = {
109 | json: "application/json",
110 | html: "text/html",
111 | xml: "text/xml",
112 | text: "text/plain",
113 | }[body.options.raw.language];
114 | } else if (body.mode === "file") {
115 | data = body.fileData;
116 | headersObj["Content-Type"] = "application/octet-stream";
117 | } else if (body.mode === "graphql") {
118 | data = JSON.stringify({
119 | query: body.graphql.query,
120 | variables: body.graphql.variables,
121 | });
122 | headersObj["Content-Type"] = "application/json";
123 | }
124 |
125 | // Option 1. StrictSSL
126 | https.globalAgent.options.rejectUnauthorized =
127 | requestOptions.strictSSL === "yes";
128 |
129 | axios.interceptors.request.use((config) => {
130 | requestStartedAt = new Date().getTime();
131 | return config;
132 | });
133 |
134 | axios.interceptors.response.use((config) => {
135 | responseDuration = new Date().getTime() - requestStartedAt;
136 | return config;
137 | });
138 |
139 | axios({
140 | method,
141 | url,
142 | baseURL: "",
143 | data: data,
144 | headers: headersObj,
145 | auth: auth.type === "basic" ? auth.basic : undefined,
146 | transformResponse: [(data) => data],
147 | responseType: "text",
148 | validateStatus: () => true,
149 | })
150 | .then((resp) =>
151 | panel.webview.postMessage({
152 | type: "response",
153 | data: resp.data,
154 | status: resp.status,
155 | statusText: resp.statusText,
156 | headers: resp.headers,
157 | duration: responseDuration,
158 | })
159 | )
160 | .catch((err) => {
161 | panel.webview.postMessage({
162 | type: "response",
163 | error: err,
164 | });
165 | vscode.window.showInformationMessage(
166 | "Error: Could not send request"
167 | );
168 | });
169 | }
170 | );
171 | }
172 | );
173 |
174 | context.subscriptions.push(disposable);
175 | }
176 |
177 | // this method is called when your extension is deactivated
178 | // eslint-disable-next-line @typescript-eslint/no-empty-function
179 | export function deactivate() {}
180 |
--------------------------------------------------------------------------------
/src/test/runTest.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 |
3 | import { runTests } from "vscode-test";
4 |
5 | async function main() {
6 | try {
7 | // The folder containing the Extension Manifest package.json
8 | // Passed to `--extensionDevelopmentPath`
9 | const extensionDevelopmentPath = path.resolve(__dirname, "../../");
10 |
11 | // The path to test runner
12 | // Passed to --extensionTestsPath
13 | const extensionTestsPath = path.resolve(__dirname, "./suite/index");
14 |
15 | // Download VS Code, unzip it and run the integration test
16 | await runTests({ extensionDevelopmentPath, extensionTestsPath });
17 | } catch (err) {
18 | console.error("Failed to run tests");
19 | process.exit(1);
20 | }
21 | }
22 |
23 | main();
24 |
--------------------------------------------------------------------------------
/src/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 |
3 | // You can import and use all API from the 'vscode' module
4 | // as well as import your extension to test it
5 | import * as vscode from "vscode";
6 | // import * as myExtension from '../../extension';
7 |
8 | suite("Extension Test Suite", () => {
9 | vscode.window.showInformationMessage("Start all tests.");
10 |
11 | test("Sample test", () => {
12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5));
13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/test/suite/index.ts:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import * as Mocha from "mocha";
3 | import * as glob from "glob";
4 |
5 | export function run(): Promise {
6 | // Create the mocha test
7 | const mocha = new Mocha({
8 | ui: "tdd",
9 | color: true,
10 | });
11 |
12 | const testsRoot = path.resolve(__dirname, "..");
13 |
14 | return new Promise((c, e) => {
15 | glob("**/**.test.js", { cwd: testsRoot }, (err, files) => {
16 | if (err) {
17 | return e(err);
18 | }
19 |
20 | // Add files to the test suite
21 | files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
22 |
23 | try {
24 | // Run the mocha test
25 | mocha.run((failures) => {
26 | if (failures > 0) {
27 | e(new Error(`${failures} tests failed.`));
28 | } else {
29 | c();
30 | }
31 | });
32 | } catch (err) {
33 | console.error(err);
34 | e(err);
35 | }
36 | });
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "jsx": "react",
7 | "lib": ["es2019", "dom"],
8 | "sourceMap": true,
9 | "rootDir": ".",
10 | "resolveJsonModule": true,
11 | "strict": false /* enable all strict type-checking options */
12 | /* Additional Checks */
13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
16 | },
17 | "exclude": ["node_modules", ".vscode-test"]
18 | }
19 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-var-requires */
2 | //@ts-check
3 |
4 | "use strict";
5 |
6 | const path = require("path");
7 | const webpack = require("webpack");
8 | const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
9 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
10 | const StaticSiteGeneratorPlugin = require("static-site-generator-webpack-plugin");
11 |
12 | const imageInlineSizeLimit = parseInt(
13 | process.env.IMAGE_INLINE_SIZE_LIMIT || "10000"
14 | );
15 |
16 | const baseConfig = (webpackEnv) => {
17 | const isEnvDevelopment = webpackEnv === "development";
18 | const isEnvProduction = webpackEnv === "production";
19 |
20 | return {
21 | mode: isEnvProduction ? "production" : isEnvDevelopment && "development",
22 | bail: isEnvProduction,
23 | devtool: isEnvProduction
24 | ? "source-map"
25 | : isEnvDevelopment && "eval-cheap-module-source-map",
26 | resolve: {
27 | fallback: {
28 | buffer: require.resolve("buffer"),
29 | path: require.resolve("path-browserify"),
30 | url: require.resolve("url"),
31 | },
32 | extensions: [".ts", ".tsx", ".js"],
33 | },
34 | module: {
35 | rules: [
36 | {
37 | oneOf: [
38 | {
39 | test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
40 | loader: require.resolve("url-loader"),
41 | options: {
42 | limit: imageInlineSizeLimit,
43 | name: "static/media/[name].[hash:8].[ext]",
44 | },
45 | },
46 | {
47 | test: /\.svg$/,
48 | use: [
49 | require.resolve("@svgr/webpack"),
50 | require.resolve("url-loader"),
51 | ],
52 | },
53 | {
54 | test: /\.tsx?$/,
55 | exclude: /node_modules/,
56 | loader: require.resolve("ts-loader"),
57 | },
58 | {
59 | test: /\.css$/,
60 | use: [
61 | MiniCssExtractPlugin.loader,
62 | {
63 | loader: require.resolve("css-loader"),
64 | options: {
65 | importLoaders: 1,
66 | sourceMap: isEnvProduction || isEnvDevelopment,
67 | },
68 | },
69 | ],
70 | sideEffects: true,
71 | },
72 | {
73 | loader: require.resolve("file-loader"),
74 | exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
75 | options: {
76 | name: "media/[name].[hash:8].[ext]",
77 | },
78 | },
79 | ],
80 | },
81 | ],
82 | },
83 | plugins: [
84 | new MiniCssExtractPlugin({
85 | filename: "ignore.css",
86 | }),
87 | ],
88 | };
89 | };
90 |
91 | const extensionConfig = (webpackEnv) => {
92 | return {
93 | ...baseConfig(webpackEnv),
94 | target: "node",
95 | entry: "./src/extension.ts",
96 | output: {
97 | path: path.resolve(__dirname, "dist"),
98 | filename: "extension.js",
99 | libraryTarget: "commonjs2",
100 | },
101 | externals: { vscode: "commonjs vscode" },
102 | };
103 | };
104 |
105 | const webviewConfig = (webpackEnv) => {
106 | return {
107 | ...baseConfig(webpackEnv),
108 | entry: "./webview/index.tsx",
109 | output: {
110 | path: path.resolve(__dirname, "dist"),
111 | filename: "webview.js",
112 | },
113 | plugins: [
114 | new MiniCssExtractPlugin(),
115 | new MonacoWebpackPlugin({
116 | languages: [
117 | "csharp",
118 | "dart",
119 | "go",
120 | "graphql",
121 | "html",
122 | "java",
123 | "typescript",
124 | "json",
125 | "objective-c",
126 | "php",
127 | "powershell",
128 | "python",
129 | "ruby",
130 | "shell",
131 | "swift",
132 | "xml",
133 | ],
134 | }),
135 | new webpack.ProvidePlugin({
136 | Buffer: ["buffer", "Buffer"],
137 | process: "process/browser",
138 | }),
139 | ],
140 | };
141 | };
142 |
143 | const prerenderConfig = (webpackEnv) => {
144 | const config = baseConfig(webpackEnv);
145 |
146 | return {
147 | ...config,
148 | target: "node",
149 | entry: "./webview/prerender.tsx",
150 | output: {
151 | path: path.resolve(__dirname, "dist"),
152 | filename: "prerender.js",
153 | libraryTarget: "commonjs2",
154 | },
155 | plugins: [
156 | new MiniCssExtractPlugin({
157 | filename: "ignore.css",
158 | }),
159 | new StaticSiteGeneratorPlugin({
160 | paths: ["/"],
161 | }),
162 | new webpack.ProvidePlugin({
163 | Buffer: ["buffer", "Buffer"],
164 | process: "process/browser",
165 | }),
166 | ],
167 | };
168 | };
169 |
170 | module.exports = [extensionConfig, webviewConfig, prerenderConfig];
171 |
--------------------------------------------------------------------------------
/webview/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | background-color: var(--background);
3 | }
4 |
--------------------------------------------------------------------------------
/webview/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import "./App.css";
3 | import { responseUpdated } from "./features/response/responseSlice";
4 | import { Postcode } from "./pages/Postcode";
5 | import { useAppDispatch } from "./redux/hooks";
6 |
7 | const App = () => {
8 | const dispatch = useAppDispatch();
9 |
10 | React.useEffect(() => {
11 | window.addEventListener("message", (event) => {
12 | if (event.data.type === "response") {
13 | dispatch(responseUpdated(event.data));
14 | }
15 | });
16 | }, []);
17 |
18 | return (
19 |