/*
Start making Packs!
Try out the hello world sample below to create your first build.
*/
// This import statement gives you access to all parts of the Coda Packs SDK.
import * as coda from "@codahq/packs-sdk";
// type ExecutionModes = "code" | "return_code" | "JsObject" | "JSON";
enum ExecutionMode {
code = "{code}",
return_code = "return {code}",
jsobject = "parse JsObject",
json = "parse JSON"
}
const ExecutionAutoComplete = Object.entries(ExecutionMode).map( ([value, display]) => ({ display, value }) )
// This line creates your new Pack.
export const pack = coda.newPack();
const commonParameters: coda.ParamDefs = [
coda.makeParameter({
name: "mode",
type: coda.ParameterType.String,
autocomplete: ExecutionAutoComplete,
suggestedValue: "prepend",
description: "Use execution mode to reduce the amount of code you have to write. "
}),
coda.makeParameter({
name: "code",
type: coda.ParameterType.String,
description: "The code to be executed"
}),
];
let variableParams: coda.ParamDefs = [
{
...commonParameters[1],
name: "moreCode"
}
]
type ExecutionResult = {
input: string,
result: string | number | boolean | object | Array<string | number | boolean | object>;
resultAsString: string
}
const ExecutionResultBaseSchema = coda.makeObjectSchema({
displayProperty: "resultAsString",
properties: {
id: { type: coda.ValueType.String },
input: { type: coda.ValueType.String, },
result: {
type: coda.ValueType.Object,
properties: {},
includeUnknownProperties: true
},
resultAsString: {
type: coda.ValueType.String,
description: "JSON.stringify'ed result"
},
},
});
function runJS(mode: ExecutionMode, firstSnippet: string, ...moreSnippets: string[]): ExecutionResult {
try {
const input = [firstSnippet, ...moreSnippets].join(';');
let code = input;
let result;
if (ExecutionMode.jsobject == mode) {
result = JSON.parse(JSON.stringify(input))
}
else if (ExecutionMode.json == mode) {
result = JSON.parse(input);
}
else {
if (ExecutionMode.return_code == mode) {
code = `return ${input}`;
}
result = Function(code)();
let modified = false;
if (!result) {
modified = true;
result = Function(`return (${code});`)();
}
if (!result) {
throw new coda.UserVisibleError('Your code must always return a value');
}
console.debug(`[HelloJS] Running ${modified ?? 'modified '}code`, { code, result });
}
return {
input,
result,
resultAsString: JSON.stringify(result)
};
}
catch(e) {
throw new coda.UserVisibleError(e.message);
}
}
/**
* SayHelloJS Action
*/
pack.addFormula({
name: "SayHelloJS",
description: "Runs some javascript code",
resultType: coda.ValueType.Object,
schema: ExecutionResultBaseSchema,
isAction: true,
parameters: commonParameters,
varargParameters: variableParams,
execute: async function ([mode, code, ...moreCode]: [ExecutionMode, string, ...string[]], context: coda.ExecutionContext) {
if (!Object.values(ExecutionMode).includes(mode)) {
throw new coda.UserVisibleError("Invalid execution mode: " + mode);
}
return runJS(mode, code, ...moreCode);
},
});
/**
* HelloJS Formula
*/
pack.addFormula({
// This is the name that will be called in the formula builder.
// Remember, your formula name cannot have spaces in it.
name: "HelloJS",
description: "Say Hello JS",
// If your formula requires one or more inputs, you’ll define them here.
// Here, we're creating a string input called “name”.
parameters: commonParameters,
varargParameters: variableParams,
// The resultType defines what will be returned in your Coda doc. Here, we're
// returning a simple text string.
resultType: coda.ValueType.Object,
schema: ExecutionResultBaseSchema,
// Everything inside this execute statement will happen anytime your Coda
// formula is called in a doc. An array of all user inputs is always the 1st
// parameter.
execute: async function ([mode, code, ...moreCode]: [ExecutionMode, string, ...string[]], context: coda.ExecutionContext) {
if (!Object.values(ExecutionMode).includes(mode)) {
throw new coda.UserVisibleError("Invalid execution mode: " + mode);
}
return runJS(mode, code, ...moreCode);
},
});
const EditorSchema = coda.makeObjectSchema({
properties: {
name: { type: coda.ValueType.String },
code: {
type: coda.ValueType.String,
codaType: coda.ValueHintType.Html,
mutable: true
},
// ...
},
// Use the SKU in mention chips, to save space.
displayProperty: "name",
// Display the full product name in cards.
titleProperty: "name",
snippetProperty: "code",
});
pack.addFormula({
name: "JsEditor",
description: "Edit your code here",
resultType: coda.ValueType.Object,
schema: EditorSchema,
parameters: [
coda.makeParameter({
type: coda.ParameterType.String,
name: "name",
description: "The name of your script",
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "code",
description: "Your javascript code.",
}),
],
execute: async function ([name, code]: [string, string], context: coda.ExecutionContext) {
return {
name, code: `<code>${code}</code>`
};
},
});