@nodii/dev 0.6.7 → 0.6.8

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 CHANGED
@@ -59,7 +59,7 @@ nodii-dev login [--no-browser] [--scope KEYS]
59
59
  nodii-dev logout
60
60
  nodii-dev whoami # OAuth identity plus the registered agent
61
61
  nodii-dev config show
62
- nodii-dev doctor [--json] # preflight: everything a lane needs, read-only
62
+ nodii-dev doctor [--figma-file KEY] [--json] # preflight: everything a lane needs, read-only
63
63
 
64
64
  nodii-dev api list [--tag TAG] [--json]
65
65
  nodii-dev api OPERATION_ID [--param name=value ...] [--body @file|-|JSON]
@@ -137,6 +137,7 @@ only the lists that differ from Dev's current guideline, and `--dry-run`
137
137
  prints them without creating anything.
138
138
 
139
139
  ```bash
140
+ nodii-dev figma file add FILE_KEY --name TEXT --kind design-system|surfaces|prototype [--module M]
140
141
  nodii-dev figma lock FILE_KEY --title TEXT
141
142
  nodii-dev figma check FILE_KEY
142
143
  nodii-dev figma log-write CHANGE_SET --tool TOOL --nodes NODE[,NODE]
@@ -149,6 +150,17 @@ nodii-dev figma release FILE_KEY
149
150
 
150
151
  ```
151
152
 
153
+ `figma file add` registers a Figma file in Dev so it can be locked; a lane
154
+ can't lock a file Dev doesn't know (`DESIGN_FILE_NOT_FOUND`). Dev first
155
+ reads the file from Figma with its own token. The name must be the file's
156
+ name in Figma: when it isn't, Dev refuses with `DESIGN_FILE_NAME_MISMATCH`
157
+ and the CLI prints the real name to run it again with. Dev also refuses a
158
+ key Figma doesn't know, or a file its Figma account can't see
159
+ (`FIGMA_FILE_NOT_FOUND`, `FIGMA_FILE_NOT_READABLE`: share the file with
160
+ that account). Registering a key Dev already has returns the stored row
161
+ unchanged. A figma.com file link works in place of the key. `figma lock` on
162
+ an unregistered file prints the `figma file add` command to run.
163
+
152
164
  `figma withdraw` moves a change set you hold from `in_review` back to
153
165
  `editing`, as long as no item has been decided (Dev's
154
166
  `withdrawDesignChangeSet`). Dev refuses when the change set doesn't exist
@@ -333,6 +345,7 @@ exits 0 only when every check is `OK`. `--json` returns the same checks as
333
345
  | `machine` | The machine this agent is assigned to and its coordinator. No machine means `lane start` would fail with `MACHINE_REQUIRED`. |
334
346
  | `repo` | Whether the repository in this directory is the agent's home repository or granted to it. Repositories are compared by short name (`nodii-clis`, not `owner/nodii-clis`), as Dev compares them. Dev does not let an OAuth agent read its own grants yet (requested in Dev), so a repository other than the home one is `CANNOT CHECK`. |
335
347
  | `lane_limit` | The agent's active lanes against its lane limit. A full limit is `OK` when a lane on this branch holds the slot. |
348
+ | `figma_file` | Only with `--figma-file KEY` (a key or figma.com link), or `NODII_DEV_FIGMA_FILE`: whether Dev has the brief's Figma file registered. `MISSING` names the `figma file add` command, since `figma lock` would fail with `DESIGN_FILE_NOT_FOUND`. |
336
349
 
337
350
  Doctor may refresh the access token, as any command does. The permission table
338
351
  is kept by hand from Dev's route policy until Dev's OpenAPI names each
