Skip to content

Commit

Permalink
Add recursive type investigation for imports (#158)
Browse files Browse the repository at this point in the history
* Recusivly look through function for types

* Improve code coverage

* Added more tests

* test with primitive parameter, object parameter, array parameter
  • Loading branch information
WilliamBergamin authored Apr 4, 2023
1 parent 90b54ce commit 3d60026
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 14 deletions.
44 changes: 32 additions & 12 deletions src/schema/slack/functions/_scripts/src/templates/template_utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { pascalCase } from "../../../../../../dev_deps.ts";
import { FunctionParameter, FunctionRecord } from "../types.ts";
import { FunctionProperty, FunctionRecord } from "../types.ts";
import SchemaTypes from "../../../../../schema_types.ts";
import SlackTypes from "../../../../schema_types.ts";
import { InternalSlackTypes } from "../../../../types/custom/mod.ts";
import { AllowedTypeValue, AllowedTypeValueObject } from "./types.ts";
import { isCustomType } from "../../../../../../types/mod.ts";
import { isArrayFunctionProperty } from "../utils.ts";
import { isObjectFunctionProperty } from "../utils.ts";

export function autogeneratedComment(): string {
const time = new Date();
Expand All @@ -31,31 +33,49 @@ export function getParameterType(type: AllowedTypeValue): string {

const getParameterList = (
functionRecord: FunctionRecord,
): FunctionParameter[] => [
): FunctionProperty[] => [
...functionRecord.input_parameters,
...functionRecord.output_parameters,
];

const hasParamsFromTypeObject = (
functionRecord: FunctionRecord,
const hasTypeObject = (
types: string[],
typeObject: AllowedTypeValueObject,
): boolean =>
getParameterList(functionRecord).some((param) =>
Object.values(typeObject)
// TODO: This needs to account for objects, arrays, and custom types
.map((val) => getParameterType(val))
.includes(param.type)
types.some((t) =>
Object.values(typeObject).map((val) => getParameterType(val)).includes(t)
);

const extractTypes = (properties: FunctionProperty[]): string[] => {
let types: Set<string> = new Set();
properties.forEach((property) => {
types.add(property.type);
if (isArrayFunctionProperty(property)) {
types = new Set([
...types,
...extractTypes([property.items]),
]);
}
if (isObjectFunctionProperty(property)) {
types = new Set([
...types,
...extractTypes(Object.values(property.properties)),
]);
}
});
return Array.from(types);
};

export function renderTypeImports(functionRecord: FunctionRecord) {
const typescript: string[] = [];
if (hasParamsFromTypeObject(functionRecord, SchemaTypes)) {
const functionRecordTypes = extractTypes(getParameterList(functionRecord));
if (hasTypeObject(functionRecordTypes, SchemaTypes)) {
typescript.push('import SchemaTypes from "../../schema_types.ts";');
}
if (hasParamsFromTypeObject(functionRecord, SlackTypes)) {
if (hasTypeObject(functionRecordTypes, SlackTypes)) {
typescript.push('import SlackTypes from "../schema_types.ts";');
}
if (hasParamsFromTypeObject(functionRecord, InternalSlackTypes)) {
if (hasTypeObject(functionRecordTypes, InternalSlackTypes)) {
typescript.push(
'import { InternalSlackTypes } from "../types/custom/mod.ts";',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Deno.test("getSlackCallbackId should generate the valid slack callback_id", () =
assertStringIncludes(actual, expected);
});

Deno.test("renderTypeImports should render all imports provided", () => {
Deno.test("renderTypeImports should render all imports provided with slack and primitive types", () => {
const dfi: FunctionRecord = {
callback_id: CALLBACK_ID,
title: TITLE,
Expand Down Expand Up @@ -75,19 +75,125 @@ Deno.test("renderTypeImports should render all imports provided", () => {
title: "Message time stamp",
description: "Message time stamp",
},
],
};
const actual = renderTypeImports(dfi);
assertStringIncludes(actual, "SchemaTypes");
assertStringIncludes(actual, "SlackTypes");
assertStringIncludes(actual, "InternalSlackTypes");
});

Deno.test("renderTypeImports should render imports required for array type", () => {
const dfi: FunctionRecord = {
callback_id: CALLBACK_ID,
title: TITLE,
description: DESCRIPTION,
type: "builtin",
input_parameters: [],
output_parameters: [
{
type: SchemaTypes.array,
name: "user_ids",
title: "User Ids",
description: "User Ids",
items: {
type: "integer",
type: SlackTypes.channel_id,
},
},
],
};
const actual = renderTypeImports(dfi);
assertStringIncludes(actual, "SchemaTypes");
assertStringIncludes(actual, "SlackTypes");
});

Deno.test("renderTypeImports should render imports required for object type", () => {
const dfi: FunctionRecord = {
callback_id: CALLBACK_ID,
title: TITLE,
description: DESCRIPTION,
type: "builtin",
input_parameters: [],
output_parameters: [
{
type: SchemaTypes.object,
name: "user_ids",
title: "User Ids",
description: "User Ids",
properties: {
my_param: {
type: SlackTypes.channel_id,
},
},
},
],
};
const actual = renderTypeImports(dfi);
assertStringIncludes(actual, "SchemaTypes");
assertStringIncludes(actual, "SlackTypes");
});

Deno.test("renderTypeImports should render imports required for a nested complex object type", () => {
const dfi: FunctionRecord = {
callback_id: CALLBACK_ID,
title: TITLE,
description: DESCRIPTION,
type: "builtin",
input_parameters: [],
output_parameters: [
{
type: SchemaTypes.array,
items: {
type: SchemaTypes.object,
properties: {
my_slack_type: {
type: InternalSlackTypes.form_input_object.id,
},
my_primitive_type: {
type: SlackTypes.channel_id,
},
},
},
name: "user_ids",
},
],
};
const actual = renderTypeImports(dfi);
assertStringIncludes(actual, "InternalSlackTypes");
assertStringIncludes(actual, "SchemaTypes");
assertStringIncludes(actual, "SlackTypes");
});

Deno.test("renderTypeImports should render imports required for primitive & complex types", () => {
const dfi: FunctionRecord = {
callback_id: CALLBACK_ID,
title: TITLE,
description: DESCRIPTION,
type: "builtin",
input_parameters: [],
output_parameters: [
{
type: SchemaTypes.array,
items: {
type: SchemaTypes.string,
},
name: "user_ids",
},
{
type: SchemaTypes.object,
name: "my_object",
properties: {
my_param: {
type: SchemaTypes.string,
},
},
},
{
type: SchemaTypes.string,
name: "my_primitive",
},
],
};
const actual = renderTypeImports(dfi);
assertStringIncludes(actual, "SchemaTypes");
});

0 comments on commit 3d60026

Please sign in to comment.