mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-11 17:46:41 -05:00
Improved prompt function add add ctx.* functions (#301)
This commit is contained in:
12
plugins/template-function-ctx/package.json
Normal file
12
plugins/template-function-ctx/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@yaak/template-function-ctx",
|
||||
"displayName": "Window Template Functions",
|
||||
"description": "Template functions for accessing attributes of the current window",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"build": "yaakcli build",
|
||||
"dev": "yaakcli dev",
|
||||
"lint": "tsc --noEmit && eslint . --ext .ts,.tsx"
|
||||
}
|
||||
}
|
||||
30
plugins/template-function-ctx/src/index.ts
Normal file
30
plugins/template-function-ctx/src/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { PluginDefinition } from '@yaakapp/api';
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [
|
||||
{
|
||||
name: 'ctx.request',
|
||||
description: 'Get the ID of the currently active request',
|
||||
args: [],
|
||||
async onRender(ctx) {
|
||||
return ctx.window.requestId();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ctx.environment',
|
||||
description: 'Get the ID of the currently active environment',
|
||||
args: [],
|
||||
async onRender(ctx) {
|
||||
return ctx.window.environmentId();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ctx.workspace',
|
||||
description: 'Get the ID of the currently active workspace',
|
||||
args: [],
|
||||
async onRender(ctx) {
|
||||
return ctx.window.workspaceId();
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
3
plugins/template-function-ctx/tsconfig.json
Normal file
3
plugins/template-function-ctx/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json"
|
||||
}
|
||||
@@ -58,7 +58,6 @@ export const plugin: PluginDefinition = {
|
||||
],
|
||||
async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
try {
|
||||
console.log('formatted', args.values.formatted);
|
||||
return filterJSONPath(
|
||||
String(args.values.input),
|
||||
String(args.values.query),
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"scripts": {
|
||||
"build": "yaakcli build",
|
||||
"dev": "yaakcli dev",
|
||||
"lint":"tsc --noEmit && eslint . --ext .ts,.tsx"
|
||||
"lint": "tsc --noEmit && eslint . --ext .ts,.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"slugify": "^1.6.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,174 @@
|
||||
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
|
||||
import slugify from 'slugify';
|
||||
|
||||
const STORE_NONE = 'none';
|
||||
const STORE_FOREVER = 'forever';
|
||||
const STORE_EXPIRE = 'expire';
|
||||
|
||||
interface Saved {
|
||||
value: string;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
templateFunctions: [{
|
||||
name: 'prompt.text',
|
||||
description: 'Prompt the user for input when sending a request',
|
||||
args: [
|
||||
{ type: 'text', name: 'title', label: 'Title' },
|
||||
{ type: 'text', name: 'label', label: 'Label', optional: true },
|
||||
{ type: 'text', name: 'defaultValue', label: 'Default Value', optional: true },
|
||||
{ type: 'text', name: 'placeholder', label: 'Placeholder', optional: true },
|
||||
],
|
||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (args.purpose !== 'send') return null;
|
||||
templateFunctions: [
|
||||
{
|
||||
name: 'prompt.text',
|
||||
description: 'Prompt the user for input when sending a request',
|
||||
previewType: 'click',
|
||||
args: [
|
||||
{ type: 'text', name: 'label', label: 'Label' },
|
||||
{
|
||||
type: 'select',
|
||||
name: 'store',
|
||||
label: 'Store Input',
|
||||
defaultValue: STORE_NONE,
|
||||
options: [
|
||||
{ label: 'Never', value: STORE_NONE },
|
||||
{ label: 'Expire', value: STORE_EXPIRE },
|
||||
{ label: 'Forever', value: STORE_FOREVER },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'h_stack',
|
||||
dynamic(_ctx, args) {
|
||||
return { hidden: args.values.store === STORE_NONE };
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'namespace',
|
||||
label: 'Namespace',
|
||||
defaultValue: '${[ctx.workspace()]}',
|
||||
optional: true,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'key',
|
||||
label: 'Key (defaults to Label)',
|
||||
optional: true,
|
||||
dynamic(_ctx, args) {
|
||||
return { placeholder: String(args.values.label || '') };
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'ttl',
|
||||
label: 'TTL (seconds)',
|
||||
placeholder: '0',
|
||||
defaultValue: '0',
|
||||
optional: true,
|
||||
dynamic(_ctx, args) {
|
||||
return { hidden: args.values.store !== STORE_EXPIRE };
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'banner',
|
||||
color: 'info',
|
||||
dynamic(_ctx, args) {
|
||||
return { hidden: args.values.store === STORE_NONE };
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
type: 'markdown',
|
||||
content: '',
|
||||
async dynamic(_ctx, args) {
|
||||
const key = buildKey(args);
|
||||
return {
|
||||
content: ['Value will be saved under: `' + key + '`'].join('\n\n'),
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'accordion',
|
||||
label: 'Advanced',
|
||||
inputs: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'title',
|
||||
label: 'Prompt Title',
|
||||
optional: true,
|
||||
placeholder: 'Enter Value',
|
||||
},
|
||||
{ type: 'text', name: 'defaultValue', label: 'Default Value', optional: true },
|
||||
{ type: 'text', name: 'placeholder', label: 'Input Placeholder', optional: true },
|
||||
{ type: 'checkbox', name: 'password', label: 'Mask Value' },
|
||||
],
|
||||
},
|
||||
],
|
||||
async onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null> {
|
||||
if (args.purpose !== 'send') return null;
|
||||
|
||||
return await ctx.prompt.text({
|
||||
id: `prompt-${args.values.label}`,
|
||||
label: String(args.values.title ?? ''),
|
||||
title: String(args.values.title ?? ''),
|
||||
defaultValue: String(args.values.defaultValue),
|
||||
placeholder: String(args.values.placeholder),
|
||||
});
|
||||
if (args.values.store !== STORE_NONE && !args.values.namespace) {
|
||||
throw new Error('Namespace is required when storing values')
|
||||
}
|
||||
|
||||
const existing = await maybeGetValue(ctx, args);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const value = await ctx.prompt.text({
|
||||
id: `prompt-${args.values.label ?? 'none'}`,
|
||||
label: String(args.values.label || 'Value'),
|
||||
title: String(args.values.title ?? 'Enter Value'),
|
||||
defaultValue: String(args.values.defaultValue ?? ''),
|
||||
placeholder: String(args.values.placeholder ?? ''),
|
||||
password: Boolean(args.values.password),
|
||||
required: false,
|
||||
});
|
||||
|
||||
if (value == null) {
|
||||
throw new Error('Prompt cancelled');
|
||||
}
|
||||
|
||||
if (args.values.store !== STORE_NONE) {
|
||||
await maybeSetValue(ctx, args, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
};
|
||||
|
||||
function buildKey(args: CallTemplateFunctionArgs) {
|
||||
return [args.values.namespace, args.values.key || args.values.label]
|
||||
.filter((v) => !!v)
|
||||
.map((v) => slugify(String(v), { lower: true, trim: true }))
|
||||
.join('.');
|
||||
}
|
||||
|
||||
async function maybeGetValue(ctx: Context, args: CallTemplateFunctionArgs) {
|
||||
if (args.values.store === STORE_NONE) return null;
|
||||
|
||||
const existing = await ctx.store.get<Saved>(buildKey(args));
|
||||
if (existing == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (args.values.store === STORE_FOREVER) {
|
||||
return existing.value;
|
||||
}
|
||||
|
||||
const ttlSeconds = parseInt(String(args.values.ttl)) || 0;
|
||||
const ageSeconds = (Date.now() - existing.createdAt) / 1000;
|
||||
if (ageSeconds > ttlSeconds) {
|
||||
ctx.store.delete(buildKey(args)).catch(console.error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return existing.value;
|
||||
}
|
||||
|
||||
async function maybeSetValue(ctx: Context, args: CallTemplateFunctionArgs, value: string) {
|
||||
if (args.values.store === STORE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.store.set<Saved>(buildKey(args), { value, createdAt: Date.now() });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user