diff --git a/package-lock.json b/package-lock.json index f8ee1c25..bfb1d1b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1070,6 +1070,10 @@ "resolved": "plugins/template-function-hash", "link": true }, + "node_modules/@yaakapp/template-function-json": { + "resolved": "plugins/template-function-json", + "link": true + }, "node_modules/@yaakapp/template-function-prompt": { "resolved": "plugins/template-function-prompt", "link": true @@ -1086,6 +1090,14 @@ "resolved": "plugins/template-function-response", "link": true }, + "node_modules/@yaakapp/template-function-uuid": { + "resolved": "plugins/template-function-uuid", + "link": true + }, + "node_modules/@yaakapp/template-function-xml": { + "resolved": "plugins/template-function-xml", + "link": true + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -7152,12 +7164,30 @@ "name": "@yaakapp/filter-jsonpath", "version": "0.0.1", "dependencies": { - "jsonpath-plus": "^9.0.0" + "jsonpath-plus": "^10.3.0" }, "devDependencies": { "@types/jsonpath": "^0.2.4" } }, + "plugins/filter-jsonpath/node_modules/jsonpath-plus": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", + "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", + "license": "MIT", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, "plugins/filter-xpath": { "name": "@yaakapp/filter-xpath", "version": "0.0.1", @@ -7223,6 +7253,45 @@ "name": "@yaakapp/template-function-hash", "version": "0.0.1" }, + "plugins/template-function-json": { + "name": "@yaakapp/template-function-json", + "version": "0.0.1", + "dependencies": { + "jsonpath-plus": "^10.3.0" + }, + "devDependencies": { + "@types/jsonpath": "^0.2.4" + } + }, + "plugins/template-function-json/node_modules/jsonpath-plus": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", + "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", + "license": "MIT", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "plugins/template-function-jsonpath": { + "name": "@yaakapp/template-function-jsonpath", + "version": "0.0.1", + "extraneous": true, + "dependencies": { + "jsonpath-plus": "^10.3.0" + }, + "devDependencies": { + "@types/jsonpath": "^0.2.4" + } + }, "plugins/template-function-prompt": { "name": "@yaakapp/template-function-prompt", "version": "0.0.1" @@ -7251,6 +7320,43 @@ "name": "@yaakapp/template-function-secure", "version": "0.0.1", "extraneous": true + }, + "plugins/template-function-uuid": { + "name": "@yaakapp/template-function-uuid", + "version": "0.0.1", + "dependencies": { + "uuid": "^11.1.0" + } + }, + "plugins/template-function-uuid/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "plugins/template-function-xml": { + "name": "@yaakapp/template-function-xml", + "version": "0.0.1", + "dependencies": { + "@xmldom/xmldom": "^0.8.10", + "xpath": "^0.0.34" + } + }, + "plugins/template-function-xpath": { + "name": "@yaakapp/template-function-xpath", + "version": "0.0.1", + "extraneous": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.10", + "xpath": "^0.0.34" + } } } } diff --git a/plugins/filter-jsonpath/package.json b/plugins/filter-jsonpath/package.json index 4d1a1c5a..028816ac 100644 --- a/plugins/filter-jsonpath/package.json +++ b/plugins/filter-jsonpath/package.json @@ -7,7 +7,7 @@ "dev": "yaakcli dev ./src/index.js" }, "dependencies": { - "jsonpath-plus": "^9.0.0" + "jsonpath-plus": "^10.3.0" }, "devDependencies": { "@types/jsonpath": "^0.2.4" diff --git a/plugins/template-function-json/package.json b/plugins/template-function-json/package.json new file mode 100755 index 00000000..b18f1a9a --- /dev/null +++ b/plugins/template-function-json/package.json @@ -0,0 +1,15 @@ +{ + "name": "@yaakapp/template-function-json", + "private": true, + "version": "0.0.1", + "scripts": { + "build": "yaakcli build ./src/index.ts", + "dev": "yaakcli dev ./src/index.js" + }, + "dependencies": { + "jsonpath-plus": "^10.3.0" + }, + "devDependencies": { + "@types/jsonpath": "^0.2.4" + } +} diff --git a/plugins/template-function-json/src/index.ts b/plugins/template-function-json/src/index.ts new file mode 100755 index 00000000..f2b622e6 --- /dev/null +++ b/plugins/template-function-json/src/index.ts @@ -0,0 +1,45 @@ +import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api'; +import { JSONPath } from 'jsonpath-plus'; + +export const plugin: PluginDefinition = { + templateFunctions: [ + { + name: 'json.jsonpath', + description: 'Filter JSON-formatted text using JSONPath syntax', + args: [ + { type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: '{ "foo": "bar" }' }, + { type: 'text', name: 'query', label: 'Query', placeholder: '$..foo' }, + { type: 'checkbox', name: 'formatted', label: 'Format Output' }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + try { + const parsed = JSON.parse(String(args.values.input)); + const query = String(args.values.query ?? '$').trim(); + let filtered = JSONPath({ path: query, json: parsed }); + if (Array.isArray(filtered)) { + filtered = filtered[0]; + } + + if (args.values.formatted) { + return JSON.stringify(filtered, null, 2); + } else { + return JSON.stringify(filtered); + } + } catch (e) { + return null; + } + }, + }, + { + name: 'json.escape', + description: 'Escape a JSON string, useful when using the output in JSON values', + args: [ + { type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: 'Hello "World"' }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + const input = String(args.values.input ?? ''); + return input.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + }, + }, + ], +}; diff --git a/plugins/template-function-uuid/package.json b/plugins/template-function-uuid/package.json new file mode 100644 index 00000000..4b1538ea --- /dev/null +++ b/plugins/template-function-uuid/package.json @@ -0,0 +1,12 @@ +{ + "name": "@yaakapp/template-function-uuid", + "private": true, + "version": "0.0.1", + "scripts": { + "build": "yaakcli build ./src/index.ts", + "dev": "yaakcli dev ./src/index.js" + }, + "dependencies": { + "uuid": "^11.1.0" + } +} diff --git a/plugins/template-function-uuid/src/index.ts b/plugins/template-function-uuid/src/index.ts new file mode 100644 index 00000000..88e3449b --- /dev/null +++ b/plugins/template-function-uuid/src/index.ts @@ -0,0 +1,76 @@ +import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api'; +import { v1, v3, v4, v5, v6, v7 } from 'uuid'; + +export const plugin: PluginDefinition = { + templateFunctions: [ + { + name: 'uuid.v1', + description: 'Generate a UUID V1', + args: [], + async onRender(_ctx: Context, _args: CallTemplateFunctionArgs): Promise { + return v1(); + }, + }, + { + name: 'uuid.v3', + description: 'Generate a UUID V3', + args: [ + { type: 'text', name: 'name', label: 'Name' }, + { + type: 'text', + name: 'namespace', + label: 'Namespace UUID', + description: 'A valid UUID to use as the namespace', + placeholder: '24ced880-3bf4-11f0-8329-cd053d577f0e', + }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + return v3(String(args.values.name), String(args.values.namespace)); + }, + }, + { + name: 'uuid.v4', + description: 'Generate a UUID V4', + args: [], + async onRender(_ctx: Context, _args: CallTemplateFunctionArgs): Promise { + return v4(); + }, + }, + { + name: 'uuid.v5', + description: 'Generate a UUID V5', + args: [ + { type: 'text', name: 'name', label: 'Name' }, + { type: 'text', name: 'namespace', label: 'Namespace' }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + return v5(String(args.values.name), String(args.values.namespace)); + }, + }, + { + name: 'uuid.v6', + description: 'Generate a UUID V6', + args: [ + { + type: 'text', + name: 'timestamp', + label: 'Timestamp', + optional: true, + description: 'Can be any format that can be parsed by JavaScript new Date(...)', + placeholder: '2025-05-28T11:15:00Z', + }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + return v6({ msecs: new Date(String(args.values.timestamp)).getTime() }); + }, + }, + { + name: 'uuid.v7', + description: 'Generate a UUID V7', + args: [], + async onRender(_ctx: Context, _args: CallTemplateFunctionArgs): Promise { + return v7(); + }, + }, + ], +}; diff --git a/plugins/template-function-xml/package.json b/plugins/template-function-xml/package.json new file mode 100755 index 00000000..d1274960 --- /dev/null +++ b/plugins/template-function-xml/package.json @@ -0,0 +1,13 @@ +{ + "name": "@yaakapp/template-function-xml", + "private": true, + "version": "0.0.1", + "scripts": { + "build": "yaakcli build ./src/index.ts", + "dev": "yaakcli dev ./src/index.js" + }, + "dependencies": { + "@xmldom/xmldom": "^0.8.10", + "xpath": "^0.0.34" + } +} diff --git a/plugins/template-function-xml/src/index.ts b/plugins/template-function-xml/src/index.ts new file mode 100755 index 00000000..fdb32b4a --- /dev/null +++ b/plugins/template-function-xml/src/index.ts @@ -0,0 +1,29 @@ +import { DOMParser } from '@xmldom/xmldom'; +import { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api'; +import xpath from 'xpath'; + +export const plugin: PluginDefinition = { + templateFunctions: [{ + name: 'xml.xpath', + description: 'Filter XML-formatted text using XPath syntax', + args: [ + { type: 'text', name: 'input', label: 'Input', multiLine: true, placeholder: '' }, + { type: 'text', name: 'query', label: 'Query', placeholder: '//foo' }, + ], + async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { + try { + const doc = new DOMParser().parseFromString(String(args.values.input), 'text/xml'); + let result = xpath.select(String(args.values.query), doc, false); + if (Array.isArray(result)) { + return String(result.map(c => String(c.firstChild))[0]); + } else if (result instanceof Node) { + return String(result.firstChild); + } else { + return String(result); + } + } catch (e) { + return null; + } + }, + }], +};