package/dist/cli.js CHANGED
@@ -26,6 +26,7 @@ import { heartbeatCurrentLane, postHook, preHook, settingsSnippet, workflowSugge
26
26
  import { setupCommand } from "./setup.js";
27
27
  import { harnessCommand } from "./harness.js";
28
28
  import { doctorCommand } from "./doctor.js";
29
+ import { figmaFileKey, notRegisteredHint } from "./figma.js";
29
30
  import { docsCommand, rulebookCommand } from "./upload.js";
30
31
  import { changeSetCommand, guidelineCommand } from "./guidelines.js";
31
32
  import {
@@ -55,7 +56,8 @@ const HELP = `nodii-dev ${VERSION}
55
56
  Usage: nodii-dev <command> [options] [--json]
56
57
 
57
58
  login | logout | whoami | config show
58
- doctor [--json] # preflight: sign-in, agent, permissions, machine, repo, lane slots
59
+ doctor [--figma-file KEY] [--json] # preflight: sign-in, agent, permissions, machine, repo, lane slots
60
+ # and, given a key (or NODII_DEV_FIGMA_FILE), that Figma file's registration
59
61
  agent register --name NAME | agent heartbeat
60
62
  issues list|show|create|update|claim|release
61
63
  issues transition ISSUE --to STATUS [--reason TEXT] [--dev-check REF]
@@ -69,6 +71,8 @@ Usage: nodii-dev <command> [options] [--json]
69
71
  design changeset list [--entry KEY] [--state STATE] | show ID
70
72
  figma lock|check|log-write|submit|apply|published|abandon|release
71
73
  figma withdraw CHANGE_SET # holder takes back a submit: in_review -> editing
74
+ figma file add FILE_KEY --name TEXT --kind design-system|surfaces|prototype [--module M]
75
+ # register a Figma file in Dev so it can be locked
72
76
  hook claude-figma-pre|claude-figma-post|print-settings
73
77
  setup [--yes|--check] # dry-run by default
74
78
  harness install|update [--include-drafts[=false]] [--adopt PATH,...] [--dry-run]
@@ -288,6 +292,38 @@ export async function figmaWithdraw(id, { request = devRequest } = {}) {
288
292
  }
289
293
  }
290
294
 
295
+ // Dev's refusals of registerDesignFile, said in terms of what to do next.
296
+ const REGISTER_REFUSALS = {
297
+ DESIGN_FILE_NAME_MISMATCH: (key, details, message) =>
298
+ details?.figmaName ? `Figma names ${key} "${details.figmaName}"; run it again with --name "${details.figmaName}".` : message,
299
+ FIGMA_FILE_NOT_FOUND: (key) => `Figma has no file ${key} that Dev's Figma account can see; check the key, or share the file with that account.`,
300
+ FIGMA_FILE_NOT_READABLE: (key) => `Dev's Figma account can't read ${key}; share the file with that account.`,
301
+ };
302
+
303
+ export async function figmaFileAdd(value, flags, { request = devRequest } = {}) {
304
+ if (!value) throw new CliError("USAGE", "figma file add FILE_KEY --name TEXT --kind KIND [--module M]", 2);
305
+ const key = figmaFileKey(value);
306
+ if (flags.module === true) throw new CliError("USAGE", "--module needs a value", 2);
307
+ const body = { key, name: requireFlag(flags, "name"), kind: requireFlag(flags, "kind"), ...(flags.module ? { module: flags.module } : {}) };
308
+ try {
309
+ return await request("POST", "/api/v1/design/files", body);
310
+ } catch (error) {
311
+ const say = REGISTER_REFUSALS[error?.code];
312
+ if (!say) throw error;
313
+ throw new CliError(error.code, say(key, error.details, error.message), error.exitCode ?? 1, error.details);
314
+ }
315
+ }
316
+
317
+ export async function figmaLock(value, title, { request = devRequest } = {}) {
318
+ const key = figmaFileKey(value);
319
+ try {
320
+ return await request("POST", `/api/v1/design/files/${encode(key)}/lock`, { changeSetTitle: title });
321
+ } catch (error) {
322
+ if (error?.code !== "DESIGN_FILE_NOT_FOUND") throw error;
323
+ throw new CliError(error.code, notRegisteredHint(key), error.exitCode ?? 1, error.details);
324
+ }
325
+ }
326
+
291
327
  export async function main(argv = process.argv.slice(2)) {
292
328
  if (argv.length === 1 && ["--version", "-v"].includes(argv[0]))
293
329
  return console.log(VERSION);
@@ -338,7 +374,8 @@ export async function main(argv = process.argv.slice(2)) {
338
374
  if (command === "setup") return emitCommand(await setupCommand(f));
339
375
  if (command === "doctor") {
340
376
  if (action) throw new CliError("USAGE", `doctor takes no arguments, got: ${[action, ...rest].join(" ")}`, 2);
341
- const result = await doctorCommand();
377
+ if (f["figma-file"] === true) throw new CliError("USAGE", "--figma-file needs a file key or figma.com link", 2);
378
+ const result = await doctorCommand(f["figma-file"] ? { figmaFile: f["figma-file"] } : {});
342
379
  emit(result.payload, json, result.human);
343
380
  if (result.exitCode) process.exitCode = result.exitCode;
344
381
  return;
@@ -544,14 +581,12 @@ export async function main(argv = process.argv.slice(2)) {
544
581
  }
545
582
  if (command === "figma") {
546
583
  if (action === "lock")
547
- return emit(
548
- await devRequest(
549
- "POST",
550
- `/api/v1/design/files/${encode(rest[0])}/lock`,
551
- { changeSetTitle: requireFlag(f, "title") },
552
- ),
553
- json,
554
- );
584
+ return emit(await figmaLock(rest[0], requireFlag(f, "title")), json);
585
+ if (action === "file") {
586
+ if (rest[0] !== "add") throw new CliError("USAGE", "figma file add FILE_KEY --name TEXT --kind KIND [--module M]", 2);
587
+ return emit(await figmaFileAdd(rest[1], f), json, (p) =>
588
+ `${p.data.fileKey} is registered in Dev: ${p.data.name} (${p.data.kind}${p.data.module ? `, ${p.data.module}` : ""}).`);
589
+ }
555
590
  if (action === "check") {
556
591
  const c = await readConfig();
557
592
  const result = await devRequest(
package/dist/core.js CHANGED
@@ -4,7 +4,7 @@ import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { homedir, platform } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
 
7
- export const VERSION = "0.6.7";
7
+ export const VERSION = "0.6.8";
8
8
  export const configPath = () =>
9
9
  process.env.NODII_DEV_CONFIG_PATH ??
10
10
  join(homedir(), ".config/nodii-dev/config.json");