@firstpick/pi-package-webui 0.2.9 → 0.3.1

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/bin/pi-webui.mjs CHANGED
@@ -1419,6 +1419,33 @@ async function getDirectoryPickerData(viewPath, activeCwd) {
1419
1419
  };
1420
1420
  }
1421
1421
 
1422
+ function cleanDirectoryCreateName(value) {
1423
+ const name = String(value || "").trim();
1424
+ if (!name) throw makeHttpError(400, "Directory name is required");
1425
+ if (name === "." || name === "..") throw makeHttpError(400, "Directory name cannot be . or ..");
1426
+ if (name.includes("\u0000")) throw makeHttpError(400, "Directory name cannot contain null bytes");
1427
+ if (name.includes("/") || name.includes("\\")) throw makeHttpError(400, "Create one directory at a time; path separators are not allowed");
1428
+ if (name.length > 255) throw makeHttpError(400, "Directory name is too long");
1429
+ return name;
1430
+ }
1431
+
1432
+ async function createDirectoryPickerDirectory(parentPath, nameValue, activeCwd) {
1433
+ const parent = await resolveCwd(parentPath || activeCwd, activeCwd);
1434
+ const name = cleanDirectoryCreateName(nameValue);
1435
+ const target = path.resolve(parent, name);
1436
+ if (path.dirname(target) !== parent) throw makeHttpError(400, "Directory must be created directly under the current path");
1437
+
1438
+ try {
1439
+ await mkdir(target);
1440
+ } catch (error) {
1441
+ if (error?.code === "EEXIST") throw makeHttpError(409, `Directory already exists: ${target}`);
1442
+ if (["EACCES", "EPERM"].includes(error?.code)) throw makeHttpError(403, `Cannot create directory ${target}: ${sanitizeError(error)}`);
1443
+ throw makeHttpError(400, `Cannot create directory ${target}: ${sanitizeError(error)}`);
1444
+ }
1445
+
1446
+ return getDirectoryPickerData(target, activeCwd);
1447
+ }
1448
+
1422
1449
  function normalizeSuggestionPath(value) {
1423
1450
  return String(value || "").replace(/\\/g, "/");
1424
1451
  }
@@ -2688,7 +2715,7 @@ async function restorableTabsForRestart() {
2688
2715
  const state = await currentSessionState(tab).catch(() => tab.lastState || null);
2689
2716
  return restorableTabDescriptor(tab, state);
2690
2717
  }));
2691
- return mergeRestorableTabDescriptors(liveDescriptors, closedRestorableTabs);
2718
+ return mergeRestorableTabDescriptors(liveDescriptors);
2692
2719
  }
2693
2720
 
2694
2721
  function spawnRestartServer(restorableTabs) {
@@ -4288,6 +4315,16 @@ const server = createServer(async (req, res) => {
4288
4315
  return;
4289
4316
  }
4290
4317
 
4318
+ if (url.pathname === "/api/directories" && req.method === "POST") {
4319
+ const body = await readJsonBody(req);
4320
+ const tab = getRequestedTab(req, url, body);
4321
+ sendJson(res, 201, {
4322
+ ok: true,
4323
+ data: await createDirectoryPickerDirectory(body.parent ?? body.cwd ?? body.path, body.name, tab.cwd),
4324
+ });
4325
+ return;
4326
+ }
4327
+
4291
4328
  if (url.pathname === "/api/path-suggestions" && req.method === "GET") {
4292
4329
  const tab = getRequestedTab(req, url);
4293
4330
  sendJson(res, 200, { ok: true, data: await getPathSuggestionData(tab, url.searchParams.get("query")) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firstpick/pi-package-webui",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "description": "Pi Web UI companion package with a local browser UI CLI plus /webui-start and /webui-status commands.",
5
5
  "license": "MIT",
6
6
  "repository": {