Skip to content

Commit

Permalink
feat(ran format): ran format
Browse files Browse the repository at this point in the history
  • Loading branch information
Blokh committed Jun 28, 2023
1 parent 2535b8e commit a076fc9
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const Cases: FunctionComponent<ICasesProps> & ICasesChildren = ({
</div>
</div>
<div className={`flex items-center justify-between`}>
<div className="dropdown dropdown-bottom dropdown-hover z-[60]">
<div className="dropdown-hover dropdown dropdown-bottom z-[60]">
<button
className={`btn-ghost btn-sm btn h-[2.125rem] gap-2 border-neutral/10 text-xs focus-visible:outline-primary theme-dark:border-neutral/50`}
tabIndex={0}
Expand Down
2 changes: 0 additions & 2 deletions packages/common/src/utils/zod-error-to-readable/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export { zodErrorToReadable } from './zod-error-to-readable';


Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ZodError } from 'zod'
import { ZodError } from 'zod';

export const zodErrorToReadable = (error: ZodError) => {
return error.issues.map((err) => {
return `${err.path?.join(`.`)}: ${err.message}`
}).join('\n');
}
return error.issues
.map(err => {
return `${err.path?.join(`.`)}: ${err.message}`;
})
.join('\n');
};
Original file line number Diff line number Diff line change
@@ -1,55 +1,54 @@
import { describe, expect, it } from 'vitest';
import { validate } from "./api-plugin.validator";
import { ZodError } from 'zod';
import { validate } from './api-plugin.validator';
import { ZodError } from 'zod';
describe('Api Validator', () => {
describe('validate Api Plugin', () => {

const apiPlugin = {
name: 'ballerineEnrichment',
url: 'https://simple-kyb-demo.s3.eu-central-1.amazonaws.com/mock-data/business_test_us.json',
method: 'GET',
stateNames: ['checkBusinessScore'],
successAction: 'API_CALL_SUCCESS',
errorAction: 'API_CALL_FAILURE',
request: {
transform: {
transformer: 'jq',
mapping: '{data: .entity.id}',
},
},
response: {
transform: {transformer: 'jq', mapping: '{result: .}'},
name: 'ballerineEnrichment',
url: 'https://simple-kyb-demo.s3.eu-central-1.amazonaws.com/mock-data/business_test_us.json',
method: 'GET',
stateNames: ['checkBusinessScore'],
successAction: 'API_CALL_SUCCESS',
errorAction: 'API_CALL_FAILURE',
request: {
transform: {
transformer: 'jq',
mapping: '{data: .entity.id}',
},
};
},
response: {
transform: { transformer: 'jq', mapping: '{result: .}' },
},
};

describe('when api plugin is valid', () => {
it('does not throw validation exception', async () => {
expect(() => validate(apiPlugin)).not.toThrow()
expect(() => validate(apiPlugin)).not.toThrow();
});
});

describe('when invalid plugin is valid - invalid request', () => {
it('does not throw validation exception', async () => {
let failingPlugin = structuredClone(apiPlugin);
failingPlugin.request.transform.transformer = {someObjectKey: "someObjectValue"};
expect(() => validate(failingPlugin)).toThrowError(ZodError)
failingPlugin.request.transform.transformer = { someObjectKey: 'someObjectValue' };
expect(() => validate(failingPlugin)).toThrowError(ZodError);
});
});

describe('when invalid plugin is valid - missing callback', () => {
it('does not throw validation exception', async () => {
let failingPlugin = structuredClone(apiPlugin);
failingPlugin.errorAction = undefined;
expect(() => validate(failingPlugin)).toThrowError(ZodError)
expect(() => validate(failingPlugin)).toThrowError(ZodError);
});
})
});

describe('when invalid plugin is valid - stateNames is string', () => {
it('does not throw validation exception', async () => {
let failingPlugin = structuredClone(apiPlugin);
failingPlugin.stateNames = "someState";
expect(() => validate(failingPlugin)).toThrowError(ZodError)
failingPlugin.stateNames = 'someState';
expect(() => validate(failingPlugin)).toThrowError(ZodError);
});
})
});
});
});
Original file line number Diff line number Diff line change
@@ -1,45 +1,53 @@
import { z } from 'zod';
import { AnyRecord } from "@/types";
import { AnyRecord } from '@/types';

