@nodii/dev 0.6.13 → 0.6.15

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/figma.js CHANGED
@@ -173,8 +173,45 @@ export function outOfScopeText(message, details, id = details?.changeSetId ?? "C
173
173
  ].join("\n");
174
174
  }
175
175
 
176
+ /** The rows of a conformance result, as `design check` and a refused submit print them. */
177
+ export function conformanceLines(r) {
178
+ const lines = [];
179
+ for (const f of r.findings ?? []) lines.push(` ${f.nodeId}\t${f.check}\t${f.detail}`);
180
+ if (r.staleOverrides?.length) {
181
+ lines.push(`${r.staleOverrides.length} stale override(s), equal to the main (not failures; clear them with Reset):`);
182
+ for (const f of r.staleOverrides) lines.push(` ${f.nodeId}\tstale\t${f.detail}`);
183
+ }
184
+ if (r.libraryUpdatePending?.length) {
185
+ lines.push(`${r.libraryUpdatePending.length} node(s) behind a library republish (not failures; accept the library update in this file, MW6-17):`);
186
+ for (const f of r.libraryUpdatePending) lines.push(` ${f.nodeId}\t${f.check ?? "libraryUpdatePending"}\t${f.detail}`);
187
+ }
188
+ // Warnings never refuse: STALE_FIGMA_VERSION is one (Dev issue 92, until
189
+ // Dev issue 107). With staleVersion, its wait is printed below instead.
190
+ const warnings = (r.warnings ?? []).filter((f) => !(r.staleVersion && f.check === "STALE_FIGMA_VERSION"));
191
+ if (warnings.length) {
192
+ lines.push(`${warnings.length} warning(s) (not refusals):`);
193
+ for (const f of warnings) lines.push(` ${f.nodeId}\t${f.check}\t${f.detail}`);
194
+ }
195
+ const v = r.staleVersion;
196
+ if (v) {
197
+ lines.push(`STALE_FIGMA_VERSION (a warning, not a refusal): version ${v.figmaVersion}${v.figmaVersionAt ? ` (${v.figmaVersionAt})` : " (not among Figma's recent versions)"} predates this lane's last write at ${v.lastWriteAt}.`);
198
+ lines.push(v.retryAfter
199
+ ? ` Figma has cut no version since (latest ${v.latestVersion ?? "none"}${v.latestVersionAt ? ` at ${v.latestVersionAt}` : ""}). Retry after ${v.retryAfter}, or ask the coordinator to have the operator File > Save to version history.`
200
+ : ` A newer version already holds the write: submit with --figma-version ${v.latestVersion}${v.latestVersionAt ? ` (${v.latestVersionAt})` : ""}.`);
201
+ }
202
+ return lines;
203
+ }
204
+
205
+ /** Dev's DS_CONFORMANCE_FAILED (DEC-0034): every finding, its warnings, and the wait on a stale version. */
206
+ export function conformanceRefusalText(message, details, id = "CHANGE_SET") {
207
+ const n = details?.findings?.length ?? 0;
208
+ return [message, `${n} finding(s); after fixing, re-run Dev's gate without submitting: nodii-dev design check --change-set ${id} --file SUBMIT.json`, ...conformanceLines(details ?? {})].join("\n");
209
+ }
210
+
176
211
  // Keep Dev's code and message; add what to do next.
177
212
  function scopeRefusal(error, id) {
213
+ if (error?.code === "DS_CONFORMANCE_FAILED")
214
+ return new CliError(error.code, conformanceRefusalText(error.message, error.details, id), error.exitCode ?? 1, error.details);
178
215
  if (error?.code === "SCOPE_CONFLICT")
179
216
  return new CliError(error.code, conflictText(error.message, error.details), error.exitCode ?? 1, error.details);
180
217
  if (error?.code === "WRITE_OUT_OF_SCOPE")
@@ -242,9 +279,48 @@ export async function figmaScopeAdd(id, scopes, { request = devRequest } = {}) {
242
279
  return changeSetCall(id, request)("POST", `/api/v1/design/change-sets/${encode(id)}/scopes`, { scopes });
243
280
  }
244
281
 
282
+ /**
283
+ * Narrows a held set to exactly these scopes (Dev issue 104,
284
+ * setDesignChangeSetScopes); the rest is released for other sets. Each must
285
+ * sit inside what the set holds: the whole file holds everything, a page its
286
+ * components and creates.
287
+ */
288
+ export async function figmaScopeSet(id, scopes, { request = devRequest } = {}) {
289
+ if (!id || !scopes.length) throw new CliError("USAGE", `figma scope set CHANGE_SET ${SCOPE_USAGE} [--scope ...]`, 2);
290
+ try {
291
+ return await request("PUT", `/api/v1/design/change-sets/${encode(id)}/scopes`, { scopes });
292
+ } catch (error) {
293
+ if (error?.code === "SCOPE_NOT_NARROWER")
294
+ throw new CliError(error.code, `${error.message}\nscope set only narrows; to claim more, run nodii-dev figma scope add ${id} --scope ...`, error.exitCode ?? 1, error.details);
295
+ if (error?.code === "WRITE_OUT_OF_SCOPE")
296
+ throw new CliError(
297
+ error.code,
298
+ [
299
+ error.message,
300
+ ...(error.details?.nodeIds?.length ? [`Would fall outside: ${error.details.nodeIds.join(", ")}`] : []),
301
+ `Keep a scope that holds them (styles and variables need --scope foundations), or revert those nodes to how they were at ${id}'s base version.`,
302
+ ].join("\n"),
303
+ error.exitCode ?? 1,
304
+ error.details,
305
+ );
306
+ throw scopeRefusal(error, id) ?? error;
307
+ }
308
+ }
309
+
310
+ /** What a narrowing left the set holding, and what it released. */
311
+ export const figmaScopeSetText = (id, data) =>
312
+ [
313
+ `${id} holds ${data?.scopes?.length ?? 0} scope(s): ${(data?.scopes ?? []).map(scopeText).join(", ") || "none"}`,
314
+ ...(data?.released?.length ? [`Released for other sets: ${data.released.map(scopeText).join(", ")}`] : []),
315
+ ].join("\n");
316
+
245
317
  export const figmaSubmit = (id, payload, { request = devRequest } = {}) =>
246
318
  changeSetCall(id, request)("POST", `/api/v1/design/change-sets/${encode(id)}/submit`, payload);
247
319
 
320
+ /** checkDesignConformance: the submit gate's dry run on a change set; changes no state. Body: { figmaVersion?, items? }. */
321
+ export const figmaConformance = (id, body = {}, { request = devRequest } = {}) =>
322
+ changeSetCall(id, request)("POST", `/api/v1/design/change-sets/${encode(id)}/conformance`, body);
323
+
248
324
  export const figmaLogWrite = (id, tool, nodeIds, { request = devRequest } = {}) =>
249
325
  changeSetCall(id, request)("POST", `/api/v1/design/change-sets/${encode(id)}/writes`, { tool, nodeIds });
250
326