pmx-canvas 0.1.34 → 0.1.35
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/CHANGELOG.md +13 -0
- package/package.json +1 -1
- package/src/server/server.ts +34 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to `pmx-canvas` are documented here. This project follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.1.35] - 2026-06-08
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **HTTP batch accepts a bare-array body again (report #49).** `POST /api/canvas/batch`
|
|
13
|
+
with a top-level `[ ... ]` array created nothing and returned `{ ok: true, results: [] }`
|
|
14
|
+
— the 0.1.33 `readJson` hardening (empty/whitespace/non-object → `{}`) also coerced
|
|
15
|
+
top-level arrays to `{}`, so the handler's bare-array branch was dead. Batch now reads
|
|
16
|
+
the body with an array-preserving variant, so both documented shapes work: the canonical
|
|
17
|
+
`{ "operations": [...] }` and a bare `[...]`. `readJson` is unchanged for every other
|
|
18
|
+
endpoint (still object-only), so the malformed-body robustness is preserved.
|
|
19
|
+
|
|
8
20
|
## [0.1.34] - 2026-06-08
|
|
9
21
|
|
|
10
22
|
### Added
|
|
@@ -1763,6 +1775,7 @@ otherwise have to discover by trial and error.
|
|
|
1763
1775
|
- Regression coverage for snapshot flat-`id` aliases on both MCP and
|
|
1764
1776
|
HTTP surfaces, plus async / top-level-`await` WebView script bodies.
|
|
1765
1777
|
|
|
1778
|
+
[0.1.35]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.35
|
|
1766
1779
|
[0.1.34]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.34
|
|
1767
1780
|
[0.1.33]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.33
|
|
1768
1781
|
[0.1.32]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.32
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmx-canvas",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Spatial canvas workbench for coding agents — infinite 2D canvas with agent-native CLI, MCP integration, nodes, edges, file watching, and snapshots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/server/index.ts",
|
package/src/server/server.ts
CHANGED
|
@@ -1072,6 +1072,34 @@ async function readJson(req: Request): Promise<Record<string, unknown>> {
|
|
|
1072
1072
|
}
|
|
1073
1073
|
}
|
|
1074
1074
|
|
|
1075
|
+
/**
|
|
1076
|
+
* Like {@link readJson}, but PRESERVES a top-level JSON array. For endpoints that
|
|
1077
|
+
* accept either an object or a bare array (e.g. `/api/canvas/batch`, whose CLI
|
|
1078
|
+
* help and handler both document a bare `[...]` form). readJson coerces arrays to
|
|
1079
|
+
* `{}` so object-shaped handlers never crash on `body.field`; this variant keeps
|
|
1080
|
+
* the array so the handler's array branch can run. Empty/whitespace/malformed
|
|
1081
|
+
* bodies still resolve to `{}`.
|
|
1082
|
+
*/
|
|
1083
|
+
async function readJsonObjectOrArray(req: Request): Promise<Record<string, unknown> | unknown[]> {
|
|
1084
|
+
let text = '';
|
|
1085
|
+
try {
|
|
1086
|
+
text = await req.text();
|
|
1087
|
+
} catch (error) {
|
|
1088
|
+
logWorkbenchWarning('readJson', error);
|
|
1089
|
+
return {};
|
|
1090
|
+
}
|
|
1091
|
+
if (!text.trim()) return {};
|
|
1092
|
+
try {
|
|
1093
|
+
const value = JSON.parse(text) as unknown;
|
|
1094
|
+
if (Array.isArray(value)) return value;
|
|
1095
|
+
if (!value || typeof value !== 'object') return {};
|
|
1096
|
+
return value as Record<string, unknown>;
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
logWorkbenchWarning('readJson', error);
|
|
1099
|
+
return {};
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1075
1103
|
function htmlEscape(value: string): string {
|
|
1076
1104
|
return value
|
|
1077
1105
|
.replaceAll('&', '&')
|
|
@@ -2495,8 +2523,12 @@ async function handleCanvasAddGraph(req: Request): Promise<Response> {
|
|
|
2495
2523
|
}
|
|
2496
2524
|
|
|
2497
2525
|
async function handleCanvasBatch(req: Request): Promise<Response> {
|
|
2498
|
-
|
|
2499
|
-
|
|
2526
|
+
// Accept both documented shapes: { operations: [...] } and a bare [...] array.
|
|
2527
|
+
// Uses the array-preserving reader so the bare-array form isn't coerced to {}.
|
|
2528
|
+
const body = await readJsonObjectOrArray(req);
|
|
2529
|
+
const operations = Array.isArray(body)
|
|
2530
|
+
? body
|
|
2531
|
+
: Array.isArray(body.operations) ? body.operations : [];
|
|
2500
2532
|
const normalized = operations
|
|
2501
2533
|
.filter((operation): operation is Record<string, unknown> => operation && typeof operation === 'object' && !Array.isArray(operation))
|
|
2502
2534
|
.map((operation) => ({
|