const RequestSchema = z.object({
transform: z.object({
transformer: z.string(),
mapping: z.string(),
}),
schema: z.object({
$schema: z.string(),
type: z.string(),
properties: z.object({}),
required: z.array(z.string()).optional(),
}).optional(),
schema: z
.object({
$schema: z.string(),
type: z.string(),
properties: z.object({}),
required: z.array(z.string()).optional(),
})
.optional(),
});

const ResponseSchema = z.object({
transform: z.object({
transformer: z.string(),
mapping: z.string(),
}),
schema: z.object({
$schema: z.string(),
type: z.string(),
properties: z.object({}),
required: z.array(z.string()).optional(),
}).optional(),
}).optional();
const ResponseSchema = z
.object({
transform: z.object({
transformer: z.string(),
mapping: z.string(),
}),
schema: z
.object({
$schema: z.string(),
type: z.string(),
properties: z.object({}),
required: z.array(z.string()).optional(),
})
.optional(),
})
.optional();

export const ApiPluginSchema = z.object({
name: z.string(),
url: z.string().url(),
logo: z.string().optional(),
method: z.string(),
headers: z.record(z.string()).optional(),
stateNames: z.array(z.string()),
successAction: z.string(),
errorAction: z.string(),
request: RequestSchema,
response: ResponseSchema,
}).strict();
export const ApiPluginSchema = z
.object({
name: z.string(),
url: z.string().url(),
logo: z.string().optional(),
method: z.string(),
headers: z.record(z.string()).optional(),
stateNames: z.array(z.string()),
successAction: z.string(),
errorAction: z.string(),
request: RequestSchema,
response: ResponseSchema,
})
.strict();

