@epilot/cli 0.1.108 → 0.1.109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/definitions/app.json +170 -38
- package/dist/{add-component-UPHG3VNG.js → add-component-TCF7V3KU.js} +1 -11
- package/dist/add-function-VRVBRNY3.js +184 -0
- package/dist/app-NATUF3YX.js +26 -0
- package/dist/bin/epilot.js +4 -4
- package/dist/{chunk-QOD77YLW.js → chunk-UDGF4AVJ.js} +263 -3
- package/dist/{deploy-NRQHZ635.js → deploy-2U5FVEE7.js} +90 -9
- package/dist/dev-JEAHUYQU.js +105 -0
- package/dist/{export-ZRDJCALM.js → export-VLAY2KZP.js} +1 -1
- package/dist/{init-BXAGJAPS.js → init-C66L5GFR.js} +164 -4
- package/dist/{remove-component-LPTHVN4P.js → remove-component-7C7MPSBF.js} +1 -1
- package/dist/{review-OZTM3XBD.js → review-JZTMQNU3.js} +1 -1
- package/dist/{upgrade-HU256V6J.js → upgrade-5RFPLKLG.js} +1 -1
- package/dist/{validate-TLSOTJAY.js → validate-J35DJW3H.js} +9 -1
- package/dist/{versions-VA4H3EPK.js → versions-2TMTHO7W.js} +1 -1
- package/package.json +1 -1
- package/dist/app-RULTIGMJ.js +0 -24
package/README.md
CHANGED
package/definitions/app.json
CHANGED
|
@@ -1501,6 +1501,18 @@
|
|
|
1501
1501
|
"type": "string"
|
|
1502
1502
|
},
|
|
1503
1503
|
"description": "Path to forward to the proxy target"
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
"name": "query",
|
|
1507
|
+
"in": "query",
|
|
1508
|
+
"required": false,
|
|
1509
|
+
"style": "form",
|
|
1510
|
+
"explode": true,
|
|
1511
|
+
"schema": {
|
|
1512
|
+
"type": "object",
|
|
1513
|
+
"additionalProperties": true
|
|
1514
|
+
},
|
|
1515
|
+
"description": "Free-form query parameters, forwarded unchanged to the proxy target"
|
|
1504
1516
|
}
|
|
1505
1517
|
],
|
|
1506
1518
|
"get": {
|
|
@@ -1812,6 +1824,13 @@
|
|
|
1812
1824
|
},
|
|
1813
1825
|
"grants": {
|
|
1814
1826
|
"$ref": "#/components/schemas/Grants"
|
|
1827
|
+
},
|
|
1828
|
+
"functions": {
|
|
1829
|
+
"type": "array",
|
|
1830
|
+
"items": {
|
|
1831
|
+
"$ref": "#/components/schemas/FunctionDefinition"
|
|
1832
|
+
},
|
|
1833
|
+
"description": "Replaces the full set of server-side functions for this version"
|
|
1815
1834
|
}
|
|
1816
1835
|
}
|
|
1817
1836
|
}
|
|
@@ -2069,10 +2088,99 @@
|
|
|
2069
2088
|
"CUSTOM_CAPABILITY",
|
|
2070
2089
|
"EXTERNAL_PRODUCT_CATALOG",
|
|
2071
2090
|
"CUSTOM_PAGE",
|
|
2072
|
-
"API_PROXY"
|
|
2091
|
+
"API_PROXY",
|
|
2092
|
+
"APP_FUNCTION"
|
|
2073
2093
|
],
|
|
2074
2094
|
"description": "Type of app component"
|
|
2075
2095
|
},
|
|
2096
|
+
"FunctionDefinition": {
|
|
2097
|
+
"type": "object",
|
|
2098
|
+
"description": "A named server-side function belonging to the app. Runs in the epilot code-execution sandbox with an installation-scoped app token. Functions with a schedule are executed automatically once per installation.\n",
|
|
2099
|
+
"required": [
|
|
2100
|
+
"name",
|
|
2101
|
+
"type",
|
|
2102
|
+
"code"
|
|
2103
|
+
],
|
|
2104
|
+
"properties": {
|
|
2105
|
+
"name": {
|
|
2106
|
+
"type": "string",
|
|
2107
|
+
"description": "Unique function name within the app",
|
|
2108
|
+
"pattern": "^[a-z0-9][a-z0-9-]{0,63}$"
|
|
2109
|
+
},
|
|
2110
|
+
"type": {
|
|
2111
|
+
"type": "string",
|
|
2112
|
+
"enum": [
|
|
2113
|
+
"workflow",
|
|
2114
|
+
"scheduled"
|
|
2115
|
+
],
|
|
2116
|
+
"description": "Where the function can be used. `workflow` functions are selectable as actions in the flow builder and run with entity context. `scheduled` functions run automatically per installation on their cron schedule.\n"
|
|
2117
|
+
},
|
|
2118
|
+
"label": {
|
|
2119
|
+
"allOf": [
|
|
2120
|
+
{
|
|
2121
|
+
"description": "Human-readable display name, e.g. shown in the flow builder action picker"
|
|
2122
|
+
},
|
|
2123
|
+
{
|
|
2124
|
+
"$ref": "#/components/schemas/TranslatedString"
|
|
2125
|
+
}
|
|
2126
|
+
]
|
|
2127
|
+
},
|
|
2128
|
+
"description": {
|
|
2129
|
+
"allOf": [
|
|
2130
|
+
{
|
|
2131
|
+
"description": "Description of the function"
|
|
2132
|
+
},
|
|
2133
|
+
{
|
|
2134
|
+
"$ref": "#/components/schemas/TranslatedString"
|
|
2135
|
+
}
|
|
2136
|
+
]
|
|
2137
|
+
},
|
|
2138
|
+
"code": {
|
|
2139
|
+
"type": "string",
|
|
2140
|
+
"maxLength": 307200,
|
|
2141
|
+
"description": "JavaScript code to execute. Must declare a top-level `async function handler(input, context)`. Maximum size: 300KB (hard limit). Security restrictions: eval() and Function() constructor are not allowed.\n"
|
|
2142
|
+
},
|
|
2143
|
+
"schedule": {
|
|
2144
|
+
"type": "string",
|
|
2145
|
+
"maxLength": 100,
|
|
2146
|
+
"description": "Cron trigger for the function, executed once per installation. Standard 5-field cron expression (e.g. \"0 3 * * *\") or rate expression (e.g. \"rate(30 minutes)\"). Minimum interval: 15 minutes. Scheduled runs are limited to 60 seconds.\n",
|
|
2147
|
+
"example": "rate(30 minutes)"
|
|
2148
|
+
},
|
|
2149
|
+
"schedule_timezone": {
|
|
2150
|
+
"type": "string",
|
|
2151
|
+
"description": "IANA timezone the cron expression is evaluated in",
|
|
2152
|
+
"default": "Europe/Berlin"
|
|
2153
|
+
},
|
|
2154
|
+
"schedule_overlap": {
|
|
2155
|
+
"type": "string",
|
|
2156
|
+
"enum": [
|
|
2157
|
+
"skip"
|
|
2158
|
+
],
|
|
2159
|
+
"default": "skip",
|
|
2160
|
+
"description": "Behavior when the previous scheduled run is still active"
|
|
2161
|
+
},
|
|
2162
|
+
"secrets": {
|
|
2163
|
+
"type": "array",
|
|
2164
|
+
"items": {
|
|
2165
|
+
"type": "string"
|
|
2166
|
+
},
|
|
2167
|
+
"description": "Keys of installation options of type secret made available to the function via input.app_options\n"
|
|
2168
|
+
},
|
|
2169
|
+
"wait_for_callback": {
|
|
2170
|
+
"type": "boolean",
|
|
2171
|
+
"description": "Workflow functions only — wait for the callback_url to be called before completing the flow action\n"
|
|
2172
|
+
},
|
|
2173
|
+
"surfaces": {
|
|
2174
|
+
"type": "object",
|
|
2175
|
+
"description": "Workflow functions only — optional custom config UI shown in the flow builder",
|
|
2176
|
+
"properties": {
|
|
2177
|
+
"flow_action_config": {
|
|
2178
|
+
"$ref": "#/components/schemas/AppBridgeSurfaceConfig"
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
},
|
|
2076
2184
|
"Author": {
|
|
2077
2185
|
"type": "object",
|
|
2078
2186
|
"required": [
|
|
@@ -2486,52 +2594,18 @@
|
|
|
2486
2594
|
}
|
|
2487
2595
|
]
|
|
2488
2596
|
},
|
|
2489
|
-
"SandboxCustomActionConfig": {
|
|
2490
|
-
"allOf": [
|
|
2491
|
-
{
|
|
2492
|
-
"$ref": "#/components/schemas/BaseCustomActionConfig"
|
|
2493
|
-
},
|
|
2494
|
-
{
|
|
2495
|
-
"type": "object",
|
|
2496
|
-
"properties": {
|
|
2497
|
-
"type": {
|
|
2498
|
-
"type": "string",
|
|
2499
|
-
"enum": [
|
|
2500
|
-
"sandbox"
|
|
2501
|
-
]
|
|
2502
|
-
},
|
|
2503
|
-
"sandbox_settings": {
|
|
2504
|
-
"type": "object",
|
|
2505
|
-
"properties": {
|
|
2506
|
-
"code": {
|
|
2507
|
-
"type": "string",
|
|
2508
|
-
"description": "JavaScript code to execute for the sandbox action. Maximum size: 300KB (hard limit). Code is stored as raw JavaScript and will be syntax-validated on save. Security restrictions: eval() and Function() constructor are not allowed.\n",
|
|
2509
|
-
"maxLength": 307200
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2512
|
-
}
|
|
2513
|
-
},
|
|
2514
|
-
"required": [
|
|
2515
|
-
"type"
|
|
2516
|
-
]
|
|
2517
|
-
}
|
|
2518
|
-
]
|
|
2519
|
-
},
|
|
2520
2597
|
"CustomFlowConfig": {
|
|
2521
2598
|
"type": "object",
|
|
2599
|
+
"description": "Configuration of an external-integration flow action. Sandboxed code belongs in the app's `functions` (type `workflow`) instead — workflow functions are selectable directly in the flow builder without a component.\n",
|
|
2522
2600
|
"oneOf": [
|
|
2523
2601
|
{
|
|
2524
2602
|
"$ref": "#/components/schemas/ExternalIntegrationCustomActionConfig"
|
|
2525
|
-
},
|
|
2526
|
-
{
|
|
2527
|
-
"$ref": "#/components/schemas/SandboxCustomActionConfig"
|
|
2528
2603
|
}
|
|
2529
2604
|
],
|
|
2530
2605
|
"discriminator": {
|
|
2531
2606
|
"propertyName": "type",
|
|
2532
2607
|
"mapping": {
|
|
2533
|
-
"external_integration": "#/components/schemas/ExternalIntegrationCustomActionConfig"
|
|
2534
|
-
"sandbox": "#/components/schemas/SandboxCustomActionConfig"
|
|
2608
|
+
"external_integration": "#/components/schemas/ExternalIntegrationCustomActionConfig"
|
|
2535
2609
|
}
|
|
2536
2610
|
}
|
|
2537
2611
|
},
|
|
@@ -4563,6 +4637,39 @@
|
|
|
4563
4637
|
}
|
|
4564
4638
|
}
|
|
4565
4639
|
},
|
|
4640
|
+
"InternalReview": {
|
|
4641
|
+
"description": "Review entry including app ownership info, used by internal admin endpoints",
|
|
4642
|
+
"allOf": [
|
|
4643
|
+
{
|
|
4644
|
+
"$ref": "#/components/schemas/Review"
|
|
4645
|
+
},
|
|
4646
|
+
{
|
|
4647
|
+
"type": "object",
|
|
4648
|
+
"properties": {
|
|
4649
|
+
"app_id": {
|
|
4650
|
+
"type": "string",
|
|
4651
|
+
"description": "ID of the app configuration",
|
|
4652
|
+
"readOnly": true
|
|
4653
|
+
},
|
|
4654
|
+
"org_id": {
|
|
4655
|
+
"type": "string",
|
|
4656
|
+
"description": "Organization ID of the app owner",
|
|
4657
|
+
"readOnly": true
|
|
4658
|
+
},
|
|
4659
|
+
"reviewed_by": {
|
|
4660
|
+
"type": "string",
|
|
4661
|
+
"description": "Identity of the internal reviewer who approved the review",
|
|
4662
|
+
"readOnly": true
|
|
4663
|
+
},
|
|
4664
|
+
"reviewed_at": {
|
|
4665
|
+
"type": "string",
|
|
4666
|
+
"description": "Timestamp of the approval",
|
|
4667
|
+
"readOnly": true
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
]
|
|
4672
|
+
},
|
|
4566
4673
|
"ConfigurationMetadata": {
|
|
4567
4674
|
"description": "Basic metadata about your app configuration which does not get versioned",
|
|
4568
4675
|
"type": "object",
|
|
@@ -4708,6 +4815,14 @@
|
|
|
4708
4815
|
},
|
|
4709
4816
|
"minItems": 0
|
|
4710
4817
|
},
|
|
4818
|
+
"functions": {
|
|
4819
|
+
"type": "array",
|
|
4820
|
+
"items": {
|
|
4821
|
+
"$ref": "#/components/schemas/FunctionDefinition"
|
|
4822
|
+
},
|
|
4823
|
+
"minItems": 0,
|
|
4824
|
+
"description": "Server-side functions of the app, including scheduled functions"
|
|
4825
|
+
},
|
|
4711
4826
|
"visibility": {
|
|
4712
4827
|
"type": "string",
|
|
4713
4828
|
"enum": [
|
|
@@ -4816,10 +4931,11 @@
|
|
|
4816
4931
|
"enum": [
|
|
4817
4932
|
"header",
|
|
4818
4933
|
"bearer",
|
|
4934
|
+
"basic",
|
|
4819
4935
|
"oauth2",
|
|
4820
4936
|
"none"
|
|
4821
4937
|
],
|
|
4822
|
-
"description": "Authentication strategy"
|
|
4938
|
+
"description": "Authentication strategy. 'basic' sends an HTTP Basic Authorization header built server-side from the 'username' and 'password' component options."
|
|
4823
4939
|
},
|
|
4824
4940
|
"auth_header": {
|
|
4825
4941
|
"type": "string",
|
|
@@ -4936,6 +5052,14 @@
|
|
|
4936
5052
|
"minLength": 0,
|
|
4937
5053
|
"readOnly": true
|
|
4938
5054
|
},
|
|
5055
|
+
"functions": {
|
|
5056
|
+
"description": "Server-side functions of the installed version, including scheduled functions",
|
|
5057
|
+
"type": "array",
|
|
5058
|
+
"items": {
|
|
5059
|
+
"$ref": "#/components/schemas/FunctionDefinition"
|
|
5060
|
+
},
|
|
5061
|
+
"readOnly": true
|
|
5062
|
+
},
|
|
4939
5063
|
"installed_version": {
|
|
4940
5064
|
"type": "string",
|
|
4941
5065
|
"description": "Version of the app that is installed",
|
|
@@ -5043,6 +5167,14 @@
|
|
|
5043
5167
|
},
|
|
5044
5168
|
"minItems": 0
|
|
5045
5169
|
},
|
|
5170
|
+
"functions": {
|
|
5171
|
+
"type": "array",
|
|
5172
|
+
"items": {
|
|
5173
|
+
"$ref": "#/components/schemas/FunctionDefinition"
|
|
5174
|
+
},
|
|
5175
|
+
"minItems": 0,
|
|
5176
|
+
"description": "Server-side functions of the app, including scheduled functions"
|
|
5177
|
+
},
|
|
5046
5178
|
"is_beta": {
|
|
5047
5179
|
"type": "boolean",
|
|
5048
5180
|
"description": "Flag to indicate if the app is in beta.",
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
log,
|
|
4
4
|
readManifest,
|
|
5
5
|
writeManifest
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UDGF4AVJ.js";
|
|
7
7
|
import "./chunk-M3M3C5WH.js";
|
|
8
8
|
import "./chunk-YHQA2AVG.js";
|
|
9
9
|
import "./chunk-7ZQ666ZQ.js";
|
|
@@ -15,16 +15,6 @@ import { existsSync, readFileSync, writeFileSync, readdirSync } from "fs";
|
|
|
15
15
|
import { resolve, join } from "path";
|
|
16
16
|
var TEMPLATES_REPO = "epilot-dev/app-templates";
|
|
17
17
|
var TEMPLATE_REGISTRY = {
|
|
18
|
-
CUSTOM_FLOW_ACTION_SANDBOX: {
|
|
19
|
-
configOnly: false,
|
|
20
|
-
manifestType: "CUSTOM_FLOW_ACTION",
|
|
21
|
-
templateDir: "custom-flow-action-sandbox",
|
|
22
|
-
description: "Sandboxed flow action (JS runs in epilot)",
|
|
23
|
-
configuration: () => ({
|
|
24
|
-
type: "sandbox",
|
|
25
|
-
sandbox_settings: { code: "// code is read from dist/ during deploy" }
|
|
26
|
-
})
|
|
27
|
-
},
|
|
28
18
|
CUSTOM_FLOW_ACTION_EXTERNAL: {
|
|
29
19
|
configOnly: true,
|
|
30
20
|
manifestType: "CUSTOM_FLOW_ACTION",
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
log,
|
|
4
|
+
readManifest,
|
|
5
|
+
validateScheduleExpression,
|
|
6
|
+
writeManifest
|
|
7
|
+
} from "./chunk-UDGF4AVJ.js";
|
|
8
|
+
import "./chunk-M3M3C5WH.js";
|
|
9
|
+
import "./chunk-YHQA2AVG.js";
|
|
10
|
+
import "./chunk-7ZQ666ZQ.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/app/add-function.ts
|
|
13
|
+
import { defineCommand } from "citty";
|
|
14
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
15
|
+
import { join, resolve } from "path";
|
|
16
|
+
var NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
17
|
+
var add_function_default = defineCommand({
|
|
18
|
+
meta: {
|
|
19
|
+
name: "add-function",
|
|
20
|
+
description: "Add a server-side function (optionally scheduled) to the app"
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
name: { type: "positional", description: "Function name (kebab-case)", required: true },
|
|
24
|
+
type: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: '"workflow" (selectable as flow action) or "scheduled" (cron per installation). Default: scheduled when --schedule is given, workflow otherwise'
|
|
27
|
+
},
|
|
28
|
+
schedule: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: 'Cron ("0 3 * * *") or rate ("rate(30 minutes)") expression to run the function once per installation'
|
|
31
|
+
},
|
|
32
|
+
label: { type: "string", description: "Display name shown to org admins (e.g. in the flow builder)" },
|
|
33
|
+
timezone: { type: "string", description: "IANA timezone for cron schedules (default: Europe/Berlin)" },
|
|
34
|
+
path: { type: "string", description: "Path to manifest.json (default: manifest.json)" }
|
|
35
|
+
},
|
|
36
|
+
run: ({ args }) => {
|
|
37
|
+
const name = args.name;
|
|
38
|
+
if (!NAME_PATTERN.test(name)) {
|
|
39
|
+
log.error(`Invalid function name "${name}" \u2014 use kebab-case (a-z, 0-9, dashes; max 64 chars)`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
const fnType = args.type ?? (args.schedule ? "scheduled" : "workflow");
|
|
43
|
+
if (fnType !== "workflow" && fnType !== "scheduled") {
|
|
44
|
+
log.error(`Invalid --type "${args.type}" \u2014 use "workflow" or "scheduled"`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
if (fnType === "scheduled" && !args.schedule) {
|
|
48
|
+
log.error("Scheduled functions require --schedule (cron or rate expression)");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
if (fnType === "workflow" && args.schedule) {
|
|
52
|
+
log.error("Workflow functions cannot have a schedule \u2014 drop --schedule or use --type scheduled");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
if (args.schedule) {
|
|
56
|
+
const result = validateScheduleExpression(args.schedule);
|
|
57
|
+
if (!result.valid) {
|
|
58
|
+
log.error(`Invalid schedule: ${result.error}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const manifestPath = resolve(args.path ?? "manifest.json");
|
|
63
|
+
const manifest = readManifest(manifestPath);
|
|
64
|
+
const rootDir = resolve(manifestPath, "..");
|
|
65
|
+
if (manifest.functions?.some((fn2) => fn2.name === name)) {
|
|
66
|
+
log.error(`Function "${name}" already exists in the manifest`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const fnDir = join(rootDir, "functions", name);
|
|
70
|
+
if (existsSync(fnDir)) {
|
|
71
|
+
log.error(`Directory already exists: ${fnDir}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
mkdirSync(join(fnDir, "src"), { recursive: true });
|
|
75
|
+
writeFileSync(
|
|
76
|
+
join(fnDir, "package.json"),
|
|
77
|
+
`${JSON.stringify(
|
|
78
|
+
{
|
|
79
|
+
name,
|
|
80
|
+
private: true,
|
|
81
|
+
version: "0.0.1",
|
|
82
|
+
type: "module",
|
|
83
|
+
scripts: { build: "tsc", dev: "tsx watch src/handler.ts" },
|
|
84
|
+
devDependencies: { typescript: "~5.8.3", tsx: "^4.0.0" }
|
|
85
|
+
},
|
|
86
|
+
null,
|
|
87
|
+
2
|
|
88
|
+
)}
|
|
89
|
+
`
|
|
90
|
+
);
|
|
91
|
+
writeFileSync(
|
|
92
|
+
join(fnDir, "tsconfig.json"),
|
|
93
|
+
`${JSON.stringify(
|
|
94
|
+
{
|
|
95
|
+
compilerOptions: {
|
|
96
|
+
target: "ES2022",
|
|
97
|
+
lib: ["ES2022", "DOM"],
|
|
98
|
+
module: "ESNext",
|
|
99
|
+
moduleResolution: "bundler",
|
|
100
|
+
strict: true,
|
|
101
|
+
rootDir: "src",
|
|
102
|
+
outDir: "dist",
|
|
103
|
+
esModuleInterop: true,
|
|
104
|
+
skipLibCheck: true
|
|
105
|
+
},
|
|
106
|
+
include: ["src"]
|
|
107
|
+
},
|
|
108
|
+
null,
|
|
109
|
+
2
|
|
110
|
+
)}
|
|
111
|
+
`
|
|
112
|
+
);
|
|
113
|
+
writeFileSync(join(fnDir, "src", "handler.ts"), handlerTemplate(name, fnType, args.schedule));
|
|
114
|
+
const fn = {
|
|
115
|
+
name,
|
|
116
|
+
type: fnType,
|
|
117
|
+
...args.label ? { label: { de: args.label } } : {},
|
|
118
|
+
handler: `./functions/${name}/dist/handler.js`,
|
|
119
|
+
...args.schedule ? { schedule: args.schedule } : {},
|
|
120
|
+
...args.timezone ? { schedule_timezone: args.timezone } : {}
|
|
121
|
+
};
|
|
122
|
+
manifest.functions = [...manifest.functions ?? [], fn];
|
|
123
|
+
writeManifest(manifestPath, manifest);
|
|
124
|
+
log.success(`Added ${fnType} function "${name}"`);
|
|
125
|
+
log.info(`Code: functions/${name}/src/handler.ts`);
|
|
126
|
+
if (args.schedule) {
|
|
127
|
+
log.info(`Schedule: ${args.schedule} (runs once per installation, max 60s per run)`);
|
|
128
|
+
} else {
|
|
129
|
+
log.info("Selectable as an action in the flow builder once the app is installed");
|
|
130
|
+
}
|
|
131
|
+
log.dim('Build with "npm run build", then "epilot app deploy"');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
var handlerTemplate = (name, fnType, schedule) => `// App function: ${name}
|
|
135
|
+
//${fnType === "scheduled" ? `
|
|
136
|
+
// Runs automatically ${schedule?.startsWith("rate(") ? `every ${schedule.slice(5, -1)}` : `on "${schedule}"`} \u2014 once per installation,
|
|
137
|
+
// inside the epilot code-execution sandbox with a 60 second budget. Do a
|
|
138
|
+
// bounded amount of work per run; the next tick picks up the rest.` : `
|
|
139
|
+
// Selectable as an action in the flow builder. Runs inside the epilot
|
|
140
|
+
// code-execution sandbox with the triggering entity in \`input.entity\`.`}
|
|
141
|
+
//
|
|
142
|
+
// Runtime contract:
|
|
143
|
+
// - top-level \`async function handler(input, context)\` \u2014 no \`export\`.
|
|
144
|
+
// - \`input.trigger\` \u2192 { type: '${fnType === "scheduled" ? "schedule" : "workflow"}', ... }.${fnType === "workflow" ? `
|
|
145
|
+
// - \`input.entity\` \u2192 the entity the flow ran on.
|
|
146
|
+
// - \`input.action_config\` \u2192 the action's configuration from the flow builder.` : `
|
|
147
|
+
// - \`input.org_id\` / \`input.app_id\` \u2192 the installation this run belongs to.`}
|
|
148
|
+
// - \`context.epilot\` \u2192 the bundled @epilot/sdk, pre-authorized with the app token
|
|
149
|
+
// (scoped to the app's permissions): \`await context.epilot.entity.searchEntities(...)\`.
|
|
150
|
+
// - \`context.fetch\` \u2192 plain fetch, e.g. for the app's API proxy or non-prod stages
|
|
151
|
+
// (derive base URLs from \`input.app_options.stage\`).
|
|
152
|
+
// - \`input.app_options.token\` \u2192 the raw app token, if you need it for fetch calls.
|
|
153
|
+
// - Return \`{ skip_reason }\` to skip, \`{ error_reason }\` to fail the run.
|
|
154
|
+
|
|
155
|
+
interface FunctionInput {
|
|
156
|
+
trigger?: { type: string; schedule?: string; scheduled_time?: string };
|
|
157
|
+
org_id?: string;
|
|
158
|
+
app_id?: string;${fnType === "workflow" ? `
|
|
159
|
+
entity?: Record<string, unknown>;
|
|
160
|
+
action_config?: Record<string, unknown>;` : ""}
|
|
161
|
+
app_options?: { token?: string; stage?: string } & Record<string, unknown>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
interface FunctionContext {
|
|
165
|
+
/** Bundled @epilot/sdk, pre-authorized \u2014 e.g. context.epilot.entity.searchEntities(...) */
|
|
166
|
+
epilot: Record<string, any>;
|
|
167
|
+
fetch: typeof fetch;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function handler(input: FunctionInput, context: FunctionContext) {
|
|
171
|
+
const token = input.app_options?.token;
|
|
172
|
+
if (!token) {
|
|
173
|
+
return { error_reason: 'Missing app token in execution context.' };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// TODO: implement your logic here
|
|
177
|
+
console.log('${name} run', { trigger: input.trigger?.type, org: input.org_id });
|
|
178
|
+
|
|
179
|
+
return { success: true };
|
|
180
|
+
}
|
|
181
|
+
`;
|
|
182
|
+
export {
|
|
183
|
+
add_function_default as default
|
|
184
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/app/index.ts
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
var app_default = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "app",
|
|
8
|
+
description: "Manage epilot Apps \u2014 create, deploy, and manage app manifests"
|
|
9
|
+
},
|
|
10
|
+
subCommands: {
|
|
11
|
+
init: () => import("./init-C66L5GFR.js").then((m) => m.default),
|
|
12
|
+
"add-component": () => import("./add-component-TCF7V3KU.js").then((m) => m.default),
|
|
13
|
+
"remove-component": () => import("./remove-component-7C7MPSBF.js").then((m) => m.default),
|
|
14
|
+
"add-function": () => import("./add-function-VRVBRNY3.js").then((m) => m.default),
|
|
15
|
+
validate: () => import("./validate-J35DJW3H.js").then((m) => m.default),
|
|
16
|
+
deploy: () => import("./deploy-2U5FVEE7.js").then((m) => m.default),
|
|
17
|
+
dev: () => import("./dev-JEAHUYQU.js").then((m) => m.default),
|
|
18
|
+
export: () => import("./export-VLAY2KZP.js").then((m) => m.default),
|
|
19
|
+
versions: () => import("./versions-2TMTHO7W.js").then((m) => m.default),
|
|
20
|
+
review: () => import("./review-JZTMQNU3.js").then((m) => m.default),
|
|
21
|
+
api: () => import("./api-5W2UMWCW.js").then((m) => m.default)
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
export {
|
|
25
|
+
app_default as default
|
|
26
|
+
};
|
package/dist/bin/epilot.js
CHANGED
|
@@ -11,7 +11,7 @@ import { defineCommand } from "citty";
|
|
|
11
11
|
var main = defineCommand({
|
|
12
12
|
meta: {
|
|
13
13
|
name: "epilot",
|
|
14
|
-
version: "0.1.
|
|
14
|
+
version: "0.1.109",
|
|
15
15
|
description: "CLI for epilot APIs"
|
|
16
16
|
},
|
|
17
17
|
args: {
|
|
@@ -31,12 +31,12 @@ var main = defineCommand({
|
|
|
31
31
|
profile: () => import("../profile-OZJL5ZPT.js").then((m) => m.default),
|
|
32
32
|
config: () => import("../config-DGZIMLZK.js").then((m) => m.default),
|
|
33
33
|
completion: () => import("../completion-TFHA4W2J.js").then((m) => m.default),
|
|
34
|
-
upgrade: () => import("../upgrade-
|
|
34
|
+
upgrade: () => import("../upgrade-5RFPLKLG.js").then((m) => m.default),
|
|
35
35
|
"access-token": () => import("../access-token-WWE6BDJH.js").then((m) => m.default),
|
|
36
36
|
address: () => import("../address-EH3C4CVB.js").then((m) => m.default),
|
|
37
37
|
"address-suggestions": () => import("../address-suggestions-RRSLOBFW.js").then((m) => m.default),
|
|
38
38
|
"ai-agents": () => import("../ai-agents-53M2KHPI.js").then((m) => m.default),
|
|
39
|
-
app: () => import("../app-
|
|
39
|
+
app: () => import("../app-NATUF3YX.js").then((m) => m.default),
|
|
40
40
|
"audit-logs": () => import("../audit-logs-YFRK3EFU.js").then((m) => m.default),
|
|
41
41
|
automation: () => import("../automation-4DEE3TUI.js").then((m) => m.default),
|
|
42
42
|
billing: () => import("../billing-XX4VVOPI.js").then((m) => m.default),
|
|
@@ -134,7 +134,7 @@ process.stderr.on("error", (err) => {
|
|
|
134
134
|
if (err.code === "EPIPE") process.exit(0);
|
|
135
135
|
throw err;
|
|
136
136
|
});
|
|
137
|
-
var VERSION = true ? "0.1.
|
|
137
|
+
var VERSION = true ? "0.1.109" : (await null).default.version;
|
|
138
138
|
var reorderedArgv = hoistFlagsAfterSubcommand(process.argv.slice(2));
|
|
139
139
|
process.argv = [process.argv[0], process.argv[1], ...reorderedArgv];
|
|
140
140
|
var args = process.argv.slice(2);
|