@nodii/dev 0.6.1 → 0.6.2
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 +27 -0
- package/dist/api.js +10 -2
- package/dist/cli.js +9 -0
- package/dist/core.js +2 -2
- package/dist/devops-openapi.json +1 -1
- package/dist/guidelines.js +223 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,7 +98,34 @@ nodii-dev heartbeat audit [SERVICE]
|
|
|
98
98
|
nodii-dev design entries [--kind KIND] [--group GROUP] [--q TEXT]
|
|
99
99
|
nodii-dev design entry KEY
|
|
100
100
|
nodii-dev design guide PAGE_TYPE
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Design-system guidelines
|
|
104
|
+
|
|
105
|
+
Edit an entry's guideline through Dev, not with signed scripts. A proposal is
|
|
106
|
+
a guideline change set; a person approves or rejects it in Dev (nobody decides
|
|
107
|
+
their own), and the approved edit becomes a design-system PR.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
nodii-dev design guideline list [--drafted] [--kind KIND] [--q TEXT] [--all]
|
|
111
|
+
nodii-dev design guideline show ENTRY > ENTRY.md # the editable Markdown form
|
|
112
|
+
nodii-dev design guideline propose ENTRY --file ENTRY.md [--summary TEXT] [--dry-run]
|
|
113
|
+
nodii-dev design changeset list [--entry KEY] [--state in_review] [--limit N]
|
|
114
|
+
nodii-dev design changeset show GCS-001
|
|
115
|
+
```
|
|
101
116
|
|
|
117
|
+
The file has one `## <list>` section per statement list (`whenToUse`,
|
|
118
|
+
`whenNotToUse`, `dos`, `donts`, and for an active guideline `anatomy`,
|
|
119
|
+
`states.states`, `states.loading`, `states.empty`, `states.error`, `copy`,
|
|
120
|
+
`composition`, `data.notes`), one `- ` bullet per item, and `(drafted)` after
|
|
121
|
+
the list name when the text still awaits a real source. A line that is an
|
|
122
|
+
HTML comment is ignored (`<!--` inside an item stays in its text), and a line
|
|
123
|
+
break inside an item reads back as a space. The `#` title, as `show` prints it,
|
|
124
|
+
names the entry: `propose` refuses a file titled for another one. `propose` sends
|
|
125
|
+
only the lists that differ from Dev's current guideline, and `--dry-run`
|
|
126
|
+
prints them without creating anything.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
102
129
|
nodii-dev figma lock FILE_KEY --title TEXT
|
|
103
130
|
nodii-dev figma check FILE_KEY
|
|
104
131
|
nodii-dev figma log-write CHANGE_SET --tool TOOL --nodes NODE[,NODE]
|
package/dist/api.js
CHANGED
|
@@ -100,7 +100,7 @@ export const GROUPS = {
|
|
|
100
100
|
decisions: "Decisions", drift: "Drift", requests: "Requests", pipelines: "Pipelines", slices: "Slices", "sql-lookups": "SqlLookups",
|
|
101
101
|
runners: "Runners", routing: "Routing", usage: "Usage", audit: "AuditLog", reconciliation: "Reconciliation", cron: "Cron", health: "Health",
|
|
102
102
|
composite: "Composite", "service-edges": "ServiceEdges", lanes: "Lanes",
|
|
103
|
-
swaps: "Swaps", ideas: "Ideas", terminology: "Terminology",
|
|
103
|
+
swaps: "Swaps", ideas: "Ideas", terminology: "Terminology", credentials: "Credentials",
|
|
104
104
|
rulebook: "ad-documents", "ad-decisions": "ad-decisions", domains: "ad-domains", standardizations: "standardizations",
|
|
105
105
|
archive: "archive", harness: "harness",
|
|
106
106
|
};
|
|
@@ -154,11 +154,19 @@ export const ALIASES = {
|
|
|
154
154
|
"terminology:list": "listTerminology", "terminology:show": "getTerminologyTerm", "terminology:create": "createTerminologyTerm", "terminology:update": "updateTerminologyTerm",
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
+
// Decisions a person makes in Dev (operator authority): nodii-dev never sends them.
|
|
158
|
+
export const PERSON_ONLY = new Set(["approveDesignGuidelineChangeSet", "rejectDesignGuidelineChangeSet", "mergeDesignRelease"]);
|
|
159
|
+
export function refusePersonOnly(operationId) {
|
|
160
|
+
if (PERSON_ONLY.has(operationId))
|
|
161
|
+
throw new CliError("PERSON_ONLY", `${operationId} is a person's decision in Dev; nodii-dev does not send it.`, 2);
|
|
162
|
+
}
|
|
163
|
+
|
|
157
164
|
export function findFirstClass(operations, group, action) {
|
|
158
165
|
const aliased = ALIASES[`${group}:${action}`];
|
|
159
166
|
if (aliased) return operations.find(x => x.operationId === aliased);
|
|
160
167
|
const tags = Array.isArray(GROUPS[group]) ? GROUPS[group] : [GROUPS[group]];
|
|
161
|
-
|
|
168
|
+
// A person-only operation is never picked by name, so a guessed verb cannot reach it.
|
|
169
|
+
const candidates = operations.filter(x => !PERSON_ONLY.has(x.operationId) && x.tags.some(t => tags.includes(t)));
|
|
162
170
|
const normalized = action?.replace(/-([a-z])/g, (_, c) => c.toUpperCase()).toLowerCase();
|
|
163
171
|
return candidates.find(x => x.operationId.toLowerCase() === normalized || x.operationId.toLowerCase().endsWith(normalized));
|
|
164
172
|
}
|
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 { docsCommand, rulebookCommand } from "./upload.js";
|
|
29
|
+
import { changeSetCommand, guidelineCommand } from "./guidelines.js";
|
|
29
30
|
import {
|
|
30
31
|
ALIASES,
|
|
31
32
|
GROUPS,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
callOperation,
|
|
34
35
|
findFirstClass,
|
|
35
36
|
flagsToOperation,
|
|
37
|
+
refusePersonOnly,
|
|
36
38
|
loadOpenApi,
|
|
37
39
|
operationsFrom,
|
|
38
40
|
parseParams,
|
|
@@ -58,6 +60,9 @@ Usage: nodii-dev <command> [options] [--json]
|
|
|
58
60
|
drift file | request file
|
|
59
61
|
decisions list|get|search
|
|
60
62
|
design entries|entry|guide
|
|
63
|
+
design guideline list [--drafted] [--all] | show ENTRY
|
|
64
|
+
design guideline propose ENTRY --file FILE.md [--summary TEXT] [--dry-run]
|
|
65
|
+
design changeset list [--entry KEY] [--state STATE] | show ID
|
|
61
66
|
figma lock|check|log-write|submit|apply|published|abandon|release
|
|
62
67
|
hook claude-figma-pre|claude-figma-post|print-settings
|
|
63
68
|
setup [--yes|--check] # dry-run by default
|
|
@@ -237,6 +242,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
237
242
|
if (!action) throw new CliError("USAGE", "api needs an operationId or list", 2);
|
|
238
243
|
const entry = operations.find((x) => x.operationId === action);
|
|
239
244
|
if (!entry) throw new CliError("UNKNOWN_OPERATION", `No OpenAPI operationId: ${action}`, 2);
|
|
245
|
+
refusePersonOnly(entry.operationId);
|
|
240
246
|
const parsed = await readBody(f.body);
|
|
241
247
|
const request = buildOperationRequest(entry, parseParams(f.param), parsed?.value);
|
|
242
248
|
return emit(await devRawRequest(request.method, request.path, parsed?.text), json);
|
|
@@ -270,6 +276,9 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
270
276
|
}
|
|
271
277
|
if (command === "docs") return emitCommand(await docsCommand(action, rest, f));
|
|
272
278
|
if (command === "rulebook" && ["list", "show", "diff"].includes(action)) return emitCommand(await rulebookCommand(action, rest, f));
|
|
279
|
+
// Guideline change sets: approving or rejecting one is a person's action in Dev.
|
|
280
|
+
if (command === "design" && action === "guideline") return emitCommand(await guidelineCommand(rest[0], rest.slice(1), f));
|
|
281
|
+
if (command === "design" && action === "changeset") return emitCommand(await changeSetCommand(rest[0], rest.slice(1), f));
|
|
273
282
|
if (command === "lane") return emitCommand(await laneCommand(action, rest, f));
|
|
274
283
|
if (command === "next") return emitCommand(await nextCommand(action, f));
|
|
275
284
|
if (command === "built") return emitCommand(await builtCommand(action, rest, f));
|
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
|
+
export const VERSION = "0.6.2";
|
|
8
8
|
export const configPath = () =>
|
|
9
9
|
process.env.NODII_DEV_CONFIG_PATH ??
|
|
10
10
|
join(homedir(), ".config/nodii-dev/config.json");
|
|
@@ -162,7 +162,7 @@ export async function checkLogin() {
|
|
|
162
162
|
export const encode = (value) => encodeURIComponent(value);
|
|
163
163
|
// Switches never take the next token as their value, so
|
|
164
164
|
// `docs upload --wait rulebook/` keeps rulebook/ as a path.
|
|
165
|
-
const SWITCHES = new Set(["json", "wait", "dry-run", "check", "all", "fleet", "help", "yes", "mine", "no-browser", "include-drafts"]);
|
|
165
|
+
const SWITCHES = new Set(["json", "wait", "dry-run", "check", "all", "fleet", "help", "yes", "mine", "no-browser", "include-drafts", "drafted"]);
|
|
166
166
|
export function parseArgs(argv) {
|
|
167
167
|
const flags = {};
|
|
168
168
|
const args = [];
|