export const validate = (apiPlugin: AnyRecord) => {
return ApiPluginSchema.parse(apiPlugin);
}
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { describe, expect, it } from 'vitest';
import { validate } from "./webhook-plugin.validator";
import { ZodError } from 'zod';
import { validate } from './webhook-plugin.validator';
import { ZodError } from 'zod';
describe('Webhook Validator', () => {
describe('validate Webhook Plugin', () => {

const webhookPlugin = {
name: 'ballerineEnrichmentHook',
url: 'https://simple-kyb-demo.s3.eu-central-1.amazonaws.com/mock-data/business_test_us.json',
method: 'GET',
headers: {'some_header': 'some_value'},
headers: { some_header: 'some_value' },
stateNames: ['checkBusinessScore'],
request: {
transform: {
Expand All @@ -20,25 +19,25 @@ describe('Webhook Validator', () => {

describe('when webhook plugin is valid', () => {
it('does not throw validation exception', async () => {
expect(() => validate(webhookPlugin)).not.toThrow()
expect(() => validate(webhookPlugin)).not.toThrow();
});
});

describe('when webhook has response - throws invalid', () => {
let failingWebhookPlugin = structuredClone(webhookPlugin)
failingWebhookPlugin.response = {transform: {transformer: 'jq', mapping: '{result: .}'}}
let failingWebhookPlugin = structuredClone(webhookPlugin);
failingWebhookPlugin.response = { transform: { transformer: 'jq', mapping: '{result: .}' } };

it('does not throw validation exception', async () => {
expect(() => validate(failingWebhookPlugin)).toThrowError(ZodError)
expect(() => validate(failingWebhookPlugin)).toThrowError(ZodError);
});
});

describe('when webhook no request - throws invalid', () => {
let failingWebhookPlugin = structuredClone(webhookPlugin)
failingWebhookPlugin.request = undefined
let failingWebhookPlugin = structuredClone(webhookPlugin);
failingWebhookPlugin.request = undefined;

it('does not throw validation exception', async () => {
expect(() => validate(failingWebhookPlugin)).toThrowError(ZodError)
expect(() => validate(failingWebhookPlugin)).toThrowError(ZodError);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiPluginSchema } from "./api-plugin.validator";
import { AnyRecord } from "@/types";
import { ApiPluginSchema } from './api-plugin.validator';
import { AnyRecord } from '@/types';

export const WebhookPluginSchema = ApiPluginSchema.pick({
name: true,
Expand All @@ -8,8 +8,8 @@ export const WebhookPluginSchema = ApiPluginSchema.pick({
headers: true,
stateNames: true,
request: true,
}).strict()
}).strict();

export const validate = (webhookPlugin: AnyRecord) => {
return WebhookPluginSchema.parse(webhookPlugin);
}
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { validateWorkflowDefinition } from "./workflow-definition-validator";
import { validateWorkflowDefinition } from './workflow-definition-validator';
describe('WorkflowDefinitionValidator', () => {
describe('validate Api Plugin', () => {
const definition = {
Expand Down Expand Up @@ -54,38 +54,40 @@ describe('WorkflowDefinitionValidator', () => {
name: 'ballerineEnrichmentHook',
url: 'https://simple-kyb-demo.s3.eu-central-1.amazonaws.com/mock-data/business_test_us.json',
method: 'GET',
headers: {'some_header': 'some_value'},
headers: { some_header: 'some_value' },
stateNames: ['checkBusinessScore'],
request: {
transform: {
transformer: 'jq',
mapping: '{data: .entity.id}',
},
},
}
},
];

const workflowDefinition = {
...definition,
...{extensions: {apiPlugins: apiPluginsSchemas}}
}
...{ extensions: { apiPlugins: apiPluginsSchemas } },
};

describe('when api plugin is valid', () => {
it('returns valid response', async () => {
const validationResponse = validateWorkflowDefinition(workflowDefinition);

expect(validationResponse).toEqual({isValid: true, error: undefined});
expect(validationResponse).toEqual({ isValid: true, error: undefined });
});
});

describe('when api plugin is invalid', () => {
it('it returns invalid response', async () => {
workflowDefinition.extensions.apiPlugins[0].request = "dwadwad"
workflowDefinition.extensions.apiPlugins[0].request = 'dwadwad';
const validationResponse = validateWorkflowDefinition(workflowDefinition);

expect(validationResponse).toEqual({isValid: false, error: "extensions.apiPlugins.0: Invalid input"});
expect(validationResponse).toEqual({
isValid: false,
error: 'extensions.apiPlugins.0: Invalid input',
});
});
});

});
});
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
import { z } from 'zod';
import { ApiPluginSchema } from "./api-plugin.validator";
import { WebhookPluginSchema } from "./webhook-plugin.validator";
import { AnyRecord } from "@/types";
import { zodErrorToReadable } from "../../utils/zod-error-to-readable";
import { ApiPluginSchema } from './api-plugin.validator';
import { WebhookPluginSchema } from './webhook-plugin.validator';
import { AnyRecord } from '@/types';
import { zodErrorToReadable } from '../../utils/zod-error-to-readable';

const ApiOrWebhookSchema = z.union([ApiPluginSchema, WebhookPluginSchema]);

const WorkflowDefinitionSchema = z.object({
extensions: z.object({
statePlugins: z.array(z.record(z.any())).optional(),
apiPlugins: z.array(ApiOrWebhookSchema).optional(),
}).optional(),
}).optional();
const WorkflowDefinitionSchema = z
.object({
extensions: z
.object({
statePlugins: z.array(z.record(z.any())).optional(),
apiPlugins: z.array(ApiOrWebhookSchema).optional(),
})
.optional(),
})
.optional();
export const validateWorkflowDefinition = (workflowDefinition: AnyRecord) => {
const parseResult = WorkflowDefinitionSchema.safeParse(workflowDefinition);

if (!parseResult.success) {
return {isValid: false, error: zodErrorToReadable(parseResult.error)};
return { isValid: false, error: zodErrorToReadable(parseResult.error) };
}
return { isValid: true, error: undefined };
}
};

export const validWorkflowDefinitionOrThrow = (workflowDefinition: AnyRecord) => {
const parseResult = WorkflowDefinitionSchema.parse(workflowDefinition);

return parseResult;
}

};

0 comments on commit a076fc9

Please sign in to comment.