@elevasis/sdk 1.5.4 → 1.6.0

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/dist/cli.cjs CHANGED
@@ -29,6 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
30
  mod
31
31
  ));
32
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
33
 
33
34
  // ../../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/package.json
34
35
  var require_package = __commonJS({
@@ -102,7 +103,7 @@ var require_package = __commonJS({
102
103
  var require_main = __commonJS({
103
104
  "../../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js"(exports2, module2) {
104
105
  var fs = require("fs");
105
- var path = require("path");
106
+ var path2 = require("path");
106
107
  var os2 = require("os");
107
108
  var crypto = require("crypto");
108
109
  var packageJson = require_package();
@@ -218,7 +219,7 @@ var require_main = __commonJS({
218
219
  possibleVaultPath = options2.path.endsWith(".vault") ? options2.path : `${options2.path}.vault`;
219
220
  }
220
221
  } else {
221
- possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
222
+ possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
222
223
  }
223
224
  if (fs.existsSync(possibleVaultPath)) {
224
225
  return possibleVaultPath;
@@ -226,7 +227,7 @@ var require_main = __commonJS({
226
227
  return null;
227
228
  }
228
229
  function _resolveHome(envPath2) {
229
- return envPath2[0] === "~" ? path.join(os2.homedir(), envPath2.slice(1)) : envPath2;
230
+ return envPath2[0] === "~" ? path2.join(os2.homedir(), envPath2.slice(1)) : envPath2;
230
231
  }
231
232
  function _configVault(options2) {
232
233
  const debug = Boolean(options2 && options2.debug);
@@ -243,7 +244,7 @@ var require_main = __commonJS({
243
244
  return { parsed };
244
245
  }
245
246
  function configDotenv(options2) {
246
- const dotenvPath = path.resolve(process.cwd(), ".env");
247
+ const dotenvPath = path2.resolve(process.cwd(), ".env");
247
248
  let encoding = "utf8";
248
249
  const debug = Boolean(options2 && options2.debug);
249
250
  const quiet = options2 && "quiet" in options2 ? options2.quiet : true;
@@ -267,13 +268,13 @@ var require_main = __commonJS({
267
268
  }
268
269
  let lastError;
269
270
  const parsedAll = {};
270
- for (const path2 of optionPaths) {
271
+ for (const path3 of optionPaths) {
271
272
  try {
272
- const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
273
+ const parsed = DotenvModule.parse(fs.readFileSync(path3, { encoding }));
273
274
  DotenvModule.populate(parsedAll, parsed, options2);
274
275
  } catch (e) {
275
276
  if (debug) {
276
- _debug(`Failed to load ${path2} ${e.message}`);
277
+ _debug(`Failed to load ${path3} ${e.message}`);
277
278
  }
278
279
  lastError = e;
279
280
  }
@@ -288,7 +289,7 @@ var require_main = __commonJS({
288
289
  const shortPaths = [];
289
290
  for (const filePath of optionPaths) {
290
291
  try {
291
- const relative2 = path.relative(process.cwd(), filePath);
292
+ const relative2 = path2.relative(process.cwd(), filePath);
292
293
  shortPaths.push(relative2);
293
294
  } catch (e) {
294
295
  if (debug) {
@@ -1283,7 +1284,7 @@ var require_command = __commonJS({
1283
1284
  "../../node_modules/.pnpm/commander@11.1.0/node_modules/commander/lib/command.js"(exports2) {
1284
1285
  var EventEmitter = require("events").EventEmitter;
1285
1286
  var childProcess = require("child_process");
1286
- var path = require("path");
1287
+ var path2 = require("path");
1287
1288
  var fs = require("fs");
1288
1289
  var process8 = require("process");
1289
1290
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -2107,9 +2108,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2107
2108
  let launchWithNode = false;
2108
2109
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2109
2110
  function findFile(baseDir, baseName) {
2110
- const localBin = path.resolve(baseDir, baseName);
2111
+ const localBin = path2.resolve(baseDir, baseName);
2111
2112
  if (fs.existsSync(localBin)) return localBin;
2112
- if (sourceExt.includes(path.extname(baseName))) return void 0;
2113
+ if (sourceExt.includes(path2.extname(baseName))) return void 0;
2113
2114
  const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
2114
2115
  if (foundExt) return `${localBin}${foundExt}`;
2115
2116
  return void 0;
@@ -2125,19 +2126,19 @@ Expecting one of '${allowedValues.join("', '")}'`);
2125
2126
  } catch (err) {
2126
2127
  resolvedScriptPath = this._scriptPath;
2127
2128
  }
2128
- executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
2129
+ executableDir = path2.resolve(path2.dirname(resolvedScriptPath), executableDir);
2129
2130
  }
2130
2131
  if (executableDir) {
2131
2132
  let localFile = findFile(executableDir, executableFile);
2132
2133
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2133
- const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
2134
+ const legacyName = path2.basename(this._scriptPath, path2.extname(this._scriptPath));
2134
2135
  if (legacyName !== this._name) {
2135
2136
  localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
2136
2137
  }
2137
2138
  }
2138
2139
  executableFile = localFile || executableFile;
2139
2140
  }
2140
- launchWithNode = sourceExt.includes(path.extname(executableFile));
2141
+ launchWithNode = sourceExt.includes(path2.extname(executableFile));
2141
2142
  let proc;
2142
2143
  if (process8.platform !== "win32") {
2143
2144
  if (launchWithNode) {
@@ -2920,7 +2921,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2920
2921
  * @return {Command}
2921
2922
  */
2922
2923
  nameFromFilename(filename) {
2923
- this._name = path.basename(filename, path.extname(filename));
2924
+ this._name = path2.basename(filename, path2.extname(filename));
2924
2925
  return this;
2925
2926
  }
2926
2927
  /**
@@ -2934,9 +2935,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2934
2935
  * @param {string} [path]
2935
2936
  * @return {string|null|Command}
2936
2937
  */
2937
- executableDir(path2) {
2938
- if (path2 === void 0) return this._executableDir;
2939
- this._executableDir = path2;
2938
+ executableDir(path3) {
2939
+ if (path3 === void 0) return this._executableDir;
2940
+ this._executableDir = path3;
2940
2941
  return this;
2941
2942
  }
2942
2943
  /**
@@ -5245,7 +5246,7 @@ var require_buffer_list = __commonJS({
5245
5246
  }
5246
5247
  }, {
5247
5248
  key: "join",
5248
- value: function join4(s) {
5249
+ value: function join7(s) {
5249
5250
  if (this.length === 0) return "";
5250
5251
  var p = this.head;
5251
5252
  var ret = "" + p.data;
@@ -11938,10 +11939,10 @@ var require_util = __commonJS({
11938
11939
  function cloneDef2(schema) {
11939
11940
  return mergeDefs2(schema._zod.def);
11940
11941
  }
11941
- function getElementAtPath2(obj, path) {
11942
- if (!path)
11942
+ function getElementAtPath2(obj, path2) {
11943
+ if (!path2)
11943
11944
  return obj;
11944
- return path.reduce((acc, key) => acc?.[key], obj);
11945
+ return path2.reduce((acc, key) => acc?.[key], obj);
11945
11946
  }
11946
11947
  function promiseAllObject2(promisesObj) {
11947
11948
  const keys = Object.keys(promisesObj);
@@ -12303,11 +12304,11 @@ var require_util = __commonJS({
12303
12304
  }
12304
12305
  return false;
12305
12306
  }
12306
- function prefixIssues2(path, issues) {
12307
+ function prefixIssues2(path2, issues) {
12307
12308
  return issues.map((iss) => {
12308
12309
  var _a;
12309
12310
  (_a = iss).path ?? (_a.path = []);
12310
- iss.path.unshift(path);
12311
+ iss.path.unshift(path2);
12311
12312
  return iss;
12312
12313
  });
12313
12314
  }
@@ -12511,7 +12512,7 @@ var require_errors2 = __commonJS({
12511
12512
  }
12512
12513
  function treeifyError2(error46, mapper = (issue2) => issue2.message) {
12513
12514
  const result = { errors: [] };
12514
- const processError = (error47, path = []) => {
12515
+ const processError = (error47, path2 = []) => {
12515
12516
  var _a, _b;
12516
12517
  for (const issue2 of error47.issues) {
12517
12518
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12521,7 +12522,7 @@ var require_errors2 = __commonJS({
12521
12522
  } else if (issue2.code === "invalid_element") {
12522
12523
  processError({ issues: issue2.issues }, issue2.path);
12523
12524
  } else {
12524
- const fullpath = [...path, ...issue2.path];
12525
+ const fullpath = [...path2, ...issue2.path];
12525
12526
  if (fullpath.length === 0) {
12526
12527
  result.errors.push(mapper(issue2));
12527
12528
  continue;
@@ -12553,8 +12554,8 @@ var require_errors2 = __commonJS({
12553
12554
  }
12554
12555
  function toDotPath2(_path) {
12555
12556
  const segs = [];
12556
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12557
- for (const seg of path) {
12557
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12558
+ for (const seg of path2) {
12558
12559
  if (typeof seg === "number")
12559
12560
  segs.push(`[${seg}]`);
12560
12561
  else if (typeof seg === "symbol")
@@ -26488,6 +26489,11 @@ var require_zod = __commonJS({
26488
26489
  });
26489
26490
 
26490
26491
  // src/cli/index.ts
26492
+ var index_exports = {};
26493
+ __export(index_exports, {
26494
+ getProjectRoot: () => getProjectRoot
26495
+ });
26496
+ module.exports = __toCommonJS(index_exports);
26491
26497
  var import_dotenv = __toESM(require_main(), 1);
26492
26498
 
26493
26499
  // ../../node_modules/.pnpm/commander@11.1.0/node_modules/commander/esm.mjs
@@ -28250,10 +28256,10 @@ function mergeDefs(...defs) {
28250
28256
  function cloneDef(schema) {
28251
28257
  return mergeDefs(schema._zod.def);
28252
28258
  }
28253
- function getElementAtPath(obj, path) {
28254
- if (!path)
28259
+ function getElementAtPath(obj, path2) {
28260
+ if (!path2)
28255
28261
  return obj;
28256
- return path.reduce((acc, key) => acc?.[key], obj);
28262
+ return path2.reduce((acc, key) => acc?.[key], obj);
28257
28263
  }
28258
28264
  function promiseAllObject(promisesObj) {
28259
28265
  const keys = Object.keys(promisesObj);
@@ -28614,11 +28620,11 @@ function aborted(x, startIndex = 0) {
28614
28620
  }
28615
28621
  return false;
28616
28622
  }
28617
- function prefixIssues(path, issues) {
28623
+ function prefixIssues(path2, issues) {
28618
28624
  return issues.map((iss) => {
28619
28625
  var _a;
28620
28626
  (_a = iss).path ?? (_a.path = []);
28621
- iss.path.unshift(path);
28627
+ iss.path.unshift(path2);
28622
28628
  return iss;
28623
28629
  });
28624
28630
  }
@@ -28780,7 +28786,7 @@ function formatError(error46, mapper = (issue2) => issue2.message) {
28780
28786
  }
28781
28787
  function treeifyError(error46, mapper = (issue2) => issue2.message) {
28782
28788
  const result = { errors: [] };
28783
- const processError = (error47, path = []) => {
28789
+ const processError = (error47, path2 = []) => {
28784
28790
  var _a, _b;
28785
28791
  for (const issue2 of error47.issues) {
28786
28792
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -28790,7 +28796,7 @@ function treeifyError(error46, mapper = (issue2) => issue2.message) {
28790
28796
  } else if (issue2.code === "invalid_element") {
28791
28797
  processError({ issues: issue2.issues }, issue2.path);
28792
28798
  } else {
28793
- const fullpath = [...path, ...issue2.path];
28799
+ const fullpath = [...path2, ...issue2.path];
28794
28800
  if (fullpath.length === 0) {
28795
28801
  result.errors.push(mapper(issue2));
28796
28802
  continue;
@@ -28822,8 +28828,8 @@ function treeifyError(error46, mapper = (issue2) => issue2.message) {
28822
28828
  }
28823
28829
  function toDotPath(_path) {
28824
28830
  const segs = [];
28825
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
28826
- for (const seg of path) {
28831
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
28832
+ for (const seg of path2) {
28827
28833
  if (typeof seg === "number")
28828
28834
  segs.push(`[${seg}]`);
28829
28835
  else if (typeof seg === "symbol")
@@ -43862,34 +43868,42 @@ function resolveApiKey(prod) {
43862
43868
  }
43863
43869
  return process.env.ELEVASIS_PLATFORM_KEY ?? "";
43864
43870
  }
43865
- function findEnvFile(startDir) {
43866
- const raw = (0, import_path.resolve)(startDir ?? process.cwd());
43867
- let cwd;
43871
+ function findProjectRoot(startDir) {
43872
+ const raw = (0, import_path.resolve)(startDir);
43873
+ let dir;
43868
43874
  try {
43869
- cwd = (0, import_fs.realpathSync)(raw);
43875
+ dir = (0, import_fs.realpathSync)(raw);
43870
43876
  } catch {
43871
- cwd = raw;
43877
+ dir = raw;
43872
43878
  }
43873
- let dir = cwd;
43874
43879
  while (true) {
43875
- const candidate = (0, import_path.resolve)(dir, ".env");
43876
- if ((0, import_fs.existsSync)(candidate)) return candidate;
43880
+ if ((0, import_fs.existsSync)((0, import_path.join)(dir, ".elevasis"))) return dir;
43877
43881
  const parent = (0, import_path.dirname)(dir);
43878
43882
  if (parent === dir) break;
43879
43883
  dir = parent;
43880
43884
  }
43881
- dir = cwd;
43882
- while (true) {
43883
- if ((0, import_fs.existsSync)((0, import_path.resolve)(dir, "pnpm-workspace.yaml"))) {
43884
- const candidate = (0, import_path.resolve)(dir, ".env");
43885
- if ((0, import_fs.existsSync)(candidate)) return candidate;
43886
- break;
43887
- }
43888
- const parent = (0, import_path.dirname)(dir);
43889
- if (parent === dir) break;
43890
- dir = parent;
43891
- }
43892
- return void 0;
43885
+ process.stderr.write(
43886
+ "Not inside an Elevasis project. Run this command from a project directory (an Elevasis project has a .elevasis file at its root).\n"
43887
+ );
43888
+ process.exit(1);
43889
+ }
43890
+ function isHelpOrVersionOnly() {
43891
+ const args = process.argv.slice(2);
43892
+ return args.length > 0 && args.every((a) => ["--help", "-h", "--version", "-V"].includes(a));
43893
+ }
43894
+ var _projectRoot;
43895
+ function getProjectRoot() {
43896
+ if (_projectRoot !== void 0) return _projectRoot;
43897
+ _projectRoot = isHelpOrVersionOnly() ? process.cwd() : findProjectRoot(process.cwd());
43898
+ return _projectRoot;
43899
+ }
43900
+ function resolveProjectRelative(relOrAbsPath) {
43901
+ if ((0, import_path.isAbsolute)(relOrAbsPath)) return relOrAbsPath;
43902
+ return (0, import_path.resolve)(getProjectRoot(), relOrAbsPath);
43903
+ }
43904
+ function findEnvFile(_startDir) {
43905
+ const candidate = (0, import_path.join)(getProjectRoot(), ".env");
43906
+ return (0, import_fs.existsSync)(candidate) ? candidate : void 0;
43893
43907
  }
43894
43908
 
43895
43909
  // src/cli/api-client.ts
@@ -43990,7 +44004,7 @@ function wrapAction(commandName, fn) {
43990
44004
  // package.json
43991
44005
  var package_default = {
43992
44006
  name: "@elevasis/sdk",
43993
- version: "1.5.4",
44007
+ version: "1.6.0",
43994
44008
  description: "SDK for building Elevasis organization resources",
43995
44009
  type: "module",
43996
44010
  bin: {
@@ -44072,8 +44086,8 @@ async function loadTsModule(filePath) {
44072
44086
  return await import(fileUrl);
44073
44087
  } finally {
44074
44088
  try {
44075
- const { unlinkSync } = await import("fs");
44076
- unlinkSync(tmpOut);
44089
+ const { unlinkSync: unlinkSync3 } = await import("fs");
44090
+ unlinkSync3(tmpOut);
44077
44091
  } catch {
44078
44092
  }
44079
44093
  }
@@ -44494,6 +44508,7 @@ function registerCheckCommand(program3) {
44494
44508
 
44495
44509
  // src/cli/commands/exec.ts
44496
44510
  var import_node_fs = require("node:fs");
44511
+ var import_node_path = require("node:path");
44497
44512
  var POLL_INTERVAL_MS = 3e3;
44498
44513
  async function pollForCompletion(resourceId, executionId, apiUrl) {
44499
44514
  const pollSpinner = ora("Waiting for completion...").start();
@@ -44545,12 +44560,34 @@ async function pollForCompletion(resourceId, executionId, apiUrl) {
44545
44560
  }
44546
44561
  function registerExecCommand(program3) {
44547
44562
  program3.command("exec <resourceId>").description(`Execute a deployed resource
44548
- Example: elevasis-sdk exec my-workflow -i '{"key":"value"}'`).option("-i, --input <json>", "Input data as JSON string").option("-f, --input-file <path>", "Read input from a JSON file (avoids shell escaping issues)").option("--async", "Execute asynchronously with polling").option("--api-url <url>", "API URL").action(
44563
+ Example: elevasis-sdk exec my-workflow -i '{"key":"value"}'`).option("-i, --input <json>", "Input data as JSON string").option(
44564
+ "-f, --input-file <path>",
44565
+ "Read input from a JSON file (avoids shell escaping issues). Relative paths resolve against the project root."
44566
+ ).option("--async", "Execute asynchronously with polling").option("--api-url <url>", "API URL").option(
44567
+ "--cleanup-input",
44568
+ "Delete the input file after a successful execution (only files under <projectRoot>/tmp/ are eligible; files outside tmp/ produce a warning and are left untouched)"
44569
+ ).action(
44549
44570
  wrapAction(
44550
44571
  "exec",
44551
44572
  async (resourceId, options2) => {
44552
- const input = options2.inputFile ? JSON.parse((0, import_node_fs.readFileSync)(options2.inputFile, "utf8")) : options2.input ? JSON.parse(options2.input) : {};
44573
+ const resolvedInputFile = options2.inputFile ? resolveProjectRelative(options2.inputFile) : void 0;
44574
+ const input = resolvedInputFile ? JSON.parse((0, import_node_fs.readFileSync)(resolvedInputFile, "utf8")) : options2.input ? JSON.parse(options2.input) : {};
44553
44575
  const apiUrl = resolveApiUrl(options2.apiUrl);
44576
+ const maybeCleanupInput = () => {
44577
+ if (!options2.cleanupInput || !resolvedInputFile) return;
44578
+ const tmpDir = (0, import_node_path.join)(getProjectRoot(), "tmp");
44579
+ if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
44580
+ try {
44581
+ (0, import_node_fs.unlinkSync)(resolvedInputFile);
44582
+ } catch {
44583
+ }
44584
+ } else {
44585
+ process.stderr.write(
44586
+ `[warn] --cleanup-input: file is not under <projectRoot>/tmp/ and was not deleted: ${resolvedInputFile}
44587
+ `
44588
+ );
44589
+ }
44590
+ };
44554
44591
  if (options2.async) {
44555
44592
  const asyncSpinner = ora(`Starting async execution of ${resourceId}...`).start();
44556
44593
  const asyncResult = await apiPost(
@@ -44562,6 +44599,7 @@ function registerExecCommand(program3) {
44562
44599
  console.log(source_default.gray(" Execution ID:"), source_default.cyan(asyncResult.executionId));
44563
44600
  console.log("");
44564
44601
  await pollForCompletion(resourceId, asyncResult.executionId, apiUrl);
44602
+ maybeCleanupInput();
44565
44603
  return;
44566
44604
  }
44567
44605
  const spinner = ora(`Executing ${resourceId}...`).start();
@@ -44573,6 +44611,7 @@ function registerExecCommand(program3) {
44573
44611
  console.log("");
44574
44612
  console.log(source_default.green(" Output:"));
44575
44613
  console.log(JSON.stringify(result.data, null, 2));
44614
+ maybeCleanupInput();
44576
44615
  } else {
44577
44616
  spinner.fail(source_default.red("Execution failed"));
44578
44617
  console.log(source_default.gray(" Execution ID:"), source_default.cyan(result.executionId));
@@ -46165,6 +46204,226 @@ function registerProjectCommands(program3) {
46165
46204
  registerNoteDelete(program3);
46166
46205
  }
46167
46206
 
46207
+ // src/cli/commands/request/request.ts
46208
+ var import_node_fs2 = require("node:fs");
46209
+ var import_node_path2 = require("node:path");
46210
+
46211
+ // ../core/src/requests/api-schemas.ts
46212
+ var RequestSeverityEnum = external_exports.enum(["critical", "warning", "info"]);
46213
+ var RequestCategoryEnum = external_exports.enum([
46214
+ "ui_bug",
46215
+ "data_inconsistency",
46216
+ "performance",
46217
+ "error_pattern",
46218
+ "configuration",
46219
+ "feature_request",
46220
+ "api_design",
46221
+ "documentation",
46222
+ "integration_request",
46223
+ "other"
46224
+ ]);
46225
+ var RequestStatusEnum = external_exports.enum(["open", "investigating", "resolved", "wont_fix"]);
46226
+ var RequestSourceEnum = external_exports.enum(["agent", "cli", "api", "webhook", "user", "external"]);
46227
+ var RequestTypeEnum = external_exports.enum(["bug", "feature", "question", "other"]);
46228
+ var CreateRequestInputSchema = external_exports.object({
46229
+ type: RequestTypeEnum,
46230
+ title: external_exports.string().min(1),
46231
+ description: external_exports.string().min(1),
46232
+ severity: RequestSeverityEnum,
46233
+ category: RequestCategoryEnum,
46234
+ affected_page: external_exports.string().nullish(),
46235
+ evidence: external_exports.record(external_exports.string(), external_exports.unknown()).nullish(),
46236
+ context: external_exports.record(external_exports.string(), external_exports.unknown()).nullish(),
46237
+ project_id: external_exports.string().uuid().nullish(),
46238
+ task_id: external_exports.string().uuid().nullish()
46239
+ }).strict();
46240
+ var ListRequestsQuerySchema = external_exports.object({
46241
+ status: RequestStatusEnum.optional(),
46242
+ severity: RequestSeverityEnum.optional(),
46243
+ project_id: external_exports.string().uuid().optional(),
46244
+ limit: external_exports.coerce.number().int().min(1).max(200).default(50)
46245
+ });
46246
+
46247
+ // src/cli/commands/request/request.ts
46248
+ function registerRequestCommands(program3) {
46249
+ program3.command("request:submit").description(
46250
+ "Submit a structured request report via POST /api/external/requests\n Example: elevasis-sdk request:submit -f ./request-report.json"
46251
+ ).option("-i, --input <json>", "Request body as JSON string").option(
46252
+ "-f, --input-file <path>",
46253
+ "Read request body from a JSON file (e.g. request-report.json, avoids shell escaping). Relative paths resolve against the project root."
46254
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").option(
46255
+ "--cleanup-input",
46256
+ "Delete the input file after a successful submission (only files under <projectRoot>/tmp/ are eligible; files outside tmp/ produce a warning and are left untouched)"
46257
+ ).action(
46258
+ wrapAction("request:submit", async (options2) => {
46259
+ if (!options2.input && !options2.inputFile) {
46260
+ throw new Error("Provide --input <json> or --input-file <path>");
46261
+ }
46262
+ const resolvedInputFile = options2.inputFile ? resolveProjectRelative(options2.inputFile) : void 0;
46263
+ const raw = resolvedInputFile ? JSON.parse((0, import_node_fs2.readFileSync)(resolvedInputFile, "utf8")) : JSON.parse(options2.input);
46264
+ const parsed = CreateRequestInputSchema.safeParse(raw);
46265
+ if (!parsed.success) {
46266
+ const issues = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
46267
+ throw new Error(`Invalid request body:
46268
+ ${issues}`);
46269
+ }
46270
+ const apiUrl = resolveApiUrl(options2.apiUrl);
46271
+ const result = await apiPost("/api/external/requests", parsed.data, apiUrl);
46272
+ if (options2.pretty) {
46273
+ const r = result.request;
46274
+ console.log(source_default.green("\nRequest submitted"));
46275
+ console.log(source_default.gray(` ID: ${r.id}`));
46276
+ console.log(source_default.gray(` Severity: ${r.severity}`));
46277
+ console.log(source_default.gray(` Category: ${r.category}`));
46278
+ console.log(source_default.gray(` Status: ${r.status}`));
46279
+ console.log();
46280
+ } else {
46281
+ console.log(JSON.stringify(result, null, 2));
46282
+ }
46283
+ if (options2.cleanupInput && resolvedInputFile) {
46284
+ const tmpDir = (0, import_node_path2.join)(getProjectRoot(), "tmp");
46285
+ if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
46286
+ try {
46287
+ (0, import_node_fs2.unlinkSync)(resolvedInputFile);
46288
+ } catch {
46289
+ }
46290
+ } else {
46291
+ process.stderr.write(
46292
+ `[warn] --cleanup-input: file is not under <projectRoot>/tmp/ and was not deleted: ${resolvedInputFile}
46293
+ `
46294
+ );
46295
+ }
46296
+ }
46297
+ })
46298
+ );
46299
+ }
46300
+
46301
+ // src/cli/commands/doctor.ts
46302
+ var import_node_fs3 = require("node:fs");
46303
+ var import_node_path3 = __toESM(require("node:path"), 1);
46304
+ function ok(label, detail) {
46305
+ console.log(`${source_default.green("[OK]")} ${source_default.bold(label)}: ${detail}`);
46306
+ }
46307
+ function fail(label, detail) {
46308
+ console.log(`${source_default.red("[FAIL]")} ${source_default.bold(label)}: ${detail}`);
46309
+ }
46310
+ function warn(label, detail) {
46311
+ console.log(`${source_default.yellow("[WARN]")} ${source_default.bold(label)}: ${detail}`);
46312
+ }
46313
+ function verbose(detail) {
46314
+ console.log(source_default.gray(` ${detail}`));
46315
+ }
46316
+ function registerDoctorCommand(program3) {
46317
+ program3.command("doctor").description("Check that your Elevasis project is correctly configured\n Example: elevasis-sdk doctor [--verbose]").option("--verbose", "Print full paths, response bodies, and error details for each check").action(async (options2) => {
46318
+ const isVerbose = Boolean(options2.verbose);
46319
+ let failCount = 0;
46320
+ console.log(source_default.cyan("Running Elevasis SDK doctor checks\u2026\n"));
46321
+ let projectRoot;
46322
+ try {
46323
+ projectRoot = findProjectRoot(process.cwd());
46324
+ ok("Project root", projectRoot);
46325
+ if (isVerbose) verbose(`Resolved via .elevasis marker: ${projectRoot}`);
46326
+ } catch (err) {
46327
+ fail(
46328
+ "Project root",
46329
+ "Not inside an Elevasis project. Run from a project directory (must contain a .elevasis file)."
46330
+ );
46331
+ if (isVerbose) {
46332
+ const msg = err instanceof Error ? err.message : String(err);
46333
+ verbose(msg);
46334
+ }
46335
+ failCount++;
46336
+ printSummary(failCount);
46337
+ process.exit(1);
46338
+ }
46339
+ const envPath2 = import_node_path3.default.join(projectRoot, ".env");
46340
+ const envExists = (0, import_node_fs3.existsSync)(envPath2);
46341
+ if (!envExists) {
46342
+ fail(".env", `Not found at ${envPath2}. Create it from .env.example and fill in ELEVASIS_PLATFORM_KEY.`);
46343
+ if (isVerbose) verbose(`Checked: ${envPath2}`);
46344
+ failCount++;
46345
+ printSummary(failCount);
46346
+ process.exit(1);
46347
+ }
46348
+ ok(".env", `Found at ${envPath2}`);
46349
+ if (isVerbose) verbose(`Path: ${envPath2}`);
46350
+ const apiKey = resolveApiKey();
46351
+ if (!apiKey) {
46352
+ fail("API key", "ELEVASIS_PLATFORM_KEY not set or empty.");
46353
+ if (isVerbose) verbose("Checked process.env.ELEVASIS_PLATFORM_KEY \u2014 not set or empty string");
46354
+ failCount++;
46355
+ printSummary(failCount);
46356
+ process.exit(1);
46357
+ }
46358
+ ok("API key", `Set (length: ${apiKey.length})`);
46359
+ if (isVerbose) verbose(`Key prefix: ${apiKey.slice(0, 6)}\u2026`);
46360
+ const apiUrl = resolveApiUrl();
46361
+ const healthUrl = `${apiUrl}/api/external/health`;
46362
+ let healthBody;
46363
+ let healthStatus;
46364
+ let networkError;
46365
+ try {
46366
+ const controller = new AbortController();
46367
+ const timeout = setTimeout(() => controller.abort(), 1e4);
46368
+ let response;
46369
+ try {
46370
+ response = await fetch(healthUrl, {
46371
+ headers: { Authorization: `Bearer ${apiKey}` },
46372
+ signal: controller.signal
46373
+ });
46374
+ } finally {
46375
+ clearTimeout(timeout);
46376
+ }
46377
+ healthStatus = response.status;
46378
+ if (response.ok) {
46379
+ healthBody = await response.json();
46380
+ ok("API", `Reachable. Workspace: ${healthBody.workspace.name} (${healthBody.workspace.id})`);
46381
+ if (isVerbose) verbose(`GET ${healthUrl} \u2192 ${response.status}`);
46382
+ if (isVerbose) verbose(`Response: ${JSON.stringify(healthBody)}`);
46383
+ const minSdkVersion = healthBody.sdkCompat?.minSdkVersion;
46384
+ if (minSdkVersion) {
46385
+ warn("SDK compat", `server minSdkVersion is ${minSdkVersion}; check is advisory in v1.`);
46386
+ if (isVerbose) verbose(`sdkCompat: ${JSON.stringify(healthBody.sdkCompat)}`);
46387
+ }
46388
+ } else if (response.status === 401) {
46389
+ fail("API", "Unauthorized. Check ELEVASIS_PLATFORM_KEY is correct.");
46390
+ if (isVerbose) {
46391
+ const body = await response.text();
46392
+ verbose(`GET ${healthUrl} \u2192 401`);
46393
+ verbose(`Response: ${body}`);
46394
+ }
46395
+ failCount++;
46396
+ } else {
46397
+ const body = await response.text();
46398
+ fail("API", `Unexpected response (${response.status}). Check ELEVASIS_API_URL and network connectivity.`);
46399
+ if (isVerbose) {
46400
+ verbose(`GET ${healthUrl} \u2192 ${response.status}`);
46401
+ verbose(`Response: ${body}`);
46402
+ }
46403
+ failCount++;
46404
+ }
46405
+ } catch (err) {
46406
+ networkError = err instanceof Error ? err.message : String(err);
46407
+ fail("API", `Unreachable at ${healthUrl}. Check ELEVASIS_API_URL and network connectivity.`);
46408
+ if (isVerbose) verbose(`Error: ${networkError}`);
46409
+ failCount++;
46410
+ }
46411
+ console.log();
46412
+ printSummary(failCount);
46413
+ if (failCount > 0) {
46414
+ process.exit(1);
46415
+ }
46416
+ });
46417
+ }
46418
+ function printSummary(failCount) {
46419
+ console.log();
46420
+ if (failCount === 0) {
46421
+ console.log(source_default.green("All checks passed. Your Elevasis project is correctly configured."));
46422
+ } else {
46423
+ console.log(source_default.red(`${failCount} check(s) failed. Fix the issues above before running other commands.`));
46424
+ }
46425
+ }
46426
+
46168
46427
  // src/cli/commands/init-claude.ts
46169
46428
  var import_path4 = require("path");
46170
46429
  var import_fs2 = require("fs");
@@ -46687,8 +46946,7 @@ if (envPath) {
46687
46946
  console.error(source_default.yellow(`\u26A0 Found .env at ${envPath} but failed to load it: ${result.error.message}`));
46688
46947
  }
46689
46948
  } else if (!process.env.ELEVASIS_PLATFORM_KEY) {
46690
- const cwd = process.cwd();
46691
- console.error(source_default.yellow(`\u26A0 No .env file found (searched upward from ${cwd})`));
46949
+ console.error(source_default.yellow(`\u26A0 No .env file found at ${getProjectRoot()}/.env`));
46692
46950
  console.error(source_default.gray(" Set ELEVASIS_PLATFORM_KEY in a .env at your project root."));
46693
46951
  }
46694
46952
  var program2 = new Command();
@@ -46707,11 +46965,13 @@ Commands:
46707
46965
  elevasis-sdk project:list [--search <query>] List projects with optional search
46708
46966
  elevasis-sdk project:resolve <query> Resolve a project ID from a name or UUID
46709
46967
  elevasis-sdk project:work <query> Open a lifecycle-aware project work brief
46968
+ elevasis-sdk request:submit -f <path> Submit a structured request report
46710
46969
  elevasis-sdk rename <id> --to <newId> [--prod] Rename resource across platform tables
46711
46970
  elevasis-sdk init-claude Initialize .claude/ config from SDK
46712
46971
  elevasis-sdk generate-docs Generate docs/index.md from frontmatter
46713
46972
  elevasis-sdk generate-resources Generate docs/resources.md from DeploymentSpec
46714
46973
  elevasis-sdk validate-docs Validate generated docs are fresh
46974
+ elevasis-sdk doctor [--verbose] Check project environment and API connectivity
46715
46975
 
46716
46976
  Use "elevasis-sdk <command> --help" for more information about a command.`
46717
46977
  ).version(SDK_VERSION);
@@ -46727,11 +46987,17 @@ registerCredsCommand(program2);
46727
46987
  registerErrorCommand(program2);
46728
46988
  registerRenameCommand(program2);
46729
46989
  registerProjectCommands(program2);
46990
+ registerRequestCommands(program2);
46991
+ registerDoctorCommand(program2);
46730
46992
  registerInitClaudeCommand(program2);
46731
46993
  registerGenerateDocsCommand(program2);
46732
46994
  registerGenerateResourcesCommand(program2);
46733
46995
  registerValidateDocsCommand(program2);
46734
46996
  program2.parse();
46997
+ // Annotate the CommonJS export names for ESM import in node:
46998
+ 0 && (module.exports = {
46999
+ getProjectRoot
47000
+ });
46735
47001
  /*! Bundled license information:
46736
47002
 
46737
47003
  safe-buffer/index.js: