From b55a2f9f5977819e8fd21c671157924b05034dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= Date: Wed, 4 Oct 2023 03:13:00 +0200 Subject: [PATCH] add text template v2 --- .../src/engines/dataflow/updateNodeInput.ts | 9 +- .../ps-nodes-config/src/modifiers/index.ts | 3 + .../src/modifiers/template/template_text.ts | 2 +- .../modifiers/template/template_text_v2.ts | 29 ++ .../@pufflig/ps-nodes/src/modifiers/index.ts | 2 + .../modifiers/template/template_chat.test.ts | 298 ------------------ .../src/modifiers/template/template_chat.ts | 64 +--- .../modifiers/template/template_text.test.ts | 163 ---------- .../src/modifiers/template/template_text.ts | 49 +-- .../template/template_text_v2.test.ts | 75 +++++ .../modifiers/template/template_text_v2.ts | 75 +++++ .../template/utils/extractVariables.ts | 4 +- packages/@pufflig/ps-types/src/types/nodes.ts | 2 +- 13 files changed, 192 insertions(+), 583 deletions(-) create mode 100644 packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text_v2.ts delete mode 100644 packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.test.ts delete mode 100644 packages/@pufflig/ps-nodes/src/modifiers/template/template_text.test.ts create mode 100644 packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.test.ts create mode 100644 packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.ts diff --git a/packages/@pufflig/ps-chains/src/engines/dataflow/updateNodeInput.ts b/packages/@pufflig/ps-chains/src/engines/dataflow/updateNodeInput.ts index 7d75270..73e908f 100644 --- a/packages/@pufflig/ps-chains/src/engines/dataflow/updateNodeInput.ts +++ b/packages/@pufflig/ps-chains/src/engines/dataflow/updateNodeInput.ts @@ -1,7 +1,6 @@ import { ParamValue } from "@pufflig/ps-types"; import { Flow, NodeState, RunOptions } from "../../types"; import { applyDefaultInputs } from "./utils/utils"; -import { identity } from "./constants"; /** * This function updates the input state of a node without executing the chain. @@ -21,19 +20,15 @@ export async function updateNodeInput( const flowState: Record = { ...flow.state }; const nodeConfig = flow.definition.nodes[nodeId]; const nodeDefinition = flow.nodeTypes[nodeConfig?.type]; - const mapInput = nodeDefinition?.mapInput || identity; if (!nodeConfig || !nodeDefinition) { throw new Error(`Definition for node ${nodeId} not found`); } - // parse the input + // compile the new state of the node const nodeState = flowState[nodeId]; const prevInput = nodeState?.input; - const parsedInput = await mapInput(input, { prevInput, globals: runOptions?.globals }); - - // compile the new state of the node - const newInput = { ...applyDefaultInputs(prevInput, nodeDefinition), ...parsedInput }; + const newInput = { ...applyDefaultInputs(prevInput, nodeDefinition), ...input }; const newState: NodeState = { ...nodeState, input: newInput }; runOptions?.onNodeInputUpdate?.(nodeId, newState); diff --git a/packages/@pufflig/ps-nodes-config/src/modifiers/index.ts b/packages/@pufflig/ps-nodes-config/src/modifiers/index.ts index 6d8c5b6..6c90192 100644 --- a/packages/@pufflig/ps-nodes-config/src/modifiers/index.ts +++ b/packages/@pufflig/ps-nodes-config/src/modifiers/index.ts @@ -3,6 +3,7 @@ import { addText, addTextNodeType } from "./add_text/add_text"; import { splitText, splitTextNodeType } from "./split_text/split_text"; import { templateChat, templateChatNodeType } from "./template/template_chat"; import { templateText, templateTextNodeType } from "./template/template_text"; +import { templateTextNodeTypeV2, templateTextV2 } from "./template/template_text_v2"; export const modifierNodes = { [addMessageNodeType]: addMessage, @@ -10,6 +11,7 @@ export const modifierNodes = { [splitTextNodeType]: splitText, [templateChatNodeType]: templateChat, [templateTextNodeType]: templateText, + [templateTextNodeTypeV2]: templateTextV2, }; export const modifierNodeTypes = { @@ -18,4 +20,5 @@ export const modifierNodeTypes = { splitTextNodeType, templateChatNodeType, templateTextNodeType, + templateTextNodeTypeV2, }; diff --git a/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text.ts b/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text.ts index dc7e046..8a75a4e 100644 --- a/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text.ts +++ b/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text.ts @@ -6,7 +6,7 @@ export const templateText: NodeConfig = { name: "Text Template", description: "Using this template, you can insert variables into text.", tags: ["modifier", "text"], - status: "stable", + status: "deprecated", outputs: [ { id: "text", diff --git a/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text_v2.ts b/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text_v2.ts new file mode 100644 index 0000000..0dbd6dc --- /dev/null +++ b/packages/@pufflig/ps-nodes-config/src/modifiers/template/template_text_v2.ts @@ -0,0 +1,29 @@ +import { NodeConfig } from "@pufflig/ps-types"; + +export const templateTextNodeTypeV2 = "modifier/template_text_v2" as const; + +export const templateTextV2: NodeConfig = { + name: "Text Template", + description: "Write text with variables", + tags: ["modifier", "text"], + status: "stable", + customSchema: "input", + outputs: [ + { + id: "text", + name: "Text", + description: "Text with variables filled in", + type: "text", + defaultValue: "", + }, + ], + inputs: [ + { + id: "template", + name: "Template", + description: "Template to fill in", + type: "text", + defaultValue: "", + }, + ], +}; diff --git a/packages/@pufflig/ps-nodes/src/modifiers/index.ts b/packages/@pufflig/ps-nodes/src/modifiers/index.ts index 0194e4a..6b2587c 100644 --- a/packages/@pufflig/ps-nodes/src/modifiers/index.ts +++ b/packages/@pufflig/ps-nodes/src/modifiers/index.ts @@ -4,6 +4,7 @@ import { addText } from "./add_text/add_text"; import { splitText } from "./split_text/split_text"; import { templateChat } from "./template/template_chat"; import { templateText } from "./template/template_text"; +import { templateTextV2 } from "./template/template_text_v2"; export const modifierNodes = { [nodeTypes.addMessageNodeType]: addMessage, @@ -11,4 +12,5 @@ export const modifierNodes = { [nodeTypes.splitTextNodeType]: splitText, [nodeTypes.templateChatNodeType]: templateChat, [nodeTypes.templateTextNodeType]: templateText, + [nodeTypes.templateTextNodeTypeV2]: templateTextV2, }; diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.test.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.test.ts deleted file mode 100644 index fafa129..0000000 --- a/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.test.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { mapInput } from "./template_chat"; - -test("mapInput - several variables with two of the same variable", async () => { - const variables = await mapInput({ - chat: { - messages: [ - { - id: "id", - role: "user", - content: "hello {{name}}", - createdAt: "date", - provider: "openAi", - }, - { - id: "id", - role: "user", - content: "summarize this text: {{text}}", - createdAt: "date", - provider: "openAi", - }, - { - id: "id", - role: "user", - content: "and then tell me the tone of this text: {{text}}", - createdAt: "date", - provider: "openAi", - }, - ], - }, - variables: [], - }); - expect(variables).toMatchInlineSnapshot(` - { - "chat": { - "messages": [ - { - "content": "hello {{name}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - { - "content": "summarize this text: {{text}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - { - "content": "and then tell me the tone of this text: {{text}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - ], - }, - "variables": [ - { - "defaultValue": "", - "description": "", - "id": "name", - "name": "name", - "type": "text", - }, - { - "defaultValue": "", - "description": "", - "id": "text", - "name": "text", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - if you pass a template and a variable, take value of the variable", async () => { - const variables = await mapInput( - { - chat: { - messages: [ - { - id: "id", - role: "user", - content: "summarize this text: {{longText}}", - createdAt: "date", - provider: "openAi", - }, - ], - }, - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "some long text", - description: "", - }, - ], - }, - {} - ); - expect(variables).toMatchInlineSnapshot(` - { - "chat": { - "messages": [ - { - "content": "summarize this text: {{longText}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - ], - }, - "variables": [ - { - "defaultValue": "some long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - removes non existing variables", async () => { - const variables = await mapInput({ - chat: { - messages: [ - { - id: "id", - role: "user", - content: "summarize this text: {{longText}}", - createdAt: "date", - provider: "openAi", - }, - ], - }, - variables: [ - { - id: "otherVariable", - name: "otherVariable", - type: "text", - defaultValue: "", - description: "", - }, - ], - }); - expect(variables).toMatchInlineSnapshot(` - { - "chat": { - "messages": [ - { - "content": "summarize this text: {{longText}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - ], - }, - "variables": [ - { - "defaultValue": "", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - keep default values from the previous state", async () => { - const variables = await mapInput( - { - chat: { - messages: [ - { - id: "id", - role: "user", - content: "summarize this text: {{longText}}", - createdAt: "date", - provider: "openAi", - }, - ], - }, - variables: [], - }, - { - prevInput: { - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "some long text", - description: "", - }, - ], - }, - } - ); - expect(variables).toMatchInlineSnapshot(` - { - "chat": { - "messages": [ - { - "content": "summarize this text: {{longText}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - ], - }, - "variables": [ - { - "defaultValue": "some long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - override values from the previous state with the new value", async () => { - const variables = await mapInput( - { - chat: { - messages: [ - { - id: "id", - role: "user", - content: "summarize this text: {{longText}}", - createdAt: "date", - provider: "openAi", - }, - ], - }, - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "new long text", - description: "", - }, - ], - }, - { - prevInput: { - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "old long text", - description: "", - }, - ], - }, - } - ); - expect(variables).toMatchInlineSnapshot(` - { - "chat": { - "messages": [ - { - "content": "summarize this text: {{longText}}", - "createdAt": "date", - "id": "id", - "provider": "openAi", - "role": "user", - }, - ], - }, - "variables": [ - { - "defaultValue": "new long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.ts index c4b4279..e12ea4a 100644 --- a/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.ts +++ b/packages/@pufflig/ps-nodes/src/modifiers/template/template_chat.ts @@ -1,9 +1,7 @@ import { nodeTypes, nodes } from "@pufflig/ps-nodes-config"; -import { Chat, MapInput, Node, NumberParam, ObjectDefinition, TextParam } from "@pufflig/ps-types"; -import _ from "lodash"; +import { Chat, Node, ObjectDefinition } from "@pufflig/ps-types"; import Mustache from "mustache"; import { objectDefinitionToMap } from "../../utils/objectDefinitionToMap"; -import { extractVariables } from "./utils/extractVariables"; export interface TemplateChatInput { chat: Chat; @@ -33,67 +31,7 @@ export const execute = async (input: TemplateChatInput) => { }; }; -/** - * Parse the input and extract variables from the template. - * If no template is provided, the input is returned as is. - * @param input - * @param prev - * @returns - */ -export const mapInput: MapInput = async (input, options = {}) => { - const { chat, variables } = input; - const { prevInput } = options; - - if (chat === undefined) { - return input; - } - const extractedVariableArrays = chat.messages.map((message) => { - var messageVars = extractVariables(message.content); - return messageVars; - }); - - const extractedVariables = _.flatten(extractedVariableArrays); - - const uniqueVariables = extractedVariables.reduce( - (uniqueArr: (NumberParam | TextParam | null)[], currentVariable: NumberParam | TextParam | null) => { - const existingVariable = uniqueArr.find((variable) => variable?.id === currentVariable?.id); - if (!existingVariable) { - uniqueArr.push(currentVariable); - } - return uniqueArr; - }, - [] - ); - - if (uniqueVariables) { - // extracted variables that already existed in the previous input are assigned the previous value - const variablesObject = uniqueVariables.map((variable) => { - const prevVariable = (prevInput?.variables || []).find((v) => v.id === variable?.id); - if (prevVariable) { - return { - ...variable, - defaultValue: prevVariable.defaultValue, - }; - } - return variable; - }); - - const newVariables = _.unionBy(_.intersectionBy(variables, variablesObject, "id"), variablesObject as any, "id"); - - return { - ...input, - variables: newVariables, - }; - } - - return { - ...input, - variables, - }; -}; - export const templateChat: Node = { ...nodes[nodeTypes.templateChatNodeType], execute, - mapInput, }; diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.test.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.test.ts deleted file mode 100644 index 2a58eca..0000000 --- a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { mapInput } from "./template_text"; - -test("mapInput - no variables", async () => { - const variables = await mapInput({ - template: `summarize {{longText}}`, - variables: [], - }); - expect(variables).toMatchInlineSnapshot(` - { - "template": "summarize {{longText}}", - "variables": [ - { - "defaultValue": "", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - if you pass a template and a variable, take value of the variable", async () => { - const variables = await mapInput( - { - template: `summarize {{longText}}`, - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "some long text", - description: "", - }, - ], - }, - {} - ); - expect(variables).toMatchInlineSnapshot(` - { - "template": "summarize {{longText}}", - "variables": [ - { - "defaultValue": "some long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - removes non existing variables", async () => { - const variables = await mapInput({ - template: `summarize {{longText}}`, - variables: [ - { - id: "otherVariable", - name: "otherVariable", - type: "text", - defaultValue: "", - description: "", - }, - ], - }); - expect(variables).toMatchInlineSnapshot(` - { - "template": "summarize {{longText}}", - "variables": [ - { - "defaultValue": "", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - keep default values from the previous state", async () => { - const variables = await mapInput( - { - template: `summarize {{longText}}`, - variables: [], - }, - { - prevInput: { - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "some long text", - description: "", - }, - ], - }, - } - ); - expect(variables).toMatchInlineSnapshot(` - { - "template": "summarize {{longText}}", - "variables": [ - { - "defaultValue": "some long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); - -test("mapInput - override values from the previous state with the new value", async () => { - const variables = await mapInput( - { - template: `summarize {{longText}}`, - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "new long text", - description: "", - }, - ], - }, - { - prevInput: { - variables: [ - { - id: "longText", - name: "longText", - type: "text", - defaultValue: "old long text", - description: "", - }, - ], - }, - } - ); - expect(variables).toMatchInlineSnapshot(` - { - "template": "summarize {{longText}}", - "variables": [ - { - "defaultValue": "new long text", - "description": "", - "id": "longText", - "name": "longText", - "type": "text", - }, - ], - } - `); -}); diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.ts index 25a8398..fdb289b 100644 --- a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.ts +++ b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text.ts @@ -1,9 +1,7 @@ import { nodeTypes, nodes } from "@pufflig/ps-nodes-config"; -import { MapInput, Node, ObjectDefinition } from "@pufflig/ps-types"; -import _ from "lodash"; +import { Node, ObjectDefinition } from "@pufflig/ps-types"; import Mustache from "mustache"; import { objectDefinitionToMap } from "../../utils/objectDefinitionToMap"; -import { extractVariables } from "./utils/extractVariables"; export interface TemplateTextInput { template: string; @@ -23,52 +21,7 @@ export const execute = async (input: TemplateTextInput) => { }; }; -/** - * Parse the input and extract variables from the template. - * If no template is provided, the input is returned as is. - * @param input - * @param prev - * @returns - */ -export const mapInput: MapInput = async (input, options = {}) => { - const { template, variables } = input; - const { prevInput } = options; - - if (template === undefined) { - return input; - } - - const extractedVariables = extractVariables(template); - - if (extractedVariables) { - // extracted variables that already existed in the previous input are assigned the previous value - const variablesObject = extractedVariables.map((variable) => { - const prevVariable = (prevInput?.variables || []).find((v) => v.id === variable.id); - if (prevVariable) { - return { - ...variable, - defaultValue: prevVariable.defaultValue, - }; - } - return variable; - }); - - const newVariables = _.unionBy(_.intersectionBy(variables, variablesObject, "id"), variablesObject as any, "id"); - - return { - ...input, - variables: newVariables, - }; - } - - return { - ...input, - variables, - }; -}; - export const templateText: Node = { ...nodes[nodeTypes.templateTextNodeType], execute, - mapInput, }; diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.test.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.test.ts new file mode 100644 index 0000000..e10f6a8 --- /dev/null +++ b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.test.ts @@ -0,0 +1,75 @@ +import { mapInput } from "./template_text_v2"; + +test("mapInput - no variables", async () => { + const variables = await mapInput({ + template: `summarize {{longText}}`, + }); + expect(variables).toMatchInlineSnapshot(` + [ + { + "defaultValue": "summarize {{longText}}", + "description": "Template to fill in", + "id": "template", + "name": "Template", + "type": "text", + }, + { + "defaultValue": "", + "description": "", + "id": "longText", + "name": "longText", + "type": "text", + }, + ] + `); +}); + +test("mapInput - if you pass a template and a variable, take value of the variable", async () => { + const variables = await mapInput({ + template: `summarize {{longText}}`, + longText: "some long text", + }); + expect(variables).toMatchInlineSnapshot(` + [ + { + "defaultValue": "summarize {{longText}}", + "description": "Template to fill in", + "id": "template", + "name": "Template", + "type": "text", + }, + { + "defaultValue": "some long text", + "description": "", + "id": "longText", + "name": "longText", + "type": "text", + }, + ] + `); +}); + +test("mapInput - ignores non existing variables", async () => { + const variables = await mapInput({ + template: `summarize {{longText}}`, + otherVariable: "", + }); + expect(variables).toMatchInlineSnapshot(` + [ + { + "defaultValue": "summarize {{longText}}", + "description": "Template to fill in", + "id": "template", + "name": "Template", + "type": "text", + }, + { + "defaultValue": "", + "description": "", + "id": "longText", + "name": "longText", + "type": "text", + }, + ] + `); +}); diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.ts new file mode 100644 index 0000000..b24c186 --- /dev/null +++ b/packages/@pufflig/ps-nodes/src/modifiers/template/template_text_v2.ts @@ -0,0 +1,75 @@ +import { nodeTypes, nodes } from "@pufflig/ps-nodes-config"; +import { MapInput, Node, ObjectDefinition, Param } from "@pufflig/ps-types"; +import Mustache from "mustache"; +import { extractVariables } from "./utils/extractVariables"; + +export interface TemplateTextInput { + template: string; + [key: string]: string; +} + +export interface TemplateTextOutput { + text: string; +} + +export const objectDefinitionToMap = (definition: ObjectDefinition) => { + const map = {} as Record; + definition.forEach((item) => { + map[item.id] = item.defaultValue; + }); + return map; +}; + +export const execute = async (input: TemplateTextInput) => { + const { template, ...variables } = input; + const renderedTemplate = Mustache.render(template, variables); + return { + text: renderedTemplate, + }; +}; + +/** + * Returns a new input definition given variables extracted from the template. + * + * @param input + * @param prev + * @returns + */ +export const mapInput: MapInput = async (input) => { + const { template, ...rest } = input; + + if (template === undefined) { + return nodes[nodeTypes.templateTextNodeTypeV2].inputs; + } + + const definitionsWithDefaults = nodes[nodeTypes.templateTextNodeTypeV2].inputs.map((input) => { + if (input.id === "template") { + return { + ...input, + defaultValue: template, + } as Param; + } + return input; + }); + + const extractedVariables = extractVariables(template); + + if (extractedVariables) { + const extractedVariablesWithDefaults = extractedVariables.map((variable) => { + return { + ...variable, + defaultValue: rest[variable.id] || "", + } as Param; + }); + + return [...definitionsWithDefaults, ...extractedVariablesWithDefaults]; + } + + return definitionsWithDefaults; +}; + +export const templateTextV2: Node = { + ...nodes[nodeTypes.templateTextNodeTypeV2], + execute, + mapInput, +}; diff --git a/packages/@pufflig/ps-nodes/src/modifiers/template/utils/extractVariables.ts b/packages/@pufflig/ps-nodes/src/modifiers/template/utils/extractVariables.ts index 1b12e65..790a13b 100644 --- a/packages/@pufflig/ps-nodes/src/modifiers/template/utils/extractVariables.ts +++ b/packages/@pufflig/ps-nodes/src/modifiers/template/utils/extractVariables.ts @@ -1,4 +1,4 @@ -import { NumberParam, ObjectDefinition, TextParam } from "@pufflig/ps-types"; +import { NumberParam, Param, TextParam } from "@pufflig/ps-types"; import Mustache from "mustache"; /** @@ -6,7 +6,7 @@ import Mustache from "mustache"; * @param template * @returns */ -export const extractVariables = (template: string, onError: (err: any) => void = () => {}): ObjectDefinition | null => { +export const extractVariables = (template: string, onError: (err: any) => void = () => {}): Param[] | null => { try { return Mustache.parse(template) .filter((v) => v[0] === "name" || v[0] === "#") diff --git a/packages/@pufflig/ps-types/src/types/nodes.ts b/packages/@pufflig/ps-types/src/types/nodes.ts index d2a7516..f9c0c60 100644 --- a/packages/@pufflig/ps-types/src/types/nodes.ts +++ b/packages/@pufflig/ps-types/src/types/nodes.ts @@ -31,7 +31,7 @@ export interface NodeOptions { } export type Execute = (input: I, options?: NodeOptions) => Promise; -export type MapInput = (input: I, options?: NodeOptions) => Promise | null>; +export type MapInput = (input: I, options?: NodeOptions) => Promise; export type GetTargets = ( input: I, result?: O,