+1








766fb96ff2
* Adding support for hosting with URL prefix to make reverse-proxy setup on sub-path possible
* Adjusting recent changes to auth.html (changing to relative URLs) after rebasing from upstream
* Adjusting service_worker and application manifest to support URL-prefix
* Add notes on Space Lua Pattern Matching (#1366)
* Remove common/space_lua/stdlib/math.md (#1371)
* Escape pipe symbol in string.gsub (#1370)
* feat: configure vim in CONFIG (#1369)
* Fix week calculation (#1368)
* Add more tests for week calculation
* Fix week calculation
* Add more tests
* Implement Lua built-in function os.difftime (#1367)
* Implement Lua built-in function os.difftime
* Test os.difftime
---------
Co-authored-by: Zef Hemel <zef@zef.me>
* Fix index page naming during server initialization (#1365)
* Allow non-zero shell exit codes (#1377)
* Generate version from git describe at build time (#1374)
* Generate version from git describe at build time
* Add 2.0-beta prefix
* Use Deno.Command instead of Deno.run
* Add missing case to math.random and check arguments (#1372)
* Fix paragraphs for the tag page (#1376)
* Render a predefined string for empty markdown table instead of pipe characters (#1387)
* Fix string.find (#1390)
* Fetch tags and history for proper version string generation (#1388)
* Fix support for disabling shortcuts (#1393)
* Add GitHub Actions Cache to reduce build times (#1394)
* Order strings in queries using collation algorithm (#1391)
Configurable with queryCollation, default value maintains old behaviour.
Added tests, schema, example settings, and documentation to query page.
Close: #614
Close: #1316
* Utility function to handle empty query results and templates (#1386)
* Add global Lua function 'some'
Moved documentation for 'each' function to non-standard section.
* Revert "Add optional argument to template.each for empty collection output (#1359)"
This reverts commit b73dadec67.
* Reimplement #1359 using 'some' function
* Update Lua to event.listEvents to match plugos syscall (#1397)
The documentation, example, and other function names use
`event.listEvents`, but `event.list` is being registered with the
client.
* Update widget header to not overflow container (#1410)
Also add a 10px margin below the header to maintain consistent spacing
around the widget contents.
* fix: case insensitive admonitions by default (#1409)
* fix: closing bracket is missing (#1408)
* Add optional priority attribute to PageCreatingContent (#1392)
* Add optional priority attribute to PageCreatingContent
* Minor simplification
* Fix comments
* Revert changes
* Add pageEventHandlers
* Use UTC year, month, and date for strings lacking time components (#1403)
* feat: allow CONFIG.md in any directory (#1398)
* fix: bundle external dependencies (#1379)
* Deno bump
* Copy-edit splash screen text (#1413)
* Fixes #1401 by implementing Lua's select
* Fixes offline capability of PWA (I hope).
Now storing config in localStorage.
* fix lint
* Reduce blast radius of Lua errors
* Fixes #1411: adds 'priority' setting for space style
* Refactor: Merging common/ into web/
* Fixes #1400
* Improves #1312 by rendering Lua expressions (but not widgets)
* Fix minor typos, add configuration to the docs
---------
Co-authored-by: wbhouston <wmbhouston@gmail.com>
Co-authored-by: Lennart Ochel <lennart.ochel@outlook.com>
Co-authored-by: Matthias Benaets <89214559+MatthiasBenaets@users.noreply.github.com>
Co-authored-by: Zef Hemel <zef@zef.me>
Co-authored-by: Marek S. Łukasiewicz <marek@lukasiewicz.tech>
Co-authored-by: Ivan Alejandro <ivanalejandro0@gmail.com>
Co-authored-by: Albert-Jan de Vries <aj+github@albert-jandevries.nl>
Co-authored-by: Cole Stowell <121599022+costowell@users.noreply.github.com>
Co-authored-by: Jim Tittsler <jimt@onjapan.net>
128 lines
3.5 KiB
TypeScript
128 lines
3.5 KiB
TypeScript
import type { Context } from "hono";
|
|
import type { ShellRequest } from "@silverbulletmd/silverbullet/type/rpc";
|
|
import type { ShellBackend } from "./shell_backend.ts";
|
|
import { StreamingShell } from "./shell_backend.ts";
|
|
import { removeUrlPrefix } from "$lib/url_prefix.ts";
|
|
|
|
/**
|
|
* Handles the /.shell endpoint for non-streaming shell commands
|
|
*/
|
|
export async function handleShellEndpoint(
|
|
c: Context,
|
|
shellBackend: ShellBackend,
|
|
readOnly: boolean,
|
|
): Promise<Response> {
|
|
const req = c.req;
|
|
const body = await req.json();
|
|
try {
|
|
if (readOnly) {
|
|
return c.text("Read only mode, no shell commands allowed", 405);
|
|
}
|
|
const shellCommand: ShellRequest = body;
|
|
// Note: in read-only this is set to NoShellSupport, so don't worry
|
|
const shellResponse = await shellBackend.handle(shellCommand);
|
|
return c.json(shellResponse);
|
|
} catch (e: any) {
|
|
console.error("Shell error", e);
|
|
return c.text(e.message, 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles the /.shell/stream endpoint for streaming shell commands
|
|
*/
|
|
export function handleShellStreamEndpoint(
|
|
c: Context,
|
|
cwd: string,
|
|
readOnly: boolean,
|
|
hostUrlPrefix?: string,
|
|
): Response {
|
|
const req = c.req;
|
|
const url = new URL(removeUrlPrefix(req.url, hostUrlPrefix));
|
|
|
|
// Check if read-only mode is enabled
|
|
if (readOnly) {
|
|
return c.text("Read only mode, no shell commands allowed", 405);
|
|
}
|
|
|
|
// Get command and arguments from query parameters
|
|
const cmd = url.searchParams.get("cmd");
|
|
if (!cmd) {
|
|
return c.text("Missing cmd parameter", 400);
|
|
}
|
|
|
|
let args: string[] = [];
|
|
const argsParam = url.searchParams.get("args");
|
|
if (argsParam) {
|
|
try {
|
|
args = JSON.parse(argsParam);
|
|
if (!Array.isArray(args)) {
|
|
return c.text("args must be a JSON array", 400);
|
|
}
|
|
} catch (_e) {
|
|
return c.text("Invalid args parameter: must be a JSON array", 400);
|
|
}
|
|
}
|
|
|
|
// Create a streaming shell
|
|
const shell = new StreamingShell(cwd);
|
|
|
|
// Upgrade the connection to a WebSocket
|
|
try {
|
|
const { socket, response } = Deno.upgradeWebSocket(req.raw);
|
|
|
|
// Set up WebSocket event handlers
|
|
socket.onopen = () => {
|
|
// Start the shell process when the WebSocket is opened
|
|
shell.start(cmd, args);
|
|
|
|
// Forward shell output to the WebSocket
|
|
shell.onOutput((type, data) => {
|
|
socket.send(JSON.stringify({
|
|
type,
|
|
data,
|
|
}));
|
|
});
|
|
};
|
|
|
|
socket.onmessage = async (event) => {
|
|
try {
|
|
const message = JSON.parse(event.data);
|
|
if (message.type === "stdin") {
|
|
await shell.writeToStdin(message.data);
|
|
} else if (message.type === "signal") {
|
|
const success = shell.sendSignal(message.signal);
|
|
if (!success) {
|
|
socket.send(JSON.stringify({
|
|
type: "error",
|
|
data: `Failed to send signal: ${message.signal}`,
|
|
}));
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error("Error handling WebSocket message:", e);
|
|
socket.send(JSON.stringify({
|
|
type: "error",
|
|
data: `Error: ${e}`,
|
|
}));
|
|
}
|
|
};
|
|
|
|
socket.onclose = async () => {
|
|
await shell.close();
|
|
};
|
|
|
|
socket.onerror = (error) => {
|
|
console.error("WebSocket error:", error);
|
|
shell.close().catch((e) => {
|
|
console.error("Error closing shell:", e);
|
|
});
|
|
};
|
|
|
|
return response;
|
|
} catch (e) {
|
|
console.error("WebSocket upgrade failed:", e);
|
|
return c.text("WebSocket upgrade failed", 400);
|
|
}
|
|
}
|