canicode 0.12.0 → 0.12.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/dist/cli/index.js +436 -51
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +119 -27
- package/dist/index.js +259 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +273 -19
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
- package/skills/canicode-roundtrip/SKILL.md +62 -8
- package/skills/canicode-roundtrip/helpers-bootstrap.js +1 -1
- package/skills/canicode-roundtrip/helpers-installer.js +2 -2
- package/skills/canicode-roundtrip/helpers.js +41 -1
- package/skills/cursor/canicode-roundtrip/SKILL.md +62 -8
- package/skills/cursor/canicode-roundtrip/helpers-bootstrap.js +1 -1
- package/skills/cursor/canicode-roundtrip/helpers-installer.js +2 -2
- package/skills/cursor/canicode-roundtrip/helpers.js +41 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { GetFileResponse, Node } from '@figma/rest-api-spec';
|
|
3
3
|
|
|
4
|
-
var version = "0.12.
|
|
4
|
+
var version = "0.12.2";
|
|
5
5
|
|
|
6
6
|
declare const SeveritySchema: z.ZodEnum<{
|
|
7
7
|
blocking: "blocking";
|
|
@@ -377,6 +377,35 @@ type Category = z.infer<typeof CategorySchema>;
|
|
|
377
377
|
declare const CATEGORIES: ("pixel-critical" | "responsive-critical" | "code-quality" | "token-management" | "semantic" | "interaction")[];
|
|
378
378
|
declare const CATEGORY_LABELS: Record<Category, string>;
|
|
379
379
|
|
|
380
|
+
declare const AcknowledgmentSchema: z.ZodObject<{
|
|
381
|
+
nodeId: z.ZodString;
|
|
382
|
+
ruleId: z.ZodString;
|
|
383
|
+
intent: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
384
|
+
kind: z.ZodDefault<z.ZodLiteral<"property">>;
|
|
385
|
+
field: z.ZodString;
|
|
386
|
+
value: z.ZodUnknown;
|
|
387
|
+
scope: z.ZodEnum<{
|
|
388
|
+
instance: "instance";
|
|
389
|
+
definition: "definition";
|
|
390
|
+
}>;
|
|
391
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
392
|
+
kind: z.ZodLiteral<"rule-opt-out">;
|
|
393
|
+
ruleId: z.ZodString;
|
|
394
|
+
}, z.core.$strict>], "kind">>>;
|
|
395
|
+
sceneWriteOutcome: z.ZodOptional<z.ZodObject<{
|
|
396
|
+
result: z.ZodEnum<{
|
|
397
|
+
unknown: "unknown";
|
|
398
|
+
succeeded: "succeeded";
|
|
399
|
+
"silent-ignored": "silent-ignored";
|
|
400
|
+
"api-rejected": "api-rejected";
|
|
401
|
+
"user-declined-propagation": "user-declined-propagation";
|
|
402
|
+
}>;
|
|
403
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
404
|
+
}, z.core.$strip>>;
|
|
405
|
+
codegenDirective: z.ZodOptional<z.ZodString>;
|
|
406
|
+
}, z.core.$strip>;
|
|
407
|
+
type Acknowledgment = z.infer<typeof AcknowledgmentSchema>;
|
|
408
|
+
|
|
380
409
|
/**
|
|
381
410
|
* Rule definition - static metadata (does not change)
|
|
382
411
|
*/
|
|
@@ -451,6 +480,20 @@ interface RuleContext {
|
|
|
451
480
|
* sync with `AnalysisNode.type` without a translation layer.
|
|
452
481
|
*/
|
|
453
482
|
rootNodeType: string;
|
|
483
|
+
/**
|
|
484
|
+
* ADR-022: lookup canicode-authored acknowledgments by `(nodeId, ruleId)`.
|
|
485
|
+
* The rule engine builds this from `RuleEngineOptions.acknowledgments` and
|
|
486
|
+
* exposes it to every rule so individual rules can short-circuit (suppress
|
|
487
|
+
* emission) when an acknowledgment carries a rule-opt-out intent. The
|
|
488
|
+
* existing density-half-weight semantic (#371) is unchanged — that path
|
|
489
|
+
* still flags `acknowledged: true` post-emit and is independent of this
|
|
490
|
+
* helper.
|
|
491
|
+
*
|
|
492
|
+
* Returns the matching acknowledgment, or `undefined` when there is no
|
|
493
|
+
* acknowledgment for the pair. Node ids are normalised by the engine, so
|
|
494
|
+
* callers can pass URL-style or Plugin-API-style ids interchangeably.
|
|
495
|
+
*/
|
|
496
|
+
findAcknowledgment: (nodeId: string, ruleId: string) => Acknowledgment | undefined;
|
|
454
497
|
}
|
|
455
498
|
/**
|
|
456
499
|
* Get or initialize per-analysis state for a rule.
|
|
@@ -701,6 +744,10 @@ declare const McpAnalyzeResponseSchema: z.ZodObject<{
|
|
|
701
744
|
}, z.core.$strip>>;
|
|
702
745
|
summary: z.ZodString;
|
|
703
746
|
failedRules: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
747
|
+
codeConnectCoverage: z.ZodOptional<z.ZodObject<{
|
|
748
|
+
mapped: z.ZodNumber;
|
|
749
|
+
total: z.ZodNumber;
|
|
750
|
+
}, z.core.$strip>>;
|
|
704
751
|
}, z.core.$strip>;
|
|
705
752
|
type McpAnalyzeResponse = z.infer<typeof McpAnalyzeResponseSchema>;
|
|
706
753
|
|
|
@@ -1123,31 +1170,6 @@ declare const GotchaSurveySchema: z.ZodObject<{
|
|
|
1123
1170
|
}, z.core.$strip>;
|
|
1124
1171
|
type GotchaSurvey = z.infer<typeof GotchaSurveySchema>;
|
|
1125
1172
|
|
|
1126
|
-
declare const AcknowledgmentSchema: z.ZodObject<{
|
|
1127
|
-
nodeId: z.ZodString;
|
|
1128
|
-
ruleId: z.ZodString;
|
|
1129
|
-
intent: z.ZodOptional<z.ZodObject<{
|
|
1130
|
-
field: z.ZodString;
|
|
1131
|
-
value: z.ZodUnknown;
|
|
1132
|
-
scope: z.ZodEnum<{
|
|
1133
|
-
instance: "instance";
|
|
1134
|
-
definition: "definition";
|
|
1135
|
-
}>;
|
|
1136
|
-
}, z.core.$strip>>;
|
|
1137
|
-
sceneWriteOutcome: z.ZodOptional<z.ZodObject<{
|
|
1138
|
-
result: z.ZodEnum<{
|
|
1139
|
-
unknown: "unknown";
|
|
1140
|
-
succeeded: "succeeded";
|
|
1141
|
-
"silent-ignored": "silent-ignored";
|
|
1142
|
-
"api-rejected": "api-rejected";
|
|
1143
|
-
"user-declined-propagation": "user-declined-propagation";
|
|
1144
|
-
}>;
|
|
1145
|
-
reason: z.ZodOptional<z.ZodString>;
|
|
1146
|
-
}, z.core.$strip>>;
|
|
1147
|
-
codegenDirective: z.ZodOptional<z.ZodString>;
|
|
1148
|
-
}, z.core.$strip>;
|
|
1149
|
-
type Acknowledgment = z.infer<typeof AcknowledgmentSchema>;
|
|
1150
|
-
|
|
1151
1173
|
/**
|
|
1152
1174
|
* Analysis issue with calculated score and metadata.
|
|
1153
1175
|
*
|
|
@@ -1234,6 +1256,7 @@ declare class RuleEngine {
|
|
|
1234
1256
|
private excludeNamePattern;
|
|
1235
1257
|
private excludeNodeTypes;
|
|
1236
1258
|
private acknowledgments;
|
|
1259
|
+
private acknowledgmentsByKey;
|
|
1237
1260
|
private scopeOverride;
|
|
1238
1261
|
constructor(options?: RuleEngineOptions);
|
|
1239
1262
|
/**
|
|
@@ -1355,6 +1378,50 @@ declare function getCategoryLabel(category: Category): string;
|
|
|
1355
1378
|
* Get severity label for display
|
|
1356
1379
|
*/
|
|
1357
1380
|
declare function getSeverityLabel(severity: Severity): string;
|
|
1381
|
+
/**
|
|
1382
|
+
* Code Connect mapping coverage metric (#526 sub-task 3). Surfaces how many of
|
|
1383
|
+
* the file's components are already wired to a code path via a `figma.connect`
|
|
1384
|
+
* declaration. Optional — only computed when the consuming repo has Code
|
|
1385
|
+
* Connect set up (figma.config.json present).
|
|
1386
|
+
*/
|
|
1387
|
+
interface CodeConnectCoverage {
|
|
1388
|
+
/** Number of components in this file that have a Code Connect mapping. */
|
|
1389
|
+
mapped: number;
|
|
1390
|
+
/** Total components in this file (numerator + unmapped). */
|
|
1391
|
+
total: number;
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Format the coverage line that ships in the analyze summary. Kept exported
|
|
1395
|
+
* so consumers (HTML report, MCP wrapper) render the same wording.
|
|
1396
|
+
*/
|
|
1397
|
+
declare function formatCodeConnectCoverageLine(coverage: CodeConnectCoverage): string;
|
|
1398
|
+
/**
|
|
1399
|
+
* ADR-022 / #526 sub-task 2: standalone analyze hint.
|
|
1400
|
+
*
|
|
1401
|
+
* `canicode analyze` and the MCP `analyze` tool cannot read Figma annotations
|
|
1402
|
+
* directly — the REST `annotations` field is private beta. When the
|
|
1403
|
+
* `unmapped-component` rule fires AND the caller did not supply an
|
|
1404
|
+
* acknowledgments list, surface a one-line hint telling the user that any
|
|
1405
|
+
* roundtrip-recorded opt-outs are invisible to standalone analyze and that
|
|
1406
|
+
* `/canicode-roundtrip` will apply them.
|
|
1407
|
+
*
|
|
1408
|
+
* Returns `null` when:
|
|
1409
|
+
* - no `unmapped-component` issue fired (nothing to explain), or
|
|
1410
|
+
* - acknowledgments were supplied (roundtrip mode — opt-outs already applied
|
|
1411
|
+
* and any remaining issues are real). `acknowledgmentsProvided` MUST track
|
|
1412
|
+
* whether the caller passed an ack channel at all, NOT whether the array
|
|
1413
|
+
* was non-empty: a roundtrip on a clean file legitimately passes `[]` and
|
|
1414
|
+
* the hint would be misleading there.
|
|
1415
|
+
*
|
|
1416
|
+
* The hint is informational; it never moves the score, never bumps severity,
|
|
1417
|
+
* and is independent of the count of `unmapped-component` issues.
|
|
1418
|
+
*/
|
|
1419
|
+
declare const ROUNDTRIP_OPT_OUT_HINT = "Some components may carry roundtrip-recorded opt-outs that this standalone analyze cannot see (Figma REST annotations field is in private beta). Run /canicode-roundtrip to apply opt-outs.";
|
|
1420
|
+
declare function formatRoundtripOptOutHintLine(issues: ReadonlyArray<{
|
|
1421
|
+
violation: {
|
|
1422
|
+
ruleId: string;
|
|
1423
|
+
};
|
|
1424
|
+
}>, acknowledgmentsProvided: boolean): string | null;
|
|
1358
1425
|
/**
|
|
1359
1426
|
* Build a JSON-serializable analysis result summary.
|
|
1360
1427
|
* Shared by CLI (--json) and MCP server (analyze tool response).
|
|
@@ -1363,6 +1430,16 @@ declare function buildResultJson(fileName: string, result: AnalysisResult, score
|
|
|
1363
1430
|
fileKey?: string;
|
|
1364
1431
|
designKey?: string;
|
|
1365
1432
|
codegenReadyMinGrade?: Grade;
|
|
1433
|
+
codeConnectCoverage?: CodeConnectCoverage;
|
|
1434
|
+
/**
|
|
1435
|
+
* ADR-022 / #526 sub-task 2: when true, the engine was called WITHOUT
|
|
1436
|
+
* an `acknowledgments` channel (standalone CLI / MCP `analyze`) and
|
|
1437
|
+
* `unmapped-component` opt-outs recorded via roundtrip cannot be seen.
|
|
1438
|
+
* Surfaces a `roundtripOptOutHint` field on the JSON response and
|
|
1439
|
+
* appends a hint line to `summary` when at least one
|
|
1440
|
+
* `unmapped-component` issue fired.
|
|
1441
|
+
*/
|
|
1442
|
+
roundtripOptOutHintEligible?: boolean;
|
|
1366
1443
|
}): Record<string, unknown>;
|
|
1367
1444
|
|
|
1368
1445
|
/**
|
|
@@ -1904,6 +1981,21 @@ declare class FigmaClient {
|
|
|
1904
1981
|
* Download an image URL and return as base64
|
|
1905
1982
|
*/
|
|
1906
1983
|
fetchImageAsBase64(imageUrl: string): Promise<string>;
|
|
1984
|
+
/**
|
|
1985
|
+
* Get the components a file has published to a team library.
|
|
1986
|
+
*
|
|
1987
|
+
* `GET /v1/files/:file_key/components` returns only components that have
|
|
1988
|
+
* been pushed via the Publish Library action — local-but-unpublished
|
|
1989
|
+
* components are absent. This is the authoritative way to detect whether
|
|
1990
|
+
* a Figma component is mappable via Code Connect (#532): `add_code_connect_map`
|
|
1991
|
+
* requires a published component and otherwise fails with "Published
|
|
1992
|
+
* component not found."
|
|
1993
|
+
*/
|
|
1994
|
+
getPublishedComponents(fileKey: string): Promise<Array<{
|
|
1995
|
+
key: string;
|
|
1996
|
+
node_id: string;
|
|
1997
|
+
name: string;
|
|
1998
|
+
}>>;
|
|
1907
1999
|
getFileNodes(fileKey: string, nodeIds: string[]): Promise<GetFileNodesResponse>;
|
|
1908
2000
|
}
|
|
1909
2001
|
declare class FigmaClientError extends Error {
|
|
@@ -2394,4 +2486,4 @@ declare class ActivityLogger {
|
|
|
2394
2486
|
getLogPath(): string;
|
|
2395
2487
|
}
|
|
2396
2488
|
|
|
2397
|
-
export { ALL_STRIP_TYPES, ActivityLogger, type AnalysisAgentInput, type AnalysisAgentOutput, type AnalysisFile, AnalysisFileSchema, type AnalysisIssue, type AnalysisNode, AnalysisNodeSchema, type AnalysisNodeType, AnalysisNodeTypeSchema, type AnalysisResult, type AnalysisScope, AnalysisScopeSchema, AnnotationPropertySchema, CATEGORIES, CATEGORY_LABELS, type CalibrationConfig, type CalibrationConfigInput, CalibrationConfigSchema, type CalibrationRun, type CalibrationStatus, CalibrationStatusSchema, type Category, CategorySchema, type CategoryScore, type CategoryScoreResult, CategoryScoreSchema, type Confidence, ConfidenceSchema, type ConversionRecord, ConversionRecordSchema, DEFAULT_CODEGEN_READY_MIN_GRADE, DEPTH_WEIGHT_CATEGORIES, DESIGN_TREE_INFO_TYPES, type DesignTreeInfoType, type DesignTreeOptions, type DesignTreeResult, type DesignTreeStripType, type Detection, DetectionSchema, type Difficulty, DifficultySchema, type EvaluationAgentInput, type EvaluationAgentOutput, FigmaClient, FigmaClientError, type FigmaClientOptions, FigmaFileLoadError, type FigmaUrlInfo, FigmaUrlInfoSchema, FigmaUrlParseError, GRADE_ORDER, type GapAnalyzerOutput, GapAnalyzerOutputSchema, type GapEntry, GapEntrySchema, type GetFileNodesResponse, type GotchaApplyResolution, type GotchaApplyStrategy, GotchaDetectionSchema, GotchaOutputChannelSchema, GotchaPersistenceIntentSchema, type GotchaSurvey, type GotchaSurveyQuestion, GotchaSurveyQuestionSchema, GotchaSurveySchema, type Grade, type GridChildAlign, GridChildAlignSchema, type GroupedSurvey, GroupedSurveySchema, type InstanceChildIdParts, type InstanceContext, InstanceContextSchema, type Issue, IssueSchema, type LayoutAlign, LayoutAlignSchema, type LayoutConstraint, LayoutConstraintSchema, type LayoutMode, LayoutModeSchema, type LayoutPositioning, LayoutPositioningSchema, type LayoutWrap, LayoutWrapSchema, type McpAnalyzeResponse, McpAnalyzeResponseSchema, type MismatchCase, MismatchCaseSchema, type MismatchType, MismatchTypeSchema, type NewRuleProposal, NewRuleProposalSchema, type NodeIssueDetail, type NodeIssueSummary, NodeIssueSummarySchema, type OutputChannel, OutputChannelSchema, type OverflowDirection, OverflowDirectionSchema, type PersistenceIntent, PersistenceIntentSchema, type Preset, RULE_ANNOTATION_PROPERTIES, RULE_CONFIGS, RULE_ID_CATEGORY, RULE_PURPOSE, type Report, type ReportMetadata, ReportMetadataSchema, ReportSchema, type Rule, type RuleApplyStrategy, RuleApplyStrategySchema, type RuleCheckFn, type RuleConfig, RuleConfigSchema, type RuleContext, type RuleDefinition, RuleDefinitionSchema, RuleEngine, type RuleEngineOptions, type RuleFailure, type RuleId, RuleImpactAssessmentSchema, type RulePurpose, RulePurposeSchema, type RuleRelatedStruggle, RuleRelatedStruggleSchema, type RuleViolation, SEVERITY_LABELS, SEVERITY_WEIGHT, type SamplingStrategy, SamplingStrategySchema, type ScoreAdjustment, ScoreAdjustmentSchema, type ScoreReport, type Severity, SeveritySchema, type StripDeltaForEval, type StripDeltaResult, StripDeltaResultSchema, StripDeltasArraySchema, StripTypeEnum, type SurveyQuestionBatch, SurveyQuestionBatchSchema, type SurveyQuestionGroup, SurveyQuestionGroupSchema, type TuningAgentInput, type TuningAgentOutput, type UncoveredStruggle, UncoveredStruggleSchema, UncoveredStrugglesInputSchema, version as VERSION, type VisualCompareCliOptions, VisualCompareCliOptionsSchema, absolutePositionInAutoLayout, analyzeFile, buildFigmaDeepLink, buildResultJson, calculateScores, collectComponentIds, collectInteractionDestinationIds, createRuleEngine, deepNesting, defineRule, detachedInstance, detectAnalysisScope, extractRuleScores, fixedSizeInAutoLayout, formatScoreSummary, generateCalibrationReport, generateDesignTree, generateDesignTreeWithStats, getAnalysisState, getAnnotationProperties, getCategoryLabel, getConfigsWithPreset, getRuleOption, getRulePurpose, getSeverityLabel, gradeToClassName, inconsistentNamingConvention, irregularSpacing, isInstanceChildNodeId, isReadyForCodeGen, loadFigmaFileFromJson, missingComponent, missingInteractionState, missingPrototype, missingSizeConstraint, noAutoLayout, nonLayoutContainer, nonSemanticName, nonStandardNaming, parseFigmaJson, parseFigmaUrl, parseInstanceChildNodeId, rawValue, resolveComponentDefinitions, resolveGotchaApplyTarget, resolveInteractionDestinations, ruleRegistry, runAnalysisAgent, runCalibrationAnalyze, runCalibrationEvaluate, runEvaluationAgent, runTuningAgent, stripDeltaToDifficulty, stripDesignTree, supportsDepthWeight, toCommentableNodeId, tokenDeltaToDifficulty, transformComponentMasterNodes, transformFigmaResponse, transformFileNodesResponse, unmappedComponent, variantStructureMismatch };
|
|
2489
|
+
export { ALL_STRIP_TYPES, ActivityLogger, type AnalysisAgentInput, type AnalysisAgentOutput, type AnalysisFile, AnalysisFileSchema, type AnalysisIssue, type AnalysisNode, AnalysisNodeSchema, type AnalysisNodeType, AnalysisNodeTypeSchema, type AnalysisResult, type AnalysisScope, AnalysisScopeSchema, AnnotationPropertySchema, CATEGORIES, CATEGORY_LABELS, type CalibrationConfig, type CalibrationConfigInput, CalibrationConfigSchema, type CalibrationRun, type CalibrationStatus, CalibrationStatusSchema, type Category, CategorySchema, type CategoryScore, type CategoryScoreResult, CategoryScoreSchema, type CodeConnectCoverage, type Confidence, ConfidenceSchema, type ConversionRecord, ConversionRecordSchema, DEFAULT_CODEGEN_READY_MIN_GRADE, DEPTH_WEIGHT_CATEGORIES, DESIGN_TREE_INFO_TYPES, type DesignTreeInfoType, type DesignTreeOptions, type DesignTreeResult, type DesignTreeStripType, type Detection, DetectionSchema, type Difficulty, DifficultySchema, type EvaluationAgentInput, type EvaluationAgentOutput, FigmaClient, FigmaClientError, type FigmaClientOptions, FigmaFileLoadError, type FigmaUrlInfo, FigmaUrlInfoSchema, FigmaUrlParseError, GRADE_ORDER, type GapAnalyzerOutput, GapAnalyzerOutputSchema, type GapEntry, GapEntrySchema, type GetFileNodesResponse, type GotchaApplyResolution, type GotchaApplyStrategy, GotchaDetectionSchema, GotchaOutputChannelSchema, GotchaPersistenceIntentSchema, type GotchaSurvey, type GotchaSurveyQuestion, GotchaSurveyQuestionSchema, GotchaSurveySchema, type Grade, type GridChildAlign, GridChildAlignSchema, type GroupedSurvey, GroupedSurveySchema, type InstanceChildIdParts, type InstanceContext, InstanceContextSchema, type Issue, IssueSchema, type LayoutAlign, LayoutAlignSchema, type LayoutConstraint, LayoutConstraintSchema, type LayoutMode, LayoutModeSchema, type LayoutPositioning, LayoutPositioningSchema, type LayoutWrap, LayoutWrapSchema, type McpAnalyzeResponse, McpAnalyzeResponseSchema, type MismatchCase, MismatchCaseSchema, type MismatchType, MismatchTypeSchema, type NewRuleProposal, NewRuleProposalSchema, type NodeIssueDetail, type NodeIssueSummary, NodeIssueSummarySchema, type OutputChannel, OutputChannelSchema, type OverflowDirection, OverflowDirectionSchema, type PersistenceIntent, PersistenceIntentSchema, type Preset, ROUNDTRIP_OPT_OUT_HINT, RULE_ANNOTATION_PROPERTIES, RULE_CONFIGS, RULE_ID_CATEGORY, RULE_PURPOSE, type Report, type ReportMetadata, ReportMetadataSchema, ReportSchema, type Rule, type RuleApplyStrategy, RuleApplyStrategySchema, type RuleCheckFn, type RuleConfig, RuleConfigSchema, type RuleContext, type RuleDefinition, RuleDefinitionSchema, RuleEngine, type RuleEngineOptions, type RuleFailure, type RuleId, RuleImpactAssessmentSchema, type RulePurpose, RulePurposeSchema, type RuleRelatedStruggle, RuleRelatedStruggleSchema, type RuleViolation, SEVERITY_LABELS, SEVERITY_WEIGHT, type SamplingStrategy, SamplingStrategySchema, type ScoreAdjustment, ScoreAdjustmentSchema, type ScoreReport, type Severity, SeveritySchema, type StripDeltaForEval, type StripDeltaResult, StripDeltaResultSchema, StripDeltasArraySchema, StripTypeEnum, type SurveyQuestionBatch, SurveyQuestionBatchSchema, type SurveyQuestionGroup, SurveyQuestionGroupSchema, type TuningAgentInput, type TuningAgentOutput, type UncoveredStruggle, UncoveredStruggleSchema, UncoveredStrugglesInputSchema, version as VERSION, type VisualCompareCliOptions, VisualCompareCliOptionsSchema, absolutePositionInAutoLayout, analyzeFile, buildFigmaDeepLink, buildResultJson, calculateScores, collectComponentIds, collectInteractionDestinationIds, createRuleEngine, deepNesting, defineRule, detachedInstance, detectAnalysisScope, extractRuleScores, fixedSizeInAutoLayout, formatCodeConnectCoverageLine, formatRoundtripOptOutHintLine, formatScoreSummary, generateCalibrationReport, generateDesignTree, generateDesignTreeWithStats, getAnalysisState, getAnnotationProperties, getCategoryLabel, getConfigsWithPreset, getRuleOption, getRulePurpose, getSeverityLabel, gradeToClassName, inconsistentNamingConvention, irregularSpacing, isInstanceChildNodeId, isReadyForCodeGen, loadFigmaFileFromJson, missingComponent, missingInteractionState, missingPrototype, missingSizeConstraint, noAutoLayout, nonLayoutContainer, nonSemanticName, nonStandardNaming, parseFigmaJson, parseFigmaUrl, parseInstanceChildNodeId, rawValue, resolveComponentDefinitions, resolveGotchaApplyTarget, resolveInteractionDestinations, ruleRegistry, runAnalysisAgent, runCalibrationAnalyze, runCalibrationEvaluate, runEvaluationAgent, runTuningAgent, stripDeltaToDifficulty, stripDesignTree, supportsDepthWeight, toCommentableNodeId, tokenDeltaToDifficulty, transformComponentMasterNodes, transformFigmaResponse, transformFileNodesResponse, unmappedComponent, variantStructureMismatch };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { existsSync, readFileSync, mkdirSync, writeFileSync, statSync } from 'fs';
|
|
3
|
-
import { resolve, join, basename, dirname } from 'path';
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, statSync, readdirSync } from 'fs';
|
|
3
|
+
import { resolve, join, basename, dirname, isAbsolute, sep } from 'path';
|
|
4
4
|
import { readFile, writeFile, appendFile } from 'fs/promises';
|
|
5
5
|
import 'crypto';
|
|
6
6
|
import { homedir } from 'os';
|
|
7
7
|
|
|
8
8
|
// package.json
|
|
9
|
-
var version = "0.12.
|
|
9
|
+
var version = "0.12.2";
|
|
10
10
|
var SeveritySchema = z.enum([
|
|
11
11
|
"blocking",
|
|
12
12
|
"risk",
|
|
@@ -359,7 +359,14 @@ var McpAnalyzeResponseSchema = z.object({
|
|
|
359
359
|
issuesByRule: z.record(z.string(), z.number().int().min(0)),
|
|
360
360
|
issues: z.array(McpIssueSchema),
|
|
361
361
|
summary: z.string(),
|
|
362
|
-
failedRules: z.array(z.string()).optional()
|
|
362
|
+
failedRules: z.array(z.string()).optional(),
|
|
363
|
+
/**
|
|
364
|
+
* #526 sub-task 3 — Code Connect mapping coverage. Optional: only emitted
|
|
365
|
+
* when the consuming repo has `figma.config.json`. Numerator = components in
|
|
366
|
+
* this file with a discovered `figma.connect` declaration; denominator =
|
|
367
|
+
* total components in the file.
|
|
368
|
+
*/
|
|
369
|
+
codeConnectCoverage: z.object({ mapped: z.number().int().min(0), total: z.number().int().min(0) }).optional()
|
|
363
370
|
});
|
|
364
371
|
var GradeSchema2 = z.enum(["S", "A+", "A", "B+", "B", "C+", "C", "D", "F"]);
|
|
365
372
|
var InstanceContextSchema = z.object({
|
|
@@ -836,11 +843,31 @@ function defineRule(rule) {
|
|
|
836
843
|
ruleRegistry.register(rule);
|
|
837
844
|
return rule;
|
|
838
845
|
}
|
|
839
|
-
var
|
|
846
|
+
var PropertyAcknowledgmentIntentSchema = z.object({
|
|
847
|
+
kind: z.literal("property").default("property"),
|
|
840
848
|
field: z.string(),
|
|
841
849
|
value: z.unknown(),
|
|
842
850
|
scope: z.enum(["instance", "definition"])
|
|
843
851
|
});
|
|
852
|
+
var RuleOptOutAcknowledgmentIntentSchema = z.object({
|
|
853
|
+
kind: z.literal("rule-opt-out"),
|
|
854
|
+
ruleId: z.string()
|
|
855
|
+
}).strict();
|
|
856
|
+
var AcknowledgmentIntentSchema = z.preprocess((raw) => {
|
|
857
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
858
|
+
const obj = raw;
|
|
859
|
+
if (obj["kind"] === void 0) {
|
|
860
|
+
return { ...obj, kind: "property" };
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
return raw;
|
|
864
|
+
}, z.discriminatedUnion("kind", [
|
|
865
|
+
PropertyAcknowledgmentIntentSchema,
|
|
866
|
+
RuleOptOutAcknowledgmentIntentSchema
|
|
867
|
+
]));
|
|
868
|
+
function isRuleOptOutIntent(intent) {
|
|
869
|
+
return intent !== void 0 && intent.kind === "rule-opt-out";
|
|
870
|
+
}
|
|
844
871
|
var AcknowledgmentSceneWriteOutcomeSchema = z.object({
|
|
845
872
|
result: z.enum([
|
|
846
873
|
"succeeded",
|
|
@@ -913,6 +940,7 @@ var RuleEngine = class {
|
|
|
913
940
|
excludeNamePattern;
|
|
914
941
|
excludeNodeTypes;
|
|
915
942
|
acknowledgments;
|
|
943
|
+
acknowledgmentsByKey;
|
|
916
944
|
scopeOverride;
|
|
917
945
|
constructor(options = {}) {
|
|
918
946
|
this.configs = options.configs ?? RULE_CONFIGS;
|
|
@@ -921,10 +949,15 @@ var RuleEngine = class {
|
|
|
921
949
|
this.targetNodeId = options.targetNodeId;
|
|
922
950
|
this.excludeNamePattern = options.excludeNodeNames && options.excludeNodeNames.length > 0 ? new RegExp(`\\b(${options.excludeNodeNames.join("|")})\\b`, "i") : null;
|
|
923
951
|
this.excludeNodeTypes = options.excludeNodeTypes && options.excludeNodeTypes.length > 0 ? new Set(options.excludeNodeTypes) : null;
|
|
952
|
+
const ackList = options.acknowledgments ?? [];
|
|
924
953
|
this.acknowledgments = new Set(
|
|
925
|
-
(
|
|
926
|
-
|
|
927
|
-
|
|
954
|
+
ackList.map((a) => `${normalizeNodeId(a.nodeId)}::${a.ruleId}`)
|
|
955
|
+
);
|
|
956
|
+
this.acknowledgmentsByKey = new Map(
|
|
957
|
+
ackList.map((a) => [
|
|
958
|
+
`${normalizeNodeId(a.nodeId)}::${a.ruleId}`,
|
|
959
|
+
a
|
|
960
|
+
])
|
|
928
961
|
);
|
|
929
962
|
this.scopeOverride = options.scope;
|
|
930
963
|
}
|
|
@@ -1008,6 +1041,7 @@ var RuleEngine = class {
|
|
|
1008
1041
|
if (this.excludeNamePattern && this.excludeNamePattern.test(node.name)) {
|
|
1009
1042
|
return;
|
|
1010
1043
|
}
|
|
1044
|
+
const acknowledgmentsByKey = this.acknowledgmentsByKey;
|
|
1011
1045
|
const context = {
|
|
1012
1046
|
file,
|
|
1013
1047
|
parent,
|
|
@@ -1019,7 +1053,8 @@ var RuleEngine = class {
|
|
|
1019
1053
|
siblings,
|
|
1020
1054
|
analysisState,
|
|
1021
1055
|
scope,
|
|
1022
|
-
rootNodeType
|
|
1056
|
+
rootNodeType,
|
|
1057
|
+
findAcknowledgment: (nodeId, ruleId) => acknowledgmentsByKey.get(`${normalizeNodeId(nodeId)}::${ruleId}`)
|
|
1023
1058
|
};
|
|
1024
1059
|
for (const rule of rules) {
|
|
1025
1060
|
const ruleId = rule.definition.id;
|
|
@@ -1378,6 +1413,20 @@ function getSeverityLabel(severity) {
|
|
|
1378
1413
|
};
|
|
1379
1414
|
return labels[severity];
|
|
1380
1415
|
}
|
|
1416
|
+
function formatCodeConnectCoverageLine(coverage) {
|
|
1417
|
+
const { mapped, total } = coverage;
|
|
1418
|
+
const pct = total === 0 ? 0 : Math.round(mapped / total * 100);
|
|
1419
|
+
return `Code Connect coverage: ${mapped}/${total} components (${pct}%) mapped`;
|
|
1420
|
+
}
|
|
1421
|
+
var ROUNDTRIP_OPT_OUT_HINT = "Some components may carry roundtrip-recorded opt-outs that this standalone analyze cannot see (Figma REST annotations field is in private beta). Run /canicode-roundtrip to apply opt-outs.";
|
|
1422
|
+
function formatRoundtripOptOutHintLine(issues, acknowledgmentsProvided) {
|
|
1423
|
+
if (acknowledgmentsProvided) return null;
|
|
1424
|
+
const hasUnmapped = issues.some(
|
|
1425
|
+
(issue) => issue.violation.ruleId === "unmapped-component"
|
|
1426
|
+
);
|
|
1427
|
+
if (!hasUnmapped) return null;
|
|
1428
|
+
return ROUNDTRIP_OPT_OUT_HINT;
|
|
1429
|
+
}
|
|
1381
1430
|
function buildResultJson(fileName, result, scores, options) {
|
|
1382
1431
|
const issuesByRule = {};
|
|
1383
1432
|
for (const issue of result.issues) {
|
|
@@ -1407,6 +1456,14 @@ function buildResultJson(fileName, result, scores, options) {
|
|
|
1407
1456
|
...issue.acknowledged === true ? { acknowledged: true } : {}
|
|
1408
1457
|
};
|
|
1409
1458
|
});
|
|
1459
|
+
const optOutHint = options?.roundtripOptOutHintEligible ? formatRoundtripOptOutHintLine(result.issues, false) : null;
|
|
1460
|
+
const summaryParts = [formatScoreSummary(scores)];
|
|
1461
|
+
if (options?.codeConnectCoverage) {
|
|
1462
|
+
summaryParts.push(formatCodeConnectCoverageLine(options.codeConnectCoverage));
|
|
1463
|
+
}
|
|
1464
|
+
if (optOutHint) {
|
|
1465
|
+
summaryParts.push(optOutHint);
|
|
1466
|
+
}
|
|
1410
1467
|
const json = {
|
|
1411
1468
|
version,
|
|
1412
1469
|
analyzedAt: result.analyzedAt,
|
|
@@ -1426,8 +1483,14 @@ function buildResultJson(fileName, result, scores, options) {
|
|
|
1426
1483
|
},
|
|
1427
1484
|
issuesByRule,
|
|
1428
1485
|
issues,
|
|
1429
|
-
summary:
|
|
1486
|
+
summary: summaryParts.join("\n\n")
|
|
1430
1487
|
};
|
|
1488
|
+
if (options?.codeConnectCoverage) {
|
|
1489
|
+
json["codeConnectCoverage"] = options.codeConnectCoverage;
|
|
1490
|
+
}
|
|
1491
|
+
if (optOutHint) {
|
|
1492
|
+
json["roundtripOptOutHint"] = optOutHint;
|
|
1493
|
+
}
|
|
1431
1494
|
if (result.failedRules.length > 0) {
|
|
1432
1495
|
json["failedRules"] = result.failedRules;
|
|
1433
1496
|
}
|
|
@@ -3046,6 +3109,130 @@ var irregularSpacing = defineRule({
|
|
|
3046
3109
|
definition: irregularSpacingDef,
|
|
3047
3110
|
check: irregularSpacingCheck
|
|
3048
3111
|
});
|
|
3112
|
+
var FIGMA_CONFIG_FILENAME = "figma.config.json";
|
|
3113
|
+
var FIGMA_CONNECT_FILE_GLOB = /\.figma\.(tsx?|jsx?)$/;
|
|
3114
|
+
var NODE_ID_QUERY_RE = /[?&]node-id=([0-9A-Za-z%:\-_]+)/;
|
|
3115
|
+
function parseCodeConnectMappings(cwd) {
|
|
3116
|
+
const configPath = join(cwd, FIGMA_CONFIG_FILENAME);
|
|
3117
|
+
if (!existsSync(configPath)) {
|
|
3118
|
+
return {
|
|
3119
|
+
mappedNodeIds: /* @__PURE__ */ new Set(),
|
|
3120
|
+
scannedFiles: [],
|
|
3121
|
+
skipReason: "no-config",
|
|
3122
|
+
skippedReason: `${FIGMA_CONFIG_FILENAME} not found at ${cwd}`
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
let config;
|
|
3126
|
+
try {
|
|
3127
|
+
config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
3128
|
+
} catch (err) {
|
|
3129
|
+
return {
|
|
3130
|
+
mappedNodeIds: /* @__PURE__ */ new Set(),
|
|
3131
|
+
scannedFiles: [],
|
|
3132
|
+
skipReason: "malformed-config",
|
|
3133
|
+
skippedReason: `malformed ${FIGMA_CONFIG_FILENAME}: ${err.message}`
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3136
|
+
const includes = config.codeConnect?.include ?? config.include ?? [];
|
|
3137
|
+
if (includes.length === 0) {
|
|
3138
|
+
return {
|
|
3139
|
+
mappedNodeIds: /* @__PURE__ */ new Set(),
|
|
3140
|
+
scannedFiles: [],
|
|
3141
|
+
skipReason: "no-includes",
|
|
3142
|
+
skippedReason: `${FIGMA_CONFIG_FILENAME} has no codeConnect.include paths`
|
|
3143
|
+
};
|
|
3144
|
+
}
|
|
3145
|
+
const candidateFiles = /* @__PURE__ */ new Set();
|
|
3146
|
+
for (const includePattern of includes) {
|
|
3147
|
+
for (const file of resolveInclude(cwd, includePattern)) {
|
|
3148
|
+
candidateFiles.add(file);
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
const mappedNodeIds = /* @__PURE__ */ new Set();
|
|
3152
|
+
const scannedFiles = [];
|
|
3153
|
+
for (const file of candidateFiles) {
|
|
3154
|
+
scannedFiles.push(file);
|
|
3155
|
+
let contents;
|
|
3156
|
+
try {
|
|
3157
|
+
contents = readFileSync(file, "utf-8");
|
|
3158
|
+
} catch {
|
|
3159
|
+
continue;
|
|
3160
|
+
}
|
|
3161
|
+
for (const nodeId of extractNodeIdsFromSource(contents)) {
|
|
3162
|
+
mappedNodeIds.add(nodeId);
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
return { mappedNodeIds, scannedFiles };
|
|
3166
|
+
}
|
|
3167
|
+
function resolveInclude(cwd, includePattern) {
|
|
3168
|
+
const results = [];
|
|
3169
|
+
const absolute = isAbsolute(includePattern) ? includePattern : resolve(cwd, includePattern);
|
|
3170
|
+
const segments = absolute.split(sep);
|
|
3171
|
+
let firstGlobIdx = segments.findIndex((s) => /[*?{[]/.test(s));
|
|
3172
|
+
if (firstGlobIdx === -1) {
|
|
3173
|
+
if (existsSync(absolute)) {
|
|
3174
|
+
const stat = statSync(absolute);
|
|
3175
|
+
if (stat.isFile() && FIGMA_CONNECT_FILE_GLOB.test(absolute)) {
|
|
3176
|
+
results.push(absolute);
|
|
3177
|
+
} else if (stat.isDirectory()) {
|
|
3178
|
+
walkDir(absolute, results);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
return results;
|
|
3182
|
+
}
|
|
3183
|
+
const rootSegments = segments.slice(0, firstGlobIdx);
|
|
3184
|
+
const root = rootSegments.length === 0 ? sep : rootSegments.join(sep);
|
|
3185
|
+
if (!existsSync(root)) return results;
|
|
3186
|
+
const rootStat = statSync(root);
|
|
3187
|
+
if (!rootStat.isDirectory()) return results;
|
|
3188
|
+
walkDir(root, results);
|
|
3189
|
+
const prefix = rootSegments.join(sep) + sep;
|
|
3190
|
+
return results.filter((f) => f.startsWith(prefix) || rootSegments.length === 0);
|
|
3191
|
+
}
|
|
3192
|
+
function walkDir(dir, out) {
|
|
3193
|
+
let entries;
|
|
3194
|
+
try {
|
|
3195
|
+
entries = readdirSync(dir);
|
|
3196
|
+
} catch {
|
|
3197
|
+
return;
|
|
3198
|
+
}
|
|
3199
|
+
for (const entry of entries) {
|
|
3200
|
+
if (entry === "node_modules" || entry.startsWith(".")) continue;
|
|
3201
|
+
const full = join(dir, entry);
|
|
3202
|
+
let stat;
|
|
3203
|
+
try {
|
|
3204
|
+
stat = statSync(full);
|
|
3205
|
+
} catch {
|
|
3206
|
+
continue;
|
|
3207
|
+
}
|
|
3208
|
+
if (stat.isDirectory()) {
|
|
3209
|
+
walkDir(full, out);
|
|
3210
|
+
} else if (stat.isFile() && FIGMA_CONNECT_FILE_GLOB.test(full)) {
|
|
3211
|
+
out.push(full);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
function extractNodeIdsFromSource(source) {
|
|
3216
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
3217
|
+
const re = new RegExp(NODE_ID_QUERY_RE, "g");
|
|
3218
|
+
let match;
|
|
3219
|
+
while ((match = re.exec(source)) !== null) {
|
|
3220
|
+
const raw = match[1];
|
|
3221
|
+
if (!raw) continue;
|
|
3222
|
+
const decoded = safeDecode(raw);
|
|
3223
|
+
nodeIds.add(decoded.replace(/-/g, ":"));
|
|
3224
|
+
}
|
|
3225
|
+
return nodeIds;
|
|
3226
|
+
}
|
|
3227
|
+
function safeDecode(raw) {
|
|
3228
|
+
try {
|
|
3229
|
+
return decodeURIComponent(raw);
|
|
3230
|
+
} catch {
|
|
3231
|
+
return raw;
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
// src/core/rules/component/index.ts
|
|
3049
3236
|
var STYLE_COMPARE_KEYS = ["fills", "strokes", "effects", "cornerRadius", "strokeWeight", "individualStrokeWeights"];
|
|
3050
3237
|
function detectStyleOverrides(master, instance) {
|
|
3051
3238
|
const overrides = [];
|
|
@@ -3254,11 +3441,23 @@ var variantStructureMismatch = defineRule({
|
|
|
3254
3441
|
check: variantStructureMismatchCheck
|
|
3255
3442
|
});
|
|
3256
3443
|
var CODE_CONNECT_SETUP_KEY = "unmapped-component:setup-detected";
|
|
3444
|
+
var CODE_CONNECT_MAPPINGS_KEY = "unmapped-component:mappings";
|
|
3445
|
+
var SEEN_MAIN_IDS_KEY = "unmapped-component:seen-main-ids";
|
|
3257
3446
|
function codeConnectIsSetUp(context) {
|
|
3258
3447
|
return getAnalysisState(context, CODE_CONNECT_SETUP_KEY, () => {
|
|
3259
3448
|
return existsSync(join(process.cwd(), "figma.config.json"));
|
|
3260
3449
|
});
|
|
3261
3450
|
}
|
|
3451
|
+
function codeConnectMappings(context) {
|
|
3452
|
+
return getAnalysisState(
|
|
3453
|
+
context,
|
|
3454
|
+
CODE_CONNECT_MAPPINGS_KEY,
|
|
3455
|
+
() => parseCodeConnectMappings(process.cwd())
|
|
3456
|
+
);
|
|
3457
|
+
}
|
|
3458
|
+
function seenMainIds(context) {
|
|
3459
|
+
return getAnalysisState(context, SEEN_MAIN_IDS_KEY, () => /* @__PURE__ */ new Set());
|
|
3460
|
+
}
|
|
3262
3461
|
var unmappedComponentDef = {
|
|
3263
3462
|
id: "unmapped-component",
|
|
3264
3463
|
name: "Unmapped Component",
|
|
@@ -3268,14 +3467,33 @@ var unmappedComponentDef = {
|
|
|
3268
3467
|
fix: "Run /canicode-roundtrip on this component to register a mapping. Figma's get_code_connect_map will skip if a mapping already exists."
|
|
3269
3468
|
};
|
|
3270
3469
|
var unmappedComponentCheck = (node, context) => {
|
|
3271
|
-
if (node.type !== "COMPONENT" && node.type !== "COMPONENT_SET") return null;
|
|
3272
|
-
if (isInsideInstance(context)) return null;
|
|
3273
3470
|
if (!codeConnectIsSetUp(context)) return null;
|
|
3471
|
+
let mainId = null;
|
|
3472
|
+
let mainName = node.name;
|
|
3473
|
+
if (node.type === "COMPONENT" || node.type === "COMPONENT_SET") {
|
|
3474
|
+
if (isInsideInstance(context)) return null;
|
|
3475
|
+
mainId = node.id;
|
|
3476
|
+
} else if (node.type === "INSTANCE" && node.componentId) {
|
|
3477
|
+
mainId = node.componentId;
|
|
3478
|
+
const meta = context.file.components[node.componentId];
|
|
3479
|
+
if (meta?.name) mainName = meta.name;
|
|
3480
|
+
} else {
|
|
3481
|
+
return null;
|
|
3482
|
+
}
|
|
3483
|
+
const seen = seenMainIds(context);
|
|
3484
|
+
if (seen.has(mainId)) return null;
|
|
3485
|
+
seen.add(mainId);
|
|
3486
|
+
const mappings = codeConnectMappings(context);
|
|
3487
|
+
if (mappings.mappedNodeIds.has(mainId)) return null;
|
|
3488
|
+
const ack = context.findAcknowledgment(mainId, unmappedComponentDef.id);
|
|
3489
|
+
if (ack && isRuleOptOutIntent(ack.intent) && ack.intent.ruleId === unmappedComponentDef.id) {
|
|
3490
|
+
return null;
|
|
3491
|
+
}
|
|
3274
3492
|
return {
|
|
3275
3493
|
ruleId: unmappedComponentDef.id,
|
|
3276
|
-
nodeId:
|
|
3494
|
+
nodeId: mainId,
|
|
3277
3495
|
nodePath: context.path.join(" > "),
|
|
3278
|
-
...unmappedComponentMsg(
|
|
3496
|
+
...unmappedComponentMsg(mainName)
|
|
3279
3497
|
};
|
|
3280
3498
|
};
|
|
3281
3499
|
var unmappedComponent = defineRule({
|
|
@@ -3785,6 +4003,32 @@ var FigmaClient = class _FigmaClient {
|
|
|
3785
4003
|
const buffer = await response.arrayBuffer();
|
|
3786
4004
|
return Buffer.from(buffer).toString("base64");
|
|
3787
4005
|
}
|
|
4006
|
+
/**
|
|
4007
|
+
* Get the components a file has published to a team library.
|
|
4008
|
+
*
|
|
4009
|
+
* `GET /v1/files/:file_key/components` returns only components that have
|
|
4010
|
+
* been pushed via the Publish Library action — local-but-unpublished
|
|
4011
|
+
* components are absent. This is the authoritative way to detect whether
|
|
4012
|
+
* a Figma component is mappable via Code Connect (#532): `add_code_connect_map`
|
|
4013
|
+
* requires a published component and otherwise fails with "Published
|
|
4014
|
+
* component not found."
|
|
4015
|
+
*/
|
|
4016
|
+
async getPublishedComponents(fileKey) {
|
|
4017
|
+
const url = `${FIGMA_API_BASE}/files/${fileKey}/components`;
|
|
4018
|
+
const response = await fetch(url, {
|
|
4019
|
+
headers: { "X-Figma-Token": this.token }
|
|
4020
|
+
});
|
|
4021
|
+
if (!response.ok) {
|
|
4022
|
+
const error = await response.json().catch(() => ({}));
|
|
4023
|
+
throw new FigmaClientError(
|
|
4024
|
+
`Failed to fetch published components: ${response.status} ${response.statusText}`,
|
|
4025
|
+
response.status,
|
|
4026
|
+
error
|
|
4027
|
+
);
|
|
4028
|
+
}
|
|
4029
|
+
const data = await response.json();
|
|
4030
|
+
return data.meta?.components ?? [];
|
|
4031
|
+
}
|
|
3788
4032
|
async getFileNodes(fileKey, nodeIds) {
|
|
3789
4033
|
const ids = nodeIds.join(",");
|
|
3790
4034
|
const url = `${FIGMA_API_BASE}/files/${fileKey}/nodes?ids=${encodeURIComponent(ids)}`;
|
|
@@ -5427,6 +5671,6 @@ var ActivityLogger = class {
|
|
|
5427
5671
|
}
|
|
5428
5672
|
};
|
|
5429
5673
|
|
|
5430
|
-
export { ALL_STRIP_TYPES, ActivityLogger, AnalysisFileSchema, AnalysisNodeSchema, AnalysisNodeTypeSchema, AnalysisScopeSchema, AnnotationPropertySchema, CATEGORIES, CATEGORY_LABELS, CalibrationConfigSchema, CalibrationStatusSchema, CategorySchema, CategoryScoreSchema, ConfidenceSchema, ConversionRecordSchema, DEFAULT_CODEGEN_READY_MIN_GRADE, DEPTH_WEIGHT_CATEGORIES, DESIGN_TREE_INFO_TYPES, DetectionSchema, DifficultySchema, FigmaClient, FigmaClientError, FigmaFileLoadError, FigmaUrlInfoSchema, FigmaUrlParseError, GRADE_ORDER, GapAnalyzerOutputSchema, GapEntrySchema, GotchaDetectionSchema, GotchaOutputChannelSchema, GotchaPersistenceIntentSchema, GotchaSurveyQuestionSchema, GotchaSurveySchema, GridChildAlignSchema, GroupedSurveySchema, InstanceContextSchema, IssueSchema, LayoutAlignSchema, LayoutConstraintSchema, LayoutModeSchema, LayoutPositioningSchema, LayoutWrapSchema, McpAnalyzeResponseSchema, MismatchCaseSchema, MismatchTypeSchema, NewRuleProposalSchema, NodeIssueSummarySchema, OutputChannelSchema, OverflowDirectionSchema, PersistenceIntentSchema, RULE_ANNOTATION_PROPERTIES, RULE_CONFIGS, RULE_ID_CATEGORY, RULE_PURPOSE, ReportMetadataSchema, ReportSchema, RuleApplyStrategySchema, RuleConfigSchema, RuleDefinitionSchema, RuleEngine, RuleImpactAssessmentSchema, RulePurposeSchema, RuleRelatedStruggleSchema, SEVERITY_LABELS, SEVERITY_WEIGHT, SamplingStrategySchema, ScoreAdjustmentSchema, SeveritySchema, StripDeltaResultSchema, StripDeltasArraySchema, StripTypeEnum, SurveyQuestionBatchSchema, SurveyQuestionGroupSchema, UncoveredStruggleSchema, UncoveredStrugglesInputSchema, version as VERSION, VisualCompareCliOptionsSchema, absolutePositionInAutoLayout, analyzeFile, buildFigmaDeepLink, buildResultJson, calculateScores, collectComponentIds, collectInteractionDestinationIds, createRuleEngine, deepNesting, defineRule, detachedInstance, detectAnalysisScope, extractRuleScores, fixedSizeInAutoLayout, formatScoreSummary, generateCalibrationReport, generateDesignTree, generateDesignTreeWithStats, getAnalysisState, getAnnotationProperties, getCategoryLabel, getConfigsWithPreset, getRuleOption, getRulePurpose, getSeverityLabel, gradeToClassName, inconsistentNamingConvention, irregularSpacing, isInstanceChildNodeId, isReadyForCodeGen, loadFigmaFileFromJson, missingComponent, missingInteractionState, missingPrototype, missingSizeConstraint, noAutoLayout, nonLayoutContainer, nonSemanticName, nonStandardNaming, parseFigmaJson, parseFigmaUrl, parseInstanceChildNodeId, rawValue, resolveComponentDefinitions, resolveGotchaApplyTarget, resolveInteractionDestinations, ruleRegistry, runAnalysisAgent, runCalibrationAnalyze, runCalibrationEvaluate, runEvaluationAgent, runTuningAgent, stripDeltaToDifficulty, stripDesignTree, supportsDepthWeight, toCommentableNodeId, tokenDeltaToDifficulty, transformComponentMasterNodes, transformFigmaResponse, transformFileNodesResponse, unmappedComponent, variantStructureMismatch };
|
|
5674
|
+
export { ALL_STRIP_TYPES, ActivityLogger, AnalysisFileSchema, AnalysisNodeSchema, AnalysisNodeTypeSchema, AnalysisScopeSchema, AnnotationPropertySchema, CATEGORIES, CATEGORY_LABELS, CalibrationConfigSchema, CalibrationStatusSchema, CategorySchema, CategoryScoreSchema, ConfidenceSchema, ConversionRecordSchema, DEFAULT_CODEGEN_READY_MIN_GRADE, DEPTH_WEIGHT_CATEGORIES, DESIGN_TREE_INFO_TYPES, DetectionSchema, DifficultySchema, FigmaClient, FigmaClientError, FigmaFileLoadError, FigmaUrlInfoSchema, FigmaUrlParseError, GRADE_ORDER, GapAnalyzerOutputSchema, GapEntrySchema, GotchaDetectionSchema, GotchaOutputChannelSchema, GotchaPersistenceIntentSchema, GotchaSurveyQuestionSchema, GotchaSurveySchema, GridChildAlignSchema, GroupedSurveySchema, InstanceContextSchema, IssueSchema, LayoutAlignSchema, LayoutConstraintSchema, LayoutModeSchema, LayoutPositioningSchema, LayoutWrapSchema, McpAnalyzeResponseSchema, MismatchCaseSchema, MismatchTypeSchema, NewRuleProposalSchema, NodeIssueSummarySchema, OutputChannelSchema, OverflowDirectionSchema, PersistenceIntentSchema, ROUNDTRIP_OPT_OUT_HINT, RULE_ANNOTATION_PROPERTIES, RULE_CONFIGS, RULE_ID_CATEGORY, RULE_PURPOSE, ReportMetadataSchema, ReportSchema, RuleApplyStrategySchema, RuleConfigSchema, RuleDefinitionSchema, RuleEngine, RuleImpactAssessmentSchema, RulePurposeSchema, RuleRelatedStruggleSchema, SEVERITY_LABELS, SEVERITY_WEIGHT, SamplingStrategySchema, ScoreAdjustmentSchema, SeveritySchema, StripDeltaResultSchema, StripDeltasArraySchema, StripTypeEnum, SurveyQuestionBatchSchema, SurveyQuestionGroupSchema, UncoveredStruggleSchema, UncoveredStrugglesInputSchema, version as VERSION, VisualCompareCliOptionsSchema, absolutePositionInAutoLayout, analyzeFile, buildFigmaDeepLink, buildResultJson, calculateScores, collectComponentIds, collectInteractionDestinationIds, createRuleEngine, deepNesting, defineRule, detachedInstance, detectAnalysisScope, extractRuleScores, fixedSizeInAutoLayout, formatCodeConnectCoverageLine, formatRoundtripOptOutHintLine, formatScoreSummary, generateCalibrationReport, generateDesignTree, generateDesignTreeWithStats, getAnalysisState, getAnnotationProperties, getCategoryLabel, getConfigsWithPreset, getRuleOption, getRulePurpose, getSeverityLabel, gradeToClassName, inconsistentNamingConvention, irregularSpacing, isInstanceChildNodeId, isReadyForCodeGen, loadFigmaFileFromJson, missingComponent, missingInteractionState, missingPrototype, missingSizeConstraint, noAutoLayout, nonLayoutContainer, nonSemanticName, nonStandardNaming, parseFigmaJson, parseFigmaUrl, parseInstanceChildNodeId, rawValue, resolveComponentDefinitions, resolveGotchaApplyTarget, resolveInteractionDestinations, ruleRegistry, runAnalysisAgent, runCalibrationAnalyze, runCalibrationEvaluate, runEvaluationAgent, runTuningAgent, stripDeltaToDifficulty, stripDesignTree, supportsDepthWeight, toCommentableNodeId, tokenDeltaToDifficulty, transformComponentMasterNodes, transformFigmaResponse, transformFileNodesResponse, unmappedComponent, variantStructureMismatch };
|
|
5431
5675
|
//# sourceMappingURL=index.js.map
|
|
5432
5676
|
//# sourceMappingURL=index.js.map
|