@epilot/cli 0.1.9 → 0.1.11
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 +3 -3
- package/definitions/app.json +56 -6
- package/definitions/blueprint-manifest.json +115 -1
- package/definitions/customer-portal.json +757 -81
- package/definitions/data-management.json +10 -0
- package/definitions/email-settings.json +121 -0
- package/definitions/email-template.json +25 -3
- package/definitions/entity.json +328 -10
- package/definitions/erp-integration.json +472 -13
- package/definitions/journey.json +274 -12
- package/definitions/kanban.json +654 -78
- package/definitions/organization.json +614 -51
- package/definitions/partner-directory.json +795 -229
- package/definitions/permissions.json +41 -6
- package/definitions/webhooks.json +111 -2
- package/definitions/workflow.json +40 -0
- package/dist/{access-token-PTTCRMGK.js → access-token-CIM4RLBP.js} +1 -1
- package/dist/add-component-IW4644NE.js +241 -0
- package/dist/{address-2FDPEPR6.js → address-EDRTUWTP.js} +1 -1
- package/dist/{address-suggestions-XBEK5DDQ.js → address-suggestions-S5WEST2N.js} +1 -1
- package/dist/{ai-agents-ZY5BNVTN.js → ai-agents-RXDDJDAR.js} +1 -1
- package/dist/{app-IT5FWGUK.js → api-36XROHLK.js} +5 -5
- package/dist/app-BKS7M4UQ.js +24 -0
- package/dist/{audit-logs-FB4TE4TI.js → audit-logs-PXGDGJGV.js} +1 -1
- package/dist/{automation-JE5LDKJM.js → automation-LS6MVLP2.js} +1 -1
- package/dist/{billing-GOFCP5T3.js → billing-KVYFUKZK.js} +1 -1
- package/dist/bin/epilot.js +52 -52
- package/dist/{blueprint-manifest-WJIQKFYK.js → blueprint-manifest-W4ZGJD2Z.js} +1 -1
- package/dist/{chunk-P5IZZW4Y.js → chunk-BYAEI4Z2.js} +1 -1
- package/dist/{chunk-PHXL66VA.js → chunk-K2UQOP3Q.js} +28 -11
- package/dist/chunk-POCU2J27.js +365 -0
- package/dist/{completion-EKFXGPNK.js → completion-HTO64G2S.js} +1 -1
- package/dist/{consent-DSMWWHUL.js → consent-M4QB2HPM.js} +1 -1
- package/dist/{customer-portal-IJYTJYUZ.js → customer-portal-SVO2YCXA.js} +1 -1
- package/dist/{dashboard-DOAX6XDG.js → dashboard-CYCXIX74.js} +1 -1
- package/dist/{data-management-C4JPPUPD.js → data-management-KXAPA7ZU.js} +1 -1
- package/dist/{deduplication-7OGLZLAC.js → deduplication-M3KEVJRG.js} +1 -1
- package/dist/deploy-UQZAUHAB.js +214 -0
- package/dist/{design-3CAYTWFY.js → design-UVJJ2KO2.js} +1 -1
- package/dist/{document-NT5JOJQV.js → document-5HB632XE.js} +1 -1
- package/dist/{email-settings-2M3WJTQS.js → email-settings-H7HQTDYE.js} +1 -1
- package/dist/{email-template-F4PLBPPC.js → email-template-2DHZ3VKF.js} +1 -1
- package/dist/{entity-32LKMZAU.js → entity-HED6QHG7.js} +1 -1
- package/dist/{entity-mapping-OBCZDYQJ.js → entity-mapping-QP22B65Z.js} +1 -1
- package/dist/{environments-H3TBCDQE.js → environments-6LLEIGWV.js} +1 -1
- package/dist/{erp-integration-UW6H55EK.js → erp-integration-DXFYJ2F3.js} +1 -1
- package/dist/{event-catalog-NVAPTZ4M.js → event-catalog-2ZCZTATY.js} +1 -1
- package/dist/export-US5GMHTS.js +44 -0
- package/dist/{file-US2HR4SV.js → file-R6IIXOIZ.js} +1 -1
- package/dist/{iban-7QUCOULB.js → iban-EQD2VROZ.js} +1 -1
- package/dist/init-DGPWBRRB.js +524 -0
- package/dist/{journey-E5T4BZZX.js → journey-V7X2KUKH.js} +1 -1
- package/dist/{kanban-7UHU5VE6.js → kanban-EPI6C3FR.js} +1 -1
- package/dist/{message-7KY33RJE.js → message-477EJ5JO.js} +1 -1
- package/dist/{metering-P7BZGMY7.js → metering-5EAEKRSL.js} +1 -1
- package/dist/{notes-TNJ7FPA3.js → notes-CVXNRULU.js} +1 -1
- package/dist/{notification-6KXEFVO5.js → notification-6HXS76XP.js} +1 -1
- package/dist/{organization-FF4Y3PBO.js → organization-O33CZQKD.js} +1 -1
- package/dist/{partner-directory-VH2SBAS2.js → partner-directory-NZWGCKSB.js} +2 -2
- package/dist/{permissions-KENZ4HNY.js → permissions-6QEOBJ6M.js} +1 -1
- package/dist/{pricing-P6QZ77VJ.js → pricing-KNYSULCW.js} +1 -1
- package/dist/{pricing-tier-2IRJMTM6.js → pricing-tier-OCHP6SHT.js} +1 -1
- package/dist/{purpose-IHROR6LQ.js → purpose-NGM42XWB.js} +1 -1
- package/dist/remove-component-B2GMICMD.js +89 -0
- package/dist/review-QFPON37R.js +69 -0
- package/dist/{sandbox-62XQPOU6.js → sandbox-YX3VVAQG.js} +1 -1
- package/dist/{submission-PUWGOYQB.js → submission-YOWVSZNA.js} +1 -1
- package/dist/{targeting-QB3DFYNI.js → targeting-BMZCOG72.js} +1 -1
- package/dist/{template-variables-IPKRUJ4E.js → template-variables-YTABZL3E.js} +1 -1
- package/dist/{upgrade-KDDTJRUC.js → upgrade-KZSOPDCR.js} +1 -1
- package/dist/{user-2CP75TFC.js → user-3N5ZOUYS.js} +1 -1
- package/dist/validate-G7K6AVBI.js +53 -0
- package/dist/{validation-rules-GNI4EEG5.js → validation-rules-QVS7LKEP.js} +1 -1
- package/dist/versions-UTPAWTIU.js +109 -0
- package/dist/{webhooks-2OWUX7UL.js → webhooks-6WMWACOW.js} +1 -1
- package/dist/{workflow-WSLERVJI.js → workflow-ZO2MKDBS.js} +1 -1
- package/dist/{workflow-definition-FP3WKHGG.js → workflow-definition-RCWKIPYI.js} +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
log,
|
|
4
|
+
writeManifest
|
|
5
|
+
} from "./chunk-POCU2J27.js";
|
|
6
|
+
import "./chunk-RSA7K5HB.js";
|
|
7
|
+
import "./chunk-PDMWUCWD.js";
|
|
8
|
+
import "./chunk-7ZQ666ZQ.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/app/init.ts
|
|
11
|
+
import { defineCommand } from "citty";
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
13
|
+
import { resolve, join } from "path";
|
|
14
|
+
var init_default = defineCommand({
|
|
15
|
+
meta: { name: "init", description: "Scaffold a new epilot app project" },
|
|
16
|
+
args: {
|
|
17
|
+
name: { type: "positional", description: "App name (also used as directory name)", required: false }
|
|
18
|
+
},
|
|
19
|
+
run: ({ args }) => {
|
|
20
|
+
const name = args.name ?? "my-epilot-app";
|
|
21
|
+
const rootDir = resolve(name);
|
|
22
|
+
if (existsSync(rootDir)) {
|
|
23
|
+
log.error(`Directory "${name}" already exists.`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
mkdirSync(rootDir, { recursive: true });
|
|
27
|
+
mkdirSync(join(rootDir, "components"));
|
|
28
|
+
const manifest = {
|
|
29
|
+
$schema: "https://cdn.app.dev.sls.epilot.io/v1/schema.json",
|
|
30
|
+
manifest_version: 1,
|
|
31
|
+
name,
|
|
32
|
+
description: { de: "App description", en: "App description" },
|
|
33
|
+
category: "integration",
|
|
34
|
+
author: { company: "Your Company", name: "Your Name", email: "dev@example.com" },
|
|
35
|
+
components: []
|
|
36
|
+
};
|
|
37
|
+
writeManifest(join(rootDir, "manifest.json"), manifest);
|
|
38
|
+
writeFileSync(
|
|
39
|
+
join(rootDir, "package.json"),
|
|
40
|
+
`${JSON.stringify(
|
|
41
|
+
{
|
|
42
|
+
name,
|
|
43
|
+
version: "0.0.1",
|
|
44
|
+
private: true,
|
|
45
|
+
packageManager: "npm@10.9.2",
|
|
46
|
+
workspaces: ["components/*"],
|
|
47
|
+
scripts: {
|
|
48
|
+
build: "turbo build",
|
|
49
|
+
dev: "turbo dev",
|
|
50
|
+
lint: "turbo lint",
|
|
51
|
+
deploy: "epilot app deploy"
|
|
52
|
+
},
|
|
53
|
+
devDependencies: {
|
|
54
|
+
turbo: "^2"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
null,
|
|
58
|
+
2
|
|
59
|
+
)}
|
|
60
|
+
`
|
|
61
|
+
);
|
|
62
|
+
writeFileSync(
|
|
63
|
+
join(rootDir, "turbo.json"),
|
|
64
|
+
`${JSON.stringify(
|
|
65
|
+
{
|
|
66
|
+
$schema: "https://turbo.build/schema.json",
|
|
67
|
+
tasks: {
|
|
68
|
+
build: {
|
|
69
|
+
dependsOn: ["^build"],
|
|
70
|
+
outputs: ["dist/**"]
|
|
71
|
+
},
|
|
72
|
+
dev: {
|
|
73
|
+
cache: false,
|
|
74
|
+
persistent: true
|
|
75
|
+
},
|
|
76
|
+
lint: {}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
null,
|
|
80
|
+
2
|
|
81
|
+
)}
|
|
82
|
+
`
|
|
83
|
+
);
|
|
84
|
+
writeFileSync(join(rootDir, ".gitignore"), ["node_modules", "dist", ".turbo", ""].join("\n"));
|
|
85
|
+
writeFileSync(
|
|
86
|
+
join(rootDir, "components", "README.md"),
|
|
87
|
+
[
|
|
88
|
+
"# Components",
|
|
89
|
+
"",
|
|
90
|
+
"Each subdirectory is a component package in the monorepo.",
|
|
91
|
+
"",
|
|
92
|
+
"Add a new component with:",
|
|
93
|
+
"",
|
|
94
|
+
"```bash",
|
|
95
|
+
"epilot app add-component <name> --type CUSTOM_CAPABILITY",
|
|
96
|
+
"```",
|
|
97
|
+
"",
|
|
98
|
+
"Available component types:",
|
|
99
|
+
"",
|
|
100
|
+
"Code-based (have src/ and build step):",
|
|
101
|
+
"- `CUSTOM_FLOW_ACTION_SANDBOX` \u2014 Sandboxed flow action (JS runs in epilot)",
|
|
102
|
+
"- `CUSTOM_CAPABILITY` \u2014 Custom entity tab or group",
|
|
103
|
+
"- `CUSTOM_JOURNEY_BLOCK` \u2014 Custom journey builder block",
|
|
104
|
+
"- `CUSTOM_PAGE` \u2014 Custom navigation page",
|
|
105
|
+
"- `CUSTOM_PORTAL_BLOCK` \u2014 Custom portal widget",
|
|
106
|
+
"",
|
|
107
|
+
"Config-only (configuration.json):",
|
|
108
|
+
"- `CUSTOM_FLOW_ACTION_EXTERNAL` \u2014 External integration webhook",
|
|
109
|
+
"- `PORTAL_EXTENSION` \u2014 Portal extension hooks",
|
|
110
|
+
"- `EXTERNAL_PRODUCT_CATALOG` \u2014 External product catalog hooks",
|
|
111
|
+
""
|
|
112
|
+
].join("\n")
|
|
113
|
+
);
|
|
114
|
+
writeFileSync(
|
|
115
|
+
join(rootDir, "README.md"),
|
|
116
|
+
[
|
|
117
|
+
`# ${name}`,
|
|
118
|
+
"",
|
|
119
|
+
"An [epilot](https://epilot.cloud) app.",
|
|
120
|
+
"",
|
|
121
|
+
"## Getting started",
|
|
122
|
+
"",
|
|
123
|
+
"```bash",
|
|
124
|
+
"# Install dependencies",
|
|
125
|
+
"npm install",
|
|
126
|
+
"",
|
|
127
|
+
"# Add a component",
|
|
128
|
+
"epilot app add-component my-action --type CUSTOM_FLOW_ACTION",
|
|
129
|
+
"",
|
|
130
|
+
"# Build all components",
|
|
131
|
+
"npm run build",
|
|
132
|
+
"",
|
|
133
|
+
"# Validate the manifest",
|
|
134
|
+
"epilot app validate",
|
|
135
|
+
"",
|
|
136
|
+
"# Deploy (dry run)",
|
|
137
|
+
"epilot app deploy --dry-run",
|
|
138
|
+
"",
|
|
139
|
+
"# Deploy for real",
|
|
140
|
+
"epilot app deploy",
|
|
141
|
+
"```",
|
|
142
|
+
"",
|
|
143
|
+
"## Project structure",
|
|
144
|
+
"",
|
|
145
|
+
"```",
|
|
146
|
+
`${name}/`,
|
|
147
|
+
"\u251C\u2500\u2500 manifest.json # App manifest (source of truth)",
|
|
148
|
+
"\u251C\u2500\u2500 package.json # Monorepo root",
|
|
149
|
+
"\u251C\u2500\u2500 turbo.json # Turborepo config",
|
|
150
|
+
"\u2514\u2500\u2500 components/",
|
|
151
|
+
" \u2514\u2500\u2500 <component-name>/ # Each component is a package",
|
|
152
|
+
" \u251C\u2500\u2500 package.json",
|
|
153
|
+
" \u251C\u2500\u2500 src/",
|
|
154
|
+
" \u2514\u2500\u2500 dist/",
|
|
155
|
+
"```",
|
|
156
|
+
""
|
|
157
|
+
].join("\n")
|
|
158
|
+
);
|
|
159
|
+
writeFileSync(
|
|
160
|
+
join(rootDir, "SKILL.md"),
|
|
161
|
+
`---
|
|
162
|
+
name: epilot App Builder
|
|
163
|
+
description: Build, deploy, and manage epilot Apps using the declarative manifest system and CLI. Covers all component types, project structure, and deployment workflow.
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
# epilot App Builder
|
|
167
|
+
|
|
168
|
+
You are working inside an epilot App project. This is a monorepo managed by Turborepo with a declarative \`manifest.json\` at the root. Your job is to help build, configure, and deploy this app.
|
|
169
|
+
|
|
170
|
+
## Project Structure
|
|
171
|
+
|
|
172
|
+
\`\`\`
|
|
173
|
+
<app-name>/
|
|
174
|
+
\u251C\u2500\u2500 manifest.json # Declarative app manifest (source of truth)
|
|
175
|
+
\u251C\u2500\u2500 package.json # npm workspaces monorepo root
|
|
176
|
+
\u251C\u2500\u2500 turbo.json # Turborepo task config
|
|
177
|
+
\u251C\u2500\u2500 SKILL.md # This file (AI agent instructions)
|
|
178
|
+
\u2514\u2500\u2500 components/ # Each component is a workspace package
|
|
179
|
+
\u251C\u2500\u2500 <component-name>/ # Code-based component
|
|
180
|
+
\u2502 \u251C\u2500\u2500 package.json
|
|
181
|
+
\u2502 \u251C\u2500\u2500 tsconfig.json
|
|
182
|
+
\u2502 \u251C\u2500\u2500 vite.config.ts
|
|
183
|
+
\u2502 \u251C\u2500\u2500 src/
|
|
184
|
+
\u2502 \u2514\u2500\u2500 dist/ # Build output (uploaded on deploy)
|
|
185
|
+
\u2514\u2500\u2500 <component-name>/ # Config-only component
|
|
186
|
+
\u2514\u2500\u2500 configuration.json
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
## manifest.json Schema
|
|
190
|
+
|
|
191
|
+
The manifest is the source of truth. The CLI reads it to create, update, and deploy the app.
|
|
192
|
+
|
|
193
|
+
\`\`\`json
|
|
194
|
+
{
|
|
195
|
+
"$schema": "https://cdn.app.sls.epilot.io/v1/schema.json",
|
|
196
|
+
"manifest_version": 1,
|
|
197
|
+
"app_id": "uuid (set automatically after first deploy)",
|
|
198
|
+
"name": "App Name",
|
|
199
|
+
"description": { "de": "German description (required)", "en": "English description" },
|
|
200
|
+
"category": "integration",
|
|
201
|
+
"author": { "company": "Company", "name": "Name", "email": "dev@example.com" },
|
|
202
|
+
"documentation_url": "https://docs.example.com",
|
|
203
|
+
"support_email": "support@example.com",
|
|
204
|
+
"pricing": { "pricing_type": "FREE" },
|
|
205
|
+
"notifications": { "email": "dev@example.com", "events": ["app.installed", "app.uninstalled"] },
|
|
206
|
+
"permissions": [
|
|
207
|
+
{ "action": "entity:read", "resource": "contact" },
|
|
208
|
+
{ "action": "entity:write", "resource": "order" }
|
|
209
|
+
],
|
|
210
|
+
"blueprint": { "manifest_id": "uuid" },
|
|
211
|
+
"assets": { "logo": "./assets/logo.png" },
|
|
212
|
+
"components": []
|
|
213
|
+
}
|
|
214
|
+
\`\`\`
|
|
215
|
+
|
|
216
|
+
**Important rules:**
|
|
217
|
+
- \`description.de\` is always required (German)
|
|
218
|
+
- \`app_id\` is set automatically after first \`epilot app deploy\` \u2014 never set it manually
|
|
219
|
+
- \`_dir\` on components is a CLI-internal field mapping to the directory in \`components/\`
|
|
220
|
+
- Component \`id\` must be a UUID
|
|
221
|
+
- Option values of type \`secret\` are never stored in the manifest \u2014 they are set per-installation
|
|
222
|
+
|
|
223
|
+
## CLI Commands
|
|
224
|
+
|
|
225
|
+
All commands use \`epilot app <command>\`. Authentication uses stored credentials (\`epilot auth login\`) or \`--token\` / \`EPILOT_TOKEN\` env var.
|
|
226
|
+
|
|
227
|
+
### \`epilot app init <name>\`
|
|
228
|
+
Scaffold a new app project (monorepo with turbo, manifest.json, components/ dir).
|
|
229
|
+
|
|
230
|
+
### \`epilot app add-component <name> --type <TYPE>\`
|
|
231
|
+
Add a component. Downloads template from GitHub, adds entry to manifest.json.
|
|
232
|
+
Run interactively (no args) to get a type selector and name prompt.
|
|
233
|
+
|
|
234
|
+
### \`epilot app remove-component <name>\`
|
|
235
|
+
Remove a component from manifest and delete its directory.
|
|
236
|
+
Run interactively (no args) to get a component selector.
|
|
237
|
+
|
|
238
|
+
### \`epilot app validate\`
|
|
239
|
+
Validate manifest.json locally against the schema.
|
|
240
|
+
|
|
241
|
+
### \`epilot app deploy [--dry-run] [--new-version] [--server <url>]\`
|
|
242
|
+
Deploy the app:
|
|
243
|
+
1. Creates app on first deploy (writes \`app_id\` back to manifest)
|
|
244
|
+
2. Updates metadata (name, description, etc.)
|
|
245
|
+
3. Uploads assets (bundles, zips) and resolves CDN URLs
|
|
246
|
+
4. Upserts components with resolved URLs
|
|
247
|
+
5. Deletes remote components not in the manifest (sync)
|
|
248
|
+
|
|
249
|
+
**Important:** Components with missing build artifacts (bundle/zip) are skipped. Run \`npm run build\` first.
|
|
250
|
+
|
|
251
|
+
The deploy command reads \`components/<dir>/configuration.json\` at deploy time and uses it as the component's configuration. This means you edit config in the component directory, not in manifest.json.
|
|
252
|
+
|
|
253
|
+
### \`epilot app export --app-id <id> [-o manifest.json]\`
|
|
254
|
+
Export an existing app from the API as a manifest.json.
|
|
255
|
+
|
|
256
|
+
### \`epilot app versions [--app-id <id>]\`
|
|
257
|
+
List all versions with visibility, review status, and component count.
|
|
258
|
+
|
|
259
|
+
### \`epilot app review --technical-contact <email> --marketing-contact <email> [--demo-url <url>]\`
|
|
260
|
+
Submit the latest version for public marketplace review.
|
|
261
|
+
|
|
262
|
+
### \`epilot app api <operationId> [params]\`
|
|
263
|
+
Raw access to App API operations (OpenAPI-based).
|
|
264
|
+
|
|
265
|
+
## Component Types
|
|
266
|
+
|
|
267
|
+
### Code-based components (have src/, build step, produce dist/)
|
|
268
|
+
|
|
269
|
+
#### CUSTOM_JOURNEY_BLOCK
|
|
270
|
+
A Web Component embedded in the epilot Journey Builder. Built as a single UMD bundle.
|
|
271
|
+
|
|
272
|
+
**Stack:** React + Vite + \`@r2wc/react-to-web-component\` + \`@epilot/concorde-elements\`
|
|
273
|
+
**Build output:** \`dist/bundle.js\` (single file, CSS injected by JS)
|
|
274
|
+
**Manifest configuration:**
|
|
275
|
+
\`\`\`json
|
|
276
|
+
{
|
|
277
|
+
"component_type": "CUSTOM_JOURNEY_BLOCK",
|
|
278
|
+
"configuration": {
|
|
279
|
+
"component_url": "./components/<name>/dist/bundle.js",
|
|
280
|
+
"component_tag": "<name>",
|
|
281
|
+
"component_args": []
|
|
282
|
+
},
|
|
283
|
+
"assets": { "bundle": "./components/<name>/dist/bundle.js" }
|
|
284
|
+
}
|
|
285
|
+
\`\`\`
|
|
286
|
+
|
|
287
|
+
The \`component_url\` is a local path in the manifest. On deploy, the CLI uploads the bundle and replaces it with the CDN URL automatically.
|
|
288
|
+
|
|
289
|
+
**Key files:**
|
|
290
|
+
- \`src/main.tsx\` \u2014 Wraps React app as Web Component using \`r2wc\`, defines the custom element tag
|
|
291
|
+
- \`src/App.tsx\` \u2014 React component using \`@epilot/concorde-elements\` (Button, Card, Input)
|
|
292
|
+
- \`vite.config.ts\` \u2014 UMD build with \`fileName: () => 'bundle.js'\`, CSS injected by JS, single file output
|
|
293
|
+
|
|
294
|
+
**Component props (passed by the Journey runtime):**
|
|
295
|
+
\`\`\`typescript
|
|
296
|
+
type AppProps<T> = {
|
|
297
|
+
container: {
|
|
298
|
+
setValue: React.Dispatch<T> // Set the block's value
|
|
299
|
+
value?: T // Current value
|
|
300
|
+
theme?: string // Stringified theme JSON
|
|
301
|
+
errors?: string // Validation errors
|
|
302
|
+
required?: boolean // Whether the block is required
|
|
303
|
+
args?: string // Extra args from Journey Builder config
|
|
304
|
+
subscribe: (blockId: string, fn: (state: unknown) => void) => () => void
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
\`\`\`
|
|
308
|
+
|
|
309
|
+
#### CUSTOM_CAPABILITY
|
|
310
|
+
A tab or group on entity detail pages. Uses App Bridge for communication with epilot.
|
|
311
|
+
|
|
312
|
+
**Stack:** React + Vite + Tailwind + \`@epilot/volt-ui\` + \`@epilot/app-bridge\`
|
|
313
|
+
**Build output:** \`dist/\` directory (zipped and uploaded on deploy)
|
|
314
|
+
**Manifest configuration:**
|
|
315
|
+
\`\`\`json
|
|
316
|
+
{
|
|
317
|
+
"component_type": "CUSTOM_CAPABILITY",
|
|
318
|
+
"configuration": { "type": "tab", "allowed_schemas": ["contact", "order"] },
|
|
319
|
+
"surfaces": { "capability_config": { "app_url": "./components/<name>/dist/index.html" } },
|
|
320
|
+
"assets": { "zip": "./components/<name>/dist/" }
|
|
321
|
+
}
|
|
322
|
+
\`\`\`
|
|
323
|
+
|
|
324
|
+
\`allowed_schemas\` controls which entity types show the tab. Empty array = all schemas.
|
|
325
|
+
\`type\` can be \`"tab"\` or \`"group"\`.
|
|
326
|
+
|
|
327
|
+
**Key files:**
|
|
328
|
+
- \`src/main.tsx\` \u2014 Renders React app inside \`AppBridgeProvider\`
|
|
329
|
+
- \`src/AppBridgeProvider.tsx\` \u2014 Initializes App Bridge, receives auth token from parent
|
|
330
|
+
- \`src/AppBridgeContext.ts\` \u2014 React context for the bridge token
|
|
331
|
+
- \`vite.config.ts\` \u2014 Standard Vite build with \`base: './'\` for relative paths
|
|
332
|
+
|
|
333
|
+
#### CUSTOM_PAGE
|
|
334
|
+
A full custom page in the epilot navigation sidebar. Same stack as CUSTOM_CAPABILITY.
|
|
335
|
+
|
|
336
|
+
**Manifest configuration:**
|
|
337
|
+
\`\`\`json
|
|
338
|
+
{
|
|
339
|
+
"component_type": "CUSTOM_PAGE",
|
|
340
|
+
"configuration": { "slug": "<name>", "nav_label": "Page Title", "nav_icon": "layout" },
|
|
341
|
+
"surfaces": { "page": { "app_url": "./components/<name>/dist/index.html" } },
|
|
342
|
+
"assets": { "zip": "./components/<name>/dist/" }
|
|
343
|
+
}
|
|
344
|
+
\`\`\`
|
|
345
|
+
|
|
346
|
+
Reserved slugs (cannot use): entity, settings, dashboard, apps.
|
|
347
|
+
|
|
348
|
+
#### CUSTOM_PORTAL_BLOCK
|
|
349
|
+
A widget in the epilot Customer Portal. Same stack as CUSTOM_CAPABILITY.
|
|
350
|
+
|
|
351
|
+
**Manifest configuration:**
|
|
352
|
+
\`\`\`json
|
|
353
|
+
{
|
|
354
|
+
"component_type": "CUSTOM_PORTAL_BLOCK",
|
|
355
|
+
"configuration": {},
|
|
356
|
+
"surfaces": { "portal_block": { "app_url": "./components/<name>/dist/index.html" } },
|
|
357
|
+
"assets": { "zip": "./components/<name>/dist/" }
|
|
358
|
+
}
|
|
359
|
+
\`\`\`
|
|
360
|
+
|
|
361
|
+
#### CUSTOM_FLOW_ACTION_SANDBOX
|
|
362
|
+
JavaScript code that runs in epilot's sandboxed runtime when a flow action is triggered.
|
|
363
|
+
|
|
364
|
+
**Stack:** TypeScript (compiled to JS)
|
|
365
|
+
**Build output:** \`dist/handler.js\`
|
|
366
|
+
**Manifest configuration:**
|
|
367
|
+
\`\`\`json
|
|
368
|
+
{
|
|
369
|
+
"component_type": "CUSTOM_FLOW_ACTION",
|
|
370
|
+
"configuration": {
|
|
371
|
+
"type": "sandbox",
|
|
372
|
+
"sandbox_settings": { "code": "// read from dist/ during deploy" }
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
\`\`\`
|
|
376
|
+
|
|
377
|
+
**Restrictions:** Max 300KB. \`eval()\` and \`Function()\` constructor are not allowed.
|
|
378
|
+
|
|
379
|
+
### Config-only components (no build step, just configuration.json)
|
|
380
|
+
|
|
381
|
+
#### CUSTOM_FLOW_ACTION_EXTERNAL
|
|
382
|
+
An external webhook called by epilot when a flow action triggers. No code to build.
|
|
383
|
+
|
|
384
|
+
**configuration.json:**
|
|
385
|
+
\`\`\`json
|
|
386
|
+
{
|
|
387
|
+
"type": "external_integration",
|
|
388
|
+
"external_integration_settings": {
|
|
389
|
+
"url": "https://api.example.com/webhook",
|
|
390
|
+
"headers": { "Content-Type": "application/json" }
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
\`\`\`
|
|
394
|
+
|
|
395
|
+
Set \`"wait_for_callback": true\` if epilot should wait for your endpoint to respond before continuing the flow.
|
|
396
|
+
|
|
397
|
+
#### PORTAL_EXTENSION
|
|
398
|
+
Hooks that customize Customer Portal behavior. No UI, just configuration.
|
|
399
|
+
|
|
400
|
+
**configuration.json:**
|
|
401
|
+
\`\`\`json
|
|
402
|
+
{
|
|
403
|
+
"hooks": [
|
|
404
|
+
{
|
|
405
|
+
"type": "registration_identifiers_check",
|
|
406
|
+
"call": {
|
|
407
|
+
"method": "POST",
|
|
408
|
+
"url": "https://api.example.com/portal/register",
|
|
409
|
+
"headers": { "x-api-key": "{{api_key}}" }
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
}
|
|
414
|
+
\`\`\`
|
|
415
|
+
|
|
416
|
+
**Available hook types:** \`registration_identifiers_check\`, \`contract_identification\`, \`meter_reading_plausibility_check\`, \`consumption_data_retrieval\`, \`cost_data_retrieval\`, \`price_data_retrieval\`.
|
|
417
|
+
|
|
418
|
+
Use \`{{option_key}}\` syntax in URLs/headers to interpolate secret option values set per-installation.
|
|
419
|
+
|
|
420
|
+
#### EXTERNAL_PRODUCT_CATALOG
|
|
421
|
+
Hooks that provide products from an external catalog to epilot Journeys.
|
|
422
|
+
|
|
423
|
+
**configuration.json:**
|
|
424
|
+
\`\`\`json
|
|
425
|
+
{
|
|
426
|
+
"hooks": [
|
|
427
|
+
{
|
|
428
|
+
"id": "get-products",
|
|
429
|
+
"name": { "de": "Produkte abrufen", "en": "Get Products" },
|
|
430
|
+
"type": "products",
|
|
431
|
+
"call": {
|
|
432
|
+
"method": "POST",
|
|
433
|
+
"url": "https://api.example.com/products",
|
|
434
|
+
"headers": { "Content-Type": "application/json", "x-api-key": "{{api_key}}" }
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
\`\`\`
|
|
440
|
+
|
|
441
|
+
**Hook types:** \`products\`, \`product-recommendations\`.
|
|
442
|
+
|
|
443
|
+
## Workflow: Building an App from Scratch
|
|
444
|
+
|
|
445
|
+
\`\`\`bash
|
|
446
|
+
# 1. Scaffold the project
|
|
447
|
+
epilot app init my-app
|
|
448
|
+
cd my-app
|
|
449
|
+
|
|
450
|
+
# 2. Add components (interactive or with flags)
|
|
451
|
+
epilot app add-component my-block --type CUSTOM_JOURNEY_BLOCK
|
|
452
|
+
epilot app add-component my-tab --type CUSTOM_CAPABILITY
|
|
453
|
+
epilot app add-component my-webhook --type CUSTOM_FLOW_ACTION_EXTERNAL
|
|
454
|
+
|
|
455
|
+
# 3. Install dependencies
|
|
456
|
+
npm install
|
|
457
|
+
|
|
458
|
+
# 4. Develop components
|
|
459
|
+
cd components/my-block && npm run dev # local dev server
|
|
460
|
+
cd components/my-tab && npm run dev # local dev server
|
|
461
|
+
|
|
462
|
+
# 5. Edit config-only components
|
|
463
|
+
# Edit components/my-webhook/configuration.json directly
|
|
464
|
+
|
|
465
|
+
# 6. Build all components
|
|
466
|
+
npm run build
|
|
467
|
+
|
|
468
|
+
# 7. Validate the manifest
|
|
469
|
+
epilot app validate
|
|
470
|
+
|
|
471
|
+
# 8. Deploy (dry run first)
|
|
472
|
+
epilot app deploy --dry-run
|
|
473
|
+
epilot app deploy
|
|
474
|
+
|
|
475
|
+
# 9. Check versions
|
|
476
|
+
epilot app versions
|
|
477
|
+
|
|
478
|
+
# 10. Submit for marketplace review
|
|
479
|
+
epilot app review --technical-contact dev@example.com --marketing-contact marketing@example.com
|
|
480
|
+
\`\`\`
|
|
481
|
+
|
|
482
|
+
## Key Concepts
|
|
483
|
+
|
|
484
|
+
### Configuration override
|
|
485
|
+
For every component with a \`_dir\` field, the CLI reads \`components/<dir>/configuration.json\` at deploy time and uses it as the component's configuration, overriding whatever is in manifest.json. This means: **edit configuration in the component directory, not in manifest.json.**
|
|
486
|
+
|
|
487
|
+
### Asset upload flow
|
|
488
|
+
1. CLI reads local paths from manifest (\`./components/x/dist/bundle.js\`)
|
|
489
|
+
2. Requests a presigned S3 upload URL from the App API
|
|
490
|
+
3. Uploads the file to S3
|
|
491
|
+
4. Gets back the CDN URL
|
|
492
|
+
5. Injects the CDN URL into the component configuration/surfaces before upserting
|
|
493
|
+
|
|
494
|
+
### Permissions
|
|
495
|
+
Apps can request permissions via the \`permissions\` array in the manifest. These are created as a role when the app is installed. Common actions: \`entity:read\`, \`entity:write\`, \`entity:delete\`, \`workflow:read\`, \`workflow:write\`.
|
|
496
|
+
|
|
497
|
+
### Options
|
|
498
|
+
Components can declare \`options\` \u2014 configuration values set by the installing organization. Types: \`text\`, \`number\`, \`boolean\`, \`secret\`. Secret values are encrypted and never included in the manifest. Use \`{{option_key}}\` in configuration URLs/headers for interpolation.
|
|
499
|
+
|
|
500
|
+
### Descriptions
|
|
501
|
+
All user-facing text (app name, component names, descriptions) must include a \`de\` (German) translation. \`en\` is optional but recommended.
|
|
502
|
+
|
|
503
|
+
### App Bridge
|
|
504
|
+
Components that render inside epilot (capabilities, pages, portal blocks) use \`@epilot/app-bridge\` to communicate with the parent window. The bridge provides an auth token and language setting. Always wrap your React app in an \`AppBridgeProvider\`.
|
|
505
|
+
|
|
506
|
+
### Volt UI
|
|
507
|
+
Use \`@epilot/volt-ui\` for UI components in App Bridge surfaces (capabilities, pages, portal blocks). It provides cards, buttons, forms, selectors, and more \u2014 consistent with epilot's design system.
|
|
508
|
+
|
|
509
|
+
### Concorde Elements
|
|
510
|
+
Use \`@epilot/concorde-elements\` for UI components in Journey Blocks. It provides buttons, cards, inputs \u2014 consistent with epilot's journey design system.
|
|
511
|
+
`
|
|
512
|
+
);
|
|
513
|
+
log.success(`Created ${name}/`);
|
|
514
|
+
log.info("");
|
|
515
|
+
log.info(` cd ${name}`);
|
|
516
|
+
log.info(" npm install");
|
|
517
|
+
log.info(" epilot app add-component my-action --type CUSTOM_FLOW_ACTION");
|
|
518
|
+
log.info("");
|
|
519
|
+
log.dim("See README.md for more details.");
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
export {
|
|
523
|
+
init_default as default
|
|
524
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
callApi
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BYAEI4Z2.js";
|
|
5
5
|
import "./chunk-RSA7K5HB.js";
|
|
6
6
|
import "./chunk-PDMWUCWD.js";
|
|
7
7
|
import "./chunk-IOLKUHUB.js";
|
|
@@ -10,7 +10,7 @@ import "./chunk-7ZQ666ZQ.js";
|
|
|
10
10
|
// src/commands/apis/partner-directory.ts
|
|
11
11
|
import { defineCommand } from "citty";
|
|
12
12
|
var partner_directory_default = defineCommand({
|
|
13
|
-
meta: { name: "partner-directory", description: "Partner API" },
|
|
13
|
+
meta: { name: "partner-directory", description: "Partner Directory API" },
|
|
14
14
|
args: {
|
|
15
15
|
operation: { type: "positional", description: "operationId to call", required: false },
|
|
16
16
|
param: { type: "string", alias: "p", description: "Parameter key=value" },
|