@nextclaw/server 0.15.23 → 0.15.24

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/index.js CHANGED
@@ -4,7 +4,7 @@ import { serve } from "@hono/node-server";
4
4
  import { AccessManager, PanelAppError, injectUiContentParamsBootstrap, isInboxDeliveryError, isPanelAppError, isPreferenceError, isProjectError, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError } from "@nextclaw/kernel";
5
5
  import { WebSocket, WebSocketServer } from "ws";
6
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
- import { mkdir, open, readFile, readdir, realpath, stat } from "node:fs/promises";
7
+ import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
8
8
  import { basename, dirname, extname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
9
9
  import { createHash, randomBytes, randomUUID } from "node:crypto";
10
10
  import * as NextclawCore from "@nextclaw/core";
@@ -4839,6 +4839,8 @@ var ServiceAppsRoutesController = class {
4839
4839
  };
4840
4840
  //#endregion
4841
4841
  //#region src/app/utils/ncp-session-event-stream.utils.ts
4842
+ const NCP_SESSION_STREAM_HEARTBEAT_INTERVAL_MS = 25e3;
4843
+ const NCP_SESSION_STREAM_HEARTBEAT_FRAME = ": keepalive\n\n";
4842
4844
  function readEventSessionId(event) {
4843
4845
  const payload = "payload" in event ? event.payload : null;
4844
4846
  if (!payload || typeof payload !== "object") return null;
@@ -4852,8 +4854,13 @@ function createNcpSessionEventStreamResponse(eventBus, payload, signal) {
4852
4854
  let controller = null;
4853
4855
  let closed = false;
4854
4856
  let unsubscribe = () => void 0;
4857
+ let heartbeat = null;
4855
4858
  const cleanup = () => {
4856
4859
  unsubscribe();
4860
+ if (heartbeat) {
4861
+ clearInterval(heartbeat);
4862
+ heartbeat = null;
4863
+ }
4857
4864
  signal.removeEventListener("abort", close);
4858
4865
  };
4859
4866
  const close = () => {
@@ -4870,6 +4877,9 @@ function createNcpSessionEventStreamResponse(eventBus, payload, signal) {
4870
4877
  start: (streamController) => {
4871
4878
  controller = streamController;
4872
4879
  unsubscribe = eventBus.on(eventKeys.ncpEvent, push);
4880
+ heartbeat = setInterval(() => {
4881
+ if (!closed && !signal.aborted) controller?.enqueue(encoder.encode(NCP_SESSION_STREAM_HEARTBEAT_FRAME));
4882
+ }, NCP_SESSION_STREAM_HEARTBEAT_INTERVAL_MS);
4873
4883
  signal.addEventListener("abort", close, { once: true });
4874
4884
  if (signal.aborted) close();
4875
4885
  },
@@ -5079,6 +5089,28 @@ function isServerPathBrowseError(error) {
5079
5089
  return error instanceof ServerPathBrowseError;
5080
5090
  }
5081
5091
  //#endregion
5092
+ //#region src/features/server-path/utils/server-path-search.utils.ts
5093
+ function isServerPathInside(basePath, candidatePath) {
5094
+ const relativePath = relative(basePath, candidatePath);
5095
+ return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
5096
+ }
5097
+ function normalizeServerPathRelativePath(value) {
5098
+ return value.split(sep).join("/");
5099
+ }
5100
+ function resolveServerPathSearchScore(entry, query) {
5101
+ if (!query) return 1;
5102
+ const normalizedQuery = query.toLocaleLowerCase();
5103
+ const normalizedName = entry.name.toLocaleLowerCase();
5104
+ const normalizedPath = entry.relativePath.toLocaleLowerCase();
5105
+ if (!normalizedQuery.split(/\s+/).filter(Boolean).every((term) => normalizedPath.includes(term))) return 0;
5106
+ if (normalizedName === normalizedQuery) return 1e3;
5107
+ if (normalizedName.startsWith(normalizedQuery)) return 850;
5108
+ if (normalizedName.includes(normalizedQuery)) return 700;
5109
+ if (normalizedPath.startsWith(normalizedQuery)) return 600;
5110
+ if (normalizedPath.split("/").some((segment) => segment.startsWith(normalizedQuery))) return 550;
5111
+ return 400 - Math.min(normalizedPath.length, 300);
5112
+ }
5113
+ //#endregion
5082
5114
  //#region src/features/server-path/utils/server-path-directory.utils.ts
5083
5115
  var ServerPathDirectoryCreateError = class extends Error {
5084
5116
  constructor(code, message) {
@@ -5092,28 +5124,46 @@ function normalizeDirectoryName(value) {
5092
5124
  if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\")) throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_NAME_INVALID", "directory name is invalid");
5093
5125
  return name;
5094
5126
  }
5095
- function readFileErrorCode(error) {
5127
+ function readFileErrorCode$1(error) {
5096
5128
  return typeof error === "object" && error !== null && "code" in error ? String(error.code ?? "") : void 0;
5097
5129
  }
5098
- async function createServerPathDirectory(input) {
5099
- let parentPath;
5130
+ function resolveDirectoryPath(value) {
5100
5131
  try {
5101
- parentPath = resolveServerPath({ path: typeof input.parentPath === "string" ? input.parentPath : null });
5132
+ return resolveServerPath({ path: typeof value === "string" ? value : null });
5102
5133
  } catch (error) {
5103
5134
  if (error instanceof ServerPathResolutionError) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", error.message);
5104
5135
  throw error;
5105
5136
  }
5137
+ }
5138
+ async function assertParentInsideBase(baseValue, parentPath) {
5139
+ if (typeof baseValue !== "string" || !baseValue.trim()) return;
5140
+ const basePath = resolveDirectoryPath(baseValue);
5141
+ if (!isServerPathInside(basePath, parentPath)) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "parent path must stay inside the project root");
5142
+ try {
5143
+ const [realBasePath, realParentPath] = await Promise.all([realpath(basePath), realpath(parentPath)]);
5144
+ if (!isServerPathInside(realBasePath, realParentPath)) throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "parent path must stay inside the project root");
5145
+ } catch (error) {
5146
+ if (error instanceof ServerPathDirectoryCreateError) throw error;
5147
+ throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_INVALID", "project root and parent path must exist");
5148
+ }
5149
+ }
5150
+ function throwDirectoryCreationError(error) {
5151
+ const code = readFileErrorCode$1(error);
5152
+ if (code === "EEXIST") throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_EXISTS", "directory already exists");
5153
+ if (code === "ENOENT") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_FOUND", "parent directory does not exist");
5154
+ if (code === "ENOTDIR") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_DIRECTORY", "parent path must point to a directory");
5155
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_WRITABLE", "parent directory is not writable");
5156
+ throw error;
5157
+ }
5158
+ async function createServerPathDirectory(input) {
5159
+ const parentPath = resolveDirectoryPath(input.parentPath);
5160
+ await assertParentInsideBase(input.basePath, parentPath);
5106
5161
  const directoryPath = join(parentPath, normalizeDirectoryName(input.name));
5107
5162
  try {
5108
5163
  await mkdir(directoryPath);
5109
5164
  return { path: directoryPath };
5110
5165
  } catch (error) {
5111
- const code = readFileErrorCode(error);
5112
- if (code === "EEXIST") throw new ServerPathDirectoryCreateError("SERVER_PATH_DIRECTORY_EXISTS", "directory already exists");
5113
- if (code === "ENOENT") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_FOUND", "parent directory does not exist");
5114
- if (code === "ENOTDIR") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_DIRECTORY", "parent path must point to a directory");
5115
- if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathDirectoryCreateError("SERVER_PATH_PARENT_NOT_WRITABLE", "parent directory is not writable");
5116
- throw error;
5166
+ throwDirectoryCreationError(error);
5117
5167
  }
5118
5168
  }
5119
5169
  function isServerPathDirectoryCreateError(error) {
@@ -5405,28 +5455,6 @@ function isServerPathContentError(error) {
5405
5455
  return error instanceof ServerPathContentError;
5406
5456
  }
5407
5457
  //#endregion
5408
- //#region src/features/server-path/utils/server-path-search.utils.ts
5409
- function isServerPathInside(basePath, candidatePath) {
5410
- const relativePath = relative(basePath, candidatePath);
5411
- return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
5412
- }
5413
- function normalizeServerPathRelativePath(value) {
5414
- return value.split(sep).join("/");
5415
- }
5416
- function resolveServerPathSearchScore(entry, query) {
5417
- if (!query) return 1;
5418
- const normalizedQuery = query.toLocaleLowerCase();
5419
- const normalizedName = entry.name.toLocaleLowerCase();
5420
- const normalizedPath = entry.relativePath.toLocaleLowerCase();
5421
- if (!normalizedQuery.split(/\s+/).filter(Boolean).every((term) => normalizedPath.includes(term))) return 0;
5422
- if (normalizedName === normalizedQuery) return 1e3;
5423
- if (normalizedName.startsWith(normalizedQuery)) return 850;
5424
- if (normalizedName.includes(normalizedQuery)) return 700;
5425
- if (normalizedPath.startsWith(normalizedQuery)) return 600;
5426
- if (normalizedPath.split("/").some((segment) => segment.startsWith(normalizedQuery))) return 550;
5427
- return 400 - Math.min(normalizedPath.length, 300);
5428
- }
5429
- //#endregion
5430
5458
  //#region src/features/server-path/services/server-path-search.service.ts
5431
5459
  const DEFAULT_RESULT_LIMIT = 50;
5432
5460
  const MAX_RESULT_LIMIT = 100;
@@ -5614,6 +5642,199 @@ function isServerPathSearchError(error) {
5614
5642
  return error instanceof ServerPathSearchError;
5615
5643
  }
5616
5644
  //#endregion
5645
+ //#region src/features/server-path/utils/server-path-mutation.utils.ts
5646
+ var ServerPathMutationError = class extends Error {
5647
+ constructor(code, message, details) {
5648
+ super(message);
5649
+ this.code = code;
5650
+ this.details = details;
5651
+ this.name = "ServerPathMutationError";
5652
+ }
5653
+ };
5654
+ function readFileErrorCode(error) {
5655
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code ?? "") : void 0;
5656
+ }
5657
+ function resolveScopedPaths(input) {
5658
+ let basePath;
5659
+ let targetPath;
5660
+ try {
5661
+ basePath = resolveServerPath({ path: typeof input.basePath === "string" ? input.basePath : null });
5662
+ targetPath = resolveServerPath({
5663
+ path: typeof input.targetPath === "string" ? input.targetPath : null,
5664
+ basePath
5665
+ });
5666
+ } catch (error) {
5667
+ if (error instanceof ServerPathResolutionError) throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", error.message);
5668
+ throw error;
5669
+ }
5670
+ if (!isServerPathInside(basePath, targetPath)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
5671
+ if (!input.allowRoot && targetPath === basePath) throw new ServerPathMutationError("SERVER_PATH_ROOT_PROTECTED", "the project root cannot be deleted");
5672
+ return {
5673
+ basePath,
5674
+ targetPath
5675
+ };
5676
+ }
5677
+ async function resolveRealBasePath(basePath) {
5678
+ try {
5679
+ const resolved = await realpath(basePath);
5680
+ if (!(await stat(resolved)).isDirectory()) throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", "project root must point to a directory");
5681
+ return resolved;
5682
+ } catch (error) {
5683
+ if (error instanceof ServerPathMutationError) throw error;
5684
+ throw new ServerPathMutationError("SERVER_PATH_BASE_INVALID", "project root does not exist or is not accessible");
5685
+ }
5686
+ }
5687
+ async function assertExistingPathInsideRealBase(params) {
5688
+ const [realBasePath, realTargetPath] = await Promise.all([resolveRealBasePath(params.basePath), realpath(params.targetPath).catch(() => null)]);
5689
+ if (!realTargetPath) throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
5690
+ if (!isServerPathInside(realBasePath, realTargetPath)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
5691
+ }
5692
+ function normalizeEntryName(value) {
5693
+ const name = typeof value === "string" ? value.trim() : "";
5694
+ if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || name.includes("\0") || basename(name) !== name) throw new ServerPathMutationError("SERVER_PATH_FILE_NAME_INVALID", "entry name is invalid");
5695
+ return name;
5696
+ }
5697
+ async function createServerPathFile(input) {
5698
+ const { basePath, targetPath: parentPath } = resolveScopedPaths({
5699
+ basePath: input.basePath,
5700
+ targetPath: input.parentPath,
5701
+ allowRoot: true
5702
+ });
5703
+ await assertExistingPathInsideRealBase({
5704
+ basePath,
5705
+ targetPath: parentPath
5706
+ });
5707
+ if (!(await stat(parentPath).catch(() => null))?.isDirectory()) throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "file parent must point to a directory");
5708
+ const name = normalizeEntryName(input.name);
5709
+ const path = join(parentPath, name);
5710
+ try {
5711
+ await writeFile(path, "", { flag: "wx" });
5712
+ } catch (error) {
5713
+ const code = readFileErrorCode(error);
5714
+ if (code === "EEXIST") throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "target file already exists");
5715
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "file parent is not writable");
5716
+ throw error;
5717
+ }
5718
+ return {
5719
+ name,
5720
+ path,
5721
+ kind: "file"
5722
+ };
5723
+ }
5724
+ async function renameServerPathEntry(input) {
5725
+ const { basePath, targetPath } = resolveScopedPaths({
5726
+ basePath: input.basePath,
5727
+ targetPath: input.path
5728
+ });
5729
+ await assertExistingPathInsideRealBase({
5730
+ basePath,
5731
+ targetPath
5732
+ });
5733
+ const entryStats = await lstat(targetPath).catch(() => null);
5734
+ if (!entryStats) throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
5735
+ const name = normalizeEntryName(input.name);
5736
+ const path = join(resolve(targetPath, ".."), name);
5737
+ if (!isServerPathInside(basePath, path)) throw new ServerPathMutationError("SERVER_PATH_OUTSIDE_BASE", "target path must stay inside the project root");
5738
+ if (await lstat(path).then(() => true).catch(() => false)) throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "target entry already exists");
5739
+ try {
5740
+ await rename(targetPath, path);
5741
+ } catch (error) {
5742
+ const code = readFileErrorCode(error);
5743
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "target path is not writable");
5744
+ throw error;
5745
+ }
5746
+ return {
5747
+ oldPath: targetPath,
5748
+ path,
5749
+ name,
5750
+ kind: entryStats.isDirectory() ? "directory" : "file"
5751
+ };
5752
+ }
5753
+ async function deleteServerPathEntry(input) {
5754
+ const { basePath, targetPath } = resolveScopedPaths({
5755
+ basePath: input.basePath,
5756
+ targetPath: input.path
5757
+ });
5758
+ await assertExistingPathInsideRealBase({
5759
+ basePath,
5760
+ targetPath
5761
+ });
5762
+ let entryStats;
5763
+ try {
5764
+ entryStats = await lstat(targetPath);
5765
+ } catch {
5766
+ throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
5767
+ }
5768
+ const kind = entryStats.isDirectory() ? "directory" : "file";
5769
+ try {
5770
+ await rm(targetPath, {
5771
+ recursive: kind === "directory",
5772
+ force: false
5773
+ });
5774
+ } catch (error) {
5775
+ const code = readFileErrorCode(error);
5776
+ if (code === "ENOENT") throw new ServerPathMutationError("SERVER_PATH_ENTRY_NOT_FOUND", "target path does not exist");
5777
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "target path is not writable");
5778
+ throw error;
5779
+ }
5780
+ return {
5781
+ path: targetPath,
5782
+ kind
5783
+ };
5784
+ }
5785
+ async function uploadServerPathFiles(input) {
5786
+ const { basePath, targetPath } = resolveScopedPaths({
5787
+ basePath: input.basePath,
5788
+ targetPath: input.targetPath,
5789
+ allowRoot: true
5790
+ });
5791
+ await assertExistingPathInsideRealBase({
5792
+ basePath,
5793
+ targetPath
5794
+ });
5795
+ if (!(await stat(targetPath).catch(() => null))?.isDirectory()) throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "upload target must point to a directory");
5796
+ if (input.files.length === 0) throw new ServerPathMutationError("SERVER_PATH_ENTRY_INVALID", "at least one upload file is required");
5797
+ const normalizedFiles = input.files.map((file) => ({
5798
+ file,
5799
+ name: normalizeEntryName(file.name)
5800
+ }));
5801
+ const uniqueNames = /* @__PURE__ */ new Set();
5802
+ for (const { name } of normalizedFiles) {
5803
+ if (uniqueNames.has(name)) throw new ServerPathMutationError("SERVER_PATH_FILE_NAME_INVALID", "upload file names must be unique");
5804
+ uniqueNames.add(name);
5805
+ }
5806
+ if (!input.overwrite) {
5807
+ const conflicts = (await Promise.all(normalizedFiles.map(async ({ name }) => {
5808
+ return await lstat(join(targetPath, name)).then(() => true).catch(() => false) ? name : null;
5809
+ }))).filter((name) => Boolean(name));
5810
+ if (conflicts.length > 0) throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "one or more upload files already exist", { conflicts });
5811
+ }
5812
+ try {
5813
+ return {
5814
+ files: await Promise.all(normalizedFiles.map(async ({ file, name }) => {
5815
+ const path = resolve(targetPath, name);
5816
+ const content = Buffer.from(await file.arrayBuffer());
5817
+ await writeFile(path, content, { flag: input.overwrite ? "w" : "wx" });
5818
+ return {
5819
+ name,
5820
+ path,
5821
+ sizeBytes: content.byteLength
5822
+ };
5823
+ })),
5824
+ overwritten: input.overwrite
5825
+ };
5826
+ } catch (error) {
5827
+ const code = readFileErrorCode(error);
5828
+ if (code === "EEXIST") throw new ServerPathMutationError("SERVER_PATH_FILE_EXISTS", "one or more upload files already exist");
5829
+ if (code === "ENOENT" || code === "ENOTDIR") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_DIRECTORY", "upload target must point to an existing directory");
5830
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") throw new ServerPathMutationError("SERVER_PATH_TARGET_NOT_WRITABLE", "upload target is not writable");
5831
+ throw error;
5832
+ }
5833
+ }
5834
+ function isServerPathMutationError(error) {
5835
+ return error instanceof ServerPathMutationError;
5836
+ }
5837
+ //#endregion
5617
5838
  //#region src/features/server-path/controllers/server-path.controller.ts
