@lotics/cli 0.45.0 → 0.45.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/dist/dev/rpc_handler.test.js +10 -0
- package/dist/dev/server.d.ts +9 -0
- package/dist/dev/server.js +12 -1
- package/dist/src/cli.js +4 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { dispatchRpc } from "./rpc_handler.js";
|
|
3
|
+
import { serializeRpcResult } from "./server.js";
|
|
3
4
|
function mockClient(over) {
|
|
4
5
|
return over;
|
|
5
6
|
}
|
|
@@ -56,3 +57,12 @@ describe("dispatchRpc — comment ops", () => {
|
|
|
56
57
|
await expect(dispatchRpc(client, { app_id: "app_x", op: "comments.counts", payload: {} })).rejects.toThrow(/table_id/);
|
|
57
58
|
});
|
|
58
59
|
});
|
|
60
|
+
describe("serializeRpcResult — every RPC response body is valid JSON", () => {
|
|
61
|
+
it("serializes a void result (comments.delete) as null, never an empty body", () => {
|
|
62
|
+
expect(serializeRpcResult(undefined)).toBe("null");
|
|
63
|
+
expect(JSON.parse(serializeRpcResult(undefined))).toBeNull();
|
|
64
|
+
});
|
|
65
|
+
it("passes object results through", () => {
|
|
66
|
+
expect(JSON.parse(serializeRpcResult({ comments: [] }))).toEqual({ comments: [] });
|
|
67
|
+
});
|
|
68
|
+
});
|
package/dist/dev/server.d.ts
CHANGED
|
@@ -37,6 +37,15 @@ export interface DevServerHandle {
|
|
|
37
37
|
/** Stops Vite + HTTP server. Safe to call multiple times. */
|
|
38
38
|
stop: () => Promise<void>;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Serialize an RPC result for the HTTP response body. Ops with no return
|
|
42
|
+
* value (e.g. comments.delete) resolve `undefined` — in production they
|
|
43
|
+
* travel over postMessage where undefined structured-clones fine, but
|
|
44
|
+
* `JSON.stringify(undefined)` is not a string, so the body would be EMPTY
|
|
45
|
+
* and the wrapper's `JSON.parse` throws "Unexpected end of JSON input".
|
|
46
|
+
* Serialize those as `null`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function serializeRpcResult(result: unknown): string;
|
|
40
49
|
export declare function startDevServer(args: DevServerArgs): Promise<DevServerHandle>;
|
|
41
50
|
/** Used by the CLI command for cross-platform `open <url>`. Best-effort —
|
|
42
51
|
* if the platform opener isn't installed (common in WSL, headless CI, some
|
package/dist/dev/server.js
CHANGED
|
@@ -18,6 +18,17 @@ import { dispatchRpc } from "./rpc_handler.js";
|
|
|
18
18
|
import { buildWrapperPage } from "./wrapper_page.js";
|
|
19
19
|
const DEFAULT_PORT = 5174;
|
|
20
20
|
const DEFAULT_VITE_PORT = 5173;
|
|
21
|
+
/**
|
|
22
|
+
* Serialize an RPC result for the HTTP response body. Ops with no return
|
|
23
|
+
* value (e.g. comments.delete) resolve `undefined` — in production they
|
|
24
|
+
* travel over postMessage where undefined structured-clones fine, but
|
|
25
|
+
* `JSON.stringify(undefined)` is not a string, so the body would be EMPTY
|
|
26
|
+
* and the wrapper's `JSON.parse` throws "Unexpected end of JSON input".
|
|
27
|
+
* Serialize those as `null`.
|
|
28
|
+
*/
|
|
29
|
+
export function serializeRpcResult(result) {
|
|
30
|
+
return JSON.stringify(result ?? null);
|
|
31
|
+
}
|
|
21
32
|
export async function startDevServer(args) {
|
|
22
33
|
const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
|
|
23
34
|
const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
|
|
@@ -95,7 +106,7 @@ export async function startDevServer(args) {
|
|
|
95
106
|
const ms = Date.now() - startedAt;
|
|
96
107
|
process.stderr.write(`[rpc] ${body.op} ${ms}ms\n`);
|
|
97
108
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
98
|
-
res.end(
|
|
109
|
+
res.end(serializeRpcResult(result));
|
|
99
110
|
}
|
|
100
111
|
catch (err) {
|
|
101
112
|
const message = err instanceof Error ? err.message : String(err);
|
package/dist/src/cli.js
CHANGED
|
@@ -31032,6 +31032,9 @@ function escapeHtml2(s) {
|
|
|
31032
31032
|
// src/dev/server.ts
|
|
31033
31033
|
var DEFAULT_PORT = 5174;
|
|
31034
31034
|
var DEFAULT_VITE_PORT = 5173;
|
|
31035
|
+
function serializeRpcResult(result) {
|
|
31036
|
+
return JSON.stringify(result ?? null);
|
|
31037
|
+
}
|
|
31035
31038
|
async function startDevServer(args) {
|
|
31036
31039
|
const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
|
|
31037
31040
|
const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
|
|
@@ -31099,7 +31102,7 @@ async function startDevServer(args) {
|
|
|
31099
31102
|
process.stderr.write(`[rpc] ${body.op} ${ms}ms
|
|
31100
31103
|
`);
|
|
31101
31104
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
31102
|
-
res.end(
|
|
31105
|
+
res.end(serializeRpcResult(result));
|
|
31103
31106
|
} catch (err2) {
|
|
31104
31107
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
31105
31108
|
process.stderr.write(`[rpc] ERROR ${message}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/cli",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.1",
|
|
4
4
|
"description": "Lotics SDK and CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,4 +41,4 @@
|
|
|
41
41
|
"url": "https://github.com/lotics/lotics.git",
|
|
42
42
|
"directory": "packages/sdk"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|