breaking: remove old action format design
Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
@@ -14,85 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createTemplateAction } from './createTemplateAction';
|
||||
import { z } from 'zod';
|
||||
|
||||
describe('createTemplateAction', () => {
|
||||
it('should allow creating with jsonschema and use the old deprecated types', () => {
|
||||
const action = createTemplateAction<{ repoUrl: string }, { test: string }>({
|
||||
id: 'test',
|
||||
schema: {
|
||||
input: {
|
||||
type: 'object',
|
||||
required: ['repoUrl'],
|
||||
properties: {
|
||||
repoUrl: { type: 'string' },
|
||||
},
|
||||
},
|
||||
output: {
|
||||
type: 'object',
|
||||
required: ['test'],
|
||||
properties: {
|
||||
test: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
handler: async ctx => {
|
||||
// @ts-expect-error - repoUrl is string
|
||||
const a: number = ctx.input.repoUrl;
|
||||
|
||||
const b: string = ctx.input.repoUrl;
|
||||
expect(b).toBeDefined();
|
||||
|
||||
const stream = ctx.logStream;
|
||||
expect(stream).toBeDefined();
|
||||
|
||||
ctx.output('test', 'value');
|
||||
|
||||
// @ts-expect-error - not valid output type
|
||||
ctx.output('test', 4);
|
||||
|
||||
// @ts-expect-error - not valid output name
|
||||
ctx.output('test2', 'value');
|
||||
},
|
||||
});
|
||||
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow creating with zod and use the old deprecated types', () => {
|
||||
const action = createTemplateAction({
|
||||
id: 'test',
|
||||
schema: {
|
||||
input: z.object({
|
||||
repoUrl: z.string(),
|
||||
}),
|
||||
output: z.object({
|
||||
test: z.string(),
|
||||
}),
|
||||
},
|
||||
handler: async ctx => {
|
||||
// @ts-expect-error - repoUrl is string
|
||||
const a: number = ctx.input.repoUrl;
|
||||
|
||||
const b: string = ctx.input.repoUrl;
|
||||
expect(b).toBeDefined();
|
||||
|
||||
const stream = ctx.logStream;
|
||||
expect(stream).toBeDefined();
|
||||
|
||||
ctx.output('test', 'value');
|
||||
|
||||
// @ts-expect-error - not valid output type
|
||||
ctx.output('test', 4);
|
||||
|
||||
// @ts-expect-error - not valid output name
|
||||
ctx.output('test2', 'value');
|
||||
},
|
||||
});
|
||||
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow creating with new first class zod support', () => {
|
||||
const action = createTemplateAction({
|
||||
id: 'test',
|
||||
@@ -128,4 +51,54 @@ describe('createTemplateAction', () => {
|
||||
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow creating with a function for input and output schema for more complex types', () => {
|
||||
const action = createTemplateAction({
|
||||
id: 'test',
|
||||
schema: {
|
||||
input: z =>
|
||||
z.union([
|
||||
z.object({
|
||||
repoUrl: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
numberThing: z.number(),
|
||||
}),
|
||||
]),
|
||||
output: z =>
|
||||
z.object({
|
||||
test: z.string(),
|
||||
}),
|
||||
},
|
||||
handler: async ctx => {
|
||||
ctx.output('test', 'value');
|
||||
|
||||
// @ts-expect-error - not valid output type
|
||||
ctx.output('test', 4);
|
||||
|
||||
// @ts-expect-error - not valid output name
|
||||
ctx.output('test2', 'value');
|
||||
|
||||
if ('repoUrl' in ctx.input) {
|
||||
// @ts-expect-error - not valid input type
|
||||
const a: number = ctx.input.repoUrl;
|
||||
|
||||
const b: string = ctx.input.repoUrl;
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect(b).toBeDefined();
|
||||
}
|
||||
|
||||
if ('numberThing' in ctx.input) {
|
||||
const a: number = ctx.input.numberThing;
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect(a).toBeDefined();
|
||||
|
||||
// @ts-expect-error - not valid input type
|
||||
const b: string = ctx.input.numberThing;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
expect(action).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,14 +30,18 @@ export type TemplateActionOptions<
|
||||
TActionInput extends JsonObject = {},
|
||||
TActionOutput extends JsonObject = {},
|
||||
TInputSchema extends
|
||||
| JsonObject
|
||||
| z.ZodType
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType } = JsonObject,
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
| ((zImpl: typeof z) => z.ZodType) = {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
TOutputSchema extends
|
||||
| JsonObject
|
||||
| z.ZodType
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType } = JsonObject,
|
||||
TSchemaType extends 'v1' | 'v2' = 'v1' | 'v2',
|
||||
| {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
}
|
||||
| ((zImpl: typeof z) => z.ZodType) = {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
TSchemaType extends 'v2' = 'v2',
|
||||
> = {
|
||||
id: string;
|
||||
description?: string;
|
||||
@@ -62,109 +66,82 @@ type FlattenOptionalProperties<T extends { [key in string]: unknown }> = Expand<
|
||||
[K in keyof T as undefined extends T[K] ? K : never]?: T[K];
|
||||
}
|
||||
>;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated migrate to using the new built in zod schema definitions for schemas
|
||||
*/
|
||||
export function createTemplateAction<
|
||||
TInputParams extends JsonObject = JsonObject,
|
||||
TOutputParams extends JsonObject = JsonObject,
|
||||
TInputSchema extends JsonObject = JsonObject,
|
||||
TOutputSchema extends JsonObject = JsonObject,
|
||||
TActionInput extends JsonObject = TInputParams,
|
||||
TActionOutput extends JsonObject = TOutputParams,
|
||||
>(
|
||||
action: TemplateActionOptions<
|
||||
TActionInput,
|
||||
TActionOutput,
|
||||
TInputSchema,
|
||||
TOutputSchema,
|
||||
'v1'
|
||||
>,
|
||||
): TemplateAction<TActionInput, TActionOutput, 'v1'>;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated migrate to using the new built in zod schema definitions for schemas
|
||||
*/
|
||||
export function createTemplateAction<
|
||||
TInputParams extends JsonObject = JsonObject,
|
||||
TOutputParams extends JsonObject = JsonObject,
|
||||
TInputSchema extends z.ZodType = z.ZodType,
|
||||
TOutputSchema extends z.ZodType = z.ZodType,
|
||||
TActionInput extends JsonObject = z.infer<TInputSchema>,
|
||||
TActionOutput extends JsonObject = z.infer<TOutputSchema>,
|
||||
>(
|
||||
action: TemplateActionOptions<
|
||||
TActionInput,
|
||||
TActionOutput,
|
||||
TInputSchema,
|
||||
TOutputSchema,
|
||||
'v1'
|
||||
>,
|
||||
): TemplateAction<TActionInput, TActionOutput, 'v1'>;
|
||||
/**
|
||||
* This function is used to create new template actions to get type safety.
|
||||
* Will convert zod schemas to json schemas for use throughout the system.
|
||||
* @public
|
||||
*/
|
||||
export function createTemplateAction<
|
||||
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
|
||||
TOutputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
|
||||
TInputSchema extends
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
| ((zImpl: typeof z) => z.ZodType),
|
||||
TOutputSchema extends
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
| ((zImpl: typeof z) => z.ZodType),
|
||||
>(
|
||||
action: TemplateActionOptions<
|
||||
{
|
||||
[key in keyof TInputSchema]: z.infer<ReturnType<TInputSchema[key]>>;
|
||||
},
|
||||
{
|
||||
[key in keyof TOutputSchema]: z.infer<ReturnType<TOutputSchema[key]>>;
|
||||
},
|
||||
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
? {
|
||||
[key in keyof TInputSchema]: z.infer<ReturnType<TInputSchema[key]>>;
|
||||
}
|
||||
: TInputSchema extends (zImpl: typeof z) => z.ZodType
|
||||
? z.infer<ReturnType<TInputSchema>>
|
||||
: never,
|
||||
TOutputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
? {
|
||||
[key in keyof TOutputSchema]: z.infer<ReturnType<TOutputSchema[key]>>;
|
||||
}
|
||||
: TOutputSchema extends (zImpl: typeof z) => z.ZodType
|
||||
? z.infer<ReturnType<TOutputSchema>>
|
||||
: never,
|
||||
TInputSchema,
|
||||
TOutputSchema,
|
||||
'v2'
|
||||
>,
|
||||
): TemplateAction<
|
||||
FlattenOptionalProperties<{
|
||||
[key in keyof TInputSchema]: z.output<ReturnType<TInputSchema[key]>>;
|
||||
}>,
|
||||
FlattenOptionalProperties<{
|
||||
[key in keyof TOutputSchema]: z.output<ReturnType<TOutputSchema[key]>>;
|
||||
}>,
|
||||
FlattenOptionalProperties<
|
||||
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
? {
|
||||
[key in keyof TInputSchema]: z.output<ReturnType<TInputSchema[key]>>;
|
||||
}
|
||||
: TInputSchema extends (zImpl: typeof z) => z.ZodType
|
||||
? z.output<ReturnType<TInputSchema>>
|
||||
: never
|
||||
>,
|
||||
FlattenOptionalProperties<
|
||||
TOutputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
? {
|
||||
[key in keyof TOutputSchema]: z.output<
|
||||
ReturnType<TOutputSchema[key]>
|
||||
>;
|
||||
}
|
||||
: TOutputSchema extends (zImpl: typeof z) => z.ZodType
|
||||
? z.output<ReturnType<TOutputSchema>>
|
||||
: never
|
||||
>,
|
||||
'v2'
|
||||
>;
|
||||
export function createTemplateAction<
|
||||
TInputParams extends JsonObject = JsonObject,
|
||||
TOutputParams extends JsonObject = JsonObject,
|
||||
TInputSchema extends
|
||||
| JsonObject
|
||||
| z.ZodType
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType } = JsonObject,
|
||||
TOutputSchema extends
|
||||
| JsonObject
|
||||
| z.ZodType
|
||||
| { [key in string]: (zImpl: typeof z) => z.ZodType } = JsonObject,
|
||||
TActionInput extends JsonObject = TInputSchema extends z.ZodType<
|
||||
any,
|
||||
any,
|
||||
infer IReturn
|
||||
>
|
||||
? IReturn
|
||||
: TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType } = {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
TOutputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType } = {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
},
|
||||
TActionInput extends JsonObject = TInputSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
}
|
||||
? Expand<{
|
||||
[key in keyof TInputSchema]: z.infer<ReturnType<TInputSchema[key]>>;
|
||||
}>
|
||||
: TInputParams,
|
||||
TActionOutput extends JsonObject = TOutputSchema extends z.ZodType<
|
||||
any,
|
||||
any,
|
||||
infer IReturn
|
||||
>
|
||||
? IReturn
|
||||
: TOutputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
: never,
|
||||
TActionOutput extends JsonObject = TOutputSchema extends {
|
||||
[key in string]: (zImpl: typeof z) => z.ZodType;
|
||||
}
|
||||
? Expand<{
|
||||
[key in keyof TOutputSchema]: z.infer<ReturnType<TOutputSchema[key]>>;
|
||||
}>
|
||||
: TOutputParams,
|
||||
: never,
|
||||
>(
|
||||
action: TemplateActionOptions<
|
||||
TActionInput,
|
||||
@@ -172,13 +149,7 @@ export function createTemplateAction<
|
||||
TInputSchema,
|
||||
TOutputSchema
|
||||
>,
|
||||
): TemplateAction<
|
||||
TActionInput,
|
||||
TActionOutput,
|
||||
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }
|
||||
? 'v2'
|
||||
: 'v1'
|
||||
> {
|
||||
): TemplateAction<TActionInput, TActionOutput, 'v2'> {
|
||||
const { inputSchema, outputSchema } = parseSchemas(
|
||||
action as TemplateActionOptions<any, any, any>,
|
||||
);
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Logger } from 'winston';
|
||||
import { Writable } from 'stream';
|
||||
import { JsonObject, JsonValue } from '@backstage/types';
|
||||
import { TaskSecrets } from '../tasks';
|
||||
import { TemplateInfo } from '@backstage/plugin-scaffolder-common';
|
||||
@@ -32,143 +30,75 @@ import {
|
||||
export type ActionContext<
|
||||
TActionInput extends JsonObject,
|
||||
TActionOutput extends JsonObject = JsonObject,
|
||||
TSchemaType extends 'v1' | 'v2' = 'v1',
|
||||
> = TSchemaType extends 'v2'
|
||||
? {
|
||||
logger: LoggerService;
|
||||
secrets?: TaskSecrets;
|
||||
workspacePath: string;
|
||||
input: TActionInput;
|
||||
checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T>;
|
||||
output(
|
||||
name: keyof TActionOutput,
|
||||
value: TActionOutput[keyof TActionOutput],
|
||||
): void;
|
||||
/**
|
||||
* Creates a temporary directory for use by the action, which is then cleaned up automatically.
|
||||
*/
|
||||
createTemporaryDirectory(): Promise<string>;
|
||||
_TSchemaType extends 'v2' = 'v2',
|
||||
> = {
|
||||
logger: LoggerService;
|
||||
secrets?: TaskSecrets;
|
||||
workspacePath: string;
|
||||
input: TActionInput;
|
||||
checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T>;
|
||||
output(
|
||||
name: keyof TActionOutput,
|
||||
value: TActionOutput[keyof TActionOutput],
|
||||
): void;
|
||||
/**
|
||||
* Creates a temporary directory for use by the action, which is then cleaned up automatically.
|
||||
*/
|
||||
createTemporaryDirectory(): Promise<string>;
|
||||
|
||||
/**
|
||||
* Get the credentials for the current request
|
||||
*/
|
||||
getInitiatorCredentials(): Promise<BackstageCredentials>;
|
||||
/**
|
||||
* Get the credentials for the current request
|
||||
*/
|
||||
getInitiatorCredentials(): Promise<BackstageCredentials>;
|
||||
|
||||
/**
|
||||
* Task information
|
||||
*/
|
||||
task: {
|
||||
id: string;
|
||||
};
|
||||
/**
|
||||
* Task information
|
||||
*/
|
||||
task: {
|
||||
id: string;
|
||||
};
|
||||
|
||||
templateInfo?: TemplateInfo;
|
||||
templateInfo?: TemplateInfo;
|
||||
|
||||
/**
|
||||
* Whether this action invocation is a dry-run or not.
|
||||
* This will only ever be true if the actions as marked as supporting dry-runs.
|
||||
*/
|
||||
isDryRun?: boolean;
|
||||
/**
|
||||
* Whether this action invocation is a dry-run or not.
|
||||
* This will only ever be true if the actions as marked as supporting dry-runs.
|
||||
*/
|
||||
isDryRun?: boolean;
|
||||
|
||||
/**
|
||||
* The user which triggered the action.
|
||||
*/
|
||||
user?: {
|
||||
/**
|
||||
* The decorated entity from the Catalog
|
||||
*/
|
||||
entity?: UserEntity;
|
||||
/**
|
||||
* An entity ref for the author of the task
|
||||
*/
|
||||
ref?: string;
|
||||
};
|
||||
/**
|
||||
* The user which triggered the action.
|
||||
*/
|
||||
user?: {
|
||||
/**
|
||||
* The decorated entity from the Catalog
|
||||
*/
|
||||
entity?: UserEntity;
|
||||
/**
|
||||
* An entity ref for the author of the task
|
||||
*/
|
||||
ref?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implement the signal to make your custom step abortable https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
/**
|
||||
* Implement the signal to make your custom step abortable https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
|
||||
/**
|
||||
* Optional value of each invocation
|
||||
*/
|
||||
each?: JsonObject;
|
||||
}
|
||||
: /** @deprecated **/
|
||||
{
|
||||
// TODO(blam): move this to LoggerService
|
||||
logger: Logger;
|
||||
/** @deprecated - use `ctx.logger` instead */
|
||||
logStream: Writable;
|
||||
secrets?: TaskSecrets;
|
||||
workspacePath: string;
|
||||
input: TActionInput;
|
||||
checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T>;
|
||||
output(
|
||||
name: keyof TActionOutput,
|
||||
value: TActionOutput[keyof TActionOutput],
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Creates a temporary directory for use by the action, which is then cleaned up automatically.
|
||||
*/
|
||||
createTemporaryDirectory(): Promise<string>;
|
||||
|
||||
/**
|
||||
* Get the credentials for the current request
|
||||
*/
|
||||
getInitiatorCredentials(): Promise<BackstageCredentials>;
|
||||
|
||||
/**
|
||||
* Task information
|
||||
*/
|
||||
task: {
|
||||
id: string;
|
||||
};
|
||||
|
||||
templateInfo?: TemplateInfo;
|
||||
|
||||
/**
|
||||
* Whether this action invocation is a dry-run or not.
|
||||
* This will only ever be true if the actions as marked as supporting dry-runs.
|
||||
*/
|
||||
isDryRun?: boolean;
|
||||
|
||||
/**
|
||||
* The user which triggered the action.
|
||||
*/
|
||||
user?: {
|
||||
/**
|
||||
* The decorated entity from the Catalog
|
||||
*/
|
||||
entity?: UserEntity;
|
||||
/**
|
||||
* An entity ref for the author of the task
|
||||
*/
|
||||
ref?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implement the signal to make your custom step abortable https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
|
||||
/**
|
||||
* Optional value of each invocation
|
||||
*/
|
||||
each?: JsonObject;
|
||||
};
|
||||
/**
|
||||
* Optional value of each invocation
|
||||
*/
|
||||
each?: JsonObject;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type TemplateAction<
|
||||
TActionInput extends JsonObject = JsonObject,
|
||||
TActionOutput extends JsonObject = JsonObject,
|
||||
TSchemaType extends 'v1' | 'v2' = 'v1',
|
||||
TSchemaType extends 'v2' = 'v2',
|
||||
> = {
|
||||
id: string;
|
||||
description?: string;
|
||||
|
||||
@@ -130,11 +130,7 @@ function checkRequiredParams(repoUrl: URL, ...params: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
const isZodSchema = (schema: unknown): schema is z.ZodType => {
|
||||
return typeof schema === 'object' && !!schema && 'safeParseAsync' in schema;
|
||||
};
|
||||
|
||||
const isNativeZodSchema = (
|
||||
const isKeyValueZodCallback = (
|
||||
schema: unknown,
|
||||
): schema is { [key in string]: (zImpl: typeof z) => z.ZodType } => {
|
||||
return (
|
||||
@@ -144,23 +140,20 @@ const isNativeZodSchema = (
|
||||
);
|
||||
};
|
||||
|
||||
const isZodFunctionDefinition = (
|
||||
schema: unknown,
|
||||
): schema is (zImpl: typeof z) => z.ZodType => {
|
||||
return typeof schema === 'function';
|
||||
};
|
||||
|
||||
export const parseSchemas = (
|
||||
action: TemplateActionOptions,
|
||||
action: TemplateActionOptions<any, any, any>,
|
||||
): { inputSchema?: Schema; outputSchema?: Schema } => {
|
||||
if (!action.schema) {
|
||||
return { inputSchema: undefined, outputSchema: undefined };
|
||||
}
|
||||
|
||||
if (isZodSchema(action.schema.input)) {
|
||||
return {
|
||||
inputSchema: zodToJsonSchema(action.schema.input) as Schema,
|
||||
outputSchema: isZodSchema(action.schema.output)
|
||||
? (zodToJsonSchema(action.schema.output) as Schema)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (isNativeZodSchema(action.schema.input)) {
|
||||
if (isKeyValueZodCallback(action.schema.input)) {
|
||||
const input = z.object(
|
||||
Object.fromEntries(
|
||||
Object.entries(action.schema.input).map(([k, v]) => [k, v(z)]),
|
||||
@@ -169,7 +162,7 @@ export const parseSchemas = (
|
||||
|
||||
return {
|
||||
inputSchema: zodToJsonSchema(input) as Schema,
|
||||
outputSchema: isNativeZodSchema(action.schema.output)
|
||||
outputSchema: isKeyValueZodCallback(action.schema.output)
|
||||
? (zodToJsonSchema(
|
||||
z.object(
|
||||
Object.fromEntries(
|
||||
@@ -181,9 +174,18 @@ export const parseSchemas = (
|
||||
};
|
||||
}
|
||||
|
||||
if (isZodFunctionDefinition(action.schema.input)) {
|
||||
return {
|
||||
inputSchema: zodToJsonSchema(action.schema.input(z)) as Schema,
|
||||
outputSchema: isZodFunctionDefinition(action.schema.output)
|
||||
? (zodToJsonSchema(action.schema.output(z)) as Schema)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
inputSchema: action.schema.input,
|
||||
outputSchema: action.schema.output,
|
||||
inputSchema: undefined,
|
||||
outputSchema: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user