5618
5839
  function readIncludeFilesFlag(value) {
5619
5840
  return value === "1" || value === "true";
@@ -5661,6 +5882,7 @@ var ServerPathRoutesController = class {
5661
5882
  if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_DIRECTORY", "directory input is required"), 400);
5662
5883
  try {
5663
5884
  return c.json(ok(await createServerPathDirectory({
5885
+ basePath: body.data.basePath,
5664
5886
  parentPath: body.data.parentPath,
5665
5887
  name: body.data.name
5666
5888
  })), 201);
@@ -5669,6 +5891,68 @@ var ServerPathRoutesController = class {
5669
5891
  throw error;
5670
5892
  }
5671
5893
  };
5894
+ uploadFiles = async (c) => {
5895
+ let formData;
5896
+ try {
5897
+ formData = await c.req.raw.formData();
5898
+ } catch {
5899
+ return c.json(err("INVALID_SERVER_PATH_UPLOAD", "multipart upload is required"), 400);
5900
+ }
5901
+ const files = formData.getAll("files").flatMap((value) => typeof value === "string" ? [] : [{
5902
+ name: value.name,
5903
+ arrayBuffer: () => value.arrayBuffer()
5904
+ }]);
5905
+ try {
5906
+ return c.json(ok(await uploadServerPathFiles({
5907
+ basePath: formData.get("basePath"),
5908
+ targetPath: formData.get("targetPath"),
5909
+ overwrite: formData.get("overwrite") === "true",
5910
+ files
5911
+ })), 201);
5912
+ } catch (error) {
5913
+ if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
5914
+ throw error;
5915
+ }
5916
+ };
5917
+ createFile = async (c) => {
5918
+ const body = await readJson(c.req.raw);
5919
+ if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_FILE", "file input is required"), 400);
5920
+ try {
5921
+ return c.json(ok(await createServerPathFile({
5922
+ basePath: body.data.basePath,
5923
+ parentPath: body.data.parentPath,
5924
+ name: body.data.name
5925
+ })), 201);
5926
+ } catch (error) {
5927
+ if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
5928
+ throw error;
5929
+ }
5930
+ };
5931
+ renameEntry = async (c) => {
5932
+ const body = await readJson(c.req.raw);
5933
+ if (!body.ok || !isRecord$2(body.data)) return c.json(err("INVALID_SERVER_PATH_RENAME", "rename input is required"), 400);
5934
+ try {
5935
+ return c.json(ok(await renameServerPathEntry({
5936
+ basePath: body.data.basePath,
5937
+ path: body.data.path,
5938
+ name: body.data.name
5939
+ })));
5940
+ } catch (error) {
5941
+ if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), error.code === "SERVER_PATH_FILE_EXISTS" ? 409 : 400);
5942
+ throw error;
5943
+ }
5944
+ };
5945
+ deleteEntry = async (c) => {
5946
+ try {
5947
+ return c.json(ok(await deleteServerPathEntry({
5948
+ basePath: c.req.query("basePath"),
5949
+ path: c.req.query("path")
5950
+ })));
5951
+ } catch (error) {
5952
+ if (isServerPathMutationError(error)) return c.json(err(error.code, error.message, error.details), 400);
5953
+ throw error;
5954
+ }
5955
+ };
5672
5956
  read = async (c) => {
5673
5957
  try {
5674
5958
  const payload = await readServerPath({
@@ -6095,6 +6379,26 @@ var UiRouteRegistry = class {
6095
6379
  "/api/server-paths/directory",
6096
6380
  serverPath.createDirectory
6097
6381
  ],
6382
+ [
6383
+ "post",
6384
+ "/api/server-paths/file",
6385
+ serverPath.createFile
6386
+ ],
6387
+ [
6388
+ "post",
6389
+ "/api/server-paths/files",
6390
+ serverPath.uploadFiles
6391
+ ],
6392
+ [
6393
+ "patch",
6394
+ "/api/server-paths/entry",
6395
+ serverPath.renameEntry
6396
+ ],
6397
+ [
6398
+ "delete",
6399
+ "/api/server-paths/entry",
6400
+ serverPath.deleteEntry
6401
+ ],
6098
6402
  [
6099
6403
  "get",
6100
6404
  "/api/server-paths/read",