@creator-notes/cnotes 0.26.0 → 0.29.0
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/README.md +3 -4
- package/dist/cn.js +0 -2
- package/dist/cn.js.map +1 -1
- package/dist/commands/canvas.d.ts.map +1 -1
- package/dist/commands/canvas.js +125 -54
- package/dist/commands/canvas.js.map +1 -1
- package/dist/commands/relationships.d.ts.map +1 -1
- package/dist/commands/relationships.js +145 -14
- package/dist/commands/relationships.js.map +1 -1
- package/dist/lib/api-client.d.ts +1 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +2 -1
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/build-schema.d.ts +3 -1
- package/dist/lib/build-schema.d.ts.map +1 -1
- package/dist/lib/build-schema.js +3 -1
- package/dist/lib/build-schema.js.map +1 -1
- package/dist/lib/canvas-read.d.ts +59 -13
- package/dist/lib/canvas-read.d.ts.map +1 -1
- package/dist/lib/canvas-read.js +209 -17
- package/dist/lib/canvas-read.js.map +1 -1
- package/dist/lib/install-skill.d.ts +7 -2
- package/dist/lib/install-skill.d.ts.map +1 -1
- package/dist/lib/install-skill.js +44 -12
- package/dist/lib/install-skill.js.map +1 -1
- package/dist/mcp-server.js +56 -58
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/skills/cnotes/SKILL.md +144 -73
- package/skills/cnotes/references/humanizer.md +267 -0
package/README.md
CHANGED
|
@@ -36,14 +36,13 @@ cnotes search semantic "onboarding flow"
|
|
|
36
36
|
| `cnotes versions list\|create` | `cnotes v` | Note version history |
|
|
37
37
|
| `cnotes canvas list\|get\|create\|delete` | `cnotes c` | Manage canvases |
|
|
38
38
|
| `cnotes canvas place` | | Declarative layout — server packs items with no overlap |
|
|
39
|
-
| `cnotes canvas add-node\|add-text\|add-
|
|
39
|
+
| `cnotes canvas add-node\|add-text\|add-list\|add-link` | | Add a single node at explicit `--x`/`--y` (`add-richtext` is a deprecated alias of `add-text`) |
|
|
40
40
|
| `cnotes canvas bulk-add\|bulk-move\|bulk-remove` | | Bulk canvas operations — requires explicit coordinates |
|
|
41
41
|
| `cnotes canvas from-template` | | Create canvas from template |
|
|
42
42
|
| `cnotes search semantic` | `cnotes s` | Semantic search across notes |
|
|
43
43
|
| `cnotes timeline` | `cnotes tl` | Recent activity feed |
|
|
44
44
|
| `cnotes relationships list` | `cnotes rel` | Note relationships |
|
|
45
45
|
| `cnotes types list\|create\|update` | `cnotes t` | Manage note types (supertags) |
|
|
46
|
-
| `cnotes memory query\|facts\|entities` | `cnotes mem` | Query workspace knowledge |
|
|
47
46
|
| `cnotes workspace list\|select\|current` | | Workspace management |
|
|
48
47
|
| `cnotes config get-server\|set-server` | | CLI configuration |
|
|
49
48
|
| `cnotes mcp setup` | | Print MCP server config for Claude |
|
|
@@ -171,7 +170,7 @@ cnotes canvas agent-run wrap \
|
|
|
171
170
|
--canvas <canvasId> \
|
|
172
171
|
--prompt "Reorganize roadmap into Q1/Q2 clusters" \
|
|
173
172
|
-- bash -c '
|
|
174
|
-
cnotes canvas add-text "$CANVAS" --
|
|
173
|
+
cnotes canvas add-text "$CANVAS" --content "# Q1" --x 100 --y 100
|
|
175
174
|
cnotes canvas add-edge "$CANVAS" --source <id1> --target <id2>
|
|
176
175
|
'
|
|
177
176
|
```
|
|
@@ -187,7 +186,7 @@ Four building blocks:
|
|
|
187
186
|
- **`stack`** — items flow along one axis (`vertical` or `horizontal`), like CSS flexbox
|
|
188
187
|
- **`grid`** — N columns, items wrap to new rows, like CSS grid auto-flow
|
|
189
188
|
- **`anchor`** — place a sub-tree relative to an existing canvas node
|
|
190
|
-
- **`item`** — a leaf: `note`, `
|
|
189
|
+
- **`item`** — a leaf: `note`, `richtext` (the Text element — a markdown heading with no tint IS a heading), `list`, `canvas` (link), or `section` (frame)
|
|
191
190
|
|
|
192
191
|
Example — a richtext header above a 3-column grid of notes:
|
|
193
192
|
|
package/dist/cn.js
CHANGED
|
@@ -17,7 +17,6 @@ import { registerRelationshipsCommands } from "./commands/relationships.js";
|
|
|
17
17
|
import { registerSearchCommands } from "./commands/search.js";
|
|
18
18
|
import { registerTimelineCommands } from "./commands/timeline.js";
|
|
19
19
|
import { registerTypesCommands } from "./commands/types.js";
|
|
20
|
-
import { registerMemoryCommands } from "./commands/memory.js";
|
|
21
20
|
import { registerFilesCommands } from "./commands/files.js";
|
|
22
21
|
import { registerMcpCommands } from "./commands/mcp.js";
|
|
23
22
|
import { registerInitCommand } from "./commands/init.js";
|
|
@@ -69,7 +68,6 @@ registerRelationshipsCommands(program);
|
|
|
69
68
|
registerSearchCommands(program);
|
|
70
69
|
registerTimelineCommands(program);
|
|
71
70
|
registerTypesCommands(program);
|
|
72
|
-
registerMemoryCommands(program);
|
|
73
71
|
registerFilesCommands(program);
|
|
74
72
|
registerMcpCommands(program);
|
|
75
73
|
registerSchemaCommand(program);
|
package/dist/cn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cn.js","sourceRoot":"","sources":["../src/cn.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AACvC,MAAM,WAAW,GAAW,GAAG,CAAC,OAAO,CAAC;AACxC,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cn.js","sourceRoot":"","sources":["../src/cn.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/commands/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/commands/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAkG5C,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAg+D7D"}
|
package/dist/commands/canvas.js
CHANGED
|
@@ -657,55 +657,19 @@ Examples:
|
|
|
657
657
|
handleError(error, cfg.json);
|
|
658
658
|
}
|
|
659
659
|
});
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
`)
|
|
674
|
-
.action(async (canvasId, opts) => {
|
|
675
|
-
const cfg = resolveConfig(program.opts());
|
|
676
|
-
const api = new ApiClient(cfg.serverUrl, cfg.token);
|
|
677
|
-
const fontSize = opts.size === "paragraph" ? 18 : 32;
|
|
678
|
-
try {
|
|
679
|
-
const data = await api.post(`/api/canvas/${canvasId}`, {
|
|
680
|
-
action: "addTextNode",
|
|
681
|
-
content: opts.text,
|
|
682
|
-
fontSize,
|
|
683
|
-
colorVariant: opts.color,
|
|
684
|
-
positionX: parseInt(opts.x, 10),
|
|
685
|
-
positionY: parseInt(opts.y, 10),
|
|
686
|
-
});
|
|
687
|
-
if (cfg.json) {
|
|
688
|
-
outputJson(data);
|
|
689
|
-
}
|
|
690
|
-
else {
|
|
691
|
-
console.log(`Added text node to canvas at (${opts.x}, ${opts.y})`);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
catch (error) {
|
|
695
|
-
handleError(error, cfg.json);
|
|
696
|
-
}
|
|
697
|
-
});
|
|
698
|
-
canvas
|
|
699
|
-
.command("add-richtext")
|
|
700
|
-
.description("Add a richtext sticky to a canvas: orientation banners, emphasis quoting a note, image tiles. Sticky-sized (≤ ~3 sentences) — richtext is unversioned and unsearchable, so knowledge worth keeping goes in a typed note. Plain markdown only: NO [NOTE-X](relationship:...) mention syntax (corrupts the card)")
|
|
701
|
-
.argument("<canvasId>", "Canvas ID")
|
|
702
|
-
.option("--content <content>", "Richtext content inline (markdown; plain display IDs only, no mention syntax)")
|
|
703
|
-
.option("--content-file <path>", "Read richtext content (markdown) from a file")
|
|
704
|
-
.addOption(new Option("--size <size>", "Display size: small (560px), medium (1120px), large (1680px billboard)").choices(["small", "medium", "large"]))
|
|
705
|
-
.option("--color <hex>", "Background color hex — omit unless it encodes a role used consistently on this canvas; never pastels")
|
|
706
|
-
.option("--x <n>", "X position", "100")
|
|
707
|
-
.option("--y <n>", "Y position", "100")
|
|
708
|
-
.action(async (canvasId, opts) => {
|
|
660
|
+
// --- Text element (wire type `richtext`) ---
|
|
661
|
+
//
|
|
662
|
+
// The canvas has ONE free-form text element, called "Text", and it is a richtext
|
|
663
|
+
// node. The old `text` node kind (the "Heading": plain string + fontSize) is LEGACY:
|
|
664
|
+
// existing ones still render, move and delete, but nothing creates them any more. A
|
|
665
|
+
// Text element with no background tint and `# Foo` as its content IS a heading, which
|
|
666
|
+
// is what made the old kind redundant.
|
|
667
|
+
//
|
|
668
|
+
// `add-text` and `add-richtext` are the same command (add-richtext is the deprecated
|
|
669
|
+
// alias); both post `addRichtextNode`. The old `add-text` flags (--text, --size
|
|
670
|
+
// heading|paragraph, --color normal|muted|highlighted) are gone on purpose — an old
|
|
671
|
+
// invocation must fail loudly rather than be silently reinterpreted.
|
|
672
|
+
const addTextElementAction = async (canvasId, opts) => {
|
|
709
673
|
const cfg = resolveConfig(program.opts());
|
|
710
674
|
const api = new ApiClient(cfg.serverUrl, cfg.token);
|
|
711
675
|
let content;
|
|
@@ -719,12 +683,30 @@ Examples:
|
|
|
719
683
|
handleError(new ValidationError("Either --content or --content-file is required"), cfg.json);
|
|
720
684
|
return;
|
|
721
685
|
}
|
|
686
|
+
// --color is a background tint HEX. Reject anything else so the retired heading
|
|
687
|
+
// flags (--color normal|muted|highlighted) fail loudly instead of being posted
|
|
688
|
+
// through as a nonsense colorHex.
|
|
689
|
+
//
|
|
690
|
+
// This must accept exactly what the server accepts — #RGB or #RRGGBB, per
|
|
691
|
+
// HEX_COLOR_REGEX in convex/canvas.ts. The create mutation does NOT re-validate
|
|
692
|
+
// colorHex (only the update paths do), so anything we let through is stored raw:
|
|
693
|
+
// a hex without the leading `#` is not a valid CSS color, so the tint would
|
|
694
|
+
// silently not render AND the node would then fail every later style update.
|
|
695
|
+
// Hence: allow a bare hex for convenience, but normalize the `#` on before POST.
|
|
696
|
+
let colorHex;
|
|
697
|
+
if (opts.color) {
|
|
698
|
+
if (!/^#?(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(opts.color)) {
|
|
699
|
+
handleError(new ValidationError(`--color must be a 3- or 6-digit hex color (e.g. '#c2410c'), got '${opts.color}'. There are no named color variants — a text element has no background unless you pass a hex.`), cfg.json);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
colorHex = opts.color.startsWith("#") ? opts.color : `#${opts.color}`;
|
|
703
|
+
}
|
|
722
704
|
try {
|
|
723
705
|
const data = await api.post(`/api/canvas/${canvasId}`, {
|
|
724
706
|
action: "addRichtextNode",
|
|
725
707
|
content,
|
|
726
708
|
size: opts.size,
|
|
727
|
-
colorHex
|
|
709
|
+
colorHex,
|
|
728
710
|
positionX: parseInt(opts.x, 10),
|
|
729
711
|
positionY: parseInt(opts.y, 10),
|
|
730
712
|
});
|
|
@@ -733,13 +715,32 @@ Examples:
|
|
|
733
715
|
}
|
|
734
716
|
else {
|
|
735
717
|
const heightInfo = data.estimatedHeight ? ` — estimated height: ${data.estimatedHeight}px` : '';
|
|
736
|
-
console.log(`Added
|
|
718
|
+
console.log(`Added text element to canvas at (${opts.x}, ${opts.y})${heightInfo}`);
|
|
737
719
|
}
|
|
738
720
|
}
|
|
739
721
|
catch (error) {
|
|
740
722
|
handleError(error, cfg.json);
|
|
741
723
|
}
|
|
742
|
-
}
|
|
724
|
+
};
|
|
725
|
+
const defineAddTextCommand = (name, description) => canvas
|
|
726
|
+
.command(name)
|
|
727
|
+
.description(description)
|
|
728
|
+
.argument("<canvasId>", "Canvas ID")
|
|
729
|
+
.option("--content <content>", "Text content inline (markdown — headings, bold, links; plain display IDs only, no mention syntax)")
|
|
730
|
+
.option("--content-file <path>", "Read text content (markdown) from a file")
|
|
731
|
+
.addOption(new Option("--size <size>", "Display size: small (560px), medium (1120px), large (1680px billboard)").choices(["small", "medium", "large"]))
|
|
732
|
+
.option("--color <hex>", "Background tint hex — DEFAULT IS NO BACKGROUND; omit unless the tint encodes a role used consistently on this canvas; never pastels")
|
|
733
|
+
.option("--x <n>", "X position", "100")
|
|
734
|
+
.option("--y <n>", "Y position", "100")
|
|
735
|
+
.addHelpText("after", `
|
|
736
|
+
Examples:
|
|
737
|
+
$ cnotes canvas add-text <canvasId> --content '# Q1 Goals' # a heading: markdown h1, untinted
|
|
738
|
+
$ cnotes canvas add-text <canvasId> --content-file ./banner.md --size medium # orientation banner
|
|
739
|
+
$ cnotes canvas add-text <canvasId> --content 'Read left to right.' --color '#c2410c'
|
|
740
|
+
`)
|
|
741
|
+
.action(addTextElementAction);
|
|
742
|
+
defineAddTextCommand("add-text", "Add a Text element to a canvas — free-form rich text placed on the canvas (markdown: headings, emphasis, images), with an optional background tint (none by default). A heading is just `--content '# Title'`. Keep it card-sized (≤ ~3 sentences): text elements are unversioned and unsearchable, so knowledge worth keeping goes in a typed note. Plain markdown only: NO [NOTE-X](relationship:...) mention syntax (corrupts the card)");
|
|
743
|
+
defineAddTextCommand("add-richtext", "[DEPRECATED — use `add-text`] Alias of `add-text`: adds the same Text element (richtext) with the same flags. Kept for existing scripts; prefer `add-text`.");
|
|
743
744
|
canvas
|
|
744
745
|
.command("add-section")
|
|
745
746
|
.description("Add a section frame — a named background region (Miro-style). Whatever sits inside moves with the frame when dragged; notes inside stay individually draggable. Mints a SECTION-<n> id: mention it from notes as [[SECTION-<n>]] to deep-link readers to that region, so name frames like places (\"Shaping\", \"Open Questions\"), not sentences. With --notes the frame is created WITH those notes laid out inside it (collision-aware, no coordinate math — the preferred way to build a populated section).")
|
|
@@ -1116,7 +1117,7 @@ Placement (relative to nodes already on the canvas):
|
|
|
1116
1117
|
.command("bulk-move")
|
|
1117
1118
|
.description("Move multiple nodes to new positions in one operation")
|
|
1118
1119
|
.argument("<canvasId>", "Canvas ID (used for routing/auth)")
|
|
1119
|
-
.requiredOption("--moves <json>", "JSON array of {nodeId, nodeType, x, y} objects (nodeType: note|text|list|canvas|richtext|section)")
|
|
1120
|
+
.requiredOption("--moves <json>", "JSON array of {nodeId, nodeType, x, y} objects (nodeType: note|text|list|canvas|richtext|section; `text` is legacy — old heading nodes, no longer creatable)")
|
|
1120
1121
|
.action(async (canvasId, opts) => {
|
|
1121
1122
|
const cfg = resolveConfig(program.opts());
|
|
1122
1123
|
const api = new ApiClient(cfg.serverUrl, cfg.token);
|
|
@@ -1125,6 +1126,8 @@ Placement (relative to nodes already on the canvas):
|
|
|
1125
1126
|
if (!Array.isArray(items) || items.length === 0) {
|
|
1126
1127
|
throw new ValidationError("--moves must be a non-empty JSON array");
|
|
1127
1128
|
}
|
|
1129
|
+
// `text` is a LEGACY kind (the old "Heading" node): it can no longer be created,
|
|
1130
|
+
// but existing ones must stay movable and deletable, so it stays valid here.
|
|
1128
1131
|
const validNodeTypes = new Set(["note", "text", "list", "canvas", "richtext", "section"]);
|
|
1129
1132
|
const moves = items.map((item, i) => {
|
|
1130
1133
|
const positionX = Number(item.x);
|
|
@@ -1310,6 +1313,73 @@ Placement (relative to nodes already on the canvas):
|
|
|
1310
1313
|
handleError(error, cfg.json);
|
|
1311
1314
|
}
|
|
1312
1315
|
});
|
|
1316
|
+
canvas
|
|
1317
|
+
.command("update-section")
|
|
1318
|
+
.description("Resize, rename, move, or recolor an existing section frame IN PLACE, keeping its SECTION-<n> id. Use this to grow a frame around new content — never delete + re-add, which mints a NEW id (SECTION-51 becomes SECTION-57) and breaks every [[SECTION-51]] mention pointing at it.")
|
|
1319
|
+
.argument("<canvasId>", "Canvas ID")
|
|
1320
|
+
.requiredOption("--section <id>", "Section to update — SECTION-<n> display ID or a raw node ID")
|
|
1321
|
+
.option("--name <name>", "New frame title (title case)")
|
|
1322
|
+
.option("--x <n>", "New X position (top-left)")
|
|
1323
|
+
.option("--y <n>", "New Y position (top-left)")
|
|
1324
|
+
.option("--width <n>", "New frame width in px")
|
|
1325
|
+
.option("--height <n>", "New frame height in px")
|
|
1326
|
+
.option("--color <hex>", "New frame tint hex")
|
|
1327
|
+
.option("--clear-color", "Reset the frame tint to the default")
|
|
1328
|
+
.addHelpText("after", `
|
|
1329
|
+
Examples:
|
|
1330
|
+
# Grow a frame to fit content that has spilled out of it
|
|
1331
|
+
$ cnotes canvas update-section CANVAS-250 --section SECTION-51 --height 1800
|
|
1332
|
+
|
|
1333
|
+
# Rename without touching the id or anything inside it
|
|
1334
|
+
$ cnotes canvas update-section CANVAS-250 --section SECTION-51 --name "Open Questions"
|
|
1335
|
+
`)
|
|
1336
|
+
.action(async (canvasId, opts) => {
|
|
1337
|
+
const cfg = resolveConfig(program.opts());
|
|
1338
|
+
const api = new ApiClient(cfg.serverUrl, cfg.token);
|
|
1339
|
+
try {
|
|
1340
|
+
// Reject non-numeric input here. Number("wide") is NaN, which
|
|
1341
|
+
// JSON.stringify writes as null, so the server would answer "expected
|
|
1342
|
+
// number, received null" about a flag the user typed as a word.
|
|
1343
|
+
const numeric = (flag, raw) => {
|
|
1344
|
+
const n = Number(raw);
|
|
1345
|
+
if (!Number.isFinite(n)) {
|
|
1346
|
+
throw new ValidationError(`--${flag} must be a number (got "${raw}")`);
|
|
1347
|
+
}
|
|
1348
|
+
return n;
|
|
1349
|
+
};
|
|
1350
|
+
const body = {
|
|
1351
|
+
action: "updateSectionNode",
|
|
1352
|
+
nodeId: opts.section,
|
|
1353
|
+
};
|
|
1354
|
+
if (typeof opts.name === "string")
|
|
1355
|
+
body.name = opts.name;
|
|
1356
|
+
if (opts.x !== undefined)
|
|
1357
|
+
body.positionX = numeric("x", opts.x);
|
|
1358
|
+
if (opts.y !== undefined)
|
|
1359
|
+
body.positionY = numeric("y", opts.y);
|
|
1360
|
+
if (opts.width !== undefined)
|
|
1361
|
+
body.width = numeric("width", opts.width);
|
|
1362
|
+
if (opts.height !== undefined)
|
|
1363
|
+
body.height = numeric("height", opts.height);
|
|
1364
|
+
// '' is the server's "clear the tint" sentinel.
|
|
1365
|
+
if (opts.clearColor)
|
|
1366
|
+
body.colorHex = "";
|
|
1367
|
+
else if (typeof opts.color === "string")
|
|
1368
|
+
body.colorHex = opts.color;
|
|
1369
|
+
// workspaceId is what lets the server resolve a CANVAS-<n> handle (the
|
|
1370
|
+
// form every example here uses) rather than demanding a raw Convex id.
|
|
1371
|
+
const data = await api.post(`/api/canvas/${encodeURIComponent(canvasId)}?workspaceId=${encodeURIComponent(cfg.workspaceId)}`, body);
|
|
1372
|
+
if (cfg.json) {
|
|
1373
|
+
outputJson(data);
|
|
1374
|
+
}
|
|
1375
|
+
else {
|
|
1376
|
+
console.log(`Updated section ${opts.section}`);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
catch (error) {
|
|
1380
|
+
handleError(error, cfg.json);
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1313
1383
|
canvas
|
|
1314
1384
|
.command("move-node")
|
|
1315
1385
|
.description("Move a node to a new position on a canvas")
|
|
@@ -1317,7 +1387,8 @@ Placement (relative to nodes already on the canvas):
|
|
|
1317
1387
|
.requiredOption("--node <nodeId>", "Canvas node ID")
|
|
1318
1388
|
.requiredOption("--x <n>", "X position")
|
|
1319
1389
|
.requiredOption("--y <n>", "Y position")
|
|
1320
|
-
|
|
1390
|
+
// `text` is a LEGACY kind (the old "Heading" node) — movable/deletable, not creatable.
|
|
1391
|
+
.addOption(new Option("--type <type>", "Node type (defaults to note; `text` is legacy — old heading nodes, no longer creatable)").choices(["note", "text", "list", "canvas", "richtext", "section"]))
|
|
1321
1392
|
.action(async (canvasId, opts) => {
|
|
1322
1393
|
const cfg = resolveConfig(program.opts());
|
|
1323
1394
|
const api = new ApiClient(cfg.serverUrl, cfg.token);
|