mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 18:01:08 +01:00
gRPC request actions and "copy as gRPCurl" (#232)
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@yaak/exporter-curl",
|
||||
"name": "@yaak/action-copy-curl",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,27 @@
|
||||
import { HttpRequest, PluginDefinition } from '@yaakapp/api';
|
||||
import type { HttpRequest, PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
const NEWLINE = '\\\n ';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
httpRequestActions: [{
|
||||
label: 'Copy as Curl',
|
||||
icon: 'copy',
|
||||
async onSelect(ctx, args) {
|
||||
const rendered_request = await ctx.httpRequest.render({ httpRequest: args.httpRequest, purpose: 'preview' });
|
||||
const data = await convertToCurl(rendered_request);
|
||||
await ctx.clipboard.copyText(data);
|
||||
await ctx.toast.show({ message: 'Curl copied to clipboard', icon: 'copy', color: 'success' });
|
||||
httpRequestActions: [
|
||||
{
|
||||
label: 'Copy as Curl',
|
||||
icon: 'copy',
|
||||
async onSelect(ctx, args) {
|
||||
const rendered_request = await ctx.httpRequest.render({
|
||||
httpRequest: args.httpRequest,
|
||||
purpose: 'preview',
|
||||
});
|
||||
const data = await convertToCurl(rendered_request);
|
||||
await ctx.clipboard.copyText(data);
|
||||
await ctx.toast.show({
|
||||
message: 'Command copied to clipboard',
|
||||
icon: 'copy',
|
||||
color: 'success',
|
||||
});
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
};
|
||||
|
||||
export async function convertToCurl(request: Partial<HttpRequest>) {
|
||||
@@ -22,7 +31,6 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
||||
if (request.method) xs.push('-X', request.method);
|
||||
if (request.url) xs.push(quote(request.url));
|
||||
|
||||
|
||||
xs.push(NEWLINE);
|
||||
|
||||
// Add URL params
|
||||
@@ -51,7 +59,10 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
} else if (typeof request.body?.query === 'string') {
|
||||
const body = { query: request.body.query || '', variables: maybeParseJSON(request.body.variables, undefined) };
|
||||
const body = {
|
||||
query: request.body.query || '',
|
||||
variables: maybeParseJSON(request.body.variables, undefined),
|
||||
};
|
||||
xs.push('--data-raw', `${quote(JSON.stringify(body))}`);
|
||||
xs.push(NEWLINE);
|
||||
} else if (typeof request.body?.text === 'string') {
|
||||
@@ -84,7 +95,7 @@ export async function convertToCurl(request: Partial<HttpRequest>) {
|
||||
}
|
||||
|
||||
function quote(arg: string): string {
|
||||
const escaped = arg.replace(/'/g, '\\\'');
|
||||
const escaped = arg.replace(/'/g, "\\'");
|
||||
return `'${escaped}'`;
|
||||
}
|
||||
|
||||
@@ -92,10 +103,10 @@ function onlyEnabled(v: { name?: string; enabled?: boolean }): boolean {
|
||||
return v.enabled !== false && !!v.name;
|
||||
}
|
||||
|
||||
function maybeParseJSON(v: any, fallback: any): string {
|
||||
function maybeParseJSON<T>(v: string, fallback: T) {
|
||||
try {
|
||||
return JSON.parse(v);
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
10
plugins/action-copy-grpcurl/package.json
Normal file
10
plugins/action-copy-grpcurl/package.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@yaak/action-copy-grpcurl",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
134
plugins/action-copy-grpcurl/src/index.ts
Normal file
134
plugins/action-copy-grpcurl/src/index.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import type { GrpcRequest, PluginDefinition } from '@yaakapp/api';
|
||||
import path from 'node:path';
|
||||
|
||||
const NEWLINE = '\\\n ';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
grpcRequestActions: [
|
||||
{
|
||||
label: 'Copy as gRPCurl',
|
||||
icon: 'copy',
|
||||
async onSelect(ctx, args) {
|
||||
const rendered_request = await ctx.grpcRequest.render({
|
||||
grpcRequest: args.grpcRequest,
|
||||
purpose: 'preview',
|
||||
});
|
||||
const data = await convert(rendered_request, args.protoFiles);
|
||||
await ctx.clipboard.copyText(data);
|
||||
await ctx.toast.show({
|
||||
message: 'Command copied to clipboard',
|
||||
icon: 'copy',
|
||||
color: 'success',
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export async function convert(request: Partial<GrpcRequest>, allProtoFiles: string[]) {
|
||||
const xs = ['grpcurl'];
|
||||
|
||||
if (request.url?.startsWith('http://')) {
|
||||
xs.push('-plaintext');
|
||||
}
|
||||
|
||||
const protoIncludes = allProtoFiles.filter((f) => !f.endsWith('.proto'));
|
||||
const protoFiles = allProtoFiles.filter((f) => f.endsWith('.proto'));
|
||||
|
||||
const inferredIncludes = new Set<string>();
|
||||
for (const f of protoFiles) {
|
||||
const protoDir = findParentProtoDir(f);
|
||||
if (protoDir) {
|
||||
inferredIncludes.add(protoDir);
|
||||
} else {
|
||||
inferredIncludes.add(path.join(f, '..'));
|
||||
inferredIncludes.add(path.join(f, '..', '..'));
|
||||
}
|
||||
}
|
||||
|
||||
for (const f of protoIncludes) {
|
||||
xs.push('-import-path', quote(f));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
for (const f of inferredIncludes.values()) {
|
||||
xs.push('-import-path', quote(f));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
for (const f of protoFiles) {
|
||||
xs.push('-proto', quote(f));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
// Add headers
|
||||
for (const h of (request.metadata ?? []).filter(onlyEnabled)) {
|
||||
xs.push('-H', quote(`${h.name}: ${h.value}`));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
// Add basic authentication
|
||||
if (request.authenticationType === 'basic') {
|
||||
const user = request.authentication?.username ?? '';
|
||||
const pass = request.authentication?.password ?? '';
|
||||
const encoded = btoa(`${user}:${pass}`);
|
||||
xs.push('-H', quote(`Authorization: Basic ${encoded}`));
|
||||
xs.push(NEWLINE);
|
||||
} else if (request.authenticationType === 'bearer') {
|
||||
// Add bearer authentication
|
||||
xs.push('-H', quote(`Authorization: Bearer ${request.authentication?.token ?? ''}`));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
// Add form params
|
||||
if (request.message) {
|
||||
xs.push('-d', `${quote(JSON.stringify(JSON.parse(request.message)))}`);
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
|
||||
// Add the server address
|
||||
if (request.url) {
|
||||
const server = request.url.replace(/^https?:\/\//, ''); // remove protocol
|
||||
xs.push(server);
|
||||
}
|
||||
|
||||
// Add service + method
|
||||
if (request.service && request.method) {
|
||||
xs.push(`${request.service}/${request.method}`);
|
||||
}
|
||||
|
||||
xs.push(NEWLINE);
|
||||
|
||||
// Remove trailing newline
|
||||
if (xs[xs.length - 1] === NEWLINE) {
|
||||
xs.splice(xs.length - 1, 1);
|
||||
}
|
||||
|
||||
return xs.join(' ');
|
||||
}
|
||||
|
||||
function quote(arg: string): string {
|
||||
const escaped = arg.replace(/'/g, "\\'");
|
||||
return `'${escaped}'`;
|
||||
}
|
||||
|
||||
function onlyEnabled(v: { name?: string; enabled?: boolean }): boolean {
|
||||
return v.enabled !== false && !!v.name;
|
||||
}
|
||||
|
||||
function findParentProtoDir(startPath: string): string | null {
|
||||
let dir = path.resolve(startPath);
|
||||
|
||||
while (true) {
|
||||
if (path.basename(dir) === 'proto') {
|
||||
return dir;
|
||||
}
|
||||
|
||||
const parent = path.dirname(dir);
|
||||
if (parent === dir) {
|
||||
return null; // Reached root
|
||||
}
|
||||
|
||||
dir = parent;
|
||||
}
|
||||
}
|
||||
110
plugins/action-copy-grpcurl/tests/index.test.ts
Normal file
110
plugins/action-copy-grpcurl/tests/index.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { convert } from '../src';
|
||||
|
||||
describe('exporter-curl', () => {
|
||||
test('Simple example', async () => {
|
||||
expect(
|
||||
await convert(
|
||||
{
|
||||
url: 'https://yaak.app',
|
||||
},
|
||||
[],
|
||||
),
|
||||
).toEqual([`grpcurl yaak.app`].join(` \\\n `));
|
||||
});
|
||||
test('Basic metadata', async () => {
|
||||
expect(
|
||||
await convert(
|
||||
{
|
||||
url: 'https://yaak.app',
|
||||
metadata: [
|
||||
{ name: 'aaa', value: 'AAA' },
|
||||
{ enabled: true, name: 'bbb', value: 'BBB' },
|
||||
{ enabled: false, name: 'disabled', value: 'ddd' },
|
||||
],
|
||||
},
|
||||
[],
|
||||
),
|
||||
).toEqual([`grpcurl -H 'aaa: AAA'`, `-H 'bbb: BBB'`, `yaak.app`].join(` \\\n `));
|
||||
});
|
||||
test('Single proto file', async () => {
|
||||
expect(await convert({ url: 'https://yaak.app' }, ['/foo/bar/baz.proto'])).toEqual(
|
||||
[
|
||||
`grpcurl -import-path '/foo/bar'`,
|
||||
`-import-path '/foo'`,
|
||||
`-proto '/foo/bar/baz.proto'`,
|
||||
`yaak.app`,
|
||||
].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Multiple proto files, same dir', async () => {
|
||||
expect(
|
||||
await convert({ url: 'https://yaak.app' }, ['/foo/bar/aaa.proto', '/foo/bar/bbb.proto']),
|
||||
).toEqual(
|
||||
[
|
||||
`grpcurl -import-path '/foo/bar'`,
|
||||
`-import-path '/foo'`,
|
||||
`-proto '/foo/bar/aaa.proto'`,
|
||||
`-proto '/foo/bar/bbb.proto'`,
|
||||
`yaak.app`,
|
||||
].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Multiple proto files, different dir', async () => {
|
||||
expect(
|
||||
await convert({ url: 'https://yaak.app' }, ['/aaa/bbb/ccc.proto', '/xxx/yyy/zzz.proto']),
|
||||
).toEqual(
|
||||
[
|
||||
`grpcurl -import-path '/aaa/bbb'`,
|
||||
`-import-path '/aaa'`,
|
||||
`-import-path '/xxx/yyy'`,
|
||||
`-import-path '/xxx'`,
|
||||
`-proto '/aaa/bbb/ccc.proto'`,
|
||||
`-proto '/xxx/yyy/zzz.proto'`,
|
||||
`yaak.app`,
|
||||
].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Single include dir', async () => {
|
||||
expect(await convert({ url: 'https://yaak.app' }, ['/aaa/bbb'])).toEqual(
|
||||
[`grpcurl -import-path '/aaa/bbb'`, `yaak.app`].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Multiple include dir', async () => {
|
||||
expect(await convert({ url: 'https://yaak.app' }, ['/aaa/bbb', '/xxx/yyy'])).toEqual(
|
||||
[`grpcurl -import-path '/aaa/bbb'`, `-import-path '/xxx/yyy'`, `yaak.app`].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Mixed proto and dirs', async () => {
|
||||
expect(
|
||||
await convert({ url: 'https://yaak.app' }, ['/aaa/bbb', '/xxx/yyy', '/foo/bar.proto']),
|
||||
).toEqual(
|
||||
[
|
||||
`grpcurl -import-path '/aaa/bbb'`,
|
||||
`-import-path '/xxx/yyy'`,
|
||||
`-import-path '/foo'`,
|
||||
`-import-path '/'`,
|
||||
`-proto '/foo/bar.proto'`,
|
||||
`yaak.app`,
|
||||
].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
test('Sends data', async () => {
|
||||
expect(
|
||||
await convert(
|
||||
{
|
||||
url: 'https://yaak.app',
|
||||
message: JSON.stringify({ foo: 'bar', baz: 1.0 }, null, 2),
|
||||
},
|
||||
['/foo.proto'],
|
||||
),
|
||||
).toEqual(
|
||||
[
|
||||
`grpcurl -import-path '/'`,
|
||||
`-proto '/foo.proto'`,
|
||||
`-d '{"foo":"bar","baz":1}'`,
|
||||
`yaak.app`,
|
||||
].join(` \\\n `),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "^9.0.2"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonpath-plus": "^10.3.0"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"shell-quote": "^1.8.1"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^2.4.2"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"openapi-to-postmanv2": "^5.0.0",
|
||||
|
||||
@@ -1,32 +1,23 @@
|
||||
import { Context, Environment, Folder, HttpRequest, PluginDefinition, Workspace } from '@yaakapp/api';
|
||||
import { convertPostman } from '@yaak/importer-postman/src';
|
||||
import type { Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { ImportPluginResponse } from '@yaakapp/api/lib/plugins/ImporterPlugin';
|
||||
import { convert } from 'openapi-to-postmanv2';
|
||||
import { convertPostman } from '@yaakapp/importer-postman/src';
|
||||
|
||||
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 plugin: PluginDefinition = {
|
||||
importer: {
|
||||
name: 'OpenAPI',
|
||||
description: 'Import OpenAPI collections',
|
||||
onImport(_ctx: Context, args: { text: string }) {
|
||||
return convertOpenApi(args.text) as any;
|
||||
return convertOpenApi(args.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export async function convertOpenApi(
|
||||
contents: string,
|
||||
): Promise<{ resources: ExportResources } | undefined> {
|
||||
export async function convertOpenApi(contents: string): Promise<ImportPluginResponse | undefined> {
|
||||
let postmanCollection;
|
||||
try {
|
||||
postmanCollection = await new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
convert({ type: 'string', data: contents }, {}, (err, result: any) => {
|
||||
if (err != null) reject(err);
|
||||
|
||||
@@ -35,7 +26,7 @@ export async function convertOpenApi(
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// Probably not an OpenAPI file, so skip it
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"main": "./build/index.js",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import {
|
||||
import type {
|
||||
Context,
|
||||
Environment,
|
||||
Folder,
|
||||
HttpRequest,
|
||||
HttpRequestHeader,
|
||||
HttpUrlParameter,
|
||||
PartialImportResources,
|
||||
PluginDefinition,
|
||||
Workspace,
|
||||
} from '@yaakapp/api';
|
||||
import type { ImportPluginResponse } from '@yaakapp/api/lib/plugins/ImporterPlugin';
|
||||
|
||||
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';
|
||||
@@ -27,19 +29,19 @@ export const plugin: PluginDefinition = {
|
||||
name: 'Postman',
|
||||
description: 'Import postman collections',
|
||||
onImport(_ctx: Context, args: { text: string }) {
|
||||
return convertPostman(args.text) as any;
|
||||
return convertPostman(args.text);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function convertPostman(
|
||||
contents: string,
|
||||
): { resources: ExportResources } | undefined {
|
||||
export function convertPostman(contents: string): ImportPluginResponse | undefined {
|
||||
const root = parseJSONToRecord(contents);
|
||||
if (root == null) return;
|
||||
|
||||
const info = toRecord(root.info);
|
||||
const isValidSchema = VALID_SCHEMAS.includes(info.schema);
|
||||
const isValidSchema = VALID_SCHEMAS.includes(
|
||||
typeof info.schema === 'string' ? info.schema : 'n/a',
|
||||
);
|
||||
if (!isValidSchema || !Array.isArray(root.item)) {
|
||||
return;
|
||||
}
|
||||
@@ -53,11 +55,17 @@ export function convertPostman(
|
||||
folders: [],
|
||||
};
|
||||
|
||||
const rawDescription = info.description;
|
||||
const description =
|
||||
typeof rawDescription === 'object' && rawDescription !== null && 'content' in rawDescription
|
||||
? String(rawDescription.content)
|
||||
: String(rawDescription);
|
||||
|
||||
const workspace: ExportResources['workspaces'][0] = {
|
||||
model: 'workspace',
|
||||
id: generateId('workspace'),
|
||||
name: info.name || 'Postman Import',
|
||||
description: info.description?.content ?? info.description,
|
||||
name: info.name ? String(info.name) : 'Postman Import',
|
||||
description,
|
||||
};
|
||||
exportResources.workspaces.push(workspace);
|
||||
|
||||
@@ -68,14 +76,14 @@ export function convertPostman(
|
||||
name: 'Global Variables',
|
||||
workspaceId: workspace.id,
|
||||
variables:
|
||||
root.variable?.map((v: any) => ({
|
||||
toArray<{ key: string; value: string }>(root.variable).map((v) => ({
|
||||
name: v.key,
|
||||
value: v.value,
|
||||
})) ?? [],
|
||||
};
|
||||
exportResources.environments.push(environment);
|
||||
|
||||
const importItem = (v: Record<string, any>, folderId: string | null = null) => {
|
||||
const importItem = (v: Record<string, unknown>, folderId: string | null = null) => {
|
||||
if (typeof v.name === 'string' && Array.isArray(v.item)) {
|
||||
const folder: ExportResources['folders'][0] = {
|
||||
model: 'folder',
|
||||
@@ -94,7 +102,11 @@ export function convertPostman(
|
||||
const requestAuthPath = importAuth(r.auth);
|
||||
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
||||
|
||||
const headers: HttpRequestHeader[] = toArray(r.header).map((h) => {
|
||||
const headers: HttpRequestHeader[] = toArray<{
|
||||
key: string;
|
||||
value: string;
|
||||
disabled?: boolean;
|
||||
}>(r.header).map((h) => {
|
||||
return {
|
||||
name: h.key,
|
||||
value: h.value,
|
||||
@@ -104,7 +116,9 @@ export function convertPostman(
|
||||
|
||||
// Add body headers only if they don't already exist
|
||||
for (const bodyPatchHeader of bodyPatch.headers) {
|
||||
const existingHeader = headers.find(h => h.name.toLowerCase() === bodyPatchHeader.name.toLowerCase());
|
||||
const existingHeader = headers.find(
|
||||
(h) => h.name.toLowerCase() === bodyPatchHeader.name.toLowerCase(),
|
||||
);
|
||||
if (existingHeader) {
|
||||
continue;
|
||||
}
|
||||
@@ -119,8 +133,8 @@ export function convertPostman(
|
||||
workspaceId: workspace.id,
|
||||
folderId,
|
||||
name: v.name,
|
||||
description: v.description || undefined,
|
||||
method: r.method || 'GET',
|
||||
description: v.description ? String(v.description) : undefined,
|
||||
method: typeof r.method === 'string' ? r.method : 'GET',
|
||||
url,
|
||||
urlParameters,
|
||||
body: bodyPatch.body,
|
||||
@@ -139,17 +153,19 @@ export function convertPostman(
|
||||
importItem(item);
|
||||
}
|
||||
|
||||
const resources = deleteUndefinedAttrs(convertTemplateSyntax(exportResources));
|
||||
const resources = deleteUndefinedAttrs(
|
||||
convertTemplateSyntax(exportResources),
|
||||
) as PartialImportResources;
|
||||
|
||||
return { resources };
|
||||
}
|
||||
|
||||
function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters'> {
|
||||
if (typeof url === 'string') {
|
||||
return { url, urlParameters: [] };
|
||||
function convertUrl(rawUrl: string | unknown): Pick<HttpRequest, 'url' | 'urlParameters'> {
|
||||
if (typeof rawUrl === 'string') {
|
||||
return { url: rawUrl, urlParameters: [] };
|
||||
}
|
||||
|
||||
url = toRecord(url);
|
||||
const url = toRecord(rawUrl);
|
||||
|
||||
let v = '';
|
||||
|
||||
@@ -199,10 +215,8 @@ function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters
|
||||
return { url: v, urlParameters: params };
|
||||
}
|
||||
|
||||
function importAuth(
|
||||
rawAuth: any,
|
||||
): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
|
||||
const auth = toRecord(rawAuth);
|
||||
function importAuth(rawAuth: unknown): Pick<HttpRequest, 'authentication' | 'authenticationType'> {
|
||||
const auth = toRecord<{ username?: string; password?: string; token?: string }>(rawAuth);
|
||||
if ('basic' in auth) {
|
||||
return {
|
||||
authenticationType: 'basic',
|
||||
@@ -223,8 +237,22 @@ function importAuth(
|
||||
}
|
||||
}
|
||||
|
||||
function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
|
||||
const body = toRecord(rawBody);
|
||||
function importBody(rawBody: unknown): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
|
||||
const body = toRecord(rawBody) as {
|
||||
mode: string;
|
||||
graphql: { query?: string; variables?: string };
|
||||
urlencoded?: { key?: string; value?: string; disabled?: boolean }[];
|
||||
formdata?: {
|
||||
key?: string;
|
||||
value?: string;
|
||||
disabled?: boolean;
|
||||
contentType?: string;
|
||||
src?: string;
|
||||
}[];
|
||||
raw?: string;
|
||||
options?: { raw?: { language?: string } };
|
||||
file?: { src?: string };
|
||||
};
|
||||
if (body.mode === 'graphql') {
|
||||
return {
|
||||
headers: [
|
||||
@@ -237,7 +265,10 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
||||
bodyType: 'graphql',
|
||||
body: {
|
||||
text: JSON.stringify(
|
||||
{ query: body.graphql.query, variables: parseJSONToRecord(body.graphql.variables) },
|
||||
{
|
||||
query: body.graphql?.query || '',
|
||||
variables: parseJSONToRecord(body.graphql?.variables || '{}'),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
@@ -254,7 +285,7 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
||||
],
|
||||
bodyType: 'application/x-www-form-urlencoded',
|
||||
body: {
|
||||
form: toArray(body.urlencoded).map((f) => ({
|
||||
form: toArray<NonNullable<typeof body.urlencoded>[0]>(body.urlencoded).map((f) => ({
|
||||
enabled: !f.disabled,
|
||||
name: f.key ?? '',
|
||||
value: f.value ?? '',
|
||||
@@ -272,19 +303,19 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
||||
],
|
||||
bodyType: 'multipart/form-data',
|
||||
body: {
|
||||
form: toArray(body.formdata).map((f) =>
|
||||
form: toArray<NonNullable<typeof body.formdata>[0]>(body.formdata).map((f) =>
|
||||
f.src != null
|
||||
? {
|
||||
enabled: !f.disabled,
|
||||
contentType: f.contentType ?? null,
|
||||
name: f.key ?? '',
|
||||
file: f.src ?? '',
|
||||
}
|
||||
enabled: !f.disabled,
|
||||
contentType: f.contentType ?? null,
|
||||
name: f.key ?? '',
|
||||
file: f.src ?? '',
|
||||
}
|
||||
: {
|
||||
enabled: !f.disabled,
|
||||
name: f.key ?? '',
|
||||
value: f.value ?? '',
|
||||
},
|
||||
enabled: !f.disabled,
|
||||
name: f.key ?? '',
|
||||
value: f.value ?? '',
|
||||
},
|
||||
),
|
||||
},
|
||||
};
|
||||
@@ -315,21 +346,23 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
|
||||
}
|
||||
}
|
||||
|
||||
function parseJSONToRecord(jsonStr: string): Record<string, any> | null {
|
||||
function parseJSONToRecord<T>(jsonStr: string): Record<string, T> | null {
|
||||
try {
|
||||
return toRecord(JSON.parse(jsonStr));
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function toRecord(value: any): Record<string, any> {
|
||||
if (Object.prototype.toString.call(value) === '[object Object]') return value;
|
||||
else return {};
|
||||
function toRecord<T>(value: Record<string, T> | unknown): Record<string, T> {
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
return value as Record<string, T>;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function toArray(value: any): any[] {
|
||||
if (Object.prototype.toString.call(value) === '[object Array]') return value;
|
||||
function toArray<T>(value: unknown): T[] {
|
||||
if (Object.prototype.toString.call(value) === '[object Array]') return value as T[];
|
||||
else return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [
|
||||
@@ -7,7 +7,7 @@ export const plugin: PluginDefinition = {
|
||||
description: 'Encode a value to base64',
|
||||
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
return Buffer.from(args.values.value ?? '').toString('base64');
|
||||
return Buffer.from(String(args.values.value ?? '')).toString('base64');
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -15,7 +15,7 @@ export const plugin: PluginDefinition = {
|
||||
description: 'Decode a value from base64',
|
||||
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
return Buffer.from(args.values.value ?? '', 'base64').toString('utf-8');
|
||||
return Buffer.from(String(args.values.value ?? ''), 'base64').toString('utf-8');
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -23,7 +23,7 @@ export const plugin: PluginDefinition = {
|
||||
description: 'Encode a value for use in a URL (percent-encoding)',
|
||||
args: [{ label: 'Plain Text', type: 'text', name: 'value', multiLine: true }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
return encodeURIComponent(args.values.value ?? '');
|
||||
return encodeURIComponent(String(args.values.value ?? ''));
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -32,7 +32,7 @@ export const plugin: PluginDefinition = {
|
||||
args: [{ label: 'Encoded Value', type: 'text', name: 'value', multiLine: true }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
try {
|
||||
return decodeURIComponent(args.values.value ?? '');
|
||||
return decodeURIComponent(String(args.values.value ?? ''));
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import fs from 'node:fs';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [{
|
||||
name: 'fs.readFile',
|
||||
description: 'Read the contents of a file as utf-8',
|
||||
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (!args.values.path) return null;
|
||||
templateFunctions: [
|
||||
{
|
||||
name: 'fs.readFile',
|
||||
description: 'Read the contents of a file as utf-8',
|
||||
args: [{ title: 'Select File', type: 'file', name: 'path', label: 'File' }],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (!args.values.path) return null;
|
||||
|
||||
try {
|
||||
return fs.promises.readFile(args.values.path, 'utf-8');
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return fs.promises.readFile(String(args.values.path ?? ''), 'utf-8');
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonpath-plus": "^10.3.0"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [{
|
||||
@@ -15,10 +15,10 @@ export const plugin: PluginDefinition = {
|
||||
|
||||
return await ctx.prompt.text({
|
||||
id: `prompt-${args.values.label}`,
|
||||
label: args.values.title ?? '',
|
||||
title: args.values.title ?? '',
|
||||
defaultValue: args.values.defaultValue,
|
||||
placeholder: args.values.placeholder,
|
||||
label: String(args.values.title ?? ''),
|
||||
title: String(args.values.title ?? ''),
|
||||
defaultValue: String(args.values.defaultValue),
|
||||
placeholder: String(args.values.placeholder),
|
||||
});
|
||||
},
|
||||
}],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [{
|
||||
name: 'regex.match',
|
||||
description: 'Extract',
|
||||
args: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'regex',
|
||||
label: 'Regular Expression',
|
||||
placeholder: '^\w+=(?<value>\w*)$',
|
||||
defaultValue: '^(.*)$',
|
||||
description: 'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
|
||||
},
|
||||
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
|
||||
],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (!args.values.regex) return '';
|
||||
templateFunctions: [
|
||||
{
|
||||
name: 'regex.match',
|
||||
description: 'Extract',
|
||||
args: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'regex',
|
||||
label: 'Regular Expression',
|
||||
placeholder: '^\\w+=(?<value>\\w*)$',
|
||||
defaultValue: '^(.*)$',
|
||||
description:
|
||||
'A JavaScript regular expression, evaluated using the Node.js RegExp engine. Capture groups or named groups can be used to extract values.',
|
||||
},
|
||||
{ type: 'text', name: 'input', label: 'Input Text', multiLine: true },
|
||||
],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (!args.values.regex || !args.values.input) return '';
|
||||
|
||||
const regex = new RegExp(String(args.values.regex));
|
||||
const match = args.values.input?.match(regex);
|
||||
return match?.groups
|
||||
? Object.values(match.groups)[0] ?? ''
|
||||
: match?.[1] ?? match?.[0] ?? '';
|
||||
const input = String(args.values.input);
|
||||
const regex = new RegExp(String(args.values.regex));
|
||||
const match = input.match(regex);
|
||||
return match?.groups
|
||||
? (Object.values(match.groups)[0] ?? '')
|
||||
: (match?.[1] ?? match?.[0] ?? '');
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [
|
||||
{
|
||||
name: 'request.body',
|
||||
args: [{
|
||||
name: 'requestId',
|
||||
label: 'Http Request',
|
||||
type: 'http_request',
|
||||
}],
|
||||
args: [
|
||||
{
|
||||
name: 'requestId',
|
||||
label: 'Http Request',
|
||||
type: 'http_request',
|
||||
},
|
||||
],
|
||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? 'n/a' });
|
||||
const requestId = String(args.values.requestId ?? 'n/a');
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: requestId });
|
||||
if (httpRequest == null) return null;
|
||||
return String(await ctx.templates.render({
|
||||
data: httpRequest.body?.text ?? '',
|
||||
purpose: args.purpose,
|
||||
}));
|
||||
return String(
|
||||
await ctx.templates.render({
|
||||
data: httpRequest.body?.text ?? '',
|
||||
purpose: args.purpose,
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -30,15 +35,22 @@ export const plugin: PluginDefinition = {
|
||||
name: 'header',
|
||||
label: 'Header Name',
|
||||
type: 'text',
|
||||
}],
|
||||
},
|
||||
],
|
||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? 'n/a' });
|
||||
const headerName = String(args.values.header ?? '');
|
||||
const requestId = String(args.values.requestId ?? 'n/a');
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: requestId });
|
||||
if (httpRequest == null) return null;
|
||||
const header = httpRequest.headers.find(h => h.name.toLowerCase() === args.values.header?.toLowerCase());
|
||||
return String(await ctx.templates.render({
|
||||
data: header?.value ?? '',
|
||||
purpose: args.purpose,
|
||||
}));
|
||||
const header = httpRequest.headers.find(
|
||||
(h) => h.name.toLowerCase() === headerName.toLowerCase(),
|
||||
);
|
||||
return String(
|
||||
await ctx.templates.render({
|
||||
data: header?.value ?? '',
|
||||
purpose: args.purpose,
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonpath-plus": "^10.3.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DOMParser } from '@xmldom/xmldom';
|
||||
import {
|
||||
import type {
|
||||
CallTemplateFunctionArgs,
|
||||
Context,
|
||||
FormInput,
|
||||
@@ -47,14 +47,14 @@ export const plugin: PluginDefinition = {
|
||||
if (!args.values.request || !args.values.header) return null;
|
||||
|
||||
const response = await getResponse(ctx, {
|
||||
requestId: args.values.request,
|
||||
requestId: String(args.values.request || ''),
|
||||
purpose: args.purpose,
|
||||
behavior: args.values.behavior ?? null,
|
||||
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||
});
|
||||
if (response == null) return null;
|
||||
|
||||
const header = response.headers.find(
|
||||
h => h.name.toLowerCase() === String(args.values.header ?? '').toLowerCase(),
|
||||
(h) => h.name.toLowerCase() === String(args.values.header ?? '').toLowerCase(),
|
||||
);
|
||||
return header?.value ?? null;
|
||||
},
|
||||
@@ -77,9 +77,9 @@ export const plugin: PluginDefinition = {
|
||||
if (!args.values.request || !args.values.path) return null;
|
||||
|
||||
const response = await getResponse(ctx, {
|
||||
requestId: args.values.request,
|
||||
requestId: String(args.values.request || ''),
|
||||
purpose: args.purpose,
|
||||
behavior: args.values.behavior ?? null,
|
||||
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||
});
|
||||
if (response == null) return null;
|
||||
|
||||
@@ -90,19 +90,19 @@ export const plugin: PluginDefinition = {
|
||||
let body;
|
||||
try {
|
||||
body = readFileSync(response.bodyPath, 'utf-8');
|
||||
} catch (_) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return filterJSONPath(body, args.values.path);
|
||||
} catch (err) {
|
||||
return filterJSONPath(body, String(args.values.path || ''));
|
||||
} catch {
|
||||
// Probably not JSON, try XPath
|
||||
}
|
||||
|
||||
try {
|
||||
return filterXPath(body, args.values.path);
|
||||
} catch (err) {
|
||||
return filterXPath(body, String(args.values.path || ''));
|
||||
} catch {
|
||||
// Probably not XML
|
||||
}
|
||||
|
||||
@@ -113,17 +113,14 @@ export const plugin: PluginDefinition = {
|
||||
name: 'response.body.raw',
|
||||
description: 'Access the entire response body, as text',
|
||||
aliases: ['response'],
|
||||
args: [
|
||||
requestArg,
|
||||
behaviorArg,
|
||||
],
|
||||
args: [requestArg, behaviorArg],
|
||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (!args.values.request) return null;
|
||||
|
||||
const response = await getResponse(ctx, {
|
||||
requestId: args.values.request,
|
||||
requestId: String(args.values.request || ''),
|
||||
purpose: args.purpose,
|
||||
behavior: args.values.behavior ?? null,
|
||||
behavior: args.values.behavior ? String(args.values.behavior) : null,
|
||||
});
|
||||
if (response == null) return null;
|
||||
|
||||
@@ -134,7 +131,7 @@ export const plugin: PluginDefinition = {
|
||||
let body;
|
||||
try {
|
||||
body = readFileSync(response.bodyPath, 'utf-8');
|
||||
} catch (_) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -173,11 +170,18 @@ function filterXPath(body: string, path: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
async function getResponse(ctx: Context, { requestId, behavior, purpose }: {
|
||||
requestId: string,
|
||||
behavior: string | null,
|
||||
purpose: RenderPurpose,
|
||||
}): Promise<HttpResponse | null> {
|
||||
async function getResponse(
|
||||
ctx: Context,
|
||||
{
|
||||
requestId,
|
||||
behavior,
|
||||
purpose,
|
||||
}: {
|
||||
requestId: string;
|
||||
behavior: string | null;
|
||||
purpose: RenderPurpose;
|
||||
},
|
||||
): Promise<HttpResponse | null> {
|
||||
if (!requestId) return null;
|
||||
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: requestId ?? 'n/a' });
|
||||
@@ -195,9 +199,7 @@ async function getResponse(ctx: Context, { requestId, behavior, purpose }: {
|
||||
|
||||
// Previews happen a ton, and we don't want to send too many times on "always," so treat
|
||||
// it as "smart" during preview.
|
||||
let finalBehavior = (behavior === 'always' && purpose === 'preview')
|
||||
? 'smart'
|
||||
: behavior;
|
||||
const finalBehavior = behavior === 'always' && purpose === 'preview' ? 'smart' : behavior;
|
||||
|
||||
// Send if no responses and "smart," or "always"
|
||||
if ((finalBehavior === 'smart' && response == null) || finalBehavior === 'always') {
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^11.1.0"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
"dev": "yaakcli dev ./src/index.js",
|
||||
"lint": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user