mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-30 04:24:18 +02:00
Fix split in curl importer
https://feedback.yaak.app/p/import-from-curl-does-not-work-properly-sometimes
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { Context, Environment, Folder, HttpRequest, HttpUrlParameter, PluginDefinition, Workspace } from '@yaakapp/api';
|
import type { Context, Environment, Folder, HttpRequest, HttpUrlParameter, PluginDefinition, Workspace } from '@yaakapp/api';
|
||||||
import { ControlOperator, parse, ParseEntry } from 'shell-quote';
|
import type { ControlOperator, ParseEntry } from 'shell-quote';
|
||||||
|
import { parse } from 'shell-quote';
|
||||||
|
|
||||||
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ export const plugin: PluginDefinition = {
|
|||||||
name: 'cURL',
|
name: 'cURL',
|
||||||
description: 'Import cURL commands',
|
description: 'Import cURL commands',
|
||||||
onImport(_ctx: Context, args: { text: string }) {
|
onImport(_ctx: Context, args: { text: string }) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
return convertCurl(args.text) as any;
|
return convertCurl(args.text) as any;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -177,19 +179,15 @@ function importCommand(parseEntries: ParseEntry[], workspaceId: string) {
|
|||||||
// Build the request //
|
// Build the request //
|
||||||
// ~~~~~~~~~~~~~~~~~ //
|
// ~~~~~~~~~~~~~~~~~ //
|
||||||
|
|
||||||
// Url and Parameters
|
|
||||||
let urlParameters: HttpUrlParameter[];
|
|
||||||
let url: string;
|
|
||||||
|
|
||||||
const urlArg = getPairValue(flagsByName, (singletons[0] as string) || '', ['url']);
|
const urlArg = getPairValue(flagsByName, (singletons[0] as string) || '', ['url']);
|
||||||
const [baseUrl, search] = splitOnce(urlArg, '?');
|
const [baseUrl, search] = splitOnce(urlArg, '?');
|
||||||
urlParameters =
|
const urlParameters: HttpUrlParameter[] =
|
||||||
search?.split('&').map((p) => {
|
search?.split('&').map((p) => {
|
||||||
const v = splitOnce(p, '=');
|
const v = splitOnce(p, '=');
|
||||||
return { name: decodeURIComponent(v[0] ?? ''), value: decodeURIComponent(v[1] ?? ''), enabled: true };
|
return { name: decodeURIComponent(v[0] ?? ''), value: decodeURIComponent(v[1] ?? ''), enabled: true };
|
||||||
}) ?? [];
|
}) ?? [];
|
||||||
|
|
||||||
url = baseUrl ?? urlArg;
|
const url = baseUrl ?? urlArg;
|
||||||
|
|
||||||
// Query params
|
// Query params
|
||||||
for (const p of flagsByName['url-query'] ?? []) {
|
for (const p of flagsByName['url-query'] ?? []) {
|
||||||
@@ -375,7 +373,7 @@ interface DataParameter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pairsToDataParameters(keyedPairs: FlagsByName): DataParameter[] {
|
function pairsToDataParameters(keyedPairs: FlagsByName): DataParameter[] {
|
||||||
let dataParameters: DataParameter[] = [];
|
const dataParameters: DataParameter[] = [];
|
||||||
|
|
||||||
for (const flagName of DATA_FLAGS) {
|
for (const flagName of DATA_FLAGS) {
|
||||||
const pairs = keyedPairs[flagName];
|
const pairs = keyedPairs[flagName];
|
||||||
@@ -386,9 +384,9 @@ function pairsToDataParameters(keyedPairs: FlagsByName): DataParameter[] {
|
|||||||
|
|
||||||
for (const p of pairs) {
|
for (const p of pairs) {
|
||||||
if (typeof p !== 'string') continue;
|
if (typeof p !== 'string') continue;
|
||||||
let params = p.split("&");
|
const params = p.split("&");
|
||||||
for (const param of params) {
|
for (const param of params) {
|
||||||
const [name, value] = param.split('=');
|
const [name, value] = splitOnce(param, '=');
|
||||||
if (param.startsWith('@')) {
|
if (param.startsWith('@')) {
|
||||||
// Yaak doesn't support files in url-encoded data, so
|
// Yaak doesn't support files in url-encoded data, so
|
||||||
dataParameters.push({
|
dataParameters.push({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { HttpRequest, Workspace } from '@yaakapp/api';
|
import type { HttpRequest, Workspace } from '@yaakapp/api';
|
||||||
import { describe, expect, test } from 'vitest';
|
import { describe, expect, test } from 'vitest';
|
||||||
import { convertCurl } from '../src';
|
import { convertCurl } from '../src';
|
||||||
|
|
||||||
@@ -221,20 +221,20 @@ describe('importer-curl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Imports post data into URL', () => {
|
test('Imports post data into URL', () => {
|
||||||
expect(
|
expect(convertCurl('curl -G https://api.stripe.com/v1/payment_links -d limit=3')).toEqual({
|
||||||
convertCurl('curl -G https://api.stripe.com/v1/payment_links -d limit=3'),
|
|
||||||
).toEqual({
|
|
||||||
resources: {
|
resources: {
|
||||||
workspaces: [baseWorkspace()],
|
workspaces: [baseWorkspace()],
|
||||||
httpRequests: [
|
httpRequests: [
|
||||||
baseRequest({
|
baseRequest({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: 'https://api.stripe.com/v1/payment_links',
|
url: 'https://api.stripe.com/v1/payment_links',
|
||||||
urlParameters: [{
|
urlParameters: [
|
||||||
enabled: true,
|
{
|
||||||
name: 'limit',
|
enabled: true,
|
||||||
value: '3',
|
name: 'limit',
|
||||||
}],
|
value: '3',
|
||||||
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -243,7 +243,9 @@ describe('importer-curl', () => {
|
|||||||
|
|
||||||
test('Imports multi-line JSON', () => {
|
test('Imports multi-line JSON', () => {
|
||||||
expect(
|
expect(
|
||||||
convertCurl(`curl -H Content-Type:application/json -d $'{\n "foo":"bar"\n}' https://yaak.app`),
|
convertCurl(
|
||||||
|
`curl -H Content-Type:application/json -d $'{\n "foo":"bar"\n}' https://yaak.app`,
|
||||||
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
resources: {
|
resources: {
|
||||||
workspaces: [baseWorkspace()],
|
workspaces: [baseWorkspace()],
|
||||||
@@ -364,6 +366,31 @@ describe('importer-curl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Imports weird body', () => {
|
||||||
|
expect(convertCurl(`curl 'https://yaak.app' -X POST --data-raw 'foo=bar=baz'`)).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: "POST",
|
||||||
|
bodyType: 'application/x-www-form-urlencoded',
|
||||||
|
body: {
|
||||||
|
form: [{ name: 'foo', value: 'bar=baz', enabled: true }],
|
||||||
|
},
|
||||||
|
headers: [
|
||||||
|
{
|
||||||
|
enabled: true,
|
||||||
|
name: 'Content-Type',
|
||||||
|
value: 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const idCount: Partial<Record<string, number>> = {};
|
const idCount: Partial<Record<string, number>> = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user