️vite/esbuild (#4329)

* ️ vite

* replace webpack with esbuild in build script

* move build sr to esbuild

* esbuild send-request shim

* remove main externals

* fix lint

* remove webpack from insomnia-testing

* removes more webpack stuff

TODO after this PR: make debugging work again

* pin swagger-ui-react to version before esm change

* restore prepare script to build in bootstrap

* use default tsconfig for eslint and apply fixes

* bundle insomnia-components as cjs/esm

* makes ca_certs.ts pass linting

* builds types for insomnia-components

* improve build script for production

* skip typechecking insomnia-components

* separate package from build

* add electron to externals

* add preload bundling and fix build output

* exclude grpc/proto-loader from the bundle

* move node packages to commonjs

* don't bundle grpc since it's a node module

* fix content security error

* use vite lib mode for insomnia-components

* tidy up vite config and tsconfig options

* update package-locks

* use process.env. for static build time variables

* fix vscode debugging

Co-authored-by: jackkav <jackkav@gmail.com>
Co-authored-by: Dimitri Mitropoulos <dimitrimitropoulos@gmail.com>
This commit is contained in:
James Gatz 2022-04-18 17:27:39 +02:00 committed by GitHub
parent bdab0957d5
commit eb21506d40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 4271 additions and 28359 deletions

2
.gitignore vendored
View File

@ -31,3 +31,5 @@ packages/insomnia-smoke-test/screenshots
*.tsbuildinfo
dist
.history
packages/insomnia-app/app/network/ca_certs.ts
packages/insomnia-app/app/main.min.js.map

11
.vscode/launch.json vendored
View File

@ -16,9 +16,6 @@
"runtimeExecutable": "${workspaceFolder}/packages/insomnia-app/node_modules/.bin/electron",
"runtimeArgs": ["--remote-debugging-port=9222", "."],
"outputCapture": "std",
"sourceMapPathOverrides": {
"webpack:///./*": "${workspaceFolder}/packages/insomnia-app/app/*"
},
"windows": {
"type": "node",
"request": "launch",
@ -26,7 +23,6 @@
"runtimeExecutable": "${workspaceFolder}/packages/insomnia-app/node_modules/.bin/electron.cmd"
},
"env": {
"TS_NODE_PROJECT": "tsconfig.webpack.json",
"NODE_ENV": "development",
"ELECTRON_IS_DEV": "1"
}
@ -41,9 +37,6 @@
"order": 2
},
"port": 9222,
"sourceMapPathOverrides": {
"webpack:///./*": "${workspaceFolder}/packages/insomnia-app/app/*"
},
"webRoot": "${workspaceFolder}/packages/insomnia-app/app",
"timeout": 60000
},
@ -59,9 +52,6 @@
"autoAttachChildProcesses": true,
"trace": true,
"preLaunchTask": "Inso: Compile (Watch)",
"sourceMapPathOverrides": {
"webpack://insomniacli/./*": "${workspaceFolder}/packages/insomnia-inso/*"
},
"args": ["${input:insoCommand}", "${input:insoCommandArgs}"],
"console": "integratedTerminal"
}
@ -106,6 +96,7 @@
"group": "Insomnia",
"order": 0
},
"stopAll": true,
"preLaunchTask": "Insomnia: Compile (Watch)",
"configurations": [
"Electron: main",

17
.vscode/tasks.json vendored
View File

@ -5,32 +5,31 @@
"tasks": [
{
"label": "Insomnia: Compile Main",
"detail": "webpack --config webpack/webpack.config.electron.ts",
"detail": "esbuild.main.ts",
"type": "shell",
"promptOnClose": false,
"options": {
"cwd": "${workspaceFolder}/packages/insomnia-app",
"env": {
"NODE_ENV": "development",
"TS_NODE_PROJECT": "tsconfig.webpack.json"
}
},
"command": "${workspaceRoot}/packages/insomnia-app/node_modules/.bin/webpack --config webpack/webpack.config.electron.ts"
"command": "${workspaceRoot}/packages/insomnia-app/node_modules/.bin/esr esbuild.main.ts"
},
{
"label": "Insomnia: Compile Renderer (Watch)",
"detail": "webpack-dev-server --config webpack/webpack.config.development.ts",
"detail": "vite dev",
"type": "shell",
"promptOnClose": false,
"options": {
"cwd": "${workspaceFolder}/packages/insomnia-app",
"env": {
"TS_NODE_PROJECT": "tsconfig.webpack.json"
"NODE_ENV": "development",
}
},
"isBackground": true,
"problemMatcher": {
"owner": "webpack",
"owner": "vite",
"severity": "error",
"fileLocation": "absolute",
"pattern": [
@ -47,13 +46,13 @@
],
"background": {
"activeOnStart": true,
"beginsPattern": "Compiling\\.\\.\\.",
"beginsPattern": "vite",
"endsPattern": {
"regexp": "Compiled"
"regexp": "ready in"
}
}
},
"command": "${workspaceRoot}/packages/insomnia-app/node_modules/.bin/webpack-dev-server --config webpack/webpack.config.development.ts"
"command": "${workspaceRoot}/packages/insomnia-app/node_modules/.bin/vite dev"
},
{
"label": "Insomnia: Compile (Watch)",

View File

@ -13,8 +13,6 @@ There are a few more technologies and tools worth mentioning:
- [`React`](https://reactjs.org/) is the library used for all UI components.
- [`styled-components`](https://styled-components.com/) and [`Less`](http://lesscss.org/) are used for styling UI components.
- [`Electron Builder`](https://github.com/electron-userland/electron-builder) is used to help build, sign, and package Insomnia for distribution.
- [`Flow`](https://flow.org/) is used for adding types to the codebase. Not everything is Flow but all new code should be typed with Flow.
- [`Webpack`](https://webpack.js.org/) is the bundler used to compile the JS/Less/babel/etc
- [`libcurl`](https://curl.se/libcurl/) is the library that Insomnia uses to make requests. Libcurl is the HTTP client of choice because it allows the deepest amount of debuggability and control of HTTP requests.
- [`nedb`](https://github.com/louischatriot/nedb) a local in-memory database.
- [`node-libcurl`](https://github.com/JCMais/node-libcurl) is a Node.js wrapper around the native libcurl library.

View File

@ -37,7 +37,8 @@
"test:smoke:cli": "npm run test:cli --prefix packages/insomnia-smoke-test",
"hard-reset": "npm run clean && npm run bootstrap && npm run app-start",
"type-check": "lerna run type-check",
"changelog-image": "ts-node ./scripts/changelog-image/changelog-image.ts"
"changelog-image": "ts-node ./scripts/changelog-image/changelog-image.ts",
"dev": "npm start --prefix packages/insomnia-app"
},
"devDependencies": {
"@babel/cli": "^7.10.5",

View File

@ -2,6 +2,3 @@ build
bin
send-request
**/main.min.js
webpack.config.*.js
webpack.config.*.js.map
webpack.config.*.d.ts

View File

@ -37,6 +37,7 @@ global.requestAnimationFrame = (callback: FrameRequestCallback) => {
};
global.require = require;
// Don't console log real logs that start with a tag (eg. [db] ...). It's annoying
const log = console.log;

View File

@ -1,23 +0,0 @@
import * as globalPackage from '../../package.json';
import { globalBeforeEach } from '../__jest__/before-each';
describe('package.json', () => {
beforeEach(globalBeforeEach);
it('all packed dependencies should exist', () => {
for (const name of globalPackage.packedDependencies) {
const version = globalPackage.dependencies[name];
expect(version).toBeDefined();
}
});
it('packages must be included in webpack build or else errors happen', () => {
// If this is built by Webpack it fails on multipart/form-data
expect(globalPackage.packedDependencies.includes('httpsnippet')).toBe(false);
});
it('packages must NOT be included in webpack build or else errors happen', () => {
// PDFJS breaks if not part of Webpack build
expect(globalPackage.packedDependencies.includes('pdfjs-dist')).toBe(true);
});
});

View File

@ -5,6 +5,8 @@ import { unreachableCase } from 'ts-assert-unreachable';
import appConfig from '../../config/config.json';
import { getDataDirectory, getPortableExecutableDir } from './electron-helpers';
const env = process['env'];
// App Stuff
export const getAppVersion = () => appConfig.version;
export const getAppLongName = () => appConfig.longName;
@ -20,7 +22,7 @@ export const isLinux = () => getAppPlatform() === 'linux';
export const isWindows = () => getAppPlatform() === 'win32';
export const getAppEnvironment = () => process.env.INSOMNIA_ENV || 'production';
export const isDevelopment = () => getAppEnvironment() === 'development';
export const getSegmentWriteKey = () => appConfig.segmentWriteKeys[(isDevelopment() || process.env.PLAYWRIGHT) ? 'development' : 'production'];
export const getSegmentWriteKey = () => appConfig.segmentWriteKeys[(isDevelopment() || env.PLAYWRIGHT) ? 'development' : 'production'];
export const getAppBuildDate = () => new Date(process.env.BUILD_DATE ?? '').toLocaleDateString();
export const getBrowserUserAgent = () => encodeURIComponent(
@ -126,13 +128,13 @@ export enum UpdateURL {
}
// API
export const getApiBaseURL = () => process.env.INSOMNIA_API_URL || 'https://api.insomnia.rest';
export const getApiBaseURL = () => env.INSOMNIA_API_URL || 'https://api.insomnia.rest';
// App website
export const getAppWebsiteBaseURL = () => process.env.INSOMNIA_APP_WEBSITE_URL || 'https://app.insomnia.rest';
export const getAppWebsiteBaseURL = () => env.INSOMNIA_APP_WEBSITE_URL || 'https://app.insomnia.rest';
// GitHub API
export const getGitHubGraphQLApiURL = () => process.env.INSOMNIA_GITHUB_API_URL || 'https://api.github.com/graphql';
export const getGitHubGraphQLApiURL = () => env.INSOMNIA_GITHUB_API_URL || 'https://api.github.com/graphql';
// SYNC
export const DEFAULT_BRANCH_NAME = 'master';

View File

@ -16,11 +16,11 @@ export function clickLink(href: string) {
* This environment variable is added by electron-builder.
* see: https://www.electron.build/configuration/nsis.html#portable\
*/
export const getPortableExecutableDir = () => process.env.PORTABLE_EXECUTABLE_DIR;
export const getPortableExecutableDir = () => process.env['PORTABLE_EXECUTABLE_DIR'];
export function getDataDirectory() {
const { app } = process.type === 'renderer' ? window : electron;
return process.env.INSOMNIA_DATA_PATH || app.getPath('userData');
return process.env['INSOMNIA_DATA_PATH'] || app.getPath('userData');
}
export function getTempDir() {

View File

@ -224,7 +224,7 @@ export function decompressObject(input: string | null): any {
export function resolveHomePath(p: string) {
if (p.indexOf('~/') === 0) {
return pathJoin(process.env.HOME || '/', p.slice(1));
return pathJoin(process.env['HOME'] || '/', p.slice(1));
} else {
return p;
}

View File

@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src * insomnia://*; img-src blob: data: * insomnia://*; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src blob: data: mediastream: * insomnia://*;"
content="font-src 'self' data:; default-src * insomnia://*; img-src blob: data: * insomnia://*; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src blob: data: mediastream: * insomnia://*;"
/>
</head>
<body>
@ -21,6 +21,6 @@
"
></div>
<div id="graphql-explorer-container"></div>
<script src="bundle.js" type="application/javascript"></script>
<script src="./renderer.ts" type="module"></script>
</body>
</html>

View File

@ -2,7 +2,7 @@ import electron, { BrowserWindow, MenuItemConstructorOptions } from 'electron';
import fs from 'fs';
import * as os from 'os';
import path from 'path';
import url from 'url';
import { pathToFileURL } from 'url';
import {
changelogUrl,
@ -119,8 +119,9 @@ export function createWindow() {
});
// Load the html of the app.
const appPath = path.resolve(__dirname, './renderer.html');
const appUrl = process.env.APP_RENDER_URL || url.pathToFileURL(appPath).href;
const appPath = path.resolve(__dirname, './index.html');
const appUrl = process.env.APP_RENDER_URL || pathToFileURL(appPath).href;
console.log(`[main] Loading ${appUrl}`);
mainWindow?.loadURL(appUrl);
// Emitted when the window is closed.

View File

@ -1,9 +0,0 @@
// NOTE: this file is used by the `val-loader` webpack loader to export the NodeJS trust store during compile time.
// Do not convert it to TypeScript. It's a native node module by design.
const tls = require('tls');
module.exports = () => {
return {
code: 'module.exports = `' + tls.rootCertificates.join('\n') + '`',
};
};

View File

@ -1,4 +1,4 @@
import url from 'url';
import { parse as urlParse } from 'url';
const parseGrpcUrl = (
grpcUrl?: string,
@ -6,7 +6,7 @@ const parseGrpcUrl = (
url: string;
enableTls: boolean;
} => {
const { protocol, host, href } = url.parse(grpcUrl?.toLowerCase() || '');
const { protocol, host, href } = urlParse(grpcUrl?.toLowerCase() || '');
switch (protocol) {
case 'grpcs:':

View File

@ -57,7 +57,7 @@ import { isWorkspace } from '../models/workspace';
import * as pluginContexts from '../plugins/context/index';
import * as plugins from '../plugins/index';
import { getAuthHeader } from './authentication';
import caCerts from './ca-certs';
import caCerts from './ca_certs';
import { buildMultipart, DEFAULT_BOUNDARY } from './multipart';
import { urlMatchesCertHost } from './url-matches-cert-host';
@ -326,8 +326,8 @@ export async function _actuallySend(
} catch (err) {
// Doesn't exist yet, so write it
mkdirp.sync(baseCAPath);
// TODO: Should mock cacerts module for testing. This is literally
// coercing a function to string in tests due to lack of val-loader.
// TODO: Should mock cacerts module for testing.
// This is literally coercing a function to string in tests due to lack of val-loader.
fs.writeFileSync(fullCAPath, String(caCerts));
console.log('[net] Set CA to', fullCAPath);
}

View File

@ -18,7 +18,7 @@ import type { PluginTheme } from './misc';
export interface Module {
templateTags?: PluginTemplateTag[];
requestHooks?: ((requstContext: any) => void)[];
requestHooks?: ((requestContext: any) => void)[];
responseHooks?: ((responseContext: any) => void)[];
themes?: PluginTheme[];
requestGroupActions?: OmitInternal<RequestGroupAction>[];
@ -172,7 +172,6 @@ async function _traversePluginPath(
}
}
// Use global.require() instead of require() because Webpack wraps require()
const pluginJson = global.require(packageJSONPath);
// Not an Insomnia plugin because it doesn't have the package.json['insomnia']

View File

@ -21,13 +21,12 @@ const shell = {
showItemInFolder: options => ipcRenderer.send('showItemInFolder', options),
};
// if (process.contextIsolated) { TODO: use if rather than try after upgrading to electron 13
try {
if (process.contextIsolated) {
contextBridge.exposeInMainWorld('main', main);
contextBridge.exposeInMainWorld('dialog', dialog);
contextBridge.exposeInMainWorld('app', app);
contextBridge.exposeInMainWorld('shell', shell);
} catch {
} else {
window.main = main;
window.dialog = dialog;
window.app = app;

View File

@ -1,4 +1,5 @@
import nunjucks from 'nunjucks/browser/nunjucks';
import { type Environment } from 'nunjucks';
import * as nunjucks from 'nunjucks/browser/nunjucks';
import type { TemplateTag } from '../plugins/index';
import * as plugins from '../plugins/index';
@ -24,9 +25,9 @@ export const RENDER_TAGS = 'tags';
export const NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME = '_';
// Cached globals
let nunjucksVariablesOnly: nunjucks.Environment | null = null;
let nunjucksTagsOnly: nunjucks.Environment | null = null;
let nunjucksAll: nunjucks.Environment | null = null;
let nunjucksVariablesOnly: Environment | null = null;
let nunjucksTagsOnly: Environment | null = null;
let nunjucksAll: Environment | null = null;
/**
* Render text based on stuff

View File

@ -1,5 +1,5 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import * as PDF from 'pdfjs-dist/webpack';
import * as PDF from 'pdfjs-dist';
import React, { CSSProperties, PureComponent } from 'react';
import { AUTOBIND_CFG } from '../../../common/constants';
@ -61,6 +61,11 @@ export class ResponsePDFViewer extends PureComponent<Props, State> {
container.appendChild(canvas);
// get context and render page
const context = canvas.getContext('2d');
if (!context) {
return;
}
const renderContext = {
id: `${this.props.uniqueKey}.${i}`,
canvasContext: context,

View File

@ -1,4 +1,3 @@
/// <reference types="webpack-env" />
import { applyMiddleware, compose, createStore, Store } from 'redux';
import thunkMiddleware from 'redux-thunk';
@ -18,11 +17,5 @@ export default function() {
);
const store = createStore(reducer, enhancer);
if (__DEV__ && module.hot) {
module.hot.accept('./modules/index', () => {
store.replaceReducer(reducer);
});
}
return store as Store;
}

View File

@ -0,0 +1,67 @@
import esbuild from 'esbuild';
import { builtinModules } from 'module';
import path from 'path';
import pkg from './package.json';
interface Options {
mode?: 'development' | 'production';
}
export default async function build(options: Options) {
const mode = options.mode || 'production';
// The list of packages that will be included in the node_modules folder of the packaged app.
// Exclude all package.json dependencies except from the ones in the packedDependencies list
const unpackedDependencies = [
...Object.keys(pkg.dependencies).filter(
name => !pkg.packedDependencies.includes(name)
),
];
const __DEV__ = mode !== 'production';
const PORT = pkg.dev['dev-server-port'];
const outdir = __DEV__
? path.join(__dirname, 'app')
: path.join(__dirname, 'build');
const env: Record<string, string> = __DEV__
? {
'process.env.APP_RENDER_URL': JSON.stringify(
`http://localhost:${PORT}/index.html`
),
'process.env.NODE_ENV': JSON.stringify('development'),
'process.env.INSOMNIA_ENV': JSON.stringify('development'),
'process.env.BUILD_DATE': JSON.stringify(new Date()),
}
: {
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.INSOMNIA_ENV': JSON.stringify('production'),
'process.env.BUILD_DATE': JSON.stringify(new Date()),
};
return esbuild.build({
entryPoints: ['./app/main.development.ts'],
outfile: path.join(outdir, 'main.min.js'),
bundle: true,
platform: 'node',
sourcemap: true,
format: 'cjs',
define: env,
external: [
'electron',
'@getinsomnia/node-libcurl',
...Object.keys(unpackedDependencies),
...Object.keys(builtinModules),
],
});
}
// Build if ran as a cli script
const isMain = require.main === module;
if (isMain) {
const mode =
process.env.NODE_ENV === 'development' ? 'development' : 'production';
build({ mode });
}

View File

@ -0,0 +1,14 @@
import { build } from 'esbuild';
import path from 'path';
const outdir = path.join(__dirname, 'build');
build({
entryPoints: ['./app/preload.ts'],
outfile: path.join(outdir, 'preload.js'),
bundle: true,
platform: 'node',
sourcemap: true,
format: 'esm',
external: ['@getinsomnia/node-libcurl', 'electron'],
});

View File

@ -0,0 +1,39 @@
import { build } from 'esbuild';
import alias from 'esbuild-plugin-alias';
import path from 'path';
const env = {
window: JSON.stringify({
localStorage: {
getItem: () => undefined,
setItem: () => { },
},
performance: { now: () => 0 },
requestAnimationFrame: () => { },
cancelAnimationFrame: () => { },
}),
};
async function main() {
await build({
entryPoints: ['./send-request/index.ts'],
outfile: '../insomnia-send-request/dist/index.js',
bundle: true,
platform: 'node',
target: 'esnext',
sourcemap: true,
format: 'cjs',
define: env,
tsconfig: 'tsconfig.build.sr.json',
plugins: [
alias({
'electron': path.resolve(__dirname, './send-request/electron/index.js'),
}),
],
external: ['@getinsomnia/node-libcurl'],
});
process.exit(0);
}
main();

View File

@ -24,7 +24,6 @@ module.exports = {
verbose: true,
moduleNameMapper: {
'\\.(css|less|png)$': '<rootDir>/__mocks__/dummy.ts',
'^worker-loader!': '<rootDir>/__mocks__/dummy.ts',
'styled-components': '<rootDir>/../node_modules/styled-components',
},
};

File diff suppressed because it is too large Load Diff

View File

@ -16,25 +16,26 @@
"url": "https://github.com/Kong/insomnia/issues"
},
"scripts": {
"clean": "tsc --build tsconfig.webpack.json --clean && tsc --build tsconfig.build.json --clean",
"clean": "tsc --build tsconfig.build.json --clean",
"postclean": "rimraf build app/main.min.js",
"test": "jest",
"test:watch": "jest --watch",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"type-check:watch": "npm run type-check -- --watch",
"build:main.min.js": "cross-env TS_NODE_PROJECT=\"tsconfig.webpack.json\" cross-env NODE_ENV=development webpack --config webpack/webpack.config.electron.ts",
"start:electron": "npm run build:main.min.js && electron .",
"start:dev-server": "cross-env TS_NODE_PROJECT=\"tsconfig.webpack.json\" webpack-dev-server --config webpack/webpack.config.development.ts",
"build:main.min.js": "cross-env NODE_ENV=development esr esbuild.main.ts",
"start:electron": "cross-env NODE_ENV=development esr esbuild.main.ts && electron .",
"start:dev-server": "vite dev",
"start": "concurrently -n dev,app --kill-others \"npm run start:dev-server\" \"npm run start:electron\"",
"prebuild": "npm run clean",
"build": "npm run build:sr && npm run build:app",
"build:app": "ts-node ./scripts/build.ts --noErrorTruncation",
"build:sr": "cross-env TS_NODE_PROJECT=\"tsconfig.webpack.json\" webpack --config webpack/webpack.config.sr.ts",
"package": "ts-node scripts/package.ts",
"bump-version": "ts-node scripts/bumpVersion.ts",
"build": "npm run generate:ca-certs && npm run build:sr && npm run build:app",
"build:app": "esr --cache ./scripts/build.ts --noErrorTruncation",
"build:sr": "npm run generate:ca-certs && esr esbuild.sr.ts",
"package": "npm run build:app && esr scripts/package.ts",
"bump-version": "esr scripts/bumpVersion.ts",
"lint": "eslint . --ext .js,.ts,.tsx --cache",
"lint:fix": "npm run lint -- --fix",
"bootstrap": "npm run build:sr"
"bootstrap": "npm run build:sr",
"generate:ca-certs": "esr scripts/generateCACerts.ts"
},
"dev": {
"dev-server-port": 3334
@ -49,10 +50,6 @@
"graphql-language-service",
"highlight.js",
"insomnia-components",
"insomnia-cookies",
"insomnia-prettify",
"insomnia-url",
"insomnia-xpath",
"json-order",
"jwt-authentication",
"objectpath",
@ -77,6 +74,8 @@
],
"dependencies": {
"@getinsomnia/node-libcurl": "2.3.5-0",
"@grpc/grpc-js": "^1.1.8",
"@grpc/proto-loader": "^0.5.5",
"@hapi/hawk": "^8.0.0",
"@stoplight/spectral": "^5.9.0",
"analytics-node": "^6.0.0",
@ -88,6 +87,7 @@
"codemirror": "^5.65.2",
"codemirror-graphql": "^1.2.12",
"color": "^3.1.2",
"crypto-browserify": "^3.12.0",
"dompurify": "^2.3.6",
"electron-context-menu": "^3.1.1",
"electron-log": "^4.4.3",
@ -162,7 +162,7 @@
"reselect": "^4.1.5",
"srp-js": "^0.2.1",
"styled-components": "^5.3.3",
"swagger-ui-react": "^4.5.2",
"swagger-ui-react": "4.5.1",
"tough-cookie": "^2.3.1",
"ts-assert-unreachable": "^0.0.9",
"url-join": "^4.0.1",
@ -176,8 +176,6 @@
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@develohpanda/fluent-builder": "^2.1.2",
"@grpc/grpc-js": "^1.1.8",
"@grpc/proto-loader": "^0.5.5",
"@testing-library/dom": "^7.28.1",
"@testing-library/jest-dom": "^5.11.5",
"@testing-library/react": "^11.2.6",
@ -190,7 +188,6 @@
"@types/color": "^3.0.1",
"@types/concurrently": "^6.0.1",
"@types/deep-equal": "^1.0.1",
"@types/file-loader": "^5.0.0",
"@types/fs-extra": "^5.1.0",
"@types/hapi__hawk": "^8.0.2",
"@types/js-yaml": "^4.0.1",
@ -212,21 +209,18 @@
"@types/react-redux": "^7.1.22",
"@types/react-tabs": "^2.3.4",
"@types/redux-mock-store": "^1.0.2",
"@types/swagger-ui-react": "^4.1.1",
"@types/styled-components": "^5.1.23",
"@types/swagger-ui-react": "^4.1.1",
"@types/testing-library__jest-dom": "^5.9.5",
"@types/testing-library__react-hooks": "^4.0.0",
"@types/tough-cookie": "^2.3.7",
"@types/url-join": "^4.0.1",
"@types/uuid": "^8.3.4",
"@types/vkbeautify": "^0.99.2",
"@types/webpack": "^5.28.0",
"@types/webpack-dev-server": "^3.11.3",
"@types/webpack-env": "^1.16.0",
"@types/yaml": "^1.9.7",
"@vitejs/plugin-react": "^1.2.0",
"concurrently": "^7.0.0",
"cross-env": "^7.0.3",
"css-loader": "^2.1.1",
"date-fns": "^2.28.0",
"deep-equal": "^1.0.1",
"electron": "17.3.0",
@ -234,26 +228,20 @@
"electron-builder-squirrel-windows": "23.0.3",
"electron-devtools-installer": "^3.2.0",
"electron-notarize": "^1.1.1",
"file-loader": "^3.0.1",
"esbuild": "^0.14.27",
"esbuild-plugin-alias": "0.2.1",
"esbuild-runner": "^2.2.1",
"jest": "^26.6.3",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"license-checker": "^25.0.1",
"ncp": "^2.0.0",
"prompt-run": "^1.4.5",
"redux-mock-store": "^1.5.4",
"source-map-loader": "^1.0.0",
"style-loader": "^0.23.1",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"type-fest": "^2.12.0",
"typescript": "^4.5.5",
"url-loader": "^1.1.2",
"val-loader": "^2.1.2",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-target-electron-renderer": "^0.4.0",
"worker-loader": "^2.0.0"
"vite": "^2.8.6",
"vite-plugin-commonjs-externals": "^0.1.1"
}
}

View File

@ -1,17 +1,17 @@
import childProcess from 'child_process';
import { promises, readFileSync, writeFileSync } from 'fs';
import { build } from 'esbuild';
import { readFileSync, writeFileSync } from 'fs';
import { writeFile } from 'fs/promises';
import licenseChecker from 'license-checker';
import mkdirp from 'mkdirp';
import { ncp } from 'ncp';
import path from 'path';
import rimraf from 'rimraf';
import webpack from 'webpack';
import * as vite from 'vite';
import appConfig from '../config/config.json';
import electronWebpackConfig from '../webpack/webpack.config.electron';
import productionWebpackConfig from '../webpack/webpack.config.production';
const { readFile, writeFile } = promises;
import buildMain from '../esbuild.main';
import pkg from '../package.json';
// Start build if ran from CLI
if (require.main === module) {
@ -25,144 +25,145 @@ if (require.main === module) {
});
}
const buildWebpack = (config: webpack.Configuration) => new Promise<void>((resolve, reject) => {
webpack(config).run((err, stats) => {
if (err) {
reject(err);
return;
}
if (stats?.hasErrors()) {
reject(new Error('Failed to build webpack'));
console.log(stats.toJson().errors);
return;
}
resolve();
});
});
const emptyDir = (relPath: string) => new Promise<void>((resolve, reject) => {
const dir = path.resolve(__dirname, relPath);
rimraf(dir, err => {
if (err) {
reject(err);
} else {
mkdirp.sync(dir);
resolve();
}
});
});
const copyFiles = (relSource: string, relDest: string) => new Promise<void>((resolve, reject) => {
const source = path.resolve(__dirname, relSource);
const dest = path.resolve(__dirname, relDest);
console.log(`[build] copy "${relSource}" to "${relDest}"`);
ncp(source, dest, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
const buildLicenseList = (relSource: string, relDest: string) => new Promise<void>((resolve, reject) => {
const source = path.resolve(__dirname, relSource);
const dest = path.resolve(__dirname, relDest);
mkdirp.sync(path.dirname(dest));
licenseChecker.init(
{
start: source,
production: true,
},
(err, packages) => {
const emptyDir = (relPath: string) =>
new Promise<void>((resolve, reject) => {
const dir = path.resolve(__dirname, relPath);
rimraf(dir, err => {
if (err) {
return reject(err);
reject(err);
} else {
mkdirp.sync(dir);
resolve();
}
});
});
const header = [
'This application bundles the following third-party packages in ',
'accordance with the following licenses:',
'-------------------------------------------------------------------------',
'',
'',
].join('\n');
const copyFiles = (relSource: string, relDest: string) =>
new Promise<void>((resolve, reject) => {
const source = path.resolve(__dirname, relSource);
const dest = path.resolve(__dirname, relDest);
console.log(`[build] copy "${relSource}" to "${relDest}"`);
ncp(source, dest, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
const out = Object.keys(packages).sort().map(packageName => {
const { licenses, repository, publisher, email, licenseFile: lf } = packages[packageName];
const licenseFile = (lf || '').includes('README') ? null : lf;
return [
const buildLicenseList = (relSource: string, relDest: string) =>
new Promise<void>((resolve, reject) => {
const source = path.resolve(__dirname, relSource);
const dest = path.resolve(__dirname, relDest);
mkdirp.sync(path.dirname(dest));
licenseChecker.init(
{
start: source,
production: true,
},
(err, packages) => {
if (err) {
return reject(err);
}
const header = [
'This application bundles the following third-party packages in ',
'accordance with the following licenses:',
'-------------------------------------------------------------------------',
'',
`PACKAGE: ${packageName}`,
licenses ? `LICENSES: ${licenses}` : null,
repository ? `REPOSITORY: ${repository}` : null,
publisher ? `PUBLISHER: ${publisher}` : null,
email ? `EMAIL: ${email}` : null,
'',
licenseFile ? readFileSync(licenseFile) : '[no license file]',
'',
'',
].filter(v => v !== null).join('\n');
}).join('\n');
].join('\n');
writeFileSync(dest, `${header}${out}`);
resolve();
},
);
});
const out = Object.keys(packages)
.sort()
.map(packageName => {
const {
licenses,
repository,
publisher,
email,
licenseFile: lf,
} = packages[packageName];
const licenseFile = (lf || '').includes('README') ? null : lf;
return [
'-------------------------------------------------------------------------',
'',
`PACKAGE: ${packageName}`,
licenses ? `LICENSES: ${licenses}` : null,
repository ? `REPOSITORY: ${repository}` : null,
publisher ? `PUBLISHER: ${publisher}` : null,
email ? `EMAIL: ${email}` : null,
'',
licenseFile ? readFileSync(licenseFile) : '[no license file]',
'',
'',
]
.filter(v => v !== null)
.join('\n');
})
.join('\n');
const install = () => new Promise<void>((resolve, reject) => {
const root = path.resolve(__dirname, '../../../');
const p = childProcess.spawn('npm', ['run', 'bootstrap:electron-builder'], {
cwd: root,
shell: true,
writeFileSync(dest, `${header}${out}`);
resolve();
}
);
});
p.stdout.on('data', data => {
console.log(data.toString());
});
const install = () =>
new Promise<void>((resolve, reject) => {
const root = path.resolve(__dirname, '../../../');
p.stderr.on('data', data => {
console.log(data.toString());
});
const p = childProcess.spawn('npm', ['run', 'bootstrap:electron-builder'], {
cwd: root,
shell: true,
});
p.on('exit', code => {
console.log(`child process exited with code ${code}`);
if (code === 0) {
resolve();
} else {
reject(new Error('[build] failed to install dependencies'));
}
p.stdout.on('data', data => {
console.log(data.toString());
});
p.stderr.on('data', data => {
console.log(data.toString());
});
p.on('exit', code => {
console.log(`child process exited with code ${code}`);
if (code === 0) {
resolve();
} else {
reject(new Error('[build] failed to install dependencies'));
}
});
});
});
const generatePackageJson = async (relBasePkg: string, relOutPkg: string) => {
// Read package.json's
const basePath = path.resolve(__dirname, relBasePkg);
// Figure out which dependencies to pack
const allDependencies = Object.keys(pkg.dependencies);
const packedDependencies = pkg.packedDependencies;
const unpackedDependencies = allDependencies.filter(
name => !packedDependencies.includes(name)
);
const outPath = path.resolve(__dirname, relOutPkg);
const inputFile = String(await readFile(basePath));
const basePkg = JSON.parse(inputFile);
const appPkg = {
name: appConfig.name,
version: appConfig.version,
productName: appConfig.productName,
longName: appConfig.longName,
description: basePkg.description,
license: basePkg.license,
homepage: basePkg.homepage,
author: basePkg.author,
copyright: `Copyright © ${new Date().getFullYear()} ${basePkg.author}`,
description: pkg.description,
license: pkg.license,
homepage: pkg.homepage,
author: pkg.author,
copyright: `Copyright © ${new Date().getFullYear()} ${pkg.author}`,
main: 'main.min.js',
dependencies: {},
};
console.log(`[build] Generated build config for ${appPkg.name} ${appPkg.version}`);
console.log(
`[build] Generated build config for ${appPkg.name} ${appPkg.version}`
);
for (const key of Object.keys(appPkg)) {
if (key === undefined) {
@ -170,15 +171,12 @@ const generatePackageJson = async (relBasePkg: string, relOutPkg: string) => {
}
}
// Figure out which dependencies to pack
const allDependencies = Object.keys(basePkg.dependencies);
const packedDependencies = basePkg.packedDependencies;
const unpackedDependencies = allDependencies.filter(name => !packedDependencies.includes(name));
// Add dependencies
console.log(`[build] Adding ${unpackedDependencies.length} node dependencies`);
console.log(
`[build] Adding ${unpackedDependencies.length} node dependencies`
);
for (const name of unpackedDependencies) {
const version = basePkg.dependencies[name];
const version = pkg.dependencies[name];
if (!version) {
throw new Error(`Failed to find packed dep "${name}" in dependencies`);
}
@ -192,8 +190,14 @@ const generatePackageJson = async (relBasePkg: string, relOutPkg: string) => {
export const start = async () => {
console.log('[build] Starting build');
console.log(`[build] npm: ${childProcess.spawnSync('npm', ['--version']).stdout}`.trim());
console.log(`[build] node: ${childProcess.spawnSync('node', ['--version']).stdout}`.trim());
console.log(
`[build] npm: ${childProcess.spawnSync('npm', ['--version']).stdout}`.trim()
);
console.log(
`[build] node: ${
childProcess.spawnSync('node', ['--version']).stdout
}`.trim()
);
if (process.version.indexOf('v16.') !== 0) {
console.log('[build] Node v16.x.x is required to build');
@ -208,13 +212,37 @@ export const start = async () => {
// Build the things
console.log('[build] Building license list');
await buildLicenseList('../', path.join(buildFolder, 'opensource-licenses.txt'));
await buildLicenseList(
'../',
path.join(buildFolder, 'opensource-licenses.txt')
);
console.log('[build] Building Webpack renderer');
await buildWebpack(productionWebpackConfig as webpack.Configuration);
console.log('[build] Building main.min.js');
await buildMain({
mode: 'production',
});
console.log('[build] Building Webpack main');
await buildWebpack(electronWebpackConfig as webpack.Configuration);
console.log('[build] Building preload');
await build({
entryPoints: [path.join(__dirname, '../app/preload.js')],
outfile: path.join(__dirname, '../build/preload.js'),
platform: 'node',
bundle: true,
target: 'esnext',
sourcemap: false,
format: 'esm',
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
},
minify: true,
external: ['electron'],
});
console.log('[build] Building renderer');
await vite.build({
configFile: path.join(__dirname, '..', 'vite.config.ts'),
});
// Copy necessary files
console.log('[build] Copying files');
@ -223,7 +251,10 @@ export const start = async () => {
await copyFiles('../app/icons', buildFolder);
// Generate necessary files needed by `electron-builder`
await generatePackageJson('../package.json', path.join(buildFolder, 'package.json'));
await generatePackageJson(
'../package.json',
path.join(buildFolder, 'package.json')
);
// Install Node modules
console.log('[build] Installing dependencies');

View File

@ -0,0 +1,10 @@
import fs from 'fs/promises';
import path from 'path';
import tls from 'tls';
const filePath = path.join(__dirname, '..', 'app', 'network', 'ca_certs.ts');
const certificates = tls.rootCertificates.join('\n');
const fileContents = `export default \`${certificates}\`;\n`;
fs.writeFile(filePath, fileContents);

View File

@ -4,7 +4,6 @@ import rimraf from 'rimraf';
import appConfig from '../config/config.json';
import electronBuilderConfig from '../config/electronbuilder.json';
import { start as build } from './build';
const PLATFORM_MAP = {
darwin: 'mac',
@ -16,19 +15,6 @@ const isSupportedPlatform = (platform: NodeJS.Platform): platform is keyof typeo
PLATFORM_MAP[platform] !== undefined
);
// Start package if ran from CLI
if (require.main === module) {
process.nextTick(async () => {
try {
await build();
await module.exports.start();
} catch (err) {
console.log('[package] ERROR:', err);
process.exit(1);
}
});
}
const pkg = () => {
const { BUILD_TARGETS } = process.env;
const {
@ -64,7 +50,7 @@ const pkg = () => {
return electronBuilder.build({
config,
[targetPlatform]: target,
...targetPlatform === 'mac' ? { universal: true } : {},
...(targetPlatform === 'mac' ? { universal: true } : {}),
});
};
@ -79,7 +65,7 @@ const emptyDir = (relPath: string) => new Promise<void>((resolve, reject) => {
});
});
export const start = async () => {
const start = async () => {
console.log('[package] Removing existing directories');
if (process.env.KEEP_DIST_FOLDER !== 'yes') {
@ -91,3 +77,5 @@ export const start = async () => {
console.log('[package] Complete!');
};
start();

View File

@ -1,22 +1,7 @@
// This file implements just enough of the electron module to get sending requests to work
const os = require('os');
const path = require('path');
function getPath(name) {
switch (name) {
case 'temp':
return os.tmpdir();
case 'userData':
// Will be used to store response bodies and things
return path.join(os.tmpdir(), 'insomnia-send-request');
}
throw new Error('Invalid path:' + name);
}
module.exports = {
app: {
getPath,
getPath: (name) => name === 'temp' ? require('os').tmpdir() : require('path').join(require('os').tmpdir(), 'insomnia-send-request'),
},
ipcMain: {
on: () => {

View File

@ -5,6 +5,7 @@
"rootDir": ".",
"resolveJsonModule": true,
"strict": false,
"isolatedModules": true,
"strictNullChecks": true,
"jsx": "react",
"experimentalDecorators": true,
@ -29,11 +30,8 @@
"assets",
".babelrc.js",
"bin",
"build",
"config",
"jest.config.js",
"node_modules",
"scripts",
"webpack"
]
}

View File

@ -9,7 +9,10 @@
"package.json",
"scripts",
"send-request",
"webpack"
"vite.config.ts",
"esbuild.main.ts",
"esbuild.sr.ts",
"esbuild.preload.ts",
],
"exclude": [
"**/@types/mocha",

View File

@ -1,19 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": ".",
"rootDir": ".",
"resolveJsonModule": true,
"strict": false,
"module": "CommonJS",
"target": "ES5",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"strictNullChecks": true,
},
"include": [
"package.json",
"webpack"
],
"exclude": []
}

View File

@ -0,0 +1,79 @@
import react from '@vitejs/plugin-react';
import { builtinModules } from 'module';
import path from 'path';
import { defineConfig } from 'vite';
import commonjsExternals from 'vite-plugin-commonjs-externals';
import pkg from './package.json';
// The list of packages that will be included in the node_modules folder of the packaged app.
// Exclude all package.json dependencies except from the ones in the packedDependencies list
const unpackedDependencies = [
...Object.keys(pkg.dependencies).filter(
name => !pkg.packedDependencies.includes(name)
),
];
// The list of packages we want to keep as commonJS require().
// Must be resolvable import paths, cannot be globs
// These will be available via Node's require function from the node_modules folder or Node's builtin modules
const commonjsPackages = [
'electron',
'electron/main',
'electron/common',
'electron/renderer',
'@getinsomnia/node-libcurl',
'@getinsomnia/node-libcurl/dist/enum/CurlAuth',
'@getinsomnia/node-libcurl/dist/enum/CurlHttpVersion',
'@getinsomnia/node-libcurl/dist/enum/CurlNetrc',
'nunjucks/browser/nunjucks',
...unpackedDependencies,
...builtinModules,
];
export default defineConfig(({ mode }) => {
const __DEV__ = mode !== 'production';
return {
mode,
root: path.join(__dirname, 'app'),
base: __DEV__ ? '/' : './',
define: {
__DEV__: JSON.stringify(__DEV__),
'process.env.NODE_ENV': JSON.stringify(mode),
'process.env.INSOMNIA_ENV': JSON.stringify(mode),
},
optimizeDeps: {
exclude: commonjsPackages,
},
server: {
port: pkg.dev['dev-server-port'],
fs: {
strict: true,
},
},
build: {
sourcemap: __DEV__,
outDir: path.join(__dirname, 'build'),
assetsDir: './',
brotliSize: false,
emptyOutDir: false,
commonjsOptions: {
ignore: commonjsPackages,
},
},
plugins: [
commonjsExternals({ externals: commonjsPackages }),
react({
fastRefresh: __DEV__,
jsxRuntime: 'automatic',
babel: {
plugins: [
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
],
},
}),
],
};
});

View File

@ -1,89 +0,0 @@
// recommended by the docs: https://webpack.js.org/configuration/configuration-languages/
// just in case you run into any typescript error when configuring `devServer`
import 'webpack-dev-server';
import path from 'path';
import { Configuration, DefinePlugin, NormalModuleReplacementPlugin, optimize } from 'webpack';
import pkg from '../package.json';
const configuration: Configuration = {
devtool: 'source-map',
stats: 'minimal',
context: path.join(__dirname, '../app'),
entry: ['./renderer.ts', './renderer.html'],
output: {
path: path.join(__dirname, '../build'),
filename: 'bundle.js',
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.(less|css)$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
{ loader: 'less-loader', options: { noIeCompat: true } },
],
},
{
test: /\.(html|woff2)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
{
test: /\.(png|svg)$/,
loader: 'url-loader',
},
{
test: require.resolve('../app/network/ca-certs.js'),
use: [
{
loader: 'val-loader',
},
],
},
],
},
resolve: {
alias: {
react: path.resolve(path.join(__dirname, '../node_modules/react')),
'styled-components': path.resolve(path.join(__dirname, '../node_modules/styled-components')),
},
extensions: ['.js', '.json', '.ts', '.tsx'],
mainFields: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main'],
},
node: {
__dirname: false, // Use Node __dirname
},
externals: [
// Omit all dependencies in app/package.json (we want them loaded at runtime via NodeJS)
...Object.keys(pkg.dependencies).filter(name => !pkg.packedDependencies.includes(name)),
// To get jsonlint working...
'file',
'system',
],
plugins: [
new optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
new DefinePlugin({
'process.env.BUILD_DATE': JSON.stringify(new Date()),
}),
// see: https://github.com/Kong/insomnia/pull/3469 for why this transform is needed
new NormalModuleReplacementPlugin(
/node_modules\/vscode-languageserver-types\/lib\/umd\/main\.js/,
'../esm/main.js',
),
],
target: 'electron-renderer',
};
export default configuration;

View File

@ -1,59 +0,0 @@
import { Configuration, DefinePlugin, HotModuleReplacementPlugin, LoaderOptionsPlugin } from 'webpack';
import packageJSON from '../package.json';
import baseConfig from './webpack.config.base';
const PORT = packageJSON.dev['dev-server-port'];
const configuration: Configuration = {
...baseConfig,
devtool: 'eval-source-map',
mode: 'development',
entry: [
`webpack-dev-server/client?http://localhost:${PORT}`,
'webpack/hot/only-dev-server',
...(Array.isArray(baseConfig.entry) ? baseConfig.entry : []),
],
module: {
...baseConfig.module,
rules: [
...(baseConfig.module?.rules || []),
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
include: [/insomnia-components/],
},
],
},
output: {
...baseConfig.output,
publicPath: '/',
},
// @ts-expect-error -- TSCONVERSION I'm not convinced it's correct that for webpack v4 this isn't supposed to be here, although the types do include something similar for WebpackOptionsNormalized which is the options property of Compiler. gonna leave it here until compelled to do otherwise. we can check back later.
devServer: {
host: 'localhost',
port: PORT,
publicPath: '/',
hot: true,
disableHostCheck: true,
// This is needed for source-maps to resolve correctly
contentBase: '/',
},
optimization: {
noEmitOnErrors: true,
},
plugins: [
...(baseConfig.plugins || []),
new LoaderOptionsPlugin({ debug: true }), // Legacy global loader option
new HotModuleReplacementPlugin(),
new DefinePlugin({
__DEV__: true,
'process.env.NODE_ENV': JSON.stringify('development'),
'process.env.INSOMNIA_ENV': JSON.stringify('development'),
}),
],
};
export default configuration;

View File

@ -1,53 +0,0 @@
import path from 'path';
import { Configuration, DefinePlugin } from 'webpack';
import packageJSON from '../package.json';
import productionConfig from './webpack.config.production';
const PORT = packageJSON.dev['dev-server-port'];
let devtool: Configuration['devtool'];
let plugins: Configuration['plugins'] = [];
const output: Configuration['output'] = {
libraryTarget: 'commonjs2',
filename: 'main.min.js',
};
if (process.env.NODE_ENV === 'development') {
output.path = path.join(__dirname, '../app');
devtool = 'eval-source-map';
plugins = [
new DefinePlugin({
'process.env.APP_RENDER_URL': JSON.stringify(`http://localhost:${PORT}/renderer.html`),
'process.env.NODE_ENV': JSON.stringify('development'),
'process.env.INSOMNIA_ENV': JSON.stringify('development'),
'process.env.BUILD_DATE': JSON.stringify(new Date()),
}),
];
} else {
output.path = path.join(__dirname, '../build');
devtool = productionConfig.devtool;
plugins = productionConfig.plugins;
}
const configuration: Configuration[] = [{
...productionConfig,
devtool,
entry: ['./main.development.ts'],
output,
node: {
__dirname: false, // Use node.js __dirname
},
target: 'electron-main',
plugins,
},
{
entry: './app/preload.js',
target: 'electron-preload',
output: {
path: path.join(__dirname, '../build'),
filename: 'preload.js',
},
}];
export default configuration;

View File

@ -1,24 +0,0 @@
import { Configuration, DefinePlugin } from 'webpack';
import baseConfig from './webpack.config.base';
const configuration: Configuration = {
...baseConfig,
devtool: false,
mode: 'production',
optimization: {
// Minimization causes lots of small problems in a large project like this so
// we'll just disable it.
minimize: false,
},
plugins: [
...(baseConfig.plugins || []),
new DefinePlugin({
__DEV__: false,
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.HOT': JSON.stringify(null),
}),
],
};
export default configuration;

View File

@ -1,58 +0,0 @@
import path from 'path';
import { Configuration, ProvidePlugin } from 'webpack';
import pkg from '../package.json';
const configuration: Configuration = {
context: path.join(__dirname, '../send-request'),
entry: { index: './index.ts' },
target: 'node',
mode: 'production',
devtool: 'source-map',
stats: 'minimal',
optimization: {
minimize: false,
},
output: {
filename: '[name].js',
library: 'insomniasendrequest',
libraryTarget: 'commonjs2',
// Export directly where we need it for now
path: path.resolve(__dirname, '../../insomnia-send-request/dist'),
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: require.resolve('../app/network/ca-certs.js'),
use: [
{
loader: 'val-loader',
},
],
},
],
},
externals: [
// Omit all dependencies in app/package.json (we want them loaded at runtime via NodeJS)
...Object.keys(pkg.dependencies).filter(name => !pkg.packedDependencies.includes(name)),
],
resolve: {
alias: {
// Replace electron with a minimal polyfill that contains just enough to get
// the things in this bundle working
electron: path.resolve(path.join(__dirname, '../send-request/electron')),
},
extensions: ['.js', '.json', '.ts', '.tsx'],
},
plugins: [
new ProvidePlugin({ window: path.resolve(path.join(__dirname, '../send-request/window-shim')) }),
],
};
export default configuration;

File diff suppressed because it is too large Load Diff

View File

@ -12,21 +12,31 @@
"bugs": {
"url": "https://github.com/Kong/insomnia/issues"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"main": "./dist/commonjs/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"require": "./dist/commonjs/index.js",
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"prebuild": "npm run convert-svg",
"build": "webpack --config webpack/webpack.prod.js --display errors-only",
"build:source": "vite build",
"build:types": "tsc --build tsconfig.build.json",
"build": "concurrently --names source,types \"npm run build:source\" \"npm run build:types\"",
"clean": "rimraf dist && npm run clean:svg",
"clean:svg": "rimraf src/assets/svgr",
"clean:svg:index": "rimraf src/assets/svgr/index.tsx",
"convert-svg": "npm run clean:svg && svgr --config-file svgr.config.js --out-dir src/assets/svgr src/assets && npm run clean:svg:index",
"jest:watch": "jest --watch",
"prepare": "npm run convert-svg && npm run build",
"lint": "eslint . --ext .js,.ts,.tsx --cache",
"lint:fix": "npm run lint -- --fix",
"prepare": "npm run build",
"test": "jest",
"watch": "webpack --config webpack/webpack.dev.js --watch"
"watch": "cross-env ESBUILD_WATCH=true esr esbuild.ts"
},
"devDependencies": {
"@babel/core": "^7.7.7",
@ -47,9 +57,11 @@
"@types/react-dom": "^17.0.11",
"@types/testing-library__jest-dom": "^5.9.5",
"@types/testing-library__react-hooks": "^4.0.0",
"@types/webpack": "^5.28.0",
"@types/webpack-merge": "^5.0.0",
"babel-plugin-inline-react-svg": "^1.1.1",
"concurrently": "^7.0.0",
"cross-env": "^7.0.3",
"esbuild": "^0.14.27",
"esbuild-runner": "^2.2.1",
"jest": "^26.6.3",
"react": "^17.0.2",
"react-docgen-typescript": "^1.22.0",
@ -60,9 +72,7 @@
"type-fest": "^2.12.0",
"typescript": "^4.5.5",
"typescript-plugin-styled-components": "^2.0.0",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.11",
"webpack-merge": "^5.0.7"
"vite": "^2.9.1"
},
"dependencies": {
"@types/styled-components": "^5.1.23",

View File

@ -1,3 +1,3 @@
export { Button, ButtonProps, ButtonSizeEnum, ButtonThemeEnum, ButtonVariantEnum } from './button';
export { AsyncButton, AsyncButtonProps } from './async-button';
export { CircleButton, CircleButtonProps } from './circle-button';
export { Button, type ButtonProps, type ButtonSizeEnum, type ButtonThemeEnum, type ButtonVariantEnum } from './button';
export { AsyncButton, type AsyncButtonProps } from './async-button';
export { CircleButton, type CircleButtonProps } from './circle-button';

View File

@ -1,3 +1,3 @@
export { Dropdown, DropdownProps } from './dropdown';
export { DropdownItem, DropdownItemProps } from './dropdown-item';
export { Dropdown, type DropdownProps } from './dropdown';
export { DropdownItem, type DropdownItemProps } from './dropdown-item';
export { DropdownDivider } from './dropdown-divider';

View File

@ -3,25 +3,25 @@ export * from './dropdown';
export * from './sidebar';
export * from './list-group';
export { Breadcrumb, BreadcrumbProps, CrumbProps } from './breadcrumb';
export { Breadcrumb, type BreadcrumbProps, type CrumbProps } from './breadcrumb';
export { CardContainer } from './card-container';
export { Card, CardProps } from './card';
export { Header, HeaderProps } from './header';
export { Card, type CardProps } from './card';
export { Header, type HeaderProps } from './header';
export { MultiSwitch } from './multi-switch';
export { NoticeTable, NoticeTableProps, Notice } from './notice-table';
export { RadioButtonGroup, RadioButtonGroupProps } from './radio-button-group';
export { SvgIcon, SvgIconProps, IconEnum, ThemeEnum, IconId } from './svg-icon';
export { Switch, SwitchProps, SwitchItem } from './switch';
export { NoticeTable, type NoticeTableProps, type Notice } from './notice-table';
export { RadioButtonGroup, type RadioButtonGroupProps } from './radio-button-group';
export { SvgIcon, type SvgIconProps, type IconEnum, type ThemeEnum, type IconId } from './svg-icon';
export { Switch, type SwitchProps, type SwitchItem } from './switch';
export {
Table,
TableProps,
type TableProps,
TableBody,
TableData,
TableDataProps,
type TableDataProps,
TableHead,
TableHeader,
TableHeaderProps,
type TableHeaderProps,
TableRow,
} from './table';
export { ToggleSwitch, ToggleSwitchProps } from './toggle-switch';
export { Tooltip, TooltipProps } from './tooltip';
export { ToggleSwitch, type ToggleSwitchProps } from './toggle-switch';
export { Tooltip, type TooltipProps } from './tooltip';

View File

@ -1,7 +1,7 @@
export { ListGroupItem, ListGroupItemProps } from './list-group-item';
export { ListGroup, ListGroupProps } from './list-group';
export { UnitTestItem, UnitTestItemProps, TestItem } from './unit-test-item';
export { UnitTestRequestSelector, UnitTestRequestSelectorProps } from './unit-test-request-selector';
export { UnitTestResultBadge, UnitTestResultBadgeProps } from './unit-test-result-badge';
export { UnitTestResultItem, UnitTestResultItemProps } from './unit-test-result-item';
export { UnitTestResultTimestamp, UnitTestResultTimestampProps } from './unit-test-result-timestamp';
export { ListGroupItem, type ListGroupItemProps } from './list-group-item';
export { ListGroup, type ListGroupProps } from './list-group';
export { UnitTestItem, type UnitTestItemProps, type TestItem } from './unit-test-item';
export { UnitTestRequestSelector, type UnitTestRequestSelectorProps } from './unit-test-request-selector';
export { UnitTestResultBadge, type UnitTestResultBadgeProps } from './unit-test-result-badge';
export { UnitTestResultItem, type UnitTestResultItemProps } from './unit-test-result-item';
export { UnitTestResultTimestamp, type UnitTestResultTimestampProps } from './unit-test-result-timestamp';

View File

@ -1,6 +1,6 @@
import { motion } from 'framer-motion';
import React, { FunctionComponent, ReactNode } from 'react';
import { useToggle } from 'react-use';
import useToggle from 'react-use/lib/useToggle';
import styled from 'styled-components';
import { Button } from '../button';

View File

@ -1,18 +1,18 @@
export { Sidebar, SidebarProps } from './sidebar';
export { SidebarBadge, SidebarBadgeProps } from './sidebar-badge';
export { SidebarFilter, SidebarFilterProps } from './sidebar-filter';
export { SidebarHeader, SidebarHeaderProps } from './sidebar-header';
export { SidebarHeaders, SidebarHeadersProps } from './sidebar-headers';
export { SidebarInfo, SidebarInfoProps, SidebarInfoType } from './sidebar-info';
export { SidebarInvalidSection, SidebarInvalidSectionProps } from './sidebar-invalid-section';
export { SidebarItem, SidebarItemProps } from './sidebar-item';
export { SidebarPanel, SidebarPanelProps } from './sidebar-panel';
export { SidebarParameters, SidebarParametersProps } from './sidebar-parameters';
export { SidebarPaths, SidebarPathsProps, SidebarPathsType } from './sidebar-paths';
export { SidebarRequests, SidebarRequestsProps } from './sidebar-requests';
export { SidebarResponses, SidebarResponsesProps } from './sidebar-responses';
export { SidebarSchemas, SidebarSchemasProps } from './sidebar-schemas';
export { SidebarSection, SidebarSectionProps } from './sidebar-section';
export { SidebarSecurity, SidebarSecurityProps } from './sidebar-security';
export { SidebarServers, SidebarServersProps, SidebarServer } from './sidebar-servers';
export { SidebarTextItem, SidebarTextItemProps } from './sidebar-text-item';
export { Sidebar, type SidebarProps } from './sidebar';
export { SidebarBadge, type SidebarBadgeProps } from './sidebar-badge';
export { SidebarFilter, type SidebarFilterProps } from './sidebar-filter';
export { SidebarHeader, type SidebarHeaderProps } from './sidebar-header';
export { SidebarHeaders, type SidebarHeadersProps } from './sidebar-headers';
export { SidebarInfo, type SidebarInfoProps, type SidebarInfoType } from './sidebar-info';
export { SidebarInvalidSection, type SidebarInvalidSectionProps } from './sidebar-invalid-section';
export { SidebarItem, type SidebarItemProps } from './sidebar-item';
export { SidebarPanel, type SidebarPanelProps } from './sidebar-panel';
export { SidebarParameters, type SidebarParametersProps } from './sidebar-parameters';
export { SidebarPaths, type SidebarPathsProps, type SidebarPathsType } from './sidebar-paths';
export { SidebarRequests, type SidebarRequestsProps } from './sidebar-requests';
export { SidebarResponses, type SidebarResponsesProps } from './sidebar-responses';
export { SidebarSchemas, type SidebarSchemasProps } from './sidebar-schemas';
export { SidebarSection, type SidebarSectionProps } from './sidebar-section';
export { SidebarSecurity, type SidebarSecurityProps } from './sidebar-security';
export { SidebarServers, type SidebarServersProps, type SidebarServer } from './sidebar-servers';
export { SidebarTextItem, type SidebarTextItemProps } from './sidebar-text-item';

View File

@ -1,6 +1,6 @@
import { motion } from 'framer-motion';
import React, { ChangeEvent, FunctionComponent, ReactNode, useCallback, useLayoutEffect, useState } from 'react';
import { useToggle } from 'react-use';
import useToggle from 'react-use/lib/useToggle';
import styled from 'styled-components';
import { SidebarFilter } from './sidebar-filter';

View File

@ -1,6 +1,6 @@
import { motion } from 'framer-motion';
import React, { FunctionComponent } from 'react';
import { useToggle } from 'react-use';
import useToggle from 'react-use/lib/useToggle';
import styled from 'styled-components';
import { Dropdown } from '../dropdown/dropdown';

View File

@ -1,7 +1,9 @@
import React, { FunctionComponent, ReactNode, useCallback, useEffect, useState } from 'react';
import Switch from 'react-switch';
import ReactSwitch from 'react-switch';
import styled, { css } from 'styled-components';
// @ts-expect-error Issue with commonJS export in vite
const Switch = ReactSwitch.default;
export interface ToggleSwitchProps {
labelClassName?: string;
switchClassName?: string;

View File

@ -5,7 +5,10 @@
"outDir": "dist",
"rootDir": "src",
"jsx": "react",
"isolatedModules": true,
"lib": ["DOM"],
"experimentalDecorators": true,
"emitDeclarationOnly": true,
"resolveJsonModule": true
},
"include": [

View File

@ -5,9 +5,9 @@
},
"include": [
"src",
"webpack",
"jest.config.js",
".eslintrc.js",
"vite.config.ts",
"svgr.config.js"
],
"exclude": [

View File

@ -0,0 +1,30 @@
import { defineConfig } from 'vite';
export default defineConfig(({ mode }) => {
const __DEV__ = mode !== 'production';
return {
build: {
sourcemap: __DEV__,
lib: {
entry: './src/index.ts',
fileName: format => {
if (format === 'cjs') {
return 'commonjs/index.js';
}
return 'index.js';
},
// We use CommonJS output for running tests in jest.
formats: ['cjs', 'es'],
name: 'insomnia-components',
},
emptyOutDir: false,
rollupOptions: {
external: ['react', 'react-dom', 'styled-components', 'react-use'],
},
},
define: {
'process.env.NODE_ENV': JSON.stringify(mode),
},
};
});

View File

@ -1,38 +0,0 @@
const path = require('path');
const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default;
const styledComponentsTransformer = createStyledComponentsTransformer();
/** @type { import('webpack').Configuration } */
module.exports = {
entry: { index: './src/index.ts' },
target: 'web',
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js',
sourceMapFilename: '[name].js.map',
library: 'insomniaComponents',
libraryTarget: 'commonjs2',
},
optimization: {
// Disable minification for now, otherwise smoke tests fail
// Note, minification is disabled in insomnia-app as well
minimize: false,
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: [/node_modules/],
options: {
configFile: 'tsconfig.build.json',
getCustomTransformers: () => ({ before: [styledComponentsTransformer] }),
},
},
],
},
resolve: {
extensions: ['.js', '.json', '.ts', '.tsx'],
},
externals: ['react', 'react-dom', 'styled-components', 'react-use'],
};

View File

@ -1,8 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
/** @type { import('webpack').Configuration } */
module.exports = merge(common, ({
mode: 'development',
devtool: 'inline-source-map',
}));

View File

@ -1,8 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
/** @type { import('webpack').Configuration } */
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
});

View File

@ -2,6 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"module": "CommonJS",
"outDir": "dist",
"rootDir": "src",
"resolveJsonModule": true
@ -12,4 +13,4 @@
"exclude": [
"**/*.test.ts"
]
}
}

View File

@ -32,7 +32,6 @@
"prebuild:production": "npm run clean",
"build:production": "webpack --config webpack/webpack.config.production.js --display errors-only",
"start": "npm run build -- --watch",
"prepare": "npm run build:production",
"prepackage": "npm run build:production",
"package": "ts-node src/scripts/pkg.ts",
"pkg": "pkg .",

View File

@ -3,6 +3,7 @@
"compilerOptions": {
"composite": true,
"outDir": "dist",
"module": "CommonJS",
"rootDir": "src",
"resolveJsonModule": true
},
@ -12,4 +13,4 @@
"exclude": [
"**/*.test.ts"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
"clean": "tsc --build tsconfig.build.json --clean",
"postclean": "rimraf dist",
"test": "jest",
"build": "webpack --config webpack.config.js --display errors-only",
"build": "tsc --build tsconfig.build.json",
"watch": "npm run build -- --watch",
"prepublish": "npm run build"
},
@ -29,10 +29,7 @@
"@types/chai": "^4.2.15",
"@types/mkdirp": "^1.0.1",
"@types/mocha": "^8.2.1",
"@types/webpack": "^4.41.26",
"ts-loader": "^8.2.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
"typescript": "^4.5.5"
},
"dependencies": {
"chai": "^4.3.4",

View File

@ -13,4 +13,4 @@
"**/test-helpers",
"**/*.test.ts"
]
}
}

View File

@ -6,8 +6,7 @@
"include": [
"src",
".eslintrc.js",
"jest.config.js",
"webpack.config.js"
"jest.config.js"
],
"exclude": [
"dist"

View File

@ -1,35 +0,0 @@
const path = require('path');
/** @type { import('webpack').Configuration } */
module.exports = {
entry: { index: './src/index.ts' },
target: 'node',
mode: 'production',
devtool: 'source-map',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: 'insomniatesting',
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: [/node_modules/],
options: {
configFile: 'tsconfig.build.json',
},
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
externals: [
// Don't bundle Mocha because it needs to use require() to load tests.
// If it's bundled in the Webpack build, it will try to use Webpack's require() function and fail to import the test file because it lives outside the bundle.
'mocha',
],
};

View File

@ -4,6 +4,7 @@
"composite": true,
"outDir": "dist",
"rootDir": "src",
"module": "CommonJS",
"resolveJsonModule": true
},
"include": [
@ -12,4 +13,4 @@
"exclude": [
"**/*.test.ts"
]
}
}

View File

@ -2,6 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"module": "CommonJS",
"outDir": "dist",
"rootDir": "src",
"resolveJsonModule": true
@ -12,4 +13,4 @@
"exclude": [
"**/*.test.ts"
]
}
}