@epilot/cli 0.1.10 → 0.1.12

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.
Files changed (89) hide show
  1. package/README.md +18 -21
  2. package/definitions/app.json +56 -6
  3. package/definitions/automation.json +214 -1
  4. package/definitions/blueprint-manifest.json +1303 -60
  5. package/definitions/customer-portal.json +757 -81
  6. package/definitions/data-governance.json +1126 -0
  7. package/definitions/deduplication.json +135 -4
  8. package/definitions/design.json +103 -57
  9. package/definitions/email-settings.json +150 -0
  10. package/definitions/email-template.json +25 -3
  11. package/definitions/entity.json +405 -5
  12. package/definitions/erp-integration.json +3140 -1049
  13. package/definitions/integration-toolkit.json +7998 -0
  14. package/definitions/journey.json +18 -1
  15. package/definitions/kanban.json +25 -1
  16. package/definitions/message.json +202 -0
  17. package/definitions/organization.json +35 -1
  18. package/definitions/partner-directory.json +795 -229
  19. package/definitions/permissions.json +41 -6
  20. package/definitions/sharing.json +956 -0
  21. package/definitions/template-variables.json +12 -4
  22. package/definitions/webhooks.json +111 -2
  23. package/definitions/workflow-definition.json +87 -202
  24. package/definitions/workflow.json +142 -0
  25. package/dist/{access-token-PTTCRMGK.js → access-token-CIM4RLBP.js} +1 -1
  26. package/dist/add-component-AAVQVPKK.js +296 -0
  27. package/dist/{address-2FDPEPR6.js → address-EDRTUWTP.js} +1 -1
  28. package/dist/{address-suggestions-XBEK5DDQ.js → address-suggestions-S5WEST2N.js} +1 -1
  29. package/dist/{ai-agents-ZY5BNVTN.js → ai-agents-RXDDJDAR.js} +1 -1
  30. package/dist/{app-IT5FWGUK.js → api-36XROHLK.js} +5 -5
  31. package/dist/app-I3XXHZLD.js +24 -0
  32. package/dist/{audit-logs-FB4TE4TI.js → audit-logs-PXGDGJGV.js} +1 -1
  33. package/dist/{automation-JE5LDKJM.js → automation-LS6MVLP2.js} +1 -1
  34. package/dist/{billing-GOFCP5T3.js → billing-KVYFUKZK.js} +1 -1
  35. package/dist/bin/epilot.js +53 -52
  36. package/dist/{blueprint-manifest-WJIQKFYK.js → blueprint-manifest-W4ZGJD2Z.js} +1 -1
  37. package/dist/{chunk-P5IZZW4Y.js → chunk-BYAEI4Z2.js} +1 -1
  38. package/dist/chunk-CEP7S7X3.js +366 -0
  39. package/dist/{chunk-MNSG22DM.js → chunk-F6KWKTQJ.js} +124 -63
  40. package/dist/{completion-HZNPHJI4.js → completion-QP4IYMVI.js} +1 -1
  41. package/dist/{consent-DSMWWHUL.js → consent-M4QB2HPM.js} +1 -1
  42. package/dist/{customer-portal-IJYTJYUZ.js → customer-portal-SVO2YCXA.js} +1 -1
  43. package/dist/{dashboard-DOAX6XDG.js → dashboard-CYCXIX74.js} +1 -1
  44. package/dist/{data-management-C4JPPUPD.js → data-governance-DJAAIE6F.js} +6 -6
  45. package/dist/{deduplication-7OGLZLAC.js → deduplication-M3KEVJRG.js} +1 -1
  46. package/dist/deploy-4XDFWOEV.js +214 -0
  47. package/dist/{design-3CAYTWFY.js → design-UVJJ2KO2.js} +1 -1
  48. package/dist/{document-NT5JOJQV.js → document-5HB632XE.js} +1 -1
  49. package/dist/{email-settings-2M3WJTQS.js → email-settings-H7HQTDYE.js} +1 -1
  50. package/dist/{email-template-F4PLBPPC.js → email-template-2DHZ3VKF.js} +1 -1
  51. package/dist/{entity-32LKMZAU.js → entity-HED6QHG7.js} +1 -1
  52. package/dist/{entity-mapping-OBCZDYQJ.js → entity-mapping-QP22B65Z.js} +1 -1
  53. package/dist/{environments-H3TBCDQE.js → environments-6LLEIGWV.js} +1 -1
  54. package/dist/{event-catalog-NVAPTZ4M.js → event-catalog-2ZCZTATY.js} +1 -1
  55. package/dist/export-JA5N4JCJ.js +44 -0
  56. package/dist/{file-US2HR4SV.js → file-R6IIXOIZ.js} +1 -1
  57. package/dist/{iban-7QUCOULB.js → iban-EQD2VROZ.js} +1 -1
  58. package/dist/init-5KGNJEWF.js +524 -0
  59. package/dist/integration-toolkit-4CLQDSK7.js +54 -0
  60. package/dist/{journey-E5T4BZZX.js → journey-V7X2KUKH.js} +1 -1
  61. package/dist/{kanban-7UHU5VE6.js → kanban-EPI6C3FR.js} +1 -1
  62. package/dist/{message-7KY33RJE.js → message-477EJ5JO.js} +1 -1
  63. package/dist/{metering-P7BZGMY7.js → metering-5EAEKRSL.js} +1 -1
  64. package/dist/{notes-TNJ7FPA3.js → notes-CVXNRULU.js} +1 -1
  65. package/dist/{notification-6KXEFVO5.js → notification-6HXS76XP.js} +1 -1
  66. package/dist/{organization-FF4Y3PBO.js → organization-O33CZQKD.js} +1 -1
  67. package/dist/{partner-directory-VH2SBAS2.js → partner-directory-NZWGCKSB.js} +2 -2
  68. package/dist/{permissions-KENZ4HNY.js → permissions-6QEOBJ6M.js} +1 -1
  69. package/dist/{pricing-P6QZ77VJ.js → pricing-KNYSULCW.js} +1 -1
  70. package/dist/{pricing-tier-2IRJMTM6.js → pricing-tier-OCHP6SHT.js} +1 -1
  71. package/dist/{purpose-IHROR6LQ.js → purpose-NGM42XWB.js} +1 -1
  72. package/dist/remove-component-LXSRR23E.js +89 -0
  73. package/dist/review-HFOO3NXE.js +69 -0
  74. package/dist/{sandbox-62XQPOU6.js → sandbox-YX3VVAQG.js} +1 -1
  75. package/dist/sharing-X5U53KSU.js +54 -0
  76. package/dist/{submission-PUWGOYQB.js → submission-YOWVSZNA.js} +1 -1
  77. package/dist/{targeting-QB3DFYNI.js → targeting-BMZCOG72.js} +1 -1
  78. package/dist/{template-variables-IPKRUJ4E.js → template-variables-YTABZL3E.js} +1 -1
  79. package/dist/{upgrade-TNDH4WGQ.js → upgrade-SYSSIAQC.js} +1 -1
  80. package/dist/{user-2CP75TFC.js → user-3N5ZOUYS.js} +1 -1
  81. package/dist/validate-TUMXW56Y.js +53 -0
  82. package/dist/{validation-rules-GNI4EEG5.js → validation-rules-QVS7LKEP.js} +1 -1
  83. package/dist/versions-ZTWQAGXY.js +109 -0
  84. package/dist/{webhooks-2OWUX7UL.js → webhooks-6WMWACOW.js} +1 -1
  85. package/dist/{workflow-WSLERVJI.js → workflow-ZO2MKDBS.js} +1 -1
  86. package/dist/{workflow-definition-FP3WKHGG.js → workflow-definition-RCWKIPYI.js} +1 -1
  87. package/package.json +2 -1
  88. package/definitions/data-management.json +0 -962
  89. package/dist/erp-integration-UW6H55EK.js +0 -54
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  API_LIST
4
- } from "../chunk-MNSG22DM.js";
4
+ } from "../chunk-F6KWKTQJ.js";
5
5
 
