Skip to content

Commit

Permalink
feat: Add new type list_id, builtins for Add/Remove Reactions and m…
Browse files Browse the repository at this point in the history
…any List-related functions (#361)

* feat: Add builtins for Add/Remove Reactions and many List-related functions, too.
also updates instructions for how to generate built-in function definitions using updated `functions.list` API endpoint

* deno fmt

* Add new list_id type. Make generation script throw an exception if it finds an unfamiliar parameter type. Update generated list functions with new list_id type.

* deno fmt
  • Loading branch information
Fil Maj authored Sep 6, 2024
1 parent 2ab8d3b commit a2f4ffa
Show file tree
Hide file tree
Showing 22 changed files with 954 additions and 16 deletions.
17 changes: 5 additions & 12 deletions src/schema/slack/functions/_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,14 @@ corresponding test, the tests must be removed manually.

## Instructions

1. First, you'll need to grab the response from `functions.categories.list` API
method tester:
1. First, you'll need to grab the response from `functions.list` API method
tester:

- Choose a session token from a public production enterprise grid workspace that
is NOT enrolled in the `hermes_next` toggle. Recommend using the Slack DevRel
is NOT enrolled in any beta toggles. Recommend using the Slack DevRel
production enterprise grid token.
- Pass the `category_type=builtins_categories` parameter to this API.
- Now for the super annoying part: for each builtin category, you will need to
manually call _another_ API and assemble a functions list yourself:
- Grab the response from `functions.categories.steps.list` API method tester,
using the same session token as earlier in this step, passing each
`category_id` retrieved earlier into this API call.
- Copy the `functions` array elements from each response into a fresh
`{"functions":[]}` array in `functions.json`, slowly building up a list of
all builtin functions.
- Use `builtins` as the value for the `function_type` parameter to this API.
- Copy the response into a `functions.json` file in this directory.

2. With this `_scripts` directory as your working directory, run the generate
script:
Expand Down
2 changes: 2 additions & 0 deletions src/schema/slack/functions/_scripts/generate
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ echo "Formatting Slack function files..."
deno fmt --quiet ../*.ts
echo "Linting Slack function files..."
deno lint --quiet ../*.ts
echo "Type-checking Slack function files..."
deno check --quiet ../*.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,14 @@ const propertyToTypeScript = (
property: FunctionProperty,
): string => {
const typescript = [];
const sdkType = schemaTypeMap[property.type];
if (!sdkType) {
throw new Error(
`Unrecognized type "${property.type}"! Maybe a new automation platform type was recently introduced? If so, add it to one of the type files under src/schema.`,
);
}
typescript.push(
`type: ${schemaTypeMap[property.type]}`,
`type: ${sdkType}`,
);
if (property.description) {
typescript.push(`description: ${sanitize(property.description)}`);
Expand Down
3 changes: 1 addition & 2 deletions src/schema/slack/functions/_scripts/src/templates/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ 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";
import { isArrayFunctionProperty, isObjectFunctionProperty } from "../utils.ts";

export function autogeneratedComment(includeDate?: boolean): string {
const dateString = includeDate ? ` on ${new Date().toDateString()}` : "";
Expand Down
26 changes: 26 additions & 0 deletions src/schema/slack/functions/add_reaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import { DefineFunction } from "../../../functions/mod.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";

export default DefineFunction({
callback_id: "slack#/functions/add_reaction",
source_file: "",
title: "Add a reaction to a message",
input_parameters: {
properties: {
message_context: {
type: SlackTypes.message_context,
description: "Select a message to react to",
title: "Select a message to react to",
},
emoji: {
type: SchemaTypes.string,
description: "Reaction (emoji) name",
title: "Emoji",
},
},
required: ["message_context", "emoji"],
},
output_parameters: { properties: {}, required: [] },
});
50 changes: 50 additions & 0 deletions src/schema/slack/functions/add_reaction_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import { assertEquals, assertNotStrictEquals } from "../../../dev_deps.ts";
import { DefineWorkflow } from "../../../workflows/mod.ts";
import { ManifestFunctionSchema } from "../../../manifest/manifest_schema.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";
import AddReaction from "./add_reaction.ts";

Deno.test("AddReaction generates valid FunctionManifest", () => {
assertEquals(
AddReaction.definition.callback_id,
"slack#/functions/add_reaction",
);
const expected: ManifestFunctionSchema = {
source_file: "",
title: "Add a reaction to a message",
input_parameters: {
properties: {
message_context: {
type: SlackTypes.message_context,
description: "Select a message to react to",
title: "Select a message to react to",
},
emoji: {
type: SchemaTypes.string,
description: "Reaction (emoji) name",
title: "Emoji",
},
},
required: ["message_context", "emoji"],
},
output_parameters: { properties: {}, required: [] },
};
const actual = AddReaction.export();

assertNotStrictEquals(actual, expected);
});

Deno.test("AddReaction can be used as a Slack function in a workflow step", () => {
const testWorkflow = DefineWorkflow({
callback_id: "test_AddReaction_slack_function",
title: "Test AddReaction",
description: "This is a generated test to test AddReaction",
});
testWorkflow.addStep(AddReaction, { message_context: "test", emoji: "test" });
const actual = testWorkflow.steps[0].export();

assertEquals(actual.function_id, "slack#/functions/add_reaction");
assertEquals(actual.inputs, { message_context: "test", emoji: "test" });
});
65 changes: 65 additions & 0 deletions src/schema/slack/functions/copy_list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import { DefineFunction } from "../../../functions/mod.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";

export default DefineFunction({
callback_id: "slack#/functions/copy_list",
source_file: "",
title: "Copy a list",
input_parameters: {
properties: {
list_id: {
type: SlackTypes.list_id,
description: "Search all lists",
title: "Select a list",
},
owner_id: {
type: SlackTypes.user_id,
description: "List owner id",
title: "Owner",
},
name: {
type: SchemaTypes.string,
description: "Name of the list",
title: "Name",
},
description: {
type: SchemaTypes.string,
description: "Description of the list",
title: "Description",
},
emoji: {
type: SchemaTypes.string,
description: "Emoji for the list",
title: "Emoji",
},
include_copied_list_records: {
type: SchemaTypes.boolean,
description: "Include records from the copied list",
title: "Copy records",
},
},
required: ["list_id", "owner_id", "name", "include_copied_list_records"],
},
output_parameters: {
properties: {
list_id: {
type: SchemaTypes.string,
description: "List ID",
title: "List ID",
},
link: {
type: SchemaTypes.string,
description: "Link for the list",
title: "Link",
},
list_id_value: {
type: SlackTypes.list_id,
description: "List title",
title: "List title",
},
},
required: [],
},
});
117 changes: 117 additions & 0 deletions src/schema/slack/functions/copy_list_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import {
assertEquals,
assertExists,
assertNotStrictEquals,
} from "../../../dev_deps.ts";
import { DefineWorkflow } from "../../../workflows/mod.ts";
import { ManifestFunctionSchema } from "../../../manifest/manifest_schema.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";
import CopyList from "./copy_list.ts";

Deno.test("CopyList generates valid FunctionManifest", () => {
assertEquals(CopyList.definition.callback_id, "slack#/functions/copy_list");
const expected: ManifestFunctionSchema = {
source_file: "",
title: "Copy a list",
input_parameters: {
properties: {
list_id: {
type: SlackTypes.list_id,
description: "Search all lists",
title: "Select a list",
},
owner_id: {
type: SlackTypes.user_id,
description: "List owner id",
title: "Owner",
},
name: {
type: SchemaTypes.string,
description: "Name of the list",
title: "Name",
},
description: {
type: SchemaTypes.string,
description: "Description of the list",
title: "Description",
},
emoji: {
type: SchemaTypes.string,
description: "Emoji for the list",
title: "Emoji",
},
include_copied_list_records: {
type: SchemaTypes.boolean,
description: "Include records from the copied list",
title: "Copy records",
},
},
required: ["list_id", "owner_id", "name", "include_copied_list_records"],
},
output_parameters: {
properties: {
list_id: {
type: SchemaTypes.string,
description: "List ID",
title: "List ID",
},
link: {
type: SchemaTypes.string,
description: "Link for the list",
title: "Link",
},
list_id_value: {
type: SlackTypes.list_id,
description: "List title",
title: "List title",
},
},
required: [],
},
};
const actual = CopyList.export();

assertNotStrictEquals(actual, expected);
});

Deno.test("CopyList can be used as a Slack function in a workflow step", () => {
const testWorkflow = DefineWorkflow({
callback_id: "test_CopyList_slack_function",
title: "Test CopyList",
description: "This is a generated test to test CopyList",
});
testWorkflow.addStep(CopyList, {
list_id: "test",
owner_id: "test",
name: "test",
include_copied_list_records: "test",
});
const actual = testWorkflow.steps[0].export();

assertEquals(actual.function_id, "slack#/functions/copy_list");
assertEquals(actual.inputs, {
list_id: "test",
owner_id: "test",
name: "test",
include_copied_list_records: "test",
});
});

Deno.test("All outputs of Slack function CopyList should exist", () => {
const testWorkflow = DefineWorkflow({
callback_id: "test_CopyList_slack_function",
title: "Test CopyList",
description: "This is a generated test to test CopyList",
});
const step = testWorkflow.addStep(CopyList, {
list_id: "test",
owner_id: "test",
name: "test",
include_copied_list_records: "test",
});
assertExists(step.outputs.list_id);
assertExists(step.outputs.link);
assertExists(step.outputs.list_id_value);
});
26 changes: 26 additions & 0 deletions src/schema/slack/functions/delete_list_record.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import { DefineFunction } from "../../../functions/mod.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";

export default DefineFunction({
callback_id: "slack#/functions/delete_list_record",
source_file: "",
title: "Delete a list item",
input_parameters: {
properties: {
list_id: {
type: SlackTypes.list_id,
description: "Select a list",
title: "Select a list",
},
record_id: {
type: SchemaTypes.string,
description: "Item ID",
title: "Item ID",
},
},
required: ["list_id"],
},
output_parameters: { properties: {}, required: [] },
});
50 changes: 50 additions & 0 deletions src/schema/slack/functions/delete_list_record_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/** This file was autogenerated. Follow the steps in src/schema/slack/functions/_scripts/README.md to rebuild **/
import { assertEquals, assertNotStrictEquals } from "../../../dev_deps.ts";
import { DefineWorkflow } from "../../../workflows/mod.ts";
import { ManifestFunctionSchema } from "../../../manifest/manifest_schema.ts";
import SchemaTypes from "../../schema_types.ts";
import SlackTypes from "../schema_types.ts";
import DeleteListRecord from "./delete_list_record.ts";

Deno.test("DeleteListRecord generates valid FunctionManifest", () => {
assertEquals(
DeleteListRecord.definition.callback_id,
"slack#/functions/delete_list_record",
);
const expected: ManifestFunctionSchema = {
source_file: "",
title: "Delete a list item",
input_parameters: {
properties: {
list_id: {
type: SlackTypes.list_id,
description: "Select a list",
title: "Select a list",
},
record_id: {
type: SchemaTypes.string,
description: "Item ID",
title: "Item ID",
},
},
required: ["list_id"],
},
output_parameters: { properties: {}, required: [] },
};
const actual = DeleteListRecord.export();

assertNotStrictEquals(actual, expected);
});

Deno.test("DeleteListRecord can be used as a Slack function in a workflow step", () => {
const testWorkflow = DefineWorkflow({
callback_id: "test_DeleteListRecord_slack_function",
title: "Test DeleteListRecord",
description: "This is a generated test to test DeleteListRecord",
});
testWorkflow.addStep(DeleteListRecord, { list_id: "test" });
const actual = testWorkflow.steps[0].export();

assertEquals(actual.function_id, "slack#/functions/delete_list_record");
assertEquals(actual.inputs, { list_id: "test" });
});
Loading

0 comments on commit a2f4ffa

Please sign in to comment.