mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 01:28:35 +02:00
Curl import (#24)
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
"build:plugin:importer-insomnia": "cd plugins/importer-insomnia && vite build --emptyOutDir",
|
"build:plugin:importer-insomnia": "cd plugins/importer-insomnia && vite build --emptyOutDir",
|
||||||
"build:plugin:importer-postman": "cd plugins/importer-postman && vite build --emptyOutDir",
|
"build:plugin:importer-postman": "cd plugins/importer-postman && vite build --emptyOutDir",
|
||||||
"build:plugin:importer-yaak": "cd plugins/importer-yaak && vite build --emptyOutDir",
|
"build:plugin:importer-yaak": "cd plugins/importer-yaak && vite build --emptyOutDir",
|
||||||
|
"build:plugin:importer-curl": "cd plugins/importer-curl && vite build --emptyOutDir",
|
||||||
"build:plugin:filter-jsonpath": "cd plugins/filter-jsonpath && vite build --emptyOutDir",
|
"build:plugin:filter-jsonpath": "cd plugins/filter-jsonpath && vite build --emptyOutDir",
|
||||||
"build:plugin:filter-xpath": "cd plugins/filter-xpath && vite build --emptyOutDir",
|
"build:plugin:filter-xpath": "cd plugins/filter-xpath && vite build --emptyOutDir",
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
|
|||||||
243
plugins/importer-curl/package-lock.json
generated
Normal file
243
plugins/importer-curl/package-lock.json
generated
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
{
|
||||||
|
"name": "importer-curl",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "importer-curl",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"shell-quote": "^1.8.1",
|
||||||
|
"url": "^0.11.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
|
"random-seedable": "^1.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/shell-quote": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/shell-quote/-/shell-quote-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/call-bind": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"set-function-length": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-data-property": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"has-proto": "^1.0.1",
|
||||||
|
"has-symbols": "^1.0.3",
|
||||||
|
"hasown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.1.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-property-descriptors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-proto": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object-inspect": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/punycode": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
|
||||||
|
},
|
||||||
|
"node_modules/qs": {
|
||||||
|
"version": "6.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
|
||||||
|
"integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"side-channel": "^1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/random-seedable": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/random-seedable/-/random-seedable-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-f6gzvNhAnZBht1Prn0e/tpukUNhkANntFF42uIdWDPriyEATYaRpyH8A9bYaGecUB3AL+dXeYtBUggy18fe3rw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/set-function-length": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||||
|
"dependencies": {
|
||||||
|
"define-data-property": "^1.1.4",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"gopd": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shell-quote": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"object-inspect": "^1.13.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/url": {
|
||||||
|
"version": "0.11.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz",
|
||||||
|
"integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "^1.4.1",
|
||||||
|
"qs": "^6.11.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
plugins/importer-curl/package.json
Normal file
12
plugins/importer-curl/package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "importer-curl",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"dependencies": {
|
||||||
|
"shell-quote": "^1.8.1",
|
||||||
|
"url": "^0.11.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
|
"random-seedable": "^1.0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
405
plugins/importer-curl/src/index.ts
Normal file
405
plugins/importer-curl/src/index.ts
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
import { ControlOperator, parse, ParseEntry } from 'shell-quote';
|
||||||
|
import {
|
||||||
|
Environment,
|
||||||
|
Folder,
|
||||||
|
HttpRequest,
|
||||||
|
HttpUrlParameter,
|
||||||
|
Model,
|
||||||
|
Workspace,
|
||||||
|
} from '../../../src-web/lib/models';
|
||||||
|
|
||||||
|
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||||
|
|
||||||
|
interface ExportResources {
|
||||||
|
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
|
||||||
|
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const id = 'curl';
|
||||||
|
export const name = 'cURL';
|
||||||
|
export const description = 'cURL command line tool';
|
||||||
|
|
||||||
|
const DATA_FLAGS = ['d', 'data', 'data-raw', 'data-urlencode', 'data-binary', 'data-ascii'];
|
||||||
|
const SUPPORTED_ARGS = [
|
||||||
|
['url'], // Specify the URL explicitly
|
||||||
|
['user', 'u'], // Authentication
|
||||||
|
['digest'], // Apply auth as digest
|
||||||
|
['header', 'H'],
|
||||||
|
['cookie', 'b'],
|
||||||
|
['get', 'G'], // Put the post data in the URL
|
||||||
|
['d', 'data'], // Add url encoded data
|
||||||
|
['data-raw'],
|
||||||
|
['data-urlencode'],
|
||||||
|
['data-binary'],
|
||||||
|
['data-ascii'],
|
||||||
|
['form', 'F'], // Add multipart data
|
||||||
|
['request', 'X'], // Request method
|
||||||
|
DATA_FLAGS,
|
||||||
|
].flatMap((v) => v);
|
||||||
|
|
||||||
|
type Pair = string | boolean;
|
||||||
|
|
||||||
|
type PairsByName = Record<string, Pair[]>;
|
||||||
|
|
||||||
|
export const pluginHookImport = (rawData: string) => {
|
||||||
|
if (!rawData.match(/^\s*curl /)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commands: ParseEntry[][] = [];
|
||||||
|
|
||||||
|
// Replace non-escaped newlines with semicolons to make parsing easier
|
||||||
|
// NOTE: This is really slow in debug build but fast in release mode
|
||||||
|
const normalizedData = rawData.replace(/([^\\])\n/g, '$1; ');
|
||||||
|
|
||||||
|
let currentCommand: ParseEntry[] = [];
|
||||||
|
|
||||||
|
const parsed = parse(normalizedData);
|
||||||
|
|
||||||
|
// Break up `-XPOST` into `-X POST`
|
||||||
|
const normalizedParseEntries = parsed.flatMap((entry) => {
|
||||||
|
if (
|
||||||
|
typeof entry === 'string' &&
|
||||||
|
entry.startsWith('-') &&
|
||||||
|
!entry.startsWith('--') &&
|
||||||
|
entry.length > 2
|
||||||
|
) {
|
||||||
|
return [entry.slice(0, 2), entry.slice(2)];
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const parseEntry of normalizedParseEntries) {
|
||||||
|
if (typeof parseEntry === 'string') {
|
||||||
|
if (parseEntry.startsWith('$')) {
|
||||||
|
currentCommand.push(parseEntry.slice(1));
|
||||||
|
} else {
|
||||||
|
currentCommand.push(parseEntry);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('comment' in parseEntry) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { op } = parseEntry as { op: 'glob'; pattern: string } | { op: ControlOperator };
|
||||||
|
|
||||||
|
// `;` separates commands
|
||||||
|
if (op === ';') {
|
||||||
|
commands.push(currentCommand);
|
||||||
|
currentCommand = [];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op?.startsWith('$')) {
|
||||||
|
// Handle the case where literal like -H $'Header: \'Some Quoted Thing\''
|
||||||
|
const str = op.slice(2, op.length - 1).replace(/\\'/g, "'");
|
||||||
|
|
||||||
|
currentCommand.push(str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op === 'glob') {
|
||||||
|
currentCommand.push((parseEntry as { op: 'glob'; pattern: string }).pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.push(currentCommand);
|
||||||
|
|
||||||
|
const workspace: ExportResources['workspaces'][0] = {
|
||||||
|
model: 'workspace',
|
||||||
|
id: generateId('workspace'),
|
||||||
|
name: 'Curl Import',
|
||||||
|
};
|
||||||
|
|
||||||
|
const requests: ExportResources['httpRequests'] = commands
|
||||||
|
.filter((command) => command[0] === 'curl')
|
||||||
|
.map((v) => importCommand(v, workspace.id));
|
||||||
|
|
||||||
|
return {
|
||||||
|
resources: {
|
||||||
|
httpRequests: requests,
|
||||||
|
workspaces: [workspace],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function importCommand(parseEntries: ParseEntry[], workspaceId: string) {
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~ //
|
||||||
|
// Collect all the flags //
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~ //
|
||||||
|
const pairsByName: PairsByName = {};
|
||||||
|
const singletons: ParseEntry[] = [];
|
||||||
|
|
||||||
|
// Start at 1 so we can skip the ^curl part
|
||||||
|
for (let i = 1; i < parseEntries.length; i++) {
|
||||||
|
let parseEntry = parseEntries[i];
|
||||||
|
// trim leading spaces between parsed entries
|
||||||
|
// regex won't match otherwise (e.g. -H 'Content-Type: application/json')
|
||||||
|
if (typeof parseEntry === 'string') {
|
||||||
|
parseEntry = parseEntry.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof parseEntry === 'string' && parseEntry.match(/^-{1,2}[\w-]+/)) {
|
||||||
|
const isSingleDash = parseEntry[0] === '-' && parseEntry[1] !== '-';
|
||||||
|
let name = parseEntry.replace(/^-{1,2}/, '');
|
||||||
|
|
||||||
|
if (!SUPPORTED_ARGS.includes(name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let value;
|
||||||
|
const nextEntry = parseEntries[i + 1];
|
||||||
|
if (isSingleDash && name.length > 1) {
|
||||||
|
// Handle squished arguments like -XPOST
|
||||||
|
value = name.slice(1);
|
||||||
|
name = name.slice(0, 1);
|
||||||
|
} else if (typeof nextEntry === 'string' && !nextEntry.startsWith('-')) {
|
||||||
|
// Next arg is not a flag, so assign it as the value
|
||||||
|
value = nextEntry;
|
||||||
|
i++; // Skip next one
|
||||||
|
} else {
|
||||||
|
value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pairsByName[name] = pairsByName[name] || [];
|
||||||
|
pairsByName[name]!.push(value);
|
||||||
|
} else if (parseEntry) {
|
||||||
|
singletons.push(parseEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~ //
|
||||||
|
// Build the request //
|
||||||
|
// ~~~~~~~~~~~~~~~~~ //
|
||||||
|
|
||||||
|
// Url & parameters
|
||||||
|
|
||||||
|
let urlParameters: HttpUrlParameter[];
|
||||||
|
let url: string;
|
||||||
|
|
||||||
|
const urlArg = getPairValue(pairsByName, (singletons[0] as string) || '', ['url']);
|
||||||
|
const [baseUrl, search] = splitOnce(urlArg, '?');
|
||||||
|
urlParameters =
|
||||||
|
search?.split('&').map((p) => {
|
||||||
|
const v = splitOnce(p, '=');
|
||||||
|
return { name: v[0] ?? '', value: v[1] ?? '' };
|
||||||
|
}) ?? [];
|
||||||
|
|
||||||
|
url = baseUrl ?? urlArg;
|
||||||
|
|
||||||
|
// Authentication
|
||||||
|
const [username, password] = getPairValue(pairsByName, '', ['u', 'user']).split(/:(.*)$/);
|
||||||
|
|
||||||
|
const isDigest = getPairValue(pairsByName, false, ['digest']);
|
||||||
|
const authenticationType = username ? (isDigest ? 'digest' : 'basic') : null;
|
||||||
|
const authentication = username
|
||||||
|
? {
|
||||||
|
username: username.trim(),
|
||||||
|
password: (password ?? '').trim(),
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
const headers = [
|
||||||
|
...((pairsByName.header as string[] | undefined) || []),
|
||||||
|
...((pairsByName.H as string[] | undefined) || []),
|
||||||
|
].map((header) => {
|
||||||
|
const [name, value] = header.split(/:(.*)$/);
|
||||||
|
// remove final colon from header name if present
|
||||||
|
if (!value) {
|
||||||
|
return {
|
||||||
|
name: (name ?? '').trim().replace(/;$/, ''),
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: (name ?? '').trim(),
|
||||||
|
value: value.trim(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cookies
|
||||||
|
const cookieHeaderValue = [
|
||||||
|
...((pairsByName.cookie as string[] | undefined) || []),
|
||||||
|
...((pairsByName.b as string[] | undefined) || []),
|
||||||
|
]
|
||||||
|
.map((str) => {
|
||||||
|
const name = str.split('=', 1)[0];
|
||||||
|
const value = str.replace(`${name}=`, '');
|
||||||
|
return `${name}=${value}`;
|
||||||
|
})
|
||||||
|
.join('; ');
|
||||||
|
|
||||||
|
// Convert cookie value to header
|
||||||
|
const existingCookieHeader = headers.find((header) => header.name.toLowerCase() === 'cookie');
|
||||||
|
|
||||||
|
if (cookieHeaderValue && existingCookieHeader) {
|
||||||
|
// Has existing cookie header, so let's update it
|
||||||
|
existingCookieHeader.value += `; ${cookieHeaderValue}`;
|
||||||
|
} else if (cookieHeaderValue) {
|
||||||
|
// No existing cookie header, so let's make a new one
|
||||||
|
headers.push({
|
||||||
|
name: 'Cookie',
|
||||||
|
value: cookieHeaderValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
///Body (Text or Blob)
|
||||||
|
const dataParameters = pairsToDataParameters(pairsByName);
|
||||||
|
const contentTypeHeader = headers.find((header) => header.name.toLowerCase() === 'content-type');
|
||||||
|
const mimeType = contentTypeHeader ? contentTypeHeader.value.split(';')[0] : null;
|
||||||
|
|
||||||
|
// Body (Multipart Form Data)
|
||||||
|
const formDataParams = [
|
||||||
|
...((pairsByName.form as string[] | undefined) || []),
|
||||||
|
...((pairsByName.F as string[] | undefined) || []),
|
||||||
|
].map((str) => {
|
||||||
|
const parts = str.split('=');
|
||||||
|
const name = parts[0] ?? '';
|
||||||
|
const value = parts[1] ?? '';
|
||||||
|
const item: { name: string; value?: string; file?: string; enabled: boolean } = {
|
||||||
|
name,
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (value.indexOf('@') === 0) {
|
||||||
|
item.file = value.slice(1);
|
||||||
|
} else {
|
||||||
|
item.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Body
|
||||||
|
let body = {};
|
||||||
|
let bodyType: string | null = null;
|
||||||
|
const bodyAsGET = getPairValue(pairsByName, false, ['G', 'get']);
|
||||||
|
|
||||||
|
if (dataParameters.length > 0 && bodyAsGET) {
|
||||||
|
urlParameters.push(...dataParameters);
|
||||||
|
} else if (
|
||||||
|
dataParameters.length > 0 &&
|
||||||
|
(mimeType == null || mimeType === 'application/x-www-form-urlencoded')
|
||||||
|
) {
|
||||||
|
bodyType = mimeType ?? 'application/x-www-form-urlencoded';
|
||||||
|
body = {
|
||||||
|
params: dataParameters.map((parameter) => ({
|
||||||
|
...parameter,
|
||||||
|
name: decodeURIComponent(parameter.name || ''),
|
||||||
|
value: decodeURIComponent(parameter.value || ''),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
} else if (dataParameters.length > 0) {
|
||||||
|
bodyType =
|
||||||
|
mimeType === 'application/json' || mimeType === 'text/xml' || mimeType === 'text/plain'
|
||||||
|
? mimeType
|
||||||
|
: 'other';
|
||||||
|
body = {
|
||||||
|
text: dataParameters
|
||||||
|
.map(({ name, value }) => (name && value ? `${name}=${value}` : name || value))
|
||||||
|
.join('&'),
|
||||||
|
};
|
||||||
|
} else if (formDataParams.length) {
|
||||||
|
bodyType = mimeType ?? 'multipart/form-data';
|
||||||
|
body = {
|
||||||
|
form: formDataParams,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method
|
||||||
|
let method = getPairValue(pairsByName, '', ['X', 'request']).toUpperCase();
|
||||||
|
|
||||||
|
if (method === '' && body) {
|
||||||
|
method = 'text' in body || 'params' in body ? 'POST' : 'GET';
|
||||||
|
}
|
||||||
|
|
||||||
|
const request: ExportResources['httpRequests'][0] = {
|
||||||
|
id: generateId('http_request'),
|
||||||
|
model: 'http_request',
|
||||||
|
workspaceId,
|
||||||
|
name: '',
|
||||||
|
urlParameters,
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
authentication,
|
||||||
|
authenticationType,
|
||||||
|
body,
|
||||||
|
bodyType,
|
||||||
|
folderId: null,
|
||||||
|
sortPriority: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pairsToDataParameters = (keyedPairs: PairsByName) => {
|
||||||
|
let dataParameters: {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
contentType?: string;
|
||||||
|
filePath?: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
for (const flagName of DATA_FLAGS) {
|
||||||
|
const pairs = keyedPairs[flagName];
|
||||||
|
|
||||||
|
if (!pairs || pairs.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const p of pairs) {
|
||||||
|
if (typeof p !== 'string') continue;
|
||||||
|
|
||||||
|
const [name, value] = p.split('=');
|
||||||
|
if (p.startsWith('@')) {
|
||||||
|
// Yaak doesn't support files in url-encoded data, so
|
||||||
|
dataParameters.push({
|
||||||
|
name: name ?? '',
|
||||||
|
value: '',
|
||||||
|
filePath: p.slice(1),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dataParameters.push({
|
||||||
|
name: name ?? '',
|
||||||
|
value: flagName === 'data-urlencode' ? encodeURIComponent(value ?? '') : value ?? '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataParameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPairValue = <T extends string | boolean>(
|
||||||
|
pairsByName: PairsByName,
|
||||||
|
defaultValue: T,
|
||||||
|
names: string[],
|
||||||
|
) => {
|
||||||
|
for (const name of names) {
|
||||||
|
if (pairsByName[name] && pairsByName[name]!.length) {
|
||||||
|
return pairsByName[name]![0] as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
function splitOnce(str: string, sep: string): string[] {
|
||||||
|
const index = str.indexOf(sep);
|
||||||
|
if (index > -1) {
|
||||||
|
return [str.slice(0, index), str.slice(index + 1)];
|
||||||
|
}
|
||||||
|
return [str];
|
||||||
|
}
|
||||||
|
|
||||||
|
const idCount: Partial<Record<Model['model'], number>> = {};
|
||||||
|
function generateId(model: Model['model']): string {
|
||||||
|
idCount[model] = (idCount[model] ?? -1) + 1;
|
||||||
|
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
|
||||||
|
}
|
||||||
314
plugins/importer-curl/tests/index.test.ts
Normal file
314
plugins/importer-curl/tests/index.test.ts
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
import { HttpRequest, Model, Workspace } from '../../../src-web/lib/models';
|
||||||
|
import { pluginHookImport } from '../src';
|
||||||
|
import { XORShift } from 'random-seedable';
|
||||||
|
|
||||||
|
let originalRandom = Math.random;
|
||||||
|
|
||||||
|
describe('importer-curl', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const rand = new XORShift(123456789);
|
||||||
|
Math.random = vi.fn(() => {
|
||||||
|
return rand.float();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Math.random = originalRandom;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports basic GET', () => {
|
||||||
|
expect(pluginHookImport('curl https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Explicit URL', () => {
|
||||||
|
expect(pluginHookImport('curl --url https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Missing URL', () => {
|
||||||
|
expect(pluginHookImport('curl -X POST')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
method: 'POST',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('URL between', () => {
|
||||||
|
expect(pluginHookImport('curl -v https://yaak.app -X POST')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: 'POST',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Random flags', () => {
|
||||||
|
expect(pluginHookImport('curl --random -Z -Y -S --foo https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports --request method', () => {
|
||||||
|
expect(pluginHookImport('curl --request POST https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: 'POST',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports -XPOST method', () => {
|
||||||
|
expect(pluginHookImport('curl -XPOST --request POST https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: 'POST',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports multiple requests', () => {
|
||||||
|
expect(
|
||||||
|
pluginHookImport('curl \\\n https://yaak.app\necho "foo"\ncurl example.com;curl foo.com'),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({ url: 'https://yaak.app' }),
|
||||||
|
baseRequest({ url: 'example.com' }),
|
||||||
|
baseRequest({ url: 'foo.com' }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports form data', () => {
|
||||||
|
expect(
|
||||||
|
pluginHookImport('curl -X POST -F "a=aaa" -F b=bbb" -F f=@filepath https://yaak.app'),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
bodyType: 'multipart/form-data',
|
||||||
|
body: {
|
||||||
|
form: [
|
||||||
|
{ enabled: true, name: 'a', value: 'aaa' },
|
||||||
|
{ enabled: true, name: 'b', value: 'bbb' },
|
||||||
|
{ enabled: true, name: 'f', file: 'filepath' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports data params as form url-encoded', () => {
|
||||||
|
expect(pluginHookImport('curl -d a -d b -d c=ccc https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
bodyType: 'application/x-www-form-urlencoded',
|
||||||
|
body: {
|
||||||
|
params: [
|
||||||
|
{ name: 'a', value: '' },
|
||||||
|
{ name: 'b', value: '' },
|
||||||
|
{ name: 'c', value: 'ccc' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports data params as text', () => {
|
||||||
|
expect(
|
||||||
|
pluginHookImport('curl -H Content-Type:text/plain -d a -d b -d c=ccc https://yaak.app'),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
headers: [{ name: 'Content-Type', value: 'text/plain' }],
|
||||||
|
bodyType: 'text/plain',
|
||||||
|
body: { text: 'a&b&c=ccc' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports multiple headers', () => {
|
||||||
|
expect(
|
||||||
|
pluginHookImport('curl -H Foo:bar --header Name -H AAA:bbb -H :ccc https://yaak.app'),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
headers: [
|
||||||
|
{ name: 'Name', value: '' },
|
||||||
|
{ name: 'Foo', value: 'bar' },
|
||||||
|
{ name: 'AAA', value: 'bbb' },
|
||||||
|
{ name: '', value: 'ccc' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports basic auth', () => {
|
||||||
|
expect(pluginHookImport('curl --user user:pass https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
authenticationType: 'basic',
|
||||||
|
authentication: {
|
||||||
|
username: 'user',
|
||||||
|
password: 'pass',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports digest auth', () => {
|
||||||
|
expect(pluginHookImport('curl --digest --user user:pass https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
authenticationType: 'digest',
|
||||||
|
authentication: {
|
||||||
|
username: 'user',
|
||||||
|
password: 'pass',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports cookie as header', () => {
|
||||||
|
expect(pluginHookImport('curl --cookie "foo=bar" https://yaak.app')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
headers: [{ name: 'Cookie', value: 'foo=bar' }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports query params from the URL', () => {
|
||||||
|
expect(pluginHookImport('curl "https://yaak.app?foo=bar&baz=a%20a"')).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
urlParameters: [
|
||||||
|
{ name: 'foo', value: 'bar' },
|
||||||
|
{ name: 'baz', value: 'a%20a' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const idCount: Partial<Record<Model['model'], number>> = {};
|
||||||
|
|
||||||
|
function baseRequest(mergeWith: Partial<HttpRequest>) {
|
||||||
|
idCount.http_request = (idCount.http_request ?? -1) + 1;
|
||||||
|
return {
|
||||||
|
id: `GENERATE_ID::HTTP_REQUEST_${idCount.http_request}`,
|
||||||
|
model: 'http_request',
|
||||||
|
authentication: {},
|
||||||
|
authenticationType: null,
|
||||||
|
body: {},
|
||||||
|
bodyType: null,
|
||||||
|
folderId: null,
|
||||||
|
headers: [],
|
||||||
|
method: 'GET',
|
||||||
|
name: '',
|
||||||
|
sortPriority: 0,
|
||||||
|
url: '',
|
||||||
|
urlParameters: [],
|
||||||
|
workspaceId: `GENERATE_ID::WORKSPACE_${idCount.workspace}`,
|
||||||
|
...mergeWith,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function baseWorkspace(mergeWith: Partial<Workspace> = {}) {
|
||||||
|
idCount.workspace = (idCount.workspace ?? -1) + 1;
|
||||||
|
return {
|
||||||
|
id: `GENERATE_ID::WORKSPACE_${idCount.workspace}`,
|
||||||
|
model: 'workspace',
|
||||||
|
name: 'Curl Import',
|
||||||
|
...mergeWith,
|
||||||
|
};
|
||||||
|
}
|
||||||
13
plugins/importer-curl/vite.config.js
Normal file
13
plugins/importer-curl/vite.config.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { resolve } from 'path';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'src/index.ts'),
|
||||||
|
fileName: 'index',
|
||||||
|
formats: ['es'],
|
||||||
|
},
|
||||||
|
outDir: resolve(__dirname, '../../src-tauri/plugins/importer-curl'),
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
export function isWorkspace(obj) {
|
|
||||||
return isJSObject(obj) && obj._type === 'workspace';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isRequestGroup(obj) {
|
|
||||||
return isJSObject(obj) && obj._type === 'request_group';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isHttpRequest(obj) {
|
|
||||||
return isJSObject(obj) && obj._type === 'request';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isGrpcRequest(obj) {
|
|
||||||
return isJSObject(obj) && obj._type === 'grpc_request';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isEnvironment(obj) {
|
|
||||||
return isJSObject(obj) && obj._type === 'environment';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isJSObject(obj) {
|
|
||||||
return Object.prototype.toString.call(obj) === '[object Object]';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isJSString(obj) {
|
|
||||||
return Object.prototype.toString.call(obj) === '[object String]';
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { isJSString } from './types.js';
|
|
||||||
|
|
||||||
export function parseVariables(data) {
|
|
||||||
return Object.entries(data).map(([name, value]) => ({
|
|
||||||
enabled: true,
|
|
||||||
name,
|
|
||||||
value: `${value}`,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Insomnia syntax to Yaak syntax
|
|
||||||
* @param {string} variable - Text to convert
|
|
||||||
*/
|
|
||||||
export function convertSyntax(variable) {
|
|
||||||
if (!isJSString(variable)) return variable;
|
|
||||||
return variable.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}');
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* Import an Insomnia environment object.
|
|
||||||
* @param {Object} e - The environment object to import.
|
|
||||||
* @param workspaceId - Workspace to import into.
|
|
||||||
*/
|
|
||||||
export function importEnvironment(e, workspaceId) {
|
|
||||||
console.log('IMPORTING Environment', e._id, e.name, JSON.stringify(e, null, 2));
|
|
||||||
return {
|
|
||||||
id: e._id,
|
|
||||||
createdAt: new Date(e.created ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
workspaceId,
|
|
||||||
model: 'environment',
|
|
||||||
name: e.name,
|
|
||||||
variables: Object.entries(e.data).map(([name, value]) => ({
|
|
||||||
enabled: true,
|
|
||||||
name,
|
|
||||||
value: `${value}`,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/**
|
|
||||||
* Import an Insomnia folder object.
|
|
||||||
* @param {Object} f - The environment object to import.
|
|
||||||
* @param workspaceId - Workspace to import into.
|
|
||||||
*/
|
|
||||||
export function importFolder(f, workspaceId) {
|
|
||||||
console.log('IMPORTING FOLDER', f._id, f.name, JSON.stringify(f, null, 2));
|
|
||||||
return {
|
|
||||||
id: f._id,
|
|
||||||
createdAt: new Date(f.created ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
updatedAt: new Date(f.updated ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
folderId: f.parentId === workspaceId ? null : f.parentId,
|
|
||||||
workspaceId,
|
|
||||||
model: 'folder',
|
|
||||||
name: f.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { convertSyntax } from '../helpers/variables.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Import an Insomnia GRPC request object.
|
|
||||||
* @param {Object} r - The request object to import.
|
|
||||||
* @param workspaceId - The workspace ID to use for the request.
|
|
||||||
* @param {number} sortPriority - The sort priority to use for the request.
|
|
||||||
*/
|
|
||||||
export function importGrpcRequest(r, workspaceId, sortPriority = 0) {
|
|
||||||
console.log('IMPORTING GRPC REQUEST', r._id, r.name, JSON.stringify(r, null, 2));
|
|
||||||
|
|
||||||
const parts = r.protoMethodName.split('/').filter((p) => p !== '');
|
|
||||||
const service = parts[0] ?? null;
|
|
||||||
const method = parts[1] ?? null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: r._id,
|
|
||||||
createdAt: new Date(r.created ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
updatedAt: new Date(r.updated ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
workspaceId,
|
|
||||||
folderId: r.parentId === workspaceId ? null : r.parentId,
|
|
||||||
model: 'grpc_request',
|
|
||||||
sortPriority,
|
|
||||||
name: r.name,
|
|
||||||
url: convertSyntax(r.url),
|
|
||||||
service,
|
|
||||||
method,
|
|
||||||
message: r.body?.text ?? '',
|
|
||||||
metadata: (r.metadata ?? [])
|
|
||||||
.map(({ name, value, disabled }) => ({
|
|
||||||
enabled: !disabled,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
}))
|
|
||||||
.filter(({ name, value }) => name !== '' || value !== ''),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import { convertSyntax } from '../helpers/variables.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Import an Insomnia request object.
|
|
||||||
* @param {Object} r - The request object to import.
|
|
||||||
* @param workspaceId - The workspace ID to use for the request.
|
|
||||||
* @param {number} sortPriority - The sort priority to use for the request.
|
|
||||||
*/
|
|
||||||
export function importHttpRequest(r, workspaceId, sortPriority = 0) {
|
|
||||||
console.log('IMPORTING REQUEST', r._id, r.name, JSON.stringify(r, null, 2));
|
|
||||||
|
|
||||||
let bodyType = null;
|
|
||||||
let body = null;
|
|
||||||
if (r.body?.mimeType === 'application/graphql') {
|
|
||||||
bodyType = 'graphql';
|
|
||||||
body = convertSyntax(r.body.text);
|
|
||||||
} else if (r.body?.mimeType === 'application/json') {
|
|
||||||
bodyType = 'application/json';
|
|
||||||
body = convertSyntax(r.body.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
let authenticationType = null;
|
|
||||||
let authentication = {};
|
|
||||||
if (r.authentication.type === 'bearer') {
|
|
||||||
authenticationType = 'bearer';
|
|
||||||
authentication = {
|
|
||||||
token: convertSyntax(r.authentication.token),
|
|
||||||
};
|
|
||||||
} else if (r.authentication.type === 'basic') {
|
|
||||||
authenticationType = 'basic';
|
|
||||||
authentication = {
|
|
||||||
username: convertSyntax(r.authentication.username),
|
|
||||||
password: convertSyntax(r.authentication.password),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: r._id,
|
|
||||||
createdAt: new Date(r.created ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
updatedAt: new Date(r.updated ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
workspaceId,
|
|
||||||
folderId: r.parentId === workspaceId ? null : r.parentId,
|
|
||||||
model: 'http_request',
|
|
||||||
sortPriority,
|
|
||||||
name: r.name,
|
|
||||||
url: convertSyntax(r.url),
|
|
||||||
body,
|
|
||||||
bodyType,
|
|
||||||
authentication,
|
|
||||||
authenticationType,
|
|
||||||
method: r.method,
|
|
||||||
headers: (r.headers ?? [])
|
|
||||||
.map(({ name, value, disabled }) => ({
|
|
||||||
enabled: !disabled,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
}))
|
|
||||||
.filter(({ name, value }) => name !== '' || value !== ''),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import { importEnvironment } from './importers/environment';
|
|
||||||
import { importHttpRequest } from './importers/httpRequest';
|
|
||||||
import {
|
|
||||||
isEnvironment,
|
|
||||||
isJSObject,
|
|
||||||
isHttpRequest,
|
|
||||||
isRequestGroup,
|
|
||||||
isWorkspace,
|
|
||||||
isGrpcRequest,
|
|
||||||
} from './helpers/types.js';
|
|
||||||
import { parseVariables } from './helpers/variables.js';
|
|
||||||
import { importFolder } from './importers/folder.js';
|
|
||||||
import { importGrpcRequest } from './importers/grpcRequest';
|
|
||||||
|
|
||||||
export function pluginHookImport(contents) {
|
|
||||||
let parsed;
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(contents);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isJSObject(parsed)) return;
|
|
||||||
if (!Array.isArray(parsed.resources)) return;
|
|
||||||
|
|
||||||
const resources = {
|
|
||||||
workspaces: [],
|
|
||||||
httpRequests: [],
|
|
||||||
grpcRequests: [],
|
|
||||||
environments: [],
|
|
||||||
folders: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Import workspaces
|
|
||||||
const workspacesToImport = parsed.resources.filter(isWorkspace);
|
|
||||||
for (const workspaceToImport of workspacesToImport) {
|
|
||||||
const baseEnvironment = parsed.resources.find(
|
|
||||||
(r) => isEnvironment(r) && r.parentId === workspaceToImport._id,
|
|
||||||
);
|
|
||||||
resources.workspaces.push({
|
|
||||||
id: workspaceToImport._id,
|
|
||||||
createdAt: new Date(workspacesToImport.created ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
updatedAt: new Date(workspacesToImport.updated ?? Date.now()).toISOString().replace('Z', ''),
|
|
||||||
model: 'workspace',
|
|
||||||
name: workspaceToImport.name,
|
|
||||||
variables: baseEnvironment ? parseVariables(baseEnvironment.data) : [],
|
|
||||||
});
|
|
||||||
const environmentsToImport = parsed.resources.filter(
|
|
||||||
(r) => isEnvironment(r) && r.parentId === baseEnvironment?._id,
|
|
||||||
);
|
|
||||||
resources.environments.push(
|
|
||||||
...environmentsToImport.map((r) => importEnvironment(r, workspaceToImport._id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
const nextFolder = (parentId) => {
|
|
||||||
const children = parsed.resources.filter((r) => r.parentId === parentId);
|
|
||||||
let sortPriority = 0;
|
|
||||||
for (const child of children) {
|
|
||||||
if (isRequestGroup(child)) {
|
|
||||||
resources.folders.push(importFolder(child, workspaceToImport._id));
|
|
||||||
nextFolder(child._id);
|
|
||||||
} else if (isHttpRequest(child)) {
|
|
||||||
resources.httpRequests.push(
|
|
||||||
importHttpRequest(child, workspaceToImport._id, sortPriority++),
|
|
||||||
);
|
|
||||||
} else if (isGrpcRequest(child)) {
|
|
||||||
console.log('GRPC', JSON.stringify(child, null, 1));
|
|
||||||
resources.grpcRequests.push(
|
|
||||||
importGrpcRequest(child, workspaceToImport._id, sortPriority++),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Import folders
|
|
||||||
nextFolder(workspaceToImport._id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out any `null` values
|
|
||||||
resources.httpRequests = resources.httpRequests.filter(Boolean);
|
|
||||||
resources.grpcRequests = resources.grpcRequests.filter(Boolean);
|
|
||||||
resources.environments = resources.environments.filter(Boolean);
|
|
||||||
resources.workspaces = resources.workspaces.filter(Boolean);
|
|
||||||
|
|
||||||
return { resources };
|
|
||||||
}
|
|
||||||
274
plugins/importer-insomnia/src/index.ts
Normal file
274
plugins/importer-insomnia/src/index.ts
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
import {
|
||||||
|
Environment,
|
||||||
|
Folder,
|
||||||
|
GrpcRequest,
|
||||||
|
HttpRequest,
|
||||||
|
Workspace,
|
||||||
|
} from '../../../src-web/lib/models';
|
||||||
|
|
||||||
|
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||||
|
|
||||||
|
export interface ExportResources {
|
||||||
|
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
|
||||||
|
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
grpcRequests: AtLeast<GrpcRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pluginHookImport(contents: string) {
|
||||||
|
let parsed;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(contents);
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isJSObject(parsed)) return;
|
||||||
|
if (!Array.isArray(parsed.resources)) return;
|
||||||
|
|
||||||
|
const resources: ExportResources = {
|
||||||
|
workspaces: [],
|
||||||
|
httpRequests: [],
|
||||||
|
grpcRequests: [],
|
||||||
|
environments: [],
|
||||||
|
folders: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import workspaces
|
||||||
|
const workspacesToImport = parsed.resources.filter(isWorkspace);
|
||||||
|
for (const workspaceToImport of workspacesToImport) {
|
||||||
|
const baseEnvironment = parsed.resources.find(
|
||||||
|
(r: any) => isEnvironment(r) && r.parentId === workspaceToImport._id,
|
||||||
|
);
|
||||||
|
resources.workspaces.push({
|
||||||
|
id: convertId(workspaceToImport._id),
|
||||||
|
createdAt: new Date(workspacesToImport.created ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
updatedAt: new Date(workspacesToImport.updated ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
model: 'workspace',
|
||||||
|
name: workspaceToImport.name,
|
||||||
|
variables: baseEnvironment ? parseVariables(baseEnvironment.data) : [],
|
||||||
|
});
|
||||||
|
const environmentsToImport = parsed.resources.filter(
|
||||||
|
(r: any) => isEnvironment(r) && r.parentId === baseEnvironment?._id,
|
||||||
|
);
|
||||||
|
resources.environments.push(
|
||||||
|
...environmentsToImport.map((r: any) => importEnvironment(r, workspaceToImport._id)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const nextFolder = (parentId: string) => {
|
||||||
|
const children = parsed.resources.filter((r: any) => r.parentId === parentId);
|
||||||
|
let sortPriority = 0;
|
||||||
|
for (const child of children) {
|
||||||
|
if (isRequestGroup(child)) {
|
||||||
|
resources.folders.push(importFolder(child, workspaceToImport._id));
|
||||||
|
nextFolder(child._id);
|
||||||
|
} else if (isHttpRequest(child)) {
|
||||||
|
resources.httpRequests.push(
|
||||||
|
importHttpRequest(child, workspaceToImport._id, sortPriority++),
|
||||||
|
);
|
||||||
|
} else if (isGrpcRequest(child)) {
|
||||||
|
resources.grpcRequests.push(
|
||||||
|
importGrpcRequest(child, workspaceToImport._id, sortPriority++),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import folders
|
||||||
|
nextFolder(workspaceToImport._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out any `null` values
|
||||||
|
resources.httpRequests = resources.httpRequests.filter(Boolean);
|
||||||
|
resources.grpcRequests = resources.grpcRequests.filter(Boolean);
|
||||||
|
resources.environments = resources.environments.filter(Boolean);
|
||||||
|
resources.workspaces = resources.workspaces.filter(Boolean);
|
||||||
|
|
||||||
|
return { resources };
|
||||||
|
}
|
||||||
|
|
||||||
|
function importEnvironment(e: any, workspaceId: string): ExportResources['environments'][0] {
|
||||||
|
return {
|
||||||
|
id: convertId(e._id),
|
||||||
|
createdAt: new Date(e.created ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
workspaceId: convertId(workspaceId),
|
||||||
|
model: 'environment',
|
||||||
|
name: e.name,
|
||||||
|
variables: Object.entries(e.data).map(([name, value]) => ({
|
||||||
|
enabled: true,
|
||||||
|
name,
|
||||||
|
value: `${value}`,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function importFolder(f: any, workspaceId: string): ExportResources['folders'][0] {
|
||||||
|
return {
|
||||||
|
id: convertId(f._id),
|
||||||
|
createdAt: new Date(f.created ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
updatedAt: new Date(f.updated ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
folderId: f.parentId === workspaceId ? null : convertId(f.parentId),
|
||||||
|
workspaceId: convertId(workspaceId),
|
||||||
|
model: 'folder',
|
||||||
|
name: f.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function importGrpcRequest(
|
||||||
|
r: any,
|
||||||
|
workspaceId: string,
|
||||||
|
sortPriority = 0,
|
||||||
|
): ExportResources['grpcRequests'][0] {
|
||||||
|
const parts = r.protoMethodName.split('/').filter((p: any) => p !== '');
|
||||||
|
const service = parts[0] ?? null;
|
||||||
|
const method = parts[1] ?? null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: convertId(r._id),
|
||||||
|
createdAt: new Date(r.created ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
updatedAt: new Date(r.updated ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
workspaceId: convertId(workspaceId),
|
||||||
|
folderId: r.parentId === workspaceId ? null : convertId(r.parentId),
|
||||||
|
model: 'grpc_request',
|
||||||
|
sortPriority,
|
||||||
|
name: r.name,
|
||||||
|
url: convertSyntax(r.url),
|
||||||
|
service,
|
||||||
|
method,
|
||||||
|
message: r.body?.text ?? '',
|
||||||
|
metadata: (r.metadata ?? [])
|
||||||
|
.map((h: any) => ({
|
||||||
|
enabled: !h.disabled,
|
||||||
|
name: h.name ?? '',
|
||||||
|
value: h.value ?? '',
|
||||||
|
}))
|
||||||
|
.filter(({ name, value }: any) => name !== '' || value !== ''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function importHttpRequest(
|
||||||
|
r: any,
|
||||||
|
workspaceId: string,
|
||||||
|
sortPriority = 0,
|
||||||
|
): ExportResources['httpRequests'][0] {
|
||||||
|
let bodyType = null;
|
||||||
|
let body = {};
|
||||||
|
if (r.body.mimeType === 'application/octet-stream') {
|
||||||
|
bodyType = 'binary';
|
||||||
|
body = { filePath: r.body.fileName ?? '' };
|
||||||
|
} else if (r.body?.mimeType === 'application/x-www-form-urlencoded') {
|
||||||
|
bodyType = 'application/x-www-form-urlencoded';
|
||||||
|
body = {
|
||||||
|
form: (r.body.params ?? []).map((p: any) => ({
|
||||||
|
enabled: !p.disabled,
|
||||||
|
name: p.name ?? '',
|
||||||
|
value: p.value ?? '',
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
} else if (r.body?.mimeType === 'multipart/form-data') {
|
||||||
|
bodyType = 'multipart/form-data';
|
||||||
|
body = {
|
||||||
|
form: (r.body.params ?? []).map((p: any) => ({
|
||||||
|
enabled: !p.disabled,
|
||||||
|
name: p.name ?? '',
|
||||||
|
value: p.value ?? '',
|
||||||
|
file: p.fileName ?? null,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
} else if (r.body?.mimeType === 'application/graphql') {
|
||||||
|
bodyType = 'graphql';
|
||||||
|
body = { text: convertSyntax(r.body.text ?? '') };
|
||||||
|
} else if (r.body?.mimeType === 'application/json') {
|
||||||
|
bodyType = 'application/json';
|
||||||
|
body = { text: convertSyntax(r.body.text ?? '') };
|
||||||
|
}
|
||||||
|
|
||||||
|
let authenticationType = null;
|
||||||
|
let authentication = {};
|
||||||
|
if (r.authentication.type === 'bearer') {
|
||||||
|
authenticationType = 'bearer';
|
||||||
|
authentication = {
|
||||||
|
token: convertSyntax(r.authentication.token),
|
||||||
|
};
|
||||||
|
} else if (r.authentication.type === 'basic') {
|
||||||
|
authenticationType = 'basic';
|
||||||
|
authentication = {
|
||||||
|
username: convertSyntax(r.authentication.username),
|
||||||
|
password: convertSyntax(r.authentication.password),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: convertId(r._id),
|
||||||
|
createdAt: new Date(r.created ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
updatedAt: new Date(r.updated ?? Date.now()).toISOString().replace('Z', ''),
|
||||||
|
workspaceId: convertId(workspaceId),
|
||||||
|
folderId: r.parentId === workspaceId ? null : convertId(r.parentId),
|
||||||
|
model: 'http_request',
|
||||||
|
sortPriority,
|
||||||
|
name: r.name,
|
||||||
|
url: convertSyntax(r.url),
|
||||||
|
body,
|
||||||
|
bodyType,
|
||||||
|
authentication,
|
||||||
|
authenticationType,
|
||||||
|
method: r.method,
|
||||||
|
headers: (r.headers ?? [])
|
||||||
|
.map((h: any) => ({
|
||||||
|
enabled: !h.disabled,
|
||||||
|
name: h.name ?? '',
|
||||||
|
value: h.value ?? '',
|
||||||
|
}))
|
||||||
|
.filter(({ name, value }: any) => name !== '' || value !== ''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVariables(data: Record<string, string>) {
|
||||||
|
return Object.entries(data).map(([name, value]) => ({
|
||||||
|
enabled: true,
|
||||||
|
name,
|
||||||
|
value: `${value}`,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertSyntax(variable: string): string {
|
||||||
|
if (!isJSString(variable)) return variable;
|
||||||
|
return variable.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWorkspace(obj: any) {
|
||||||
|
return isJSObject(obj) && obj._type === 'workspace';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRequestGroup(obj: any) {
|
||||||
|
return isJSObject(obj) && obj._type === 'request_group';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHttpRequest(obj: any) {
|
||||||
|
return isJSObject(obj) && obj._type === 'request';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isGrpcRequest(obj: any) {
|
||||||
|
return isJSObject(obj) && obj._type === 'grpc_request';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEnvironment(obj: any) {
|
||||||
|
return isJSObject(obj) && obj._type === 'environment';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isJSObject(obj: any) {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object Object]';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isJSString(obj: any) {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object String]';
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertId(id: string): string {
|
||||||
|
if (id.startsWith('GENERATE_ID::')) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
return `GENERATE_ID::${id}`;
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { defineConfig } from 'vite';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'src/index.js'),
|
entry: resolve(__dirname, 'src/index.ts'),
|
||||||
fileName: 'index',
|
fileName: 'index',
|
||||||
formats: ['es'],
|
formats: ['es'],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Environment, Folder, HttpRequest, Workspace } from '../../../src-web/lib/models';
|
import { Environment, Folder, HttpRequest, Model, Workspace } from '../../../src-web/lib/models';
|
||||||
|
|
||||||
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
|
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
|
||||||
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
|
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
|
||||||
@@ -34,7 +34,7 @@ export function pluginHookImport(contents: string): { resources: ExportResources
|
|||||||
|
|
||||||
const workspace: ExportResources['workspaces'][0] = {
|
const workspace: ExportResources['workspaces'][0] = {
|
||||||
model: 'workspace',
|
model: 'workspace',
|
||||||
id: generateId('wk'),
|
id: generateId('workspace'),
|
||||||
name: info.name || 'Postman Import',
|
name: info.name || 'Postman Import',
|
||||||
description: info.description || '',
|
description: info.description || '',
|
||||||
variables:
|
variables:
|
||||||
@@ -50,7 +50,7 @@ export function pluginHookImport(contents: string): { resources: ExportResources
|
|||||||
const folder: ExportResources['folders'][0] = {
|
const folder: ExportResources['folders'][0] = {
|
||||||
model: 'folder',
|
model: 'folder',
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
id: generateId('fl'),
|
id: generateId('folder'),
|
||||||
name: v.name,
|
name: v.name,
|
||||||
folderId,
|
folderId,
|
||||||
};
|
};
|
||||||
@@ -65,7 +65,7 @@ export function pluginHookImport(contents: string): { resources: ExportResources
|
|||||||
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
||||||
const request: ExportResources['httpRequests'][0] = {
|
const request: ExportResources['httpRequests'][0] = {
|
||||||
model: 'http_request',
|
model: 'http_request',
|
||||||
id: generateId('rq'),
|
id: generateId('http_request'),
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
folderId,
|
folderId,
|
||||||
name: v.name,
|
name: v.name,
|
||||||
@@ -243,11 +243,8 @@ function convertTemplateSyntax<T>(obj: T): T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateId(prefix: 'wk' | 'rq' | 'fl'): string {
|
const idCount: Partial<Record<Model['model'], number>> = {};
|
||||||
const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
function generateId(model: Model['model']): string {
|
||||||
let id = `${prefix}_`;
|
idCount[model] = (idCount[model] ?? -1) + 1;
|
||||||
for (let i = 0; i < 10; i++) {
|
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
|
||||||
id += alphabet[Math.floor(Math.random() * alphabet.length)];
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
import { Model } from '../../../src-web/lib/models';
|
||||||
import { pluginHookImport } from '../src';
|
import { pluginHookImport } from '../src';
|
||||||
|
|
||||||
let originalRandom = Math.random;
|
let originalRandom = Math.random;
|
||||||
@@ -23,42 +24,67 @@ describe('importer-postman', () => {
|
|||||||
test('Imports ' + fixture, () => {
|
test('Imports ' + fixture, () => {
|
||||||
const contents = fs.readFileSync(path.join(p, fixture), 'utf-8');
|
const contents = fs.readFileSync(path.join(p, fixture), 'utf-8');
|
||||||
const imported = pluginHookImport(contents);
|
const imported = pluginHookImport(contents);
|
||||||
|
const folder0 = newId('folder');
|
||||||
|
const folder1 = newId('folder');
|
||||||
expect(imported).toEqual({
|
expect(imported).toEqual({
|
||||||
resources: expect.objectContaining({
|
resources: expect.objectContaining({
|
||||||
|
workspaces: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: newId('workspace'),
|
||||||
|
model: 'workspace',
|
||||||
|
name: 'New Collection',
|
||||||
|
}),
|
||||||
|
],
|
||||||
folders: expect.arrayContaining([
|
folders: expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
id: folder0,
|
||||||
|
model: 'folder',
|
||||||
|
workspaceId: existingId('workspace'),
|
||||||
name: 'Top Folder',
|
name: 'Top Folder',
|
||||||
workspaceId: 'wk_0G3J6M9QcT',
|
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
folderId: folder0,
|
||||||
|
id: folder1,
|
||||||
|
model: 'folder',
|
||||||
|
workspaceId: existingId('workspace'),
|
||||||
name: 'Nested Folder',
|
name: 'Nested Folder',
|
||||||
workspaceId: 'wk_0G3J6M9QcT',
|
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
httpRequests: expect.arrayContaining([
|
httpRequests: expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
id: newId('http_request'),
|
||||||
|
model: 'http_request',
|
||||||
name: 'Request 1',
|
name: 'Request 1',
|
||||||
workspaceId: 'wk_0G3J6M9QcT',
|
workspaceId: existingId('workspace'),
|
||||||
folderId: 'fl_vundefinedyundefinedBundefinedE0H3',
|
folderId: folder1,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
id: newId('http_request'),
|
||||||
|
model: 'http_request',
|
||||||
name: 'Request 2',
|
name: 'Request 2',
|
||||||
workspaceId: 'wk_0G3J6M9QcT',
|
workspaceId: existingId('workspace'),
|
||||||
folderId: 'fl_fWiZlundefinedoundefinedrundefined',
|
folderId: folder0,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
id: newId('http_request'),
|
||||||
|
model: 'http_request',
|
||||||
name: 'Request 3',
|
name: 'Request 3',
|
||||||
workspaceId: 'wk_0G3J6M9QcT',
|
workspaceId: existingId('workspace'),
|
||||||
folderId: null,
|
folderId: null,
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
workspaces: [
|
|
||||||
expect.objectContaining({
|
|
||||||
name: 'New Collection',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const idCount: Partial<Record<Model['model'], number>> = {};
|
||||||
|
function newId(model: Model['model']): string {
|
||||||
|
idCount[model] = (idCount[model] ?? -1) + 1;
|
||||||
|
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function existingId(model: Model['model']): string {
|
||||||
|
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model] ?? 0}`;
|
||||||
|
}
|
||||||
|
|||||||
285
src-tauri/Cargo.lock
generated
285
src-tauri/Cargo.lock
generated
@@ -483,9 +483,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_ast"
|
name = "boa_ast"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73498e9b2f0aa7db74977afa4d594657611e90587abf0dd564c0b55b4a130163"
|
checksum = "5b6fb81ca0f301f33aff7401e2ffab37dc9e0e4a1cf0ccf6b34f4d9e60aa0682"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"boa_interner",
|
"boa_interner",
|
||||||
@@ -497,30 +497,35 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_engine"
|
name = "boa_engine"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "16377479d5d6d33896e7acdd1cc698d04a8f72004025bbbddf47558cd29146a6"
|
checksum = "600e4e4a65b26efcef08a7b1cf2899d3845a32e82e067ee3b75eaf7e413ff31c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"boa_ast",
|
"boa_ast",
|
||||||
"boa_gc",
|
"boa_gc",
|
||||||
"boa_icu_provider",
|
|
||||||
"boa_interner",
|
"boa_interner",
|
||||||
"boa_macros",
|
"boa_macros",
|
||||||
"boa_parser",
|
"boa_parser",
|
||||||
"boa_profiler",
|
"boa_profiler",
|
||||||
"chrono",
|
"bytemuck",
|
||||||
|
"cfg-if",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
|
"hashbrown 0.14.3",
|
||||||
"icu_normalizer",
|
"icu_normalizer",
|
||||||
"indexmap 2.2.6",
|
"indexmap 2.2.6",
|
||||||
"itertools",
|
"intrusive-collections",
|
||||||
|
"itertools 0.12.1",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"num_enum 0.6.1",
|
"num_enum 0.7.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"paste",
|
||||||
"pollster",
|
"pollster",
|
||||||
|
"portable-atomic",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"regress",
|
"regress",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
@@ -532,39 +537,26 @@ dependencies = [
|
|||||||
"tap",
|
"tap",
|
||||||
"thin-vec",
|
"thin-vec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_gc"
|
name = "boa_gc"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c97b44beaef9d4452342d117d94607fdfa8d474280f1ba0fd97853834e3a49b2"
|
checksum = "c055ef3cd87ea7db014779195bc90c6adfc35de4902e3b2fe587adecbd384578"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boa_macros",
|
"boa_macros",
|
||||||
"boa_profiler",
|
"boa_profiler",
|
||||||
|
"hashbrown 0.14.3",
|
||||||
"thin-vec",
|
"thin-vec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "boa_icu_provider"
|
|
||||||
version = "0.17.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b30e52e34e451dd0bfc2c654a9a43ed34b0073dbd4ae3394b40313edda8627aa"
|
|
||||||
dependencies = [
|
|
||||||
"icu_collections",
|
|
||||||
"icu_normalizer",
|
|
||||||
"icu_properties",
|
|
||||||
"icu_provider",
|
|
||||||
"icu_provider_adapters",
|
|
||||||
"icu_provider_blob",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_interner"
|
name = "boa_interner"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3e5afa991908cfbe79bd3109b824e473a1dc5f74f31fab91bb44c9e245daa77"
|
checksum = "0cacc9caf022d92195c827a3e5bf83f96089d4bfaff834b359ac7b6be46e9187"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boa_gc",
|
"boa_gc",
|
||||||
"boa_macros",
|
"boa_macros",
|
||||||
@@ -578,9 +570,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_macros"
|
name = "boa_macros"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "005fa0c5bd20805466dda55eb34cd709bb31a2592bb26927b47714eeed6914d8"
|
checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -590,40 +582,34 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_parser"
|
name = "boa_parser"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e09afb035377a9044443b598187a7d34cd13164617182a4d7c348522ee3f052"
|
checksum = "9e8592556849f0619ed142ce2b3a19086769314a8d657f93a5765d06dbce4818"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"boa_ast",
|
"boa_ast",
|
||||||
"boa_icu_provider",
|
|
||||||
"boa_interner",
|
"boa_interner",
|
||||||
"boa_macros",
|
"boa_macros",
|
||||||
"boa_profiler",
|
"boa_profiler",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
"icu_locid",
|
|
||||||
"icu_properties",
|
"icu_properties",
|
||||||
"icu_provider",
|
|
||||||
"icu_provider_macros",
|
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
|
||||||
"regress",
|
"regress",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"tinystr",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_profiler"
|
name = "boa_profiler"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3190f92dfe48224adc92881c620f08ccf37ff62b91a094bb357fe53bd5e84647"
|
checksum = "e0d8372f2d5cbac600a260de87877141b42da1e18d2c7a08ccb493a49cbd55c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boa_runtime"
|
name = "boa_runtime"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80e7606e8be709e82cb78c66bc6849dfcaa5fd0f551a215bd1cf6ab3b5bb4453"
|
checksum = "088ac38072a9517691478d33c4385cfd67657ec584b57f8397820a55b660990e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boa_engine",
|
"boa_engine",
|
||||||
"boa_gc",
|
"boa_gc",
|
||||||
@@ -719,6 +705,20 @@ name = "bytemuck"
|
|||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
|
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck_derive"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.58",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
@@ -903,12 +903,6 @@ dependencies = [
|
|||||||
"inout",
|
"inout",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cobs"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cocoa"
|
name = "cocoa"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
@@ -1126,12 +1120,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "critical-section"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
@@ -1468,12 +1456,6 @@ version = "1.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
|
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "embedded-io"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
@@ -2230,15 +2212,6 @@ dependencies = [
|
|||||||
"ahash 0.7.8",
|
"ahash 0.7.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
|
||||||
dependencies = [
|
|
||||||
"ahash 0.8.11",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.3"
|
version = "0.14.3"
|
||||||
@@ -2550,12 +2523,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef8302d8dfd6044d3ddb3f807a5ef3d7bbca9a574959c6d6e4dc39aa7012d0d5"
|
checksum = "137d96353afc8544d437e8a99eceb10ab291352699573b0de5b08bda38c78c60"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"serde",
|
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
@@ -2563,29 +2535,48 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_locid"
|
name = "icu_locid"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335"
|
checksum = "5c0aa2536adc14c07e2a521e95512b75ed8ef832f0fdf9299d4a0a45d2be2a9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"litemap",
|
"litemap",
|
||||||
"serde",
|
|
||||||
"tinystr",
|
"tinystr",
|
||||||
"writeable",
|
"writeable",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_normalizer"
|
name = "icu_locid_transform"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "652869735c9fb9f5a64ba180ee16f2c848390469c116deef517ecc53f4343598"
|
checksum = "57c17d8f6524fdca4471101dd71f0a132eb6382b5d6d7f2970441cb25f6f435a"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_locid",
|
||||||
|
"icu_locid_transform_data",
|
||||||
|
"icu_provider",
|
||||||
|
"tinystr",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locid_transform_data"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "545c6c3e8bf9580e2dafee8de6f9ec14826aaf359787789c7724f1f85f47d3dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c183e31ed700f1ecd6b032d104c52fe8b15d028956b73727c97ec176b170e187"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_collections",
|
"icu_collections",
|
||||||
|
"icu_normalizer_data",
|
||||||
"icu_properties",
|
"icu_properties",
|
||||||
"icu_provider",
|
"icu_provider",
|
||||||
"serde",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"utf16_iter",
|
"utf16_iter",
|
||||||
"utf8_iter",
|
"utf8_iter",
|
||||||
@@ -2594,74 +2585,58 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_properties"
|
name = "icu_normalizer_data"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce0e1aa26851f16c9e04412a5911c86b7f8768dac8f8d4c5f1c568a7e5d7a434"
|
checksum = "22026918a80e6a9a330cb01b60f950e2b4e5284c59528fd0c6150076ef4c8522"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_properties"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "976e296217453af983efa25f287a4c1da04b9a63bf1ed63719455068e4453eb5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_collections",
|
"icu_collections",
|
||||||
|
"icu_locid_transform",
|
||||||
|
"icu_properties_data",
|
||||||
"icu_provider",
|
"icu_provider",
|
||||||
"serde",
|
|
||||||
"tinystr",
|
"tinystr",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_provider"
|
name = "icu_properties_data"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305"
|
checksum = "f6a86c0e384532b06b6c104814f9c1b13bcd5b64409001c0d05713a1f3529d99"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_provider"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba58e782287eb6950247abbf11719f83f5d4e4a5c1f2cd490d30a334bc47c2f4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_locid",
|
"icu_locid",
|
||||||
"icu_provider_macros",
|
"icu_provider_macros",
|
||||||
"postcard",
|
|
||||||
"serde",
|
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
|
"tinystr",
|
||||||
"writeable",
|
"writeable",
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_provider_adapters"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3"
|
|
||||||
dependencies = [
|
|
||||||
"icu_locid",
|
|
||||||
"icu_provider",
|
|
||||||
"serde",
|
|
||||||
"tinystr",
|
|
||||||
"yoke",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_provider_blob"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fd364c9a01f791a4bc04a74cf2a1d01d9f6926a40fd5ae1c28004e1e70d8338b"
|
|
||||||
dependencies = [
|
|
||||||
"icu_provider",
|
|
||||||
"postcard",
|
|
||||||
"serde",
|
|
||||||
"writeable",
|
|
||||||
"yoke",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_provider_macros"
|
name = "icu_provider_macros"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10"
|
checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2750,6 +2725,15 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "intrusive-collections"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b694dc9f70c3bda874626d2aed13b780f137aab435f4e9814121955cf706122e"
|
||||||
|
dependencies = [
|
||||||
|
"memoffset",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
@@ -2804,6 +2788,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@@ -3396,11 +3389,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.6.1"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1"
|
checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num_enum_derive 0.6.1",
|
"num_enum_derive 0.7.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3417,11 +3410,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum_derive"
|
name = "num_enum_derive"
|
||||||
version = "0.6.1"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
|
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate 1.3.1",
|
"proc-macro-crate 2.0.2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
@@ -3489,10 +3482,6 @@ name = "once_cell"
|
|||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
dependencies = [
|
|
||||||
"critical-section",
|
|
||||||
"portable-atomic",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
@@ -3976,17 +3965,6 @@ version = "1.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "postcard"
|
|
||||||
version = "1.0.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8"
|
|
||||||
dependencies = [
|
|
||||||
"cobs",
|
|
||||||
"embedded-io",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -4081,7 +4059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
|
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools",
|
"itertools 0.11.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
@@ -4406,11 +4384,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regress"
|
name = "regress"
|
||||||
version = "0.6.0"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82a9ecfa0cb04d0b04dddb99b8ccf4f66bc8dfd23df694b398570bd8ae3a50fb"
|
checksum = "0eae2a1ebfecc58aff952ef8ccd364329abe627762f5bf09ff42eb9d98522479"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.14.3",
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4756,9 +4734,9 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu-js"
|
name = "ryu-js"
|
||||||
version = "0.2.2"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f"
|
checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "safemem"
|
name = "safemem"
|
||||||
@@ -5233,7 +5211,7 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
|
checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools 0.11.0",
|
||||||
"nom 7.1.3",
|
"nom 7.1.3",
|
||||||
"unicode_categories",
|
"unicode_categories",
|
||||||
]
|
]
|
||||||
@@ -6114,6 +6092,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
"itoa 1.0.9",
|
"itoa 1.0.9",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"num-conv",
|
"num-conv",
|
||||||
"num_threads",
|
"num_threads",
|
||||||
@@ -6141,12 +6120,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.7.2"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8faa444297615a4e020acb64146b0603c9c395c03a97c17fd9028816d3b4d63e"
|
checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"serde",
|
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7615,11 +7593,10 @@ checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec"
|
name = "zerovec"
|
||||||
version = "0.9.6"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "591691014119b87047ead4dcf3e6adfbf73cb7c38ab6980d4f18a32138f35d46"
|
checksum = "eff4439ae91fb5c72b8abc12f3f2dbf51bd27e6eadb9f8a5bc8898dddb0e27ea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
"zerovec-derive",
|
"zerovec-derive",
|
||||||
@@ -7627,9 +7604,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec-derive"
|
name = "zerovec-derive"
|
||||||
version = "0.9.6"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a4a1638a1934450809c2266a70362bfc96cd90550c073f5b8a55014d1010157"
|
checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ openssl-sys = { version = "0.9", features = ["vendored"] } # For Ubuntu installa
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.0"
|
||||||
boa_engine = { version = "0.17.3", features = ["annex-b"] }
|
boa_engine = { version = "0.18.0", features = ["annex-b"] }
|
||||||
boa_runtime = { version = "0.17.3" }
|
boa_runtime = { version = "0.18.0" }
|
||||||
chrono = { version = "0.4.31", features = ["serde"] }
|
chrono = { version = "0.4.31", features = ["serde"] }
|
||||||
futures = "0.3.26"
|
futures = "0.3.26"
|
||||||
http = "0.2.8"
|
http = "0.2.8"
|
||||||
|
|||||||
283
src-tauri/plugins/importer-curl/index.mjs
Normal file
283
src-tauri/plugins/importer-curl/index.mjs
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
var j = "(?:" + [
|
||||||
|
"\\|\\|",
|
||||||
|
"\\&\\&",
|
||||||
|
";;",
|
||||||
|
"\\|\\&",
|
||||||
|
"\\<\\(",
|
||||||
|
"\\<\\<\\<",
|
||||||
|
">>",
|
||||||
|
">\\&",
|
||||||
|
"<\\&",
|
||||||
|
"[&;()|<>]"
|
||||||
|
].join("|") + ")", D = new RegExp("^" + j + "$"), q = "|&;()<> \\t", M = '"((\\\\"|[^"])*?)"', Q = "'((\\\\'|[^'])*?)'", V = /^#$/, _ = "'", G = '"', U = "$", R = "", z = 4294967296;
|
||||||
|
for (var L = 0; L < 4; L++)
|
||||||
|
R += (z * Math.random()).toString(16);
|
||||||
|
var J = new RegExp("^" + R);
|
||||||
|
function X(n, s) {
|
||||||
|
for (var e = s.lastIndex, t = [], c; c = s.exec(n); )
|
||||||
|
t.push(c), s.lastIndex === c.index && (s.lastIndex += 1);
|
||||||
|
return s.lastIndex = e, t;
|
||||||
|
}
|
||||||
|
function F(n, s, e) {
|
||||||
|
var t = typeof n == "function" ? n(e) : n[e];
|
||||||
|
return typeof t > "u" && e != "" ? t = "" : typeof t > "u" && (t = "$"), typeof t == "object" ? s + R + JSON.stringify(t) + R : s + t;
|
||||||
|
}
|
||||||
|
function K(n, s, e) {
|
||||||
|
e || (e = {});
|
||||||
|
var t = e.escape || "\\", c = "(\\" + t + `['"` + q + `]|[^\\s'"` + q + "])+", m = new RegExp([
|
||||||
|
"(" + j + ")",
|
||||||
|
// control chars
|
||||||
|
"(" + c + "|" + M + "|" + Q + ")+"
|
||||||
|
].join("|"), "g"), f = X(n, m);
|
||||||
|
if (f.length === 0)
|
||||||
|
return [];
|
||||||
|
s || (s = {});
|
||||||
|
var w = !1;
|
||||||
|
return f.map(function(r) {
|
||||||
|
var a = r[0];
|
||||||
|
if (!a || w)
|
||||||
|
return;
|
||||||
|
if (D.test(a))
|
||||||
|
return { op: a };
|
||||||
|
var x = !1, O = !1, p = "", A = !1, i;
|
||||||
|
function b() {
|
||||||
|
i += 1;
|
||||||
|
var v, d, T = a.charAt(i);
|
||||||
|
if (T === "{") {
|
||||||
|
if (i += 1, a.charAt(i) === "}")
|
||||||
|
throw new Error("Bad substitution: " + a.slice(i - 2, i + 1));
|
||||||
|
if (v = a.indexOf("}", i), v < 0)
|
||||||
|
throw new Error("Bad substitution: " + a.slice(i));
|
||||||
|
d = a.slice(i, v), i = v;
|
||||||
|
} else if (/[*@#?$!_-]/.test(T))
|
||||||
|
d = T, i += 1;
|
||||||
|
else {
|
||||||
|
var g = a.slice(i);
|
||||||
|
v = g.match(/[^\w\d_]/), v ? (d = g.slice(0, v.index), i += v.index - 1) : (d = g, i = a.length);
|
||||||
|
}
|
||||||
|
return F(s, "", d);
|
||||||
|
}
|
||||||
|
for (i = 0; i < a.length; i++) {
|
||||||
|
var u = a.charAt(i);
|
||||||
|
if (A = A || !x && (u === "*" || u === "?"), O)
|
||||||
|
p += u, O = !1;
|
||||||
|
else if (x)
|
||||||
|
u === x ? x = !1 : x == _ ? p += u : u === t ? (i += 1, u = a.charAt(i), u === G || u === t || u === U ? p += u : p += t + u) : u === U ? p += b() : p += u;
|
||||||
|
else if (u === G || u === _)
|
||||||
|
x = u;
|
||||||
|
else {
|
||||||
|
if (D.test(u))
|
||||||
|
return { op: a };
|
||||||
|
if (V.test(u)) {
|
||||||
|
w = !0;
|
||||||
|
var E = { comment: n.slice(r.index + i + 1) };
|
||||||
|
return p.length ? [p, E] : [E];
|
||||||
|
} else
|
||||||
|
u === t ? O = !0 : u === U ? p += b() : p += u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return A ? { op: "glob", pattern: p } : p;
|
||||||
|
}).reduce(function(r, a) {
|
||||||
|
return typeof a > "u" ? r : r.concat(a);
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
var Y = function(s, e, t) {
|
||||||
|
var c = K(s, e, t);
|
||||||
|
return typeof e != "function" ? c : c.reduce(function(m, f) {
|
||||||
|
if (typeof f == "object")
|
||||||
|
return m.concat(f);
|
||||||
|
var w = f.split(RegExp("(" + R + ".*?" + R + ")", "g"));
|
||||||
|
return w.length === 1 ? m.concat(w[0]) : m.concat(w.filter(Boolean).map(function(r) {
|
||||||
|
return J.test(r) ? JSON.parse(r.split(R)[1]) : r;
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
}, Z = Y;
|
||||||
|
const ae = "curl", se = "cURL", ie = "cURL command line tool", H = ["d", "data", "data-raw", "data-urlencode", "data-binary", "data-ascii"], ee = [
|
||||||
|
["url"],
|
||||||
|
// Specify the URL explicitly
|
||||||
|
["user", "u"],
|
||||||
|
// Authentication
|
||||||
|
["digest"],
|
||||||
|
// Apply auth as digest
|
||||||
|
["header", "H"],
|
||||||
|
["cookie", "b"],
|
||||||
|
["get", "G"],
|
||||||
|
// Put the post data in the URL
|
||||||
|
["d", "data"],
|
||||||
|
// Add url encoded data
|
||||||
|
["data-raw"],
|
||||||
|
["data-urlencode"],
|
||||||
|
["data-binary"],
|
||||||
|
["data-ascii"],
|
||||||
|
["form", "F"],
|
||||||
|
// Add multipart data
|
||||||
|
["request", "X"],
|
||||||
|
// Request method
|
||||||
|
H
|
||||||
|
].flatMap((n) => n), oe = (n) => {
|
||||||
|
if (!n.match(/^\s*curl /))
|
||||||
|
return null;
|
||||||
|
const s = [], e = n.replace(/([^\\])\n/g, "$1; ");
|
||||||
|
let t = [];
|
||||||
|
const m = Z(e).flatMap((r) => typeof r == "string" && r.startsWith("-") && !r.startsWith("--") && r.length > 2 ? [r.slice(0, 2), r.slice(2)] : r);
|
||||||
|
for (const r of m) {
|
||||||
|
if (typeof r == "string") {
|
||||||
|
r.startsWith("$") ? t.push(r.slice(1)) : t.push(r);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ("comment" in r)
|
||||||
|
continue;
|
||||||
|
const { op: a } = r;
|
||||||
|
if (a === ";") {
|
||||||
|
s.push(t), t = [];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (a != null && a.startsWith("$")) {
|
||||||
|
const x = a.slice(2, a.length - 1).replace(/\\'/g, "'");
|
||||||
|
t.push(x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
a === "glob" && t.push(r.pattern);
|
||||||
|
}
|
||||||
|
s.push(t);
|
||||||
|
const f = {
|
||||||
|
model: "workspace",
|
||||||
|
id: N("workspace"),
|
||||||
|
name: "Curl Import"
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
resources: {
|
||||||
|
httpRequests: s.filter((r) => r[0] === "curl").map((r) => te(r, f.id)),
|
||||||
|
workspaces: [f]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
function te(n, s) {
|
||||||
|
const e = {}, t = [];
|
||||||
|
for (let o = 1; o < n.length; o++) {
|
||||||
|
let l = n[o];
|
||||||
|
if (typeof l == "string" && (l = l.trim()), typeof l == "string" && l.match(/^-{1,2}[\w-]+/)) {
|
||||||
|
const $ = l[0] === "-" && l[1] !== "-";
|
||||||
|
let h = l.replace(/^-{1,2}/, "");
|
||||||
|
if (!ee.includes(h))
|
||||||
|
continue;
|
||||||
|
let y;
|
||||||
|
const S = n[o + 1];
|
||||||
|
$ && h.length > 1 ? (y = h.slice(1), h = h.slice(0, 1)) : typeof S == "string" && !S.startsWith("-") ? (y = S, o++) : y = !0, e[h] = e[h] || [], e[h].push(y);
|
||||||
|
} else
|
||||||
|
l && t.push(l);
|
||||||
|
}
|
||||||
|
let c, m;
|
||||||
|
const f = C(e, t[0] || "", ["url"]), [w, r] = W(f, "?");
|
||||||
|
c = (r == null ? void 0 : r.split("&").map((o) => {
|
||||||
|
const l = W(o, "=");
|
||||||
|
return { name: l[0] ?? "", value: l[1] ?? "" };
|
||||||
|
})) ?? [], m = w ?? f;
|
||||||
|
const [a, x] = C(e, "", ["u", "user"]).split(/:(.*)$/), O = C(e, !1, ["digest"]), p = a ? O ? "digest" : "basic" : null, A = a ? {
|
||||||
|
username: a.trim(),
|
||||||
|
password: (x ?? "").trim()
|
||||||
|
} : {}, i = [
|
||||||
|
...e.header || [],
|
||||||
|
...e.H || []
|
||||||
|
].map((o) => {
|
||||||
|
const [l, $] = o.split(/:(.*)$/);
|
||||||
|
return $ ? {
|
||||||
|
name: (l ?? "").trim(),
|
||||||
|
value: $.trim()
|
||||||
|
} : {
|
||||||
|
name: (l ?? "").trim().replace(/;$/, ""),
|
||||||
|
value: ""
|
||||||
|
};
|
||||||
|
}), b = [
|
||||||
|
...e.cookie || [],
|
||||||
|
...e.b || []
|
||||||
|
].map((o) => {
|
||||||
|
const l = o.split("=", 1)[0], $ = o.replace(`${l}=`, "");
|
||||||
|
return `${l}=${$}`;
|
||||||
|
}).join("; "), u = i.find((o) => o.name.toLowerCase() === "cookie");
|
||||||
|
b && u ? u.value += `; ${b}` : b && i.push({
|
||||||
|
name: "Cookie",
|
||||||
|
value: b
|
||||||
|
});
|
||||||
|
const E = ne(e), v = i.find((o) => o.name.toLowerCase() === "content-type"), d = v ? v.value.split(";")[0] : null, T = [
|
||||||
|
...e.form || [],
|
||||||
|
...e.F || []
|
||||||
|
].map((o) => {
|
||||||
|
const l = o.split("="), $ = l[0] ?? "", h = l[1] ?? "", y = {
|
||||||
|
name: $,
|
||||||
|
enabled: !0
|
||||||
|
};
|
||||||
|
return h.indexOf("@") === 0 ? y.file = h.slice(1) : y.value = h, y;
|
||||||
|
});
|
||||||
|
let g = {}, I = null;
|
||||||
|
const B = C(e, !1, ["G", "get"]);
|
||||||
|
E.length > 0 && B ? c.push(...E) : E.length > 0 && (d == null || d === "application/x-www-form-urlencoded") ? (I = d ?? "application/x-www-form-urlencoded", g = {
|
||||||
|
params: E.map((o) => ({
|
||||||
|
...o,
|
||||||
|
name: decodeURIComponent(o.name || ""),
|
||||||
|
value: decodeURIComponent(o.value || "")
|
||||||
|
}))
|
||||||
|
}) : E.length > 0 ? (I = d === "application/json" || d === "text/xml" || d === "text/plain" ? d : "other", g = {
|
||||||
|
text: E.map(({ name: o, value: l }) => o && l ? `${o}=${l}` : o || l).join("&")
|
||||||
|
}) : T.length && (I = d ?? "multipart/form-data", g = {
|
||||||
|
form: T
|
||||||
|
});
|
||||||
|
let P = C(e, "", ["X", "request"]).toUpperCase();
|
||||||
|
return P === "" && g && (P = "text" in g || "params" in g ? "POST" : "GET"), {
|
||||||
|
id: N("http_request"),
|
||||||
|
model: "http_request",
|
||||||
|
workspaceId: s,
|
||||||
|
name: "",
|
||||||
|
urlParameters: c,
|
||||||
|
url: m,
|
||||||
|
method: P,
|
||||||
|
headers: i,
|
||||||
|
authentication: A,
|
||||||
|
authenticationType: p,
|
||||||
|
body: g,
|
||||||
|
bodyType: I,
|
||||||
|
folderId: null,
|
||||||
|
sortPriority: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const ne = (n) => {
|
||||||
|
let s = [];
|
||||||
|
for (const e of H) {
|
||||||
|
const t = n[e];
|
||||||
|
if (!(!t || t.length === 0))
|
||||||
|
for (const c of t) {
|
||||||
|
if (typeof c != "string")
|
||||||
|
continue;
|
||||||
|
const [m, f] = c.split("=");
|
||||||
|
c.startsWith("@") ? s.push({
|
||||||
|
name: m ?? "",
|
||||||
|
value: "",
|
||||||
|
filePath: c.slice(1)
|
||||||
|
}) : s.push({
|
||||||
|
name: m ?? "",
|
||||||
|
value: e === "data-urlencode" ? encodeURIComponent(f ?? "") : f ?? ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}, C = (n, s, e) => {
|
||||||
|
for (const t of e)
|
||||||
|
if (n[t] && n[t].length)
|
||||||
|
return n[t][0];
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
function W(n, s) {
|
||||||
|
const e = n.indexOf(s);
|
||||||
|
return e > -1 ? [n.slice(0, e), n.slice(e + 1)] : [n];
|
||||||
|
}
|
||||||
|
const k = {};
|
||||||
|
function N(n) {
|
||||||
|
return k[n] = (k[n] ?? -1) + 1, `GENERATE_ID::${n.toUpperCase()}_${k[n]}`;
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
ie as description,
|
||||||
|
ae as id,
|
||||||
|
te as importCommand,
|
||||||
|
se as name,
|
||||||
|
oe as pluginHookImport
|
||||||
|
};
|
||||||
@@ -1,165 +1,179 @@
|
|||||||
function g(e, n) {
|
function A(e) {
|
||||||
return console.log("IMPORTING Environment", e._id, e.name, JSON.stringify(e, null, 2)), {
|
let a;
|
||||||
id: e._id,
|
|
||||||
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
workspaceId: n,
|
|
||||||
model: "environment",
|
|
||||||
name: e.name,
|
|
||||||
variables: Object.entries(e.data).map(([t, a]) => ({
|
|
||||||
enabled: !0,
|
|
||||||
name: t,
|
|
||||||
value: `${a}`
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function S(e) {
|
|
||||||
return m(e) && e._type === "workspace";
|
|
||||||
}
|
|
||||||
function I(e) {
|
|
||||||
return m(e) && e._type === "request_group";
|
|
||||||
}
|
|
||||||
function y(e) {
|
|
||||||
return m(e) && e._type === "request";
|
|
||||||
}
|
|
||||||
function h(e) {
|
|
||||||
return m(e) && e._type === "grpc_request";
|
|
||||||
}
|
|
||||||
function f(e) {
|
|
||||||
return m(e) && e._type === "environment";
|
|
||||||
}
|
|
||||||
function m(e) {
|
|
||||||
return Object.prototype.toString.call(e) === "[object Object]";
|
|
||||||
}
|
|
||||||
function w(e) {
|
|
||||||
return Object.prototype.toString.call(e) === "[object String]";
|
|
||||||
}
|
|
||||||
function O(e) {
|
|
||||||
return Object.entries(e).map(([n, t]) => ({
|
|
||||||
enabled: !0,
|
|
||||||
name: n,
|
|
||||||
value: `${t}`
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
function d(e) {
|
|
||||||
return w(e) ? e.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}") : e;
|
|
||||||
}
|
|
||||||
function _(e, n, t = 0) {
|
|
||||||
var l, r;
|
|
||||||
console.log("IMPORTING REQUEST", e._id, e.name, JSON.stringify(e, null, 2));
|
|
||||||
let a = null, o = null;
|
|
||||||
((l = e.body) == null ? void 0 : l.mimeType) === "application/graphql" ? (a = "graphql", o = d(e.body.text)) : ((r = e.body) == null ? void 0 : r.mimeType) === "application/json" && (a = "application/json", o = d(e.body.text));
|
|
||||||
let s = null, p = {};
|
|
||||||
return e.authentication.type === "bearer" ? (s = "bearer", p = {
|
|
||||||
token: d(e.authentication.token)
|
|
||||||
}) : e.authentication.type === "basic" && (s = "basic", p = {
|
|
||||||
username: d(e.authentication.username),
|
|
||||||
password: d(e.authentication.password)
|
|
||||||
}), {
|
|
||||||
id: e._id,
|
|
||||||
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
workspaceId: n,
|
|
||||||
folderId: e.parentId === n ? null : e.parentId,
|
|
||||||
model: "http_request",
|
|
||||||
sortPriority: t,
|
|
||||||
name: e.name,
|
|
||||||
url: d(e.url),
|
|
||||||
body: o,
|
|
||||||
bodyType: a,
|
|
||||||
authentication: p,
|
|
||||||
authenticationType: s,
|
|
||||||
method: e.method,
|
|
||||||
headers: (e.headers ?? []).map(({ name: u, value: c, disabled: i }) => ({
|
|
||||||
enabled: !i,
|
|
||||||
name: u,
|
|
||||||
value: c
|
|
||||||
})).filter(({ name: u, value: c }) => u !== "" || c !== "")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function R(e, n) {
|
|
||||||
return console.log("IMPORTING FOLDER", e._id, e.name, JSON.stringify(e, null, 2)), {
|
|
||||||
id: e._id,
|
|
||||||
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
folderId: e.parentId === n ? null : e.parentId,
|
|
||||||
workspaceId: n,
|
|
||||||
model: "folder",
|
|
||||||
name: e.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function D(e, n, t = 0) {
|
|
||||||
var p;
|
|
||||||
console.log("IMPORTING GRPC REQUEST", e._id, e.name, JSON.stringify(e, null, 2));
|
|
||||||
const a = e.protoMethodName.split("/").filter((l) => l !== ""), o = a[0] ?? null, s = a[1] ?? null;
|
|
||||||
return {
|
|
||||||
id: e._id,
|
|
||||||
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
|
||||||
workspaceId: n,
|
|
||||||
folderId: e.parentId === n ? null : e.parentId,
|
|
||||||
model: "grpc_request",
|
|
||||||
sortPriority: t,
|
|
||||||
name: e.name,
|
|
||||||
url: d(e.url),
|
|
||||||
service: o,
|
|
||||||
method: s,
|
|
||||||
message: ((p = e.body) == null ? void 0 : p.text) ?? "",
|
|
||||||
metadata: (e.metadata ?? []).map(({ name: l, value: r, disabled: u }) => ({
|
|
||||||
enabled: !u,
|
|
||||||
name: l,
|
|
||||||
value: r
|
|
||||||
})).filter(({ name: l, value: r }) => l !== "" || r !== "")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function q(e) {
|
|
||||||
let n;
|
|
||||||
try {
|
try {
|
||||||
n = JSON.parse(e);
|
a = JSON.parse(e);
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m(n) || !Array.isArray(n.resources))
|
if (!c(a) || !Array.isArray(a.resources))
|
||||||
return;
|
return;
|
||||||
const t = {
|
const n = {
|
||||||
workspaces: [],
|
workspaces: [],
|
||||||
httpRequests: [],
|
httpRequests: [],
|
||||||
grpcRequests: [],
|
grpcRequests: [],
|
||||||
environments: [],
|
environments: [],
|
||||||
folders: []
|
folders: []
|
||||||
}, a = n.resources.filter(S);
|
}, o = a.resources.filter(_);
|
||||||
for (const o of a) {
|
for (const r of o) {
|
||||||
const s = n.resources.find(
|
const l = a.resources.find(
|
||||||
(r) => f(r) && r.parentId === o._id
|
(i) => w(i) && i.parentId === r._id
|
||||||
);
|
);
|
||||||
t.workspaces.push({
|
n.workspaces.push({
|
||||||
id: o._id,
|
id: d(r._id),
|
||||||
createdAt: new Date(a.created ?? Date.now()).toISOString().replace("Z", ""),
|
createdAt: new Date(o.created ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
updatedAt: new Date(a.updated ?? Date.now()).toISOString().replace("Z", ""),
|
updatedAt: new Date(o.updated ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
model: "workspace",
|
model: "workspace",
|
||||||
name: o.name,
|
name: r.name,
|
||||||
variables: s ? O(s.data) : []
|
variables: l ? h(l.data) : []
|
||||||
});
|
});
|
||||||
const p = n.resources.filter(
|
const p = a.resources.filter(
|
||||||
(r) => f(r) && r.parentId === (s == null ? void 0 : s._id)
|
(i) => w(i) && i.parentId === (l == null ? void 0 : l._id)
|
||||||
);
|
);
|
||||||
t.environments.push(
|
n.environments.push(
|
||||||
...p.map((r) => g(r, o._id))
|
...p.map((i) => b(i, r._id))
|
||||||
);
|
);
|
||||||
const l = (r) => {
|
const s = (i) => {
|
||||||
const u = n.resources.filter((i) => i.parentId === r);
|
const f = a.resources.filter((t) => t.parentId === i);
|
||||||
let c = 0;
|
let m = 0;
|
||||||
for (const i of u)
|
for (const t of f)
|
||||||
I(i) ? (t.folders.push(R(i, o._id)), l(i._id)) : y(i) ? t.httpRequests.push(
|
D(t) ? (n.folders.push(I(t, r._id)), s(t._id)) : v(t) ? n.httpRequests.push(
|
||||||
_(i, o._id, c++)
|
g(t, r._id, m++)
|
||||||
) : h(i) && (console.log("GRPC", JSON.stringify(i, null, 1)), t.grpcRequests.push(
|
) : q(t) && n.grpcRequests.push(
|
||||||
D(i, o._id, c++)
|
S(t, r._id, m++)
|
||||||
));
|
);
|
||||||
};
|
};
|
||||||
l(o._id);
|
s(r._id);
|
||||||
}
|
}
|
||||||
return t.httpRequests = t.httpRequests.filter(Boolean), t.grpcRequests = t.grpcRequests.filter(Boolean), t.environments = t.environments.filter(Boolean), t.workspaces = t.workspaces.filter(Boolean), { resources: t };
|
return n.httpRequests = n.httpRequests.filter(Boolean), n.grpcRequests = n.grpcRequests.filter(Boolean), n.environments = n.environments.filter(Boolean), n.workspaces = n.workspaces.filter(Boolean), { resources: n };
|
||||||
|
}
|
||||||
|
function b(e, a) {
|
||||||
|
return {
|
||||||
|
id: d(e._id),
|
||||||
|
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
workspaceId: d(a),
|
||||||
|
model: "environment",
|
||||||
|
name: e.name,
|
||||||
|
variables: Object.entries(e.data).map(([n, o]) => ({
|
||||||
|
enabled: !0,
|
||||||
|
name: n,
|
||||||
|
value: `${o}`
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function I(e, a) {
|
||||||
|
return {
|
||||||
|
id: d(e._id),
|
||||||
|
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
folderId: e.parentId === a ? null : d(e.parentId),
|
||||||
|
workspaceId: d(a),
|
||||||
|
model: "folder",
|
||||||
|
name: e.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function S(e, a, n = 0) {
|
||||||
|
var p;
|
||||||
|
const o = e.protoMethodName.split("/").filter((s) => s !== ""), r = o[0] ?? null, l = o[1] ?? null;
|
||||||
|
return {
|
||||||
|
id: d(e._id),
|
||||||
|
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
workspaceId: d(a),
|
||||||
|
folderId: e.parentId === a ? null : d(e.parentId),
|
||||||
|
model: "grpc_request",
|
||||||
|
sortPriority: n,
|
||||||
|
name: e.name,
|
||||||
|
url: u(e.url),
|
||||||
|
service: r,
|
||||||
|
method: l,
|
||||||
|
message: ((p = e.body) == null ? void 0 : p.text) ?? "",
|
||||||
|
metadata: (e.metadata ?? []).map((s) => ({
|
||||||
|
enabled: !s.disabled,
|
||||||
|
name: s.name ?? "",
|
||||||
|
value: s.value ?? ""
|
||||||
|
})).filter(({ name: s, value: i }) => s !== "" || i !== "")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function g(e, a, n = 0) {
|
||||||
|
var s, i, f, m;
|
||||||
|
let o = null, r = {};
|
||||||
|
e.body.mimeType === "application/octet-stream" ? (o = "binary", r = { filePath: e.body.fileName ?? "" }) : ((s = e.body) == null ? void 0 : s.mimeType) === "application/x-www-form-urlencoded" ? (o = "application/x-www-form-urlencoded", r = {
|
||||||
|
form: (e.body.params ?? []).map((t) => ({
|
||||||
|
enabled: !t.disabled,
|
||||||
|
name: t.name ?? "",
|
||||||
|
value: t.value ?? ""
|
||||||
|
}))
|
||||||
|
}) : ((i = e.body) == null ? void 0 : i.mimeType) === "multipart/form-data" ? (o = "multipart/form-data", r = {
|
||||||
|
form: (e.body.params ?? []).map((t) => ({
|
||||||
|
enabled: !t.disabled,
|
||||||
|
name: t.name ?? "",
|
||||||
|
value: t.value ?? "",
|
||||||
|
file: t.fileName ?? null
|
||||||
|
}))
|
||||||
|
}) : ((f = e.body) == null ? void 0 : f.mimeType) === "application/graphql" ? (o = "graphql", r = { text: u(e.body.text ?? "") }) : ((m = e.body) == null ? void 0 : m.mimeType) === "application/json" && (o = "application/json", r = { text: u(e.body.text ?? "") });
|
||||||
|
let l = null, p = {};
|
||||||
|
return e.authentication.type === "bearer" ? (l = "bearer", p = {
|
||||||
|
token: u(e.authentication.token)
|
||||||
|
}) : e.authentication.type === "basic" && (l = "basic", p = {
|
||||||
|
username: u(e.authentication.username),
|
||||||
|
password: u(e.authentication.password)
|
||||||
|
}), {
|
||||||
|
id: d(e._id),
|
||||||
|
createdAt: new Date(e.created ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace("Z", ""),
|
||||||
|
workspaceId: d(a),
|
||||||
|
folderId: e.parentId === a ? null : d(e.parentId),
|
||||||
|
model: "http_request",
|
||||||
|
sortPriority: n,
|
||||||
|
name: e.name,
|
||||||
|
url: u(e.url),
|
||||||
|
body: r,
|
||||||
|
bodyType: o,
|
||||||
|
authentication: p,
|
||||||
|
authenticationType: l,
|
||||||
|
method: e.method,
|
||||||
|
headers: (e.headers ?? []).map((t) => ({
|
||||||
|
enabled: !t.disabled,
|
||||||
|
name: t.name ?? "",
|
||||||
|
value: t.value ?? ""
|
||||||
|
})).filter(({ name: t, value: y }) => t !== "" || y !== "")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function h(e) {
|
||||||
|
return Object.entries(e).map(([a, n]) => ({
|
||||||
|
enabled: !0,
|
||||||
|
name: a,
|
||||||
|
value: `${n}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function u(e) {
|
||||||
|
return O(e) ? e.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}") : e;
|
||||||
|
}
|
||||||
|
function _(e) {
|
||||||
|
return c(e) && e._type === "workspace";
|
||||||
|
}
|
||||||
|
function D(e) {
|
||||||
|
return c(e) && e._type === "request_group";
|
||||||
|
}
|
||||||
|
function v(e) {
|
||||||
|
return c(e) && e._type === "request";
|
||||||
|
}
|
||||||
|
function q(e) {
|
||||||
|
return c(e) && e._type === "grpc_request";
|
||||||
|
}
|
||||||
|
function w(e) {
|
||||||
|
return c(e) && e._type === "environment";
|
||||||
|
}
|
||||||
|
function c(e) {
|
||||||
|
return Object.prototype.toString.call(e) === "[object Object]";
|
||||||
|
}
|
||||||
|
function O(e) {
|
||||||
|
return Object.prototype.toString.call(e) === "[object String]";
|
||||||
|
}
|
||||||
|
function d(e) {
|
||||||
|
return e.startsWith("GENERATE_ID::") ? e : `GENERATE_ID::${e}`;
|
||||||
}
|
}
|
||||||
export {
|
export {
|
||||||
q as pluginHookImport
|
A as pluginHookImport
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,92 +1,92 @@
|
|||||||
const q = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", S = "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", _ = [S, q];
|
const S = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", _ = "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", O = [_, S];
|
||||||
function j(t) {
|
function v(e) {
|
||||||
var g;
|
var g;
|
||||||
const e = A(t);
|
const t = k(e);
|
||||||
if (e == null)
|
if (t == null)
|
||||||
return;
|
return;
|
||||||
const a = l(e.info);
|
const o = i(t.info);
|
||||||
if (!_.includes(a.schema) || !Array.isArray(e.item))
|
if (!O.includes(o.schema) || !Array.isArray(t.item))
|
||||||
return;
|
return;
|
||||||
const c = w(e.auth), s = {
|
const u = A(t.auth), s = {
|
||||||
workspaces: [],
|
workspaces: [],
|
||||||
environments: [],
|
environments: [],
|
||||||
httpRequests: [],
|
httpRequests: [],
|
||||||
folders: []
|
folders: []
|
||||||
}, n = {
|
}, n = {
|
||||||
model: "workspace",
|
model: "workspace",
|
||||||
id: y("wk"),
|
id: h("workspace"),
|
||||||
name: a.name || "Postman Import",
|
name: o.name || "Postman Import",
|
||||||
description: a.description || "",
|
description: o.description || "",
|
||||||
variables: ((g = e.variable) == null ? void 0 : g.map((r) => ({
|
variables: ((g = t.variable) == null ? void 0 : g.map((r) => ({
|
||||||
name: r.key,
|
name: r.key,
|
||||||
value: r.value
|
value: r.value
|
||||||
}))) ?? []
|
}))) ?? []
|
||||||
};
|
};
|
||||||
s.workspaces.push(n);
|
s.workspaces.push(n);
|
||||||
const f = (r, d = null) => {
|
const T = (r, p = null) => {
|
||||||
if (typeof r.name == "string" && Array.isArray(r.item)) {
|
if (typeof r.name == "string" && Array.isArray(r.item)) {
|
||||||
const o = {
|
const a = {
|
||||||
model: "folder",
|
model: "folder",
|
||||||
workspaceId: n.id,
|
workspaceId: n.id,
|
||||||
id: y("fl"),
|
id: h("folder"),
|
||||||
name: r.name,
|
name: r.name,
|
||||||
folderId: d
|
folderId: p
|
||||||
};
|
};
|
||||||
s.folders.push(o);
|
s.folders.push(a);
|
||||||
for (const u of r.item)
|
for (const l of r.item)
|
||||||
f(u, o.id);
|
T(l, a.id);
|
||||||
} else if (typeof r.name == "string" && "request" in r) {
|
} else if (typeof r.name == "string" && "request" in r) {
|
||||||
const o = l(r.request), u = O(o.body), T = w(o.auth), p = T.authenticationType == null ? c : T, k = {
|
const a = i(r.request), l = j(a.body), w = A(a.auth), d = w.authenticationType == null ? u : w, q = {
|
||||||
model: "http_request",
|
model: "http_request",
|
||||||
id: y("rq"),
|
id: h("http_request"),
|
||||||
workspaceId: n.id,
|
workspaceId: n.id,
|
||||||
folderId: d,
|
folderId: p,
|
||||||
name: r.name,
|
name: r.name,
|
||||||
method: o.method || "GET",
|
method: a.method || "GET",
|
||||||
url: typeof o.url == "string" ? o.url : l(o.url).raw,
|
url: typeof a.url == "string" ? a.url : i(a.url).raw,
|
||||||
body: u.body,
|
body: l.body,
|
||||||
bodyType: u.bodyType,
|
bodyType: l.bodyType,
|
||||||
authentication: p.authentication,
|
authentication: d.authentication,
|
||||||
authenticationType: p.authenticationType,
|
authenticationType: d.authenticationType,
|
||||||
headers: [
|
headers: [
|
||||||
...u.headers,
|
...l.headers,
|
||||||
...p.headers,
|
...d.headers,
|
||||||
...h(o.header).map((m) => ({
|
...b(a.header).map((m) => ({
|
||||||
name: m.key,
|
name: m.key,
|
||||||
value: m.value,
|
value: m.value,
|
||||||
enabled: !m.disabled
|
enabled: !m.disabled
|
||||||
}))
|
}))
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
s.httpRequests.push(k);
|
s.httpRequests.push(q);
|
||||||
} else
|
} else
|
||||||
console.log("Unknown item", r, d);
|
console.log("Unknown item", r, p);
|
||||||
};
|
};
|
||||||
for (const r of e.item)
|
for (const r of t.item)
|
||||||
f(r);
|
T(r);
|
||||||
return { resources: b(s) };
|
return { resources: f(s) };
|
||||||
}
|
}
|
||||||
function w(t) {
|
function A(e) {
|
||||||
const e = l(t);
|
const t = i(e);
|
||||||
return "basic" in e ? {
|
return "basic" in t ? {
|
||||||
headers: [],
|
headers: [],
|
||||||
authenticationType: "basic",
|
authenticationType: "basic",
|
||||||
authentication: {
|
authentication: {
|
||||||
username: e.basic.username || "",
|
username: t.basic.username || "",
|
||||||
password: e.basic.password || ""
|
password: t.basic.password || ""
|
||||||
}
|
}
|
||||||
} : "bearer" in e ? {
|
} : "bearer" in t ? {
|
||||||
headers: [],
|
headers: [],
|
||||||
authenticationType: "bearer",
|
authenticationType: "bearer",
|
||||||
authentication: {
|
authentication: {
|
||||||
token: e.bearer.token || ""
|
token: t.bearer.token || ""
|
||||||
}
|
}
|
||||||
} : { headers: [], authenticationType: null, authentication: {} };
|
} : { headers: [], authenticationType: null, authentication: {} };
|
||||||
}
|
}
|
||||||
function O(t) {
|
function j(e) {
|
||||||
var a, i, c, s;
|
var o, c, u, s;
|
||||||
const e = l(t);
|
const t = i(e);
|
||||||
return "graphql" in e ? {
|
return "graphql" in t ? {
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
name: "Content-Type",
|
name: "Content-Type",
|
||||||
@@ -97,12 +97,12 @@ function O(t) {
|
|||||||
bodyType: "graphql",
|
bodyType: "graphql",
|
||||||
body: {
|
body: {
|
||||||
text: JSON.stringify(
|
text: JSON.stringify(
|
||||||
{ query: e.graphql.query, variables: A(e.graphql.variables) },
|
{ query: t.graphql.query, variables: k(t.graphql.variables) },
|
||||||
null,
|
null,
|
||||||
2
|
2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} : "urlencoded" in e ? {
|
} : "urlencoded" in t ? {
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
name: "Content-Type",
|
name: "Content-Type",
|
||||||
@@ -112,13 +112,13 @@ function O(t) {
|
|||||||
],
|
],
|
||||||
bodyType: "application/x-www-form-urlencoded",
|
bodyType: "application/x-www-form-urlencoded",
|
||||||
body: {
|
body: {
|
||||||
form: h(e.urlencoded).map((n) => ({
|
form: b(t.urlencoded).map((n) => ({
|
||||||
enabled: !n.disabled,
|
enabled: !n.disabled,
|
||||||
name: n.key ?? "",
|
name: n.key ?? "",
|
||||||
value: n.value ?? ""
|
value: n.value ?? ""
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
} : "formdata" in e ? {
|
} : "formdata" in t ? {
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
name: "Content-Type",
|
name: "Content-Type",
|
||||||
@@ -128,7 +128,7 @@ function O(t) {
|
|||||||
],
|
],
|
||||||
bodyType: "multipart/form-data",
|
bodyType: "multipart/form-data",
|
||||||
body: {
|
body: {
|
||||||
form: h(e.formdata).map(
|
form: b(t.formdata).map(
|
||||||
(n) => n.src != null ? {
|
(n) => n.src != null ? {
|
||||||
enabled: !n.disabled,
|
enabled: !n.disabled,
|
||||||
name: n.key ?? "",
|
name: n.key ?? "",
|
||||||
@@ -140,46 +140,42 @@ function O(t) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} : "raw" in e ? {
|
} : "raw" in t ? {
|
||||||
headers: [
|
headers: [
|
||||||
{
|
{
|
||||||
name: "Content-Type",
|
name: "Content-Type",
|
||||||
value: ((i = (a = e.options) == null ? void 0 : a.raw) == null ? void 0 : i.language) === "json" ? "application/json" : "",
|
value: ((c = (o = t.options) == null ? void 0 : o.raw) == null ? void 0 : c.language) === "json" ? "application/json" : "",
|
||||||
enabled: !0
|
enabled: !0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
bodyType: ((s = (c = e.options) == null ? void 0 : c.raw) == null ? void 0 : s.language) === "json" ? "application/json" : "other",
|
bodyType: ((s = (u = t.options) == null ? void 0 : u.raw) == null ? void 0 : s.language) === "json" ? "application/json" : "other",
|
||||||
body: {
|
body: {
|
||||||
text: e.raw ?? ""
|
text: t.raw ?? ""
|
||||||
}
|
}
|
||||||
} : { headers: [], bodyType: null, body: {} };
|
} : { headers: [], bodyType: null, body: {} };
|
||||||
}
|
}
|
||||||
function A(t) {
|
function k(e) {
|
||||||
try {
|
try {
|
||||||
return l(JSON.parse(t));
|
return i(JSON.parse(e));
|
||||||
} catch {
|
} catch {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function l(t) {
|
function i(e) {
|
||||||
return Object.prototype.toString.call(t) === "[object Object]" ? t : {};
|
return Object.prototype.toString.call(e) === "[object Object]" ? e : {};
|
||||||
}
|
}
|
||||||
function h(t) {
|
function b(e) {
|
||||||
return Object.prototype.toString.call(t) === "[object Array]" ? t : [];
|
return Object.prototype.toString.call(e) === "[object Array]" ? e : [];
|
||||||
}
|
}
|
||||||
function b(t) {
|
function f(e) {
|
||||||
return typeof t == "string" ? t.replace(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}") : Array.isArray(t) && t != null ? t.map(b) : typeof t == "object" && t != null ? Object.fromEntries(
|
return typeof e == "string" ? e.replace(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}") : Array.isArray(e) && e != null ? e.map(f) : typeof e == "object" && e != null ? Object.fromEntries(
|
||||||
Object.entries(t).map(([e, a]) => [e, b(a)])
|
Object.entries(e).map(([t, o]) => [t, f(o)])
|
||||||
) : t;
|
) : e;
|
||||||
}
|
}
|
||||||
function y(t) {
|
const y = {};
|
||||||
const e = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
function h(e) {
|
||||||
let a = `${t}_`;
|
return y[e] = (y[e] ?? -1) + 1, `GENERATE_ID::${e.toUpperCase()}_${y[e]}`;
|
||||||
for (let i = 0; i < 10; i++)
|
|
||||||
a += e[Math.floor(Math.random() * e.length)];
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
export {
|
export {
|
||||||
y as generateId,
|
v as pluginHookImport
|
||||||
j as pluginHookImport
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ fn get_window_size(app_handle: &AppHandle) -> String {
|
|||||||
async fn get_id(app_handle: &AppHandle) -> String {
|
async fn get_id(app_handle: &AppHandle) -> String {
|
||||||
let id = get_key_value_string(app_handle, "analytics", "id", "").await;
|
let id = get_key_value_string(app_handle, "analytics", "id", "").await;
|
||||||
if id.is_empty() {
|
if id.is_empty() {
|
||||||
let new_id = generate_id(None);
|
let new_id = generate_id();
|
||||||
set_key_value_string(app_handle, "analytics", "id", new_id.as_str()).await;
|
set_key_value_string(app_handle, "analytics", "id", new_id.as_str()).await;
|
||||||
new_id
|
new_id
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -38,22 +38,7 @@ use window_ext::TrafficLightWindowExt;
|
|||||||
use crate::analytics::{AnalyticsAction, AnalyticsResource};
|
use crate::analytics::{AnalyticsAction, AnalyticsResource};
|
||||||
use crate::grpc::metadata_to_map;
|
use crate::grpc::metadata_to_map;
|
||||||
use crate::http::send_http_request;
|
use crate::http::send_http_request;
|
||||||
use crate::models::{
|
use crate::models::{cancel_pending_grpc_connections, cancel_pending_responses, create_http_response, delete_all_grpc_connections, delete_all_http_responses, delete_cookie_jar, delete_environment, delete_folder, delete_grpc_connection, delete_grpc_request, delete_http_request, delete_http_response, delete_workspace, duplicate_grpc_request, duplicate_http_request, get_cookie_jar, get_environment, get_folder, get_grpc_connection, get_grpc_request, get_http_request, get_http_response, get_key_value_raw, get_or_create_settings, get_workspace, get_workspace_export_resources, list_cookie_jars, list_environments, list_folders, list_grpc_connections, list_grpc_events, list_grpc_requests, list_http_requests, list_responses, list_workspaces, set_key_value_raw, update_response_if_id, update_settings, upsert_cookie_jar, upsert_environment, upsert_folder, upsert_grpc_connection, upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace, CookieJar, Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcEvent, GrpcEventType, GrpcRequest, HttpRequest, HttpRequestHeader, HttpResponse, KeyValue, Settings, Workspace, WorkspaceExportResources, generate_model_id, ModelType};
|
||||||
cancel_pending_grpc_connections, cancel_pending_responses, create_http_response,
|
|
||||||
delete_all_grpc_connections, delete_all_http_responses, delete_cookie_jar, delete_environment,
|
|
||||||
delete_folder, delete_grpc_connection, delete_grpc_request, delete_http_request,
|
|
||||||
delete_http_response, delete_workspace, duplicate_grpc_request, duplicate_http_request,
|
|
||||||
get_cookie_jar, get_environment, get_folder, get_grpc_connection, get_grpc_request,
|
|
||||||
get_http_request, get_http_response, get_key_value_raw, get_or_create_settings, get_workspace,
|
|
||||||
get_workspace_export_resources, list_cookie_jars, list_environments, list_folders,
|
|
||||||
list_grpc_connections, list_grpc_events, list_grpc_requests, list_http_requests,
|
|
||||||
list_responses, list_workspaces, set_key_value_raw, update_response_if_id, update_settings,
|
|
||||||
upsert_cookie_jar, upsert_environment, upsert_folder, upsert_grpc_connection,
|
|
||||||
upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace, CookieJar,
|
|
||||||
Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcEvent, GrpcEventType,
|
|
||||||
GrpcRequest, HttpRequest, HttpRequestHeader, HttpResponse, KeyValue, Settings, Workspace,
|
|
||||||
WorkspaceExportResources,
|
|
||||||
};
|
|
||||||
use crate::plugin::ImportResult;
|
use crate::plugin::ImportResult;
|
||||||
use crate::updates::{update_mode_from_str, UpdateMode, YaakUpdater};
|
use crate::updates::{update_mode_from_str, UpdateMode, YaakUpdater};
|
||||||
use crate::window_menu::app_menu;
|
use crate::window_menu::app_menu;
|
||||||
@@ -757,27 +742,59 @@ async fn cmd_import_data(
|
|||||||
None => Err("No import handlers found".to_string()),
|
None => Err("No import handlers found".to_string()),
|
||||||
Some(r) => {
|
Some(r) => {
|
||||||
let mut imported_resources = WorkspaceExportResources::default();
|
let mut imported_resources = WorkspaceExportResources::default();
|
||||||
|
let mut id_map: HashMap<String, String> = HashMap::new();
|
||||||
|
|
||||||
|
let maybe_gen_id = |id: &str, model: ModelType, ids: &mut HashMap<String, String>| -> String {
|
||||||
|
if !id.starts_with("GENERATE_ID::") {
|
||||||
|
return id.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
let unique_key = id.replace("GENERATE_ID", "");
|
||||||
|
if let Some(existing) = ids.get(unique_key.as_str()) {
|
||||||
|
existing.to_string()
|
||||||
|
} else {
|
||||||
|
let new_id = generate_model_id(model);
|
||||||
|
ids.insert(unique_key, new_id.clone());
|
||||||
|
new_id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let maybe_gen_id_opt = |id: Option<String>, model: ModelType, ids: &mut HashMap<String, String>| -> Option<String> {
|
||||||
|
match id {
|
||||||
|
Some(id) => Some(maybe_gen_id(id.as_str(), model, ids)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
info!("Importing resources");
|
info!("Importing resources");
|
||||||
for v in r.resources.workspaces {
|
for mut v in r.resources.workspaces {
|
||||||
|
v.id = maybe_gen_id(v.id.as_str(), ModelType::Workspace, &mut id_map);
|
||||||
let x = upsert_workspace(&w, v).await.map_err(|e| e.to_string())?;
|
let x = upsert_workspace(&w, v).await.map_err(|e| e.to_string())?;
|
||||||
imported_resources.workspaces.push(x.clone());
|
imported_resources.workspaces.push(x.clone());
|
||||||
info!("Imported workspace: {}", x.name);
|
info!("Imported workspace: {}", x.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in r.resources.environments {
|
for mut v in r.resources.environments {
|
||||||
|
v.id = maybe_gen_id(v.id.as_str(), ModelType::Environment, &mut id_map);
|
||||||
|
v.workspace_id = maybe_gen_id(v.workspace_id.as_str(), ModelType::Workspace, &mut id_map);
|
||||||
let x = upsert_environment(&w, v).await.map_err(|e| e.to_string())?;
|
let x = upsert_environment(&w, v).await.map_err(|e| e.to_string())?;
|
||||||
imported_resources.environments.push(x.clone());
|
imported_resources.environments.push(x.clone());
|
||||||
info!("Imported environment: {}", x.name);
|
info!("Imported environment: {}", x.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in r.resources.folders {
|
for mut v in r.resources.folders {
|
||||||
|
v.id = maybe_gen_id(v.id.as_str(), ModelType::Folder, &mut id_map);
|
||||||
|
v.workspace_id = maybe_gen_id(v.workspace_id.as_str(), ModelType::Workspace, &mut id_map);
|
||||||
|
v.folder_id = maybe_gen_id_opt(v.folder_id, ModelType::Folder, &mut id_map);
|
||||||
let x = upsert_folder(&w, v).await.map_err(|e| e.to_string())?;
|
let x = upsert_folder(&w, v).await.map_err(|e| e.to_string())?;
|
||||||
imported_resources.folders.push(x.clone());
|
imported_resources.folders.push(x.clone());
|
||||||
info!("Imported folder: {}", x.name);
|
info!("Imported folder: {}", x.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in r.resources.http_requests {
|
for mut v in r.resources.http_requests {
|
||||||
|
v.id = maybe_gen_id(v.id.as_str(), ModelType::HttpRequest, &mut id_map);
|
||||||
|
v.workspace_id = maybe_gen_id(v.workspace_id.as_str(), ModelType::Workspace, &mut id_map);
|
||||||
|
v.folder_id = maybe_gen_id_opt(v.folder_id, ModelType::Folder, &mut id_map);
|
||||||
let x = upsert_http_request(&w, v)
|
let x = upsert_http_request(&w, v)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
@@ -785,7 +802,10 @@ async fn cmd_import_data(
|
|||||||
info!("Imported request: {}", x.name);
|
info!("Imported request: {}", x.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in r.resources.grpc_requests {
|
for mut v in r.resources.grpc_requests {
|
||||||
|
v.id = maybe_gen_id(v.id.as_str(), ModelType::GrpcRequest, &mut id_map);
|
||||||
|
v.workspace_id = maybe_gen_id(v.workspace_id.as_str(), ModelType::Workspace, &mut id_map);
|
||||||
|
v.folder_id = maybe_gen_id_opt(v.folder_id, ModelType::Folder, &mut id_map);
|
||||||
let x = upsert_grpc_request(&w, &v)
|
let x = upsert_grpc_request(&w, &v)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
@@ -1657,7 +1677,7 @@ fn create_window(handle: &AppHandle, url: Option<&str>) -> WebviewWindow {
|
|||||||
if !w.is_focused().unwrap() {
|
if !w.is_focused().unwrap() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.id().0.as_str() {
|
match event.id().0.as_str() {
|
||||||
"quit" => exit(0),
|
"quit" => exit(0),
|
||||||
"close" => w.close().unwrap(),
|
"close" => w.close().unwrap(),
|
||||||
|
|||||||
@@ -4,12 +4,41 @@ use std::fs;
|
|||||||
use log::error;
|
use log::error;
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{Pool, Sqlite};
|
|
||||||
use sqlx::types::{Json, JsonValue};
|
|
||||||
use sqlx::types::chrono::NaiveDateTime;
|
use sqlx::types::chrono::NaiveDateTime;
|
||||||
|
use sqlx::types::{Json, JsonValue};
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
use tauri::{AppHandle, Manager, WebviewWindow, Wry};
|
use tauri::{AppHandle, Manager, WebviewWindow, Wry};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
pub enum ModelType {
|
||||||
|
CookieJar,
|
||||||
|
Environment,
|
||||||
|
Folder,
|
||||||
|
GrpcConnection,
|
||||||
|
GrpcEvent,
|
||||||
|
GrpcRequest,
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
Workspace,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModelType {
|
||||||
|
pub fn id_prefix(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ModelType::CookieJar => "cj",
|
||||||
|
ModelType::Environment => "ev",
|
||||||
|
ModelType::Folder => "fl",
|
||||||
|
ModelType::GrpcConnection => "gc",
|
||||||
|
ModelType::GrpcEvent => "ge",
|
||||||
|
ModelType::GrpcRequest => "gr",
|
||||||
|
ModelType::HttpRequest => "rq",
|
||||||
|
ModelType::HttpResponse => "rs",
|
||||||
|
ModelType::Workspace => "wk",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn default_true() -> bool {
|
fn default_true() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -481,10 +510,7 @@ pub async fn list_cookie_jars(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_cookie_jar(
|
pub async fn delete_cookie_jar(window: &WebviewWindow, id: &str) -> Result<CookieJar, sqlx::Error> {
|
||||||
window: &WebviewWindow,
|
|
||||||
id: &str,
|
|
||||||
) -> Result<CookieJar, sqlx::Error> {
|
|
||||||
let cookie_jar = get_cookie_jar(window, id).await?;
|
let cookie_jar = get_cookie_jar(window, id).await?;
|
||||||
let db = get_db(window).await;
|
let db = get_db(window).await;
|
||||||
|
|
||||||
@@ -516,7 +542,7 @@ pub async fn upsert_grpc_request(
|
|||||||
) -> Result<GrpcRequest, sqlx::Error> {
|
) -> Result<GrpcRequest, sqlx::Error> {
|
||||||
let db = get_db(window).await;
|
let db = get_db(window).await;
|
||||||
let id = match request.id.as_str() {
|
let id = match request.id.as_str() {
|
||||||
"" => generate_id(Some("gr")),
|
"" => generate_model_id(ModelType::GrpcRequest),
|
||||||
_ => request.id.to_string(),
|
_ => request.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = request.name.trim();
|
let trimmed_name = request.name.trim();
|
||||||
@@ -612,7 +638,7 @@ pub async fn upsert_grpc_connection(
|
|||||||
) -> Result<GrpcConnection, sqlx::Error> {
|
) -> Result<GrpcConnection, sqlx::Error> {
|
||||||
let db = get_db(window).await;
|
let db = get_db(window).await;
|
||||||
let id = match connection.id.as_str() {
|
let id = match connection.id.as_str() {
|
||||||
"" => generate_id(Some("gc")),
|
"" => generate_model_id(ModelType::GrpcConnection),
|
||||||
_ => connection.id.to_string(),
|
_ => connection.id.to_string(),
|
||||||
};
|
};
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@@ -701,7 +727,7 @@ pub async fn upsert_grpc_event(
|
|||||||
) -> Result<GrpcEvent, sqlx::Error> {
|
) -> Result<GrpcEvent, sqlx::Error> {
|
||||||
let db = get_db(window).await;
|
let db = get_db(window).await;
|
||||||
let id = match event.id.as_str() {
|
let id = match event.id.as_str() {
|
||||||
"" => generate_id(Some("ge")),
|
"" => generate_model_id(ModelType::GrpcEvent),
|
||||||
_ => event.id.to_string(),
|
_ => event.id.to_string(),
|
||||||
};
|
};
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@@ -782,7 +808,7 @@ pub async fn upsert_cookie_jar(
|
|||||||
cookie_jar: &CookieJar,
|
cookie_jar: &CookieJar,
|
||||||
) -> Result<CookieJar, sqlx::Error> {
|
) -> Result<CookieJar, sqlx::Error> {
|
||||||
let id = match cookie_jar.id.as_str() {
|
let id = match cookie_jar.id.as_str() {
|
||||||
"" => generate_id(Some("cj")),
|
"" => generate_model_id(ModelType::CookieJar),
|
||||||
_ => cookie_jar.id.to_string(),
|
_ => cookie_jar.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = cookie_jar.name.trim();
|
let trimmed_name = cookie_jar.name.trim();
|
||||||
@@ -914,7 +940,7 @@ pub async fn upsert_environment(
|
|||||||
environment: Environment,
|
environment: Environment,
|
||||||
) -> Result<Environment, sqlx::Error> {
|
) -> Result<Environment, sqlx::Error> {
|
||||||
let id = match environment.id.as_str() {
|
let id = match environment.id.as_str() {
|
||||||
"" => generate_id(Some("ev")),
|
"" => generate_model_id(ModelType::Environment),
|
||||||
_ => environment.id.to_string(),
|
_ => environment.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = environment.name.trim();
|
let trimmed_name = environment.name.trim();
|
||||||
@@ -1017,7 +1043,7 @@ pub async fn delete_folder(window: &WebviewWindow, id: &str) -> Result<Folder, s
|
|||||||
|
|
||||||
pub async fn upsert_folder(window: &WebviewWindow, r: Folder) -> Result<Folder, sqlx::Error> {
|
pub async fn upsert_folder(window: &WebviewWindow, r: Folder) -> Result<Folder, sqlx::Error> {
|
||||||
let id = match r.id.as_str() {
|
let id = match r.id.as_str() {
|
||||||
"" => generate_id(Some("fl")),
|
"" => generate_model_id(ModelType::Folder),
|
||||||
_ => r.id.to_string(),
|
_ => r.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = r.name.trim();
|
let trimmed_name = r.name.trim();
|
||||||
@@ -1064,7 +1090,7 @@ pub async fn upsert_http_request(
|
|||||||
r: HttpRequest,
|
r: HttpRequest,
|
||||||
) -> Result<HttpRequest, sqlx::Error> {
|
) -> Result<HttpRequest, sqlx::Error> {
|
||||||
let id = match r.id.as_str() {
|
let id = match r.id.as_str() {
|
||||||
"" => generate_id(Some("rq")),
|
"" => generate_model_id(ModelType::HttpRequest),
|
||||||
_ => r.id.to_string(),
|
_ => r.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = r.name.trim();
|
let trimmed_name = r.name.trim();
|
||||||
@@ -1203,7 +1229,7 @@ pub async fn create_http_response(
|
|||||||
remote_addr: Option<&str>,
|
remote_addr: Option<&str>,
|
||||||
) -> Result<HttpResponse, sqlx::Error> {
|
) -> Result<HttpResponse, sqlx::Error> {
|
||||||
let req = get_http_request(window, request_id).await?;
|
let req = get_http_request(window, request_id).await?;
|
||||||
let id = generate_id(Some("rp"));
|
let id = generate_model_id(ModelType::HttpResponse);
|
||||||
let headers_json = Json(headers);
|
let headers_json = Json(headers);
|
||||||
let db = get_db(window).await;
|
let db = get_db(window).await;
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
@@ -1281,7 +1307,7 @@ pub async fn upsert_workspace(
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
) -> Result<Workspace, sqlx::Error> {
|
) -> Result<Workspace, sqlx::Error> {
|
||||||
let id = match workspace.id.as_str() {
|
let id = match workspace.id.as_str() {
|
||||||
"" => generate_id(Some("wk")),
|
"" => generate_model_id(ModelType::Workspace),
|
||||||
_ => workspace.id.to_string(),
|
_ => workspace.id.to_string(),
|
||||||
};
|
};
|
||||||
let trimmed_name = workspace.name.trim();
|
let trimmed_name = workspace.name.trim();
|
||||||
@@ -1513,12 +1539,13 @@ pub async fn delete_all_http_responses(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_id(prefix: Option<&str>) -> String {
|
pub fn generate_model_id(model: ModelType) -> String {
|
||||||
let id = Alphanumeric.sample_string(&mut rand::thread_rng(), 10);
|
let id = generate_id();
|
||||||
match prefix {
|
format!("{}_{}", model.id_prefix(), id)
|
||||||
None => id,
|
}
|
||||||
Some(p) => format!("{p}_{id}"),
|
|
||||||
}
|
pub fn generate_id() -> String {
|
||||||
|
Alphanumeric.sample_string(&mut rand::thread_rng(), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||||
@@ -1597,7 +1624,7 @@ struct ModelPayload<M: Serialize + Clone> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_upserted_model<M: Serialize + Clone>(window: &WebviewWindow, model: M) -> M {
|
fn emit_upserted_model<M: Serialize + Clone>(window: &WebviewWindow, model: M) -> M {
|
||||||
let payload = ModelPayload{
|
let payload = ModelPayload {
|
||||||
model: model.clone(),
|
model: model.clone(),
|
||||||
window_label: window.label().to_string(),
|
window_label: window.label().to_string(),
|
||||||
};
|
};
|
||||||
@@ -1607,7 +1634,7 @@ fn emit_upserted_model<M: Serialize + Clone>(window: &WebviewWindow, model: M) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_deleted_model<M: Serialize + Clone, E>(window: &WebviewWindow, model: M) -> Result<M, E> {
|
fn emit_deleted_model<M: Serialize + Clone, E>(window: &WebviewWindow, model: M) -> Result<M, E> {
|
||||||
let payload = ModelPayload{
|
let payload = ModelPayload {
|
||||||
model: model.clone(),
|
model: model.clone(),
|
||||||
window_label: window.label().to_string(),
|
window_label: window.label().to_string(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use boa_engine::{
|
use boa_engine::{
|
||||||
Context, js_string, JsNativeError, JsValue, Module, module::SimpleModuleLoader,
|
Context, js_string, JsNativeError, JsValue, Module, module::SimpleModuleLoader,
|
||||||
property::Attribute, Source,
|
property::Attribute, Source,
|
||||||
};
|
};
|
||||||
use boa_engine::builtins::promise::PromiseState;
|
use boa_engine::builtins::promise::PromiseState;
|
||||||
use boa_engine::module::ModuleLoader;
|
|
||||||
use boa_runtime::Console;
|
use boa_runtime::Console;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -13,7 +13,7 @@ use serde_json::json;
|
|||||||
use tauri::{AppHandle, Manager};
|
use tauri::{AppHandle, Manager};
|
||||||
use tauri::path::BaseDirectory;
|
use tauri::path::BaseDirectory;
|
||||||
|
|
||||||
use crate::models::{WorkspaceExportResources};
|
use crate::models::WorkspaceExportResources;
|
||||||
|
|
||||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||||
pub struct FilterResult {
|
pub struct FilterResult {
|
||||||
@@ -67,8 +67,7 @@ pub async fn run_plugin_import(
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let resources: ImportResult =
|
let resources: ImportResult = serde_json::from_value(result_json).map_err(|e| e.to_string())?;
|
||||||
serde_json::from_value(result_json).map_err(|e| e.to_string())?;
|
|
||||||
Ok(Some(resources))
|
Ok(Some(resources))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +89,9 @@ fn run_plugin(
|
|||||||
plugin_dir, plugin_index_file
|
plugin_dir, plugin_index_file
|
||||||
);
|
);
|
||||||
|
|
||||||
// Module loader for the specific plugin
|
let loader = Rc::new(SimpleModuleLoader::new(plugin_dir).unwrap());
|
||||||
let loader = &SimpleModuleLoader::new(plugin_dir).expect("failed to create module loader");
|
|
||||||
let dyn_loader: &dyn ModuleLoader = loader;
|
|
||||||
|
|
||||||
let context = &mut Context::builder()
|
let context = &mut Context::builder()
|
||||||
.module_loader(dyn_loader)
|
.module_loader(loader.clone())
|
||||||
.build()
|
.build()
|
||||||
.expect("failed to create context");
|
.expect("failed to create context");
|
||||||
|
|
||||||
@@ -109,15 +105,13 @@ fn run_plugin(
|
|||||||
// Insert parsed entrypoint into the module loader
|
// Insert parsed entrypoint into the module loader
|
||||||
loader.insert(plugin_index_file, module.clone());
|
loader.insert(plugin_index_file, module.clone());
|
||||||
|
|
||||||
let promise_result = module
|
let promise_result = module.load_link_evaluate(context);
|
||||||
.load_link_evaluate(context)
|
|
||||||
.expect("failed to evaluate module");
|
|
||||||
|
|
||||||
// Very important to push forward the job queue after queueing promises.
|
// Very important to push forward the job queue after queueing promises.
|
||||||
context.run_jobs();
|
context.run_jobs();
|
||||||
|
|
||||||
// Checking if the final promise didn't return an error.
|
// Checking if the final promise didn't return an error.
|
||||||
match promise_result.state().expect("failed to get promise state") {
|
match promise_result.state() {
|
||||||
PromiseState::Pending => {
|
PromiseState::Pending => {
|
||||||
panic!("Promise was pending");
|
panic!("Promise was pending");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export function useImportData() {
|
|||||||
|
|
||||||
const importData = async () => {
|
const importData = async () => {
|
||||||
const selected = await open({
|
const selected = await open({
|
||||||
filters: [{ name: 'Export File', extensions: ['json', 'yaml'] }],
|
filters: [{ name: 'Export File', extensions: ['json', 'yaml', 'sh', 'txt'] }],
|
||||||
multiple: false,
|
multiple: false,
|
||||||
});
|
});
|
||||||
if (selected == null) {
|
if (selected == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user