6
6
  // bin/epilot.ts
7
7
  import { runMain } from "citty";
@@ -11,7 +11,7 @@ import { defineCommand } from "citty";
11
11
  var main = defineCommand({
12
12
  meta: {
13
13
  name: "epilot",
14
- version: "0.1.10",
14
+ version: "0.1.12",
15
15
  description: "CLI for epilot APIs"
16
16
  },
17
17
  args: {
@@ -27,54 +27,55 @@ var main = defineCommand({
27
27
  subCommands: {
28
28
  auth: () => import("../auth-AAF6Z5WZ.js").then((m) => m.default),
29
29
  profile: () => import("../profile-EK4HSQ57.js").then((m) => m.default),
30
- completion: () => import("../completion-HZNPHJI4.js").then((m) => m.default),
31
- upgrade: () => import("../upgrade-TNDH4WGQ.js").then((m) => m.default),
32
- "access-token": () => import("../access-token-PTTCRMGK.js").then((m) => m.default),
33
- address: () => import("../address-2FDPEPR6.js").then((m) => m.default),
34
- "address-suggestions": () => import("../address-suggestions-XBEK5DDQ.js").then((m) => m.default),
35
- "ai-agents": () => import("../ai-agents-ZY5BNVTN.js").then((m) => m.default),
36
- app: () => import("../app-IT5FWGUK.js").then((m) => m.default),
37
- "audit-logs": () => import("../audit-logs-FB4TE4TI.js").then((m) => m.default),
38
- automation: () => import("../automation-JE5LDKJM.js").then((m) => m.default),
39
- billing: () => import("../billing-GOFCP5T3.js").then((m) => m.default),
40
- "blueprint-manifest": () => import("../blueprint-manifest-WJIQKFYK.js").then((m) => m.default),
41
- consent: () => import("../consent-DSMWWHUL.js").then((m) => m.default),
42
- "customer-portal": () => import("../customer-portal-IJYTJYUZ.js").then((m) => m.default),
43
- dashboard: () => import("../dashboard-DOAX6XDG.js").then((m) => m.default),
44
- "data-management": () => import("../data-management-C4JPPUPD.js").then((m) => m.default),
45
- deduplication: () => import("../deduplication-7OGLZLAC.js").then((m) => m.default),
46
- design: () => import("../design-3CAYTWFY.js").then((m) => m.default),
47
- document: () => import("../document-NT5JOJQV.js").then((m) => m.default),
48
- "email-settings": () => import("../email-settings-2M3WJTQS.js").then((m) => m.default),
49
- "email-template": () => import("../email-template-F4PLBPPC.js").then((m) => m.default),
50
- entity: () => import("../entity-32LKMZAU.js").then((m) => m.default),
51
- "entity-mapping": () => import("../entity-mapping-OBCZDYQJ.js").then((m) => m.default),
52
- environments: () => import("../environments-H3TBCDQE.js").then((m) => m.default),
53
- "erp-integration": () => import("../erp-integration-UW6H55EK.js").then((m) => m.default),
54
- "event-catalog": () => import("../event-catalog-NVAPTZ4M.js").then((m) => m.default),
55
- file: () => import("../file-US2HR4SV.js").then((m) => m.default),
56
- iban: () => import("../iban-7QUCOULB.js").then((m) => m.default),
57
- journey: () => import("../journey-E5T4BZZX.js").then((m) => m.default),
58
- kanban: () => import("../kanban-7UHU5VE6.js").then((m) => m.default),
59
- message: () => import("../message-7KY33RJE.js").then((m) => m.default),
60
- metering: () => import("../metering-P7BZGMY7.js").then((m) => m.default),
61
- notes: () => import("../notes-TNJ7FPA3.js").then((m) => m.default),
62
- notification: () => import("../notification-6KXEFVO5.js").then((m) => m.default),
63
- organization: () => import("../organization-FF4Y3PBO.js").then((m) => m.default),
64
- "partner-directory": () => import("../partner-directory-VH2SBAS2.js").then((m) => m.default),
65
- permissions: () => import("../permissions-KENZ4HNY.js").then((m) => m.default),
66
- pricing: () => import("../pricing-P6QZ77VJ.js").then((m) => m.default),
67
- "pricing-tier": () => import("../pricing-tier-2IRJMTM6.js").then((m) => m.default),
68
- purpose: () => import("../purpose-IHROR6LQ.js").then((m) => m.default),
69
- sandbox: () => import("../sandbox-62XQPOU6.js").then((m) => m.default),
70
- submission: () => import("../submission-PUWGOYQB.js").then((m) => m.default),
71
- targeting: () => import("../targeting-QB3DFYNI.js").then((m) => m.default),
72
- "template-variables": () => import("../template-variables-IPKRUJ4E.js").then((m) => m.default),
73
- user: () => import("../user-2CP75TFC.js").then((m) => m.default),
74
- "validation-rules": () => import("../validation-rules-GNI4EEG5.js").then((m) => m.default),
75
- webhooks: () => import("../webhooks-2OWUX7UL.js").then((m) => m.default),
76
- workflow: () => import("../workflow-WSLERVJI.js").then((m) => m.default),
77
- "workflow-definition": () => import("../workflow-definition-FP3WKHGG.js").then((m) => m.default)
30
+ completion: () => import("../completion-QP4IYMVI.js").then((m) => m.default),
31
+ upgrade: () => import("../upgrade-SYSSIAQC.js").then((m) => m.default),
32
+ "access-token": () => import("../access-token-CIM4RLBP.js").then((m) => m.default),
33
+ address: () => import("../address-EDRTUWTP.js").then((m) => m.default),
34
+ "address-suggestions": () => import("../address-suggestions-S5WEST2N.js").then((m) => m.default),
35
+ "ai-agents": () => import("../ai-agents-RXDDJDAR.js").then((m) => m.default),
36
+ app: () => import("../app-I3XXHZLD.js").then((m) => m.default),
37
+ "audit-logs": () => import("../audit-logs-PXGDGJGV.js").then((m) => m.default),
38
+ automation: () => import("../automation-LS6MVLP2.js").then((m) => m.default),
39
+ billing: () => import("../billing-KVYFUKZK.js").then((m) => m.default),
40
+ "blueprint-manifest": () => import("../blueprint-manifest-W4ZGJD2Z.js").then((m) => m.default),
41
+ consent: () => import("../consent-M4QB2HPM.js").then((m) => m.default),
42
+ "customer-portal": () => import("../customer-portal-SVO2YCXA.js").then((m) => m.default),
43
+ dashboard: () => import("../dashboard-CYCXIX74.js").then((m) => m.default),
44
+ "data-governance": () => import("../data-governance-DJAAIE6F.js").then((m) => m.default),
45
+ deduplication: () => import("../deduplication-M3KEVJRG.js").then((m) => m.default),
46
+ design: () => import("../design-UVJJ2KO2.js").then((m) => m.default),
47
+ document: () => import("../document-5HB632XE.js").then((m) => m.default),
48
+ "email-settings": () => import("../email-settings-H7HQTDYE.js").then((m) => m.default),
49
+ "email-template": () => import("../email-template-2DHZ3VKF.js").then((m) => m.default),
50
+ entity: () => import("../entity-HED6QHG7.js").then((m) => m.default),
51
+ "entity-mapping": () => import("../entity-mapping-QP22B65Z.js").then((m) => m.default),
52
+ environments: () => import("../environments-6LLEIGWV.js").then((m) => m.default),
53
+ "event-catalog": () => import("../event-catalog-2ZCZTATY.js").then((m) => m.default),
54
+ file: () => import("../file-R6IIXOIZ.js").then((m) => m.default),
55
+ iban: () => import("../iban-EQD2VROZ.js").then((m) => m.default),
56
+ "integration-toolkit": () => import("../integration-toolkit-4CLQDSK7.js").then((m) => m.default),
57
+ journey: () => import("../journey-V7X2KUKH.js").then((m) => m.default),
58
+ kanban: () => import("../kanban-EPI6C3FR.js").then((m) => m.default),
59
+ message: () => import("../message-477EJ5JO.js").then((m) => m.default),
60
+ metering: () => import("../metering-5EAEKRSL.js").then((m) => m.default),
61
+ notes: () => import("../notes-CVXNRULU.js").then((m) => m.default),
62
+ notification: () => import("../notification-6HXS76XP.js").then((m) => m.default),
63
+ organization: () => import("../organization-O33CZQKD.js").then((m) => m.default),
64
+ "partner-directory": () => import("../partner-directory-NZWGCKSB.js").then((m) => m.default),
65
+ permissions: () => import("../permissions-6QEOBJ6M.js").then((m) => m.default),
66
+ pricing: () => import("../pricing-KNYSULCW.js").then((m) => m.default),
67
+ "pricing-tier": () => import("../pricing-tier-OCHP6SHT.js").then((m) => m.default),
68
+ purpose: () => import("../purpose-NGM42XWB.js").then((m) => m.default),
69
+ sandbox: () => import("../sandbox-YX3VVAQG.js").then((m) => m.default),
70
+ sharing: () => import("../sharing-X5U53KSU.js").then((m) => m.default),
71
+ submission: () => import("../submission-YOWVSZNA.js").then((m) => m.default),
72
+ targeting: () => import("../targeting-BMZCOG72.js").then((m) => m.default),
73
+ "template-variables": () => import("../template-variables-YTABZL3E.js").then((m) => m.default),
74
+ user: () => import("../user-3N5ZOUYS.js").then((m) => m.default),
75
+ "validation-rules": () => import("../validation-rules-QVS7LKEP.js").then((m) => m.default),
76
+ webhooks: () => import("../webhooks-6WMWACOW.js").then((m) => m.default),
77
+ workflow: () => import("../workflow-ZO2MKDBS.js").then((m) => m.default),
78
+ "workflow-definition": () => import("../workflow-definition-RCWKIPYI.js").then((m) => m.default)
78
79
  }
79
80
  });
80
81
 
@@ -87,11 +88,11 @@ process.stderr.on("error", (err) => {
87
88
  if (err.code === "EPIPE") process.exit(0);
88
89
  throw err;
89
90
  });
90
- var VERSION = true ? "0.1.10" : (await null).default.version;
91
+ var VERSION = true ? "0.1.12" : (await null).default.version;
91
92
  var args = process.argv.slice(2);
92
93
  var completionsIdx = args.indexOf("--_completions");
93
94
  if (completionsIdx >= 0) {
94
- const { handleCompletions } = await import("../completion-HZNPHJI4.js");
95
+ const { handleCompletions } = await import("../completion-QP4IYMVI.js");
95
96
  handleCompletions(args[completionsIdx + 1], args[completionsIdx + 2]);
96
97
  process.exit(0);
97
98
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -468,7 +468,7 @@ ${BOLD}epilot ${apiName} ${operationId}${RESET}`);
468
468
 
469
469
  `);
470
470
  }
471
- const params = getOperationParams(spec, operationId);
471
+ const { params } = getOperationParams(spec, operationId);
472
472
  if (params.length > 0) {
473
473
  w(`${BOLD}PARAMETERS${RESET}
474
474
 
@@ -0,0 +1,366 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ resolveToken
4
+ } from "./chunk-RSA7K5HB.js";
5
+ import {
6
+ BOLD,
7
+ DIM,
8
+ GREEN,
9
+ RED,
10
+ RESET,
11
+ YELLOW
12
+ } from "./chunk-7ZQ666ZQ.js";
13
+
14
+ // src/commands/app/manifest.ts
15
+ import { readFileSync, writeFileSync, existsSync, statSync } from "fs";
16
+ import { resolve, extname } from "path";
17
+ import { execSync } from "child_process";
18
+ var log = {
19
+ success: (msg) => process.stdout.write(`${GREEN}\u2713${RESET} ${msg}
20
+ `),
21
+ error: (msg) => process.stderr.write(`${RED}\u2717${RESET} ${msg}
22
+ `),
23
+ warn: (msg) => process.stdout.write(`${YELLOW}!${RESET} ${msg}
24
+ `),
25
+ info: (msg) => process.stdout.write(` ${msg}
26
+ `),
27
+ dim: (msg) => process.stdout.write(` ${DIM}${msg}${RESET}
28
+ `),
29
+ header: (msg) => process.stdout.write(`
30
+ ${BOLD}${msg}${RESET}
31
+ `)
32
+ };
33
+ var COMPONENT_TYPES = [
34
+ "CUSTOM_JOURNEY_BLOCK",
35
+ "CUSTOM_PORTAL_BLOCK",
36
+ "PORTAL_EXTENSION",
37
+ "CUSTOM_FLOW_ACTION",
38
+ "CUSTOM_CAPABILITY",
39
+ "EXTERNAL_PRODUCT_CATALOG",
40
+ "CUSTOM_PAGE",
41
+ "API_PROXY"
42
+ ];
43
+ function validateManifest(data) {
44
+ const errors = [];
45
+ if (!data || typeof data !== "object") {
46
+ return { valid: false, errors: [{ path: "/", message: "Must be an object" }] };
47
+ }
48
+ const obj = data;
49
+ if (obj.manifest_version !== 1) {
50
+ errors.push({ path: "/manifest_version", message: "Must be 1" });
51
+ }
52
+ if (!obj.name || typeof obj.name !== "string") {
53
+ errors.push({ path: "/name", message: "Required string" });
54
+ }
55
+ if (!obj.description || typeof obj.description !== "object") {
56
+ errors.push({ path: "/description", message: 'Required object with "de" field' });
57
+ } else if (!obj.description.de) {
58
+ errors.push({ path: "/description/de", message: "Required" });
59
+ }
60
+ if (!Array.isArray(obj.components)) {
61
+ errors.push({ path: "/components", message: "Required array" });
62
+ } else {
63
+ for (let i = 0; i < obj.components.length; i++) {
64
+ const comp = obj.components[i];
65
+ if (!comp.id) errors.push({ path: `/components/${i}/id`, message: "Required" });
66
+ if (!comp.component_type || !COMPONENT_TYPES.includes(comp.component_type)) {
67
+ errors.push({
68
+ path: `/components/${i}/component_type`,
69
+ message: `Must be one of: ${COMPONENT_TYPES.join(", ")}`
70
+ });
71
+ }
72
+ if (!comp.configuration || typeof comp.configuration !== "object") {
73
+ errors.push({ path: `/components/${i}/configuration`, message: "Required object" });
74
+ }
75
+ }
76
+ }
77
+ if (errors.length > 0) return { valid: false, errors };
78
+ return { valid: true, errors: [], manifest: data };
79
+ }
80
+ function readManifest(path) {
81
+ const absPath = resolve(path);
82
+ if (!existsSync(absPath)) {
83
+ throw new Error(`File not found: ${absPath}`);
84
+ }
85
+ const content = readFileSync(absPath, "utf-8");
86
+ const data = JSON.parse(content);
87
+ const result = validateManifest(data);
88
+ if (!result.valid) {
89
+ const msgs = result.errors.map((e) => ` ${e.path}: ${e.message}`).join("\n");
90
+ throw new Error(`Invalid manifest:
91
+ ${msgs}`);
92
+ }
93
+ return result.manifest;
94
+ }
95
+ function writeManifest(path, manifest) {
96
+ writeFileSync(resolve(path), `${JSON.stringify(manifest, null, 2)}
97
+ `, "utf-8");
98
+ }
99
+ var DEFAULT_BASE_URL = "https://app.sls.epilot.io";
100
+ async function request(baseUrl, token, method, path, body) {
101
+ const url = `${baseUrl}${path}`;
102
+ const headers = {
103
+ Authorization: `Bearer ${token}`,
104
+ "Content-Type": "application/json"
105
+ };
106
+ const response = await fetch(url, {
107
+ method,
108
+ headers,
109
+ body: body ? JSON.stringify(body) : void 0
110
+ });
111
+ if (!response.ok) {
112
+ const text2 = await response.text().catch(() => "");
113
+ throw new Error(`API ${method} ${path} failed (${response.status}): ${text2}`);
114
+ }
115
+ if (response.status === 204) return void 0;
116
+ const contentType = response.headers.get("content-type") ?? "";
117
+ const text = await response.text();
118
+ if (!text) return void 0;
119
+ if (contentType.includes("application/json")) {
120
+ return JSON.parse(text);
121
+ }
122
+ return text;
123
+ }
124
+ function createAppApiClient(opts) {
125
+ const baseUrl = opts.server ?? DEFAULT_BASE_URL;
126
+ const getToken = () => {
127
+ const token = resolveToken(opts.token, opts.profile);
128
+ if (!token) {
129
+ log.error('Not authenticated. Run "epilot auth login" first.');
130
+ process.exit(1);
131
+ }
132
+ return token;
133
+ };
134
+ return {
135
+ async createConfiguration(payload) {
136
+ return request(baseUrl, getToken(), "POST", "/v1/app-configurations", payload);
137
+ },
138
+ async getConfiguration(appId) {
139
+ return request(baseUrl, getToken(), "GET", `/v1/app-configurations/${appId}`);
140
+ },
141
+ async patchMetadata(appId, payload) {
142
+ await request(baseUrl, getToken(), "PATCH", `/v1/app-configurations/${appId}`, payload);
143
+ },
144
+ async getVersion(appId, version) {
145
+ return request(baseUrl, getToken(), "GET", `/v1/app-configurations/${appId}/versions/${version}`);
146
+ },
147
+ async listVersions(appId) {
148
+ return request(baseUrl, getToken(), "GET", `/v1/app-configurations/${appId}/versions`);
149
+ },
150
+ async patchVersion(appId, version, payload) {
151
+ await request(baseUrl, getToken(), "PATCH", `/v1/app-configurations/${appId}/versions/${version}`, payload);
152
+ },
153
+ async cloneVersion(appId, version) {
154
+ return request(
155
+ baseUrl,
156
+ getToken(),
157
+ "POST",
158
+ `/v1/app-configurations/${appId}/versions/${version}/clone`
159
+ );
160
+ },
161
+ async upsertComponent(appId, version, component) {
162
+ const componentId = component.id;
163
+ if (componentId) {
164
+ try {
165
+ await request(
166
+ baseUrl,
167
+ getToken(),
168
+ "PATCH",
169
+ `/v1/app-configurations/${appId}/versions/${version}/components/${componentId}`,
170
+ component
171
+ );
172
+ } catch (err) {
173
+ if (err instanceof Error && err.message.includes("404")) {
174
+ await request(
175
+ baseUrl,
176
+ getToken(),
177
+ "POST",
178
+ `/v1/app-configurations/${appId}/versions/${version}/components`,
179
+ component
180
+ );
181
+ } else {
182
+ throw err;
183
+ }
184
+ }
185
+ } else {
186
+ await request(
187
+ baseUrl,
188
+ getToken(),
189
+ "POST",
190
+ `/v1/app-configurations/${appId}/versions/${version}/components`,
191
+ component
192
+ );
193
+ }
194
+ },
195
+ async deleteComponent(appId, version, componentId) {
196
+ await request(
197
+ baseUrl,
198
+ getToken(),
199
+ "DELETE",
200
+ `/v1/app-configurations/${appId}/versions/${version}/components/${componentId}`
201
+ );
202
+ },
203
+ async createLogoUploadUrl(appId, filename, mimeType) {
204
+ return request(baseUrl, getToken(), "POST", `/v1/app-configurations/${appId}/logo`, {
205
+ filename,
206
+ mime_type: mimeType
207
+ });
208
+ },
209
+ async createBundleUploadUrl(appId, version, componentId) {
210
+ return request(baseUrl, getToken(), "POST", `/v1/app-configurations/${appId}/bundle`, {
211
+ version,
212
+ component_id: componentId
213
+ });
214
+ },
215
+ async createZipUploadUrl(appId, version, componentId) {
216
+ return request(baseUrl, getToken(), "POST", `/v1/app-configurations/${appId}/zip`, {
217
+ version,
218
+ component_id: componentId
219
+ });
220
+ },
221
+ async createReview(appId, version, payload) {
222
+ return request(
223
+ baseUrl,
224
+ getToken(),
225
+ "POST",
226
+ `/v1/app-configurations/${appId}/versions/${version}/review`,
227
+ payload
228
+ );
229
+ }
230
+ };
231
+ }
232
+ async function uploadFileToPresignedUrl(uploadUrl, filePath) {
233
+ const absolutePath = resolve(filePath);
234
+ const fileBuffer = readFileSync(absolutePath);
235
+ const ext = extname(filePath).toLowerCase();
236
+ const mimeTypes = {
237
+ ".js": "application/javascript",
238
+ ".mjs": "application/javascript",
239
+ ".json": "application/json",
240
+ ".html": "text/html",
241
+ ".css": "text/css",
242
+ ".png": "image/png",
243
+ ".jpg": "image/jpeg",
244
+ ".jpeg": "image/jpeg",
245
+ ".svg": "image/svg+xml",
246
+ ".zip": "application/zip"
247
+ };
248
+ const mimeType = mimeTypes[ext] ?? "application/octet-stream";
249
+ const response = await fetch(uploadUrl, {
250
+ method: "PUT",
251
+ body: fileBuffer,
252
+ headers: { "Content-Type": mimeType }
253
+ });
254
+ if (!response.ok) {
255
+ throw new Error(`Upload failed (${response.status}): ${response.statusText}`);
256
+ }
257
+ }
258
+ async function uploadDirectoryAsZip(uploadUrl, dirPath) {
259
+ const absoluteDir = resolve(dirPath);
260
+ if (!existsSync(absoluteDir) || !statSync(absoluteDir).isDirectory()) {
261
+ throw new Error(`Not a directory: ${absoluteDir}`);
262
+ }
263
+ const tmpZip = resolve(absoluteDir, "..", `.${Date.now()}-archive.zip`);
264
+ try {
265
+ execSync(`cd ${JSON.stringify(absoluteDir)} && zip -r ${JSON.stringify(tmpZip)} .`, { stdio: "pipe" });
266
+ const zipBuffer = readFileSync(tmpZip);
267
+ const response = await fetch(uploadUrl, {
268
+ method: "PUT",
269
+ body: zipBuffer,
270
+ headers: { "Content-Type": "application/zip" }
271
+ });
272
+ if (!response.ok) {
273
+ throw new Error(`Upload failed (${response.status}): ${response.statusText}`);
274
+ }
275
+ return zipBuffer.length;
276
+ } finally {
277
+ try {
278
+ execSync(`rm -f ${JSON.stringify(tmpZip)}`, { stdio: "pipe" });
279
+ } catch {
280
+ }
281
+ }
282
+ }
283
+ function formatFileSize(bytes) {
284
+ if (bytes < 1024) return `${bytes} B`;
285
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
286
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
287
+ }
288
+ function toManifest(config, version) {
289
+ const manifest = {
290
+ $schema: "https://cdn.app.sls.epilot.io/v1/schema.json",
291
+ manifest_version: 1,
292
+ app_id: config.app_id,
293
+ name: config.name,
294
+ description: config.description,
295
+ components: []
296
+ };
297
+ if (config.category) manifest.category = config.category;
298
+ if (config.author) manifest.author = config.author;
299
+ if (config.documentation_url) manifest.documentation_url = config.documentation_url;
300
+ if (config.support_email) manifest.support_email = config.support_email;
301
+ if (config.pricing) manifest.pricing = config.pricing;
302
+ if (config.notifications) manifest.notifications = config.notifications;
303
+ const role = version.role;
304
+ if (role?.grants?.length) {
305
+ manifest.permissions = role.grants.map((g) => ({
306
+ action: g.action,
307
+ ...g.resource ? { resource: g.resource } : {}
308
+ }));
309
+ }
310
+ const blueprintRef = version.blueprint_ref;
311
+ if (blueprintRef?.manifest_id) {
312
+ manifest.blueprint = { manifest_id: blueprintRef.manifest_id };
313
+ }
314
+ if (config.icon_url) {
315
+ manifest.assets = { logo: "./assets/logo.png" };
316
+ }
317
+ const components = version.components ?? [];
318
+ manifest.components = components.map((comp) => {
319
+ const component = {
320
+ id: comp.id,
321
+ component_type: comp.component_type,
322
+ configuration: comp.configuration ?? {}
323
+ };
324
+ if (comp.name) component.name = comp.name;
325
+ if (comp.description) component.description = comp.description;
326
+ if (Array.isArray(comp.options) && comp.options.length > 0) {
327
+ component.options = comp.options.map((opt) => {
328
+ const option = { key: opt.key, type: opt.type };
329
+ if (opt.label) option.label = opt.label;
330
+ if (opt.required) option.required = opt.required;
331
+ if (opt.description) option.description = opt.description;
332
+ return option;
333
+ });
334
+ }
335
+ if (comp.surfaces && typeof comp.surfaces === "object" && Object.keys(comp.surfaces).length > 0) {
336
+ component.surfaces = comp.surfaces;
337
+ }
338
+ const assets = {};
339
+ if (comp.component_type === "CUSTOM_JOURNEY_BLOCK") {
340
+ const cfg = comp.configuration;
341
+ if (cfg?.component_url) assets.bundle = `./dist/${comp.id}/bundle.js`;
342
+ }
343
+ if (comp.surfaces && typeof comp.surfaces === "object") {
344
+ for (const surface of Object.values(comp.surfaces)) {
345
+ if (surface && typeof surface === "object" && "zip_url" in surface && surface.zip_url) {
346
+ assets.zip = `./dist/${comp.id}/`;
347
+ }
348
+ }
349
+ }
350
+ if (Object.keys(assets).length > 0) component.assets = assets;
351
+ return component;
352
+ });
353
+ return manifest;
354
+ }
355
+
356
+ export {
357
+ log,
358
+ validateManifest,
359
+ readManifest,
360
+ writeManifest,
361
+ createAppApiClient,
362
+ uploadFileToPresignedUrl,
363
+ uploadDirectoryAsZip,
364
+ formatFileSize,
365
+ toManifest
366
+ };