@fragments-sdk/cli 0.3.3 → 0.4.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.
Files changed (62) hide show
  1. package/dist/bin.js +18 -13
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-MUZ6CM66.js → chunk-5JNME72P.js} +3 -3
  4. package/dist/{chunk-MUZ6CM66.js.map → chunk-5JNME72P.js.map} +1 -1
  5. package/dist/{chunk-XHNKNI6J.js → chunk-AW7MWOUH.js} +9 -1
  6. package/dist/chunk-AW7MWOUH.js.map +1 -0
  7. package/dist/{chunk-LY2CFFPY.js → chunk-FYIYMXGA.js} +2 -2
  8. package/dist/{chunk-3OTEW66K.js → chunk-LDKNZ55O.js} +4 -4
  9. package/dist/{chunk-BSCG3IP7.js → chunk-NOTYONHY.js} +2 -2
  10. package/dist/{chunk-D6VXWI45.js → chunk-ODXQAQQX.js} +8 -6
  11. package/dist/chunk-ODXQAQQX.js.map +1 -0
  12. package/dist/{chunk-PMGI7ATF.js → chunk-OZQ7Z6C3.js} +31 -2
  13. package/dist/chunk-OZQ7Z6C3.js.map +1 -0
  14. package/dist/{core-DWKLGY4N.js → core-F3VT277E.js} +5 -3
  15. package/dist/{generate-3LBZANQ3.js → generate-PNIUR75D.js} +4 -4
  16. package/dist/index.d.ts +16 -0
  17. package/dist/index.js +6 -6
  18. package/dist/{init-NKIUCYTG.js → init-ON6WYG66.js} +4 -4
  19. package/dist/mcp-bin.js +3 -3
  20. package/dist/scan-E6U644RS.js +12 -0
  21. package/dist/{service-QSZMZJBJ.js → service-U7AR2PC2.js} +4 -4
  22. package/dist/{static-viewer-MIPGZ4Z7.js → static-viewer-QL2SCWYB.js} +4 -4
  23. package/dist/{test-ZCTR4LBB.js → test-PBPKJ4WJ.js} +3 -3
  24. package/dist/{tokens-5JQ5IOR2.js → tokens-4J4PRIGT.js} +5 -5
  25. package/dist/{viewer-D7QC4GM2.js → viewer-6VCZMA3T.js} +13 -13
  26. package/package.json +1 -1
  27. package/src/bin.ts +7 -1
  28. package/src/build.ts +2 -0
  29. package/src/core/index.ts +4 -0
  30. package/src/core/parser.ts +54 -1
  31. package/src/core/schema.ts +11 -0
  32. package/src/core/types.ts +24 -0
  33. package/src/migrate/bin.ts +7 -1
  34. package/src/migrate/report.ts +1 -1
  35. package/src/service/report.ts +1 -1
  36. package/src/theme/__tests__/generator.test.ts +412 -0
  37. package/src/theme/__tests__/presets.test.ts +169 -0
  38. package/src/theme/__tests__/schema.test.ts +463 -0
  39. package/src/theme/__tests__/serializer.test.ts +326 -0
  40. package/src/theme/generator.ts +355 -0
  41. package/src/theme/index.ts +61 -0
  42. package/src/theme/presets.ts +189 -0
  43. package/src/theme/schema.ts +193 -0
  44. package/src/theme/serializer.ts +123 -0
  45. package/src/theme/types.ts +210 -0
  46. package/src/viewer/styles/globals.css +1 -1
  47. package/dist/chunk-D6VXWI45.js.map +0 -1
  48. package/dist/chunk-PMGI7ATF.js.map +0 -1
  49. package/dist/chunk-XHNKNI6J.js.map +0 -1
  50. package/dist/scan-3ZAOVO4U.js +0 -12
  51. /package/dist/{chunk-LY2CFFPY.js.map → chunk-FYIYMXGA.js.map} +0 -0
  52. /package/dist/{chunk-3OTEW66K.js.map → chunk-LDKNZ55O.js.map} +0 -0
  53. /package/dist/{chunk-BSCG3IP7.js.map → chunk-NOTYONHY.js.map} +0 -0
  54. /package/dist/{core-DWKLGY4N.js.map → core-F3VT277E.js.map} +0 -0
  55. /package/dist/{generate-3LBZANQ3.js.map → generate-PNIUR75D.js.map} +0 -0
  56. /package/dist/{init-NKIUCYTG.js.map → init-ON6WYG66.js.map} +0 -0
  57. /package/dist/{scan-3ZAOVO4U.js.map → scan-E6U644RS.js.map} +0 -0
  58. /package/dist/{service-QSZMZJBJ.js.map → service-U7AR2PC2.js.map} +0 -0
  59. /package/dist/{static-viewer-MIPGZ4Z7.js.map → static-viewer-QL2SCWYB.js.map} +0 -0
  60. /package/dist/{test-ZCTR4LBB.js.map → test-PBPKJ4WJ.js.map} +0 -0
  61. /package/dist/{tokens-5JQ5IOR2.js.map → tokens-4J4PRIGT.js.map} +0 -0
  62. /package/dist/{viewer-D7QC4GM2.js.map → viewer-6VCZMA3T.js.map} +0 -0
@@ -6,13 +6,13 @@ import {
6
6
  findStorybookDir,
7
7
  generatePreviewModule,
8
8
  loadConfig
9
- } from "./chunk-PMGI7ATF.js";
9
+ } from "./chunk-OZQ7Z6C3.js";
10
10
  import {
11
11
  generateContext
12
- } from "./chunk-LY2CFFPY.js";
12
+ } from "./chunk-FYIYMXGA.js";
13
13
  import {
14
14
  BRAND
15
- } from "./chunk-XHNKNI6J.js";
15
+ } from "./chunk-AW7MWOUH.js";
16
16
 
17
17
  // src/viewer/server.ts
18
18
  import {
@@ -242,7 +242,7 @@ var sharedRenderPool = null;
242
242
  var browserPoolModule = null;
243
243
  async function getSharedRenderPool() {
244
244
  if (!browserPoolModule) {
245
- browserPoolModule = await import("./service-QSZMZJBJ.js");
245
+ browserPoolModule = await import("./service-U7AR2PC2.js");
246
246
  }
247
247
  if (!sharedRenderPool) {
248
248
  sharedRenderPool = new browserPoolModule.BrowserPool({
@@ -471,7 +471,7 @@ function segmentsPlugin(options) {
471
471
  const address = _server.httpServer?.address();
472
472
  const port = typeof address === "object" && address ? address.port : 6006;
473
473
  const renderViewport = viewport || { width: 800, height: 600 };
474
- const { FigmaClient, bufferToBase64Url } = await import("./service-QSZMZJBJ.js");
474
+ const { FigmaClient, bufferToBase64Url } = await import("./service-U7AR2PC2.js");
475
475
  const figmaClient = new FigmaClient({
476
476
  accessToken: figmaToken
477
477
  });
@@ -562,7 +562,7 @@ function segmentsPlugin(options) {
562
562
  );
563
563
  return;
564
564
  }
565
- const { FigmaClient } = await import("./service-QSZMZJBJ.js");
565
+ const { FigmaClient } = await import("./service-U7AR2PC2.js");
566
566
  const figmaClient = new FigmaClient({ accessToken: figmaToken });
567
567
  const { fileKey, nodeId } = figmaClient.parseUrl(figmaUrl);
568
568
  const figmaDesignProps = await figmaClient.getNodeProperties(
@@ -603,7 +603,7 @@ function segmentsPlugin(options) {
603
603
  }));
604
604
  return;
605
605
  }
606
- const { getSharedTokenRegistry } = await import("./service-QSZMZJBJ.js");
606
+ const { getSharedTokenRegistry } = await import("./service-U7AR2PC2.js");
607
607
  const registry = getSharedTokenRegistry();
608
608
  if (!registry.isInitialized()) {
609
609
  await registry.initialize(config.tokens, projectRoot);
@@ -663,7 +663,7 @@ function segmentsPlugin(options) {
663
663
  }));
664
664
  return;
665
665
  }
666
- const { getSharedTokenRegistry } = await import("./service-QSZMZJBJ.js");
666
+ const { getSharedTokenRegistry } = await import("./service-U7AR2PC2.js");
667
667
  const registry = getSharedTokenRegistry();
668
668
  if (!registry.isInitialized()) {
669
669
  await registry.initialize(config.tokens, projectRoot);
@@ -725,7 +725,7 @@ function segmentsPlugin(options) {
725
725
  res.end(JSON.stringify({ error: "Could not resolve segment file path" }));
726
726
  return;
727
727
  }
728
- const { getSharedTokenRegistry } = await import("./service-QSZMZJBJ.js");
728
+ const { getSharedTokenRegistry } = await import("./service-U7AR2PC2.js");
729
729
  const registry = getSharedTokenRegistry();
730
730
  if (!registry.isInitialized()) {
731
731
  await registry.initialize(config.tokens, projectRoot);
@@ -851,7 +851,7 @@ function segmentsPlugin(options) {
851
851
  }
852
852
  const { writeFile, mkdir } = await import("fs/promises");
853
853
  const { join: join2 } = await import("path");
854
- const { BRAND: BRAND2 } = await import("./core-DWKLGY4N.js");
854
+ const { BRAND: BRAND2 } = await import("./core-F3VT277E.js");
855
855
  const fragmentsDir = join2(projectRoot, BRAND2.dataDir, BRAND2.componentsDir);
856
856
  await mkdir(fragmentsDir, { recursive: true });
857
857
  const fragmentPath = join2(
@@ -906,7 +906,7 @@ function segmentsPlugin(options) {
906
906
  const {
907
907
  getSharedTokenRegistry,
908
908
  generateTokenPatches
909
- } = await import("./service-QSZMZJBJ.js");
909
+ } = await import("./service-U7AR2PC2.js");
910
910
  const registry = getSharedTokenRegistry();
911
911
  if (!registry.isInitialized()) {
912
912
  await registry.initialize(config.tokens, projectRoot);
@@ -1568,7 +1568,7 @@ async function loadFullSegmentForCompare(_server, _segmentFiles, componentName,
1568
1568
  }
1569
1569
  }
1570
1570
  async function compareImages(image1Base64, image2Base64, threshold) {
1571
- const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-QSZMZJBJ.js");
1571
+ const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-U7AR2PC2.js");
1572
1572
  const { PNG } = await import("pngjs");
1573
1573
  const buffer1 = base64UrlToBuffer(image1Base64);
1574
1574
  const buffer2 = base64UrlToBuffer(image2Base64);
@@ -11101,4 +11101,4 @@ export {
11101
11101
  segmentsPlugin,
11102
11102
  useTheme
11103
11103
  };
11104
- //# sourceMappingURL=viewer-D7QC4GM2.js.map
11104
+ //# sourceMappingURL=viewer-6VCZMA3T.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fragments-sdk/cli",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "CLI, MCP server, and dev tools for Fragments design system",
5
5
  "type": "module",
6
6
  "bin": {
package/src/bin.ts CHANGED
@@ -8,9 +8,15 @@
8
8
 
9
9
  import { Command } from 'commander';
10
10
  import pc from 'picocolors';
11
+ import { readFileSync } from 'node:fs';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { dirname, join } from 'node:path';
11
14
  import { BRAND } from './core/index.js';
12
15
  import { loadConfig } from './core/node.js';
13
16
 
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8')) as { version: string };
19
+
14
20
  // Import command implementations
15
21
  import { validate } from './commands/validate.js';
16
22
  import { build } from './commands/build.js';
@@ -40,7 +46,7 @@ const program = new Command();
40
46
  program
41
47
  .name(BRAND.cliCommand)
42
48
  .description(`${BRAND.name} - Design system documentation and compliance tool`)
43
- .version('0.1.0');
49
+ .version(pkg.version);
44
50
 
45
51
  // ============================================================================
46
52
  // VALIDATE COMMAND
package/src/build.ts CHANGED
@@ -111,6 +111,8 @@ export async function buildSegments(
111
111
  ...(v.figma && { figma: v.figma }),
112
112
  ...(v.args && { args: v.args }),
113
113
  })),
114
+ // Include AI metadata if present
115
+ ...(parsed.ai && { ai: parsed.ai }),
114
116
  };
115
117
 
116
118
  segments[parsed.meta.name] = compiled;
package/src/core/index.ts CHANGED
@@ -32,6 +32,8 @@ export type {
32
32
  // Contract and provenance types
33
33
  SegmentContract,
34
34
  SegmentGenerated,
35
+ // AI metadata type
36
+ AIMetadata,
35
37
  // Screenshot types
36
38
  ScreenshotConfig,
37
39
  ServiceConfig,
@@ -87,6 +89,8 @@ export {
87
89
  segmentGeneratedSchema,
88
90
  segmentBanSchema,
89
91
  recipeDefinitionSchema,
92
+ // AI metadata schema
93
+ aiMetadataSchema,
90
94
  } from "./schema.js";
91
95
 
92
96
  // Main API
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import ts from "typescript";
11
- import type { SegmentMeta, SegmentUsage, PropDefinition } from "./types.js";
11
+ import type { SegmentMeta, SegmentUsage, PropDefinition, AIMetadata } from "./types.js";
12
12
 
13
13
  /**
14
14
  * Parsed segment metadata (extracted statically from AST)
@@ -45,6 +45,9 @@ export interface ParsedSegmentMetadata {
45
45
  note: string;
46
46
  }>;
47
47
 
48
+ /** AI-specific metadata for playground context generation */
49
+ ai?: AIMetadata;
50
+
48
51
  /** Parse warnings */
49
52
  warnings: string[];
50
53
  }
@@ -129,6 +132,9 @@ export function parseSegmentFile(
129
132
  // Extract relations
130
133
  const relations = extractRelations(arg, warnings);
131
134
 
135
+ // Extract AI metadata
136
+ const ai = extractAIMetadata(arg, warnings);
137
+
132
138
  return {
133
139
  componentImport,
134
140
  componentName,
@@ -137,6 +143,7 @@ export function parseSegmentFile(
137
143
  props,
138
144
  variants,
139
145
  relations,
146
+ ai,
140
147
  warnings,
141
148
  };
142
149
  }
@@ -460,6 +467,52 @@ function extractRelations(
460
467
  return relations;
461
468
  }
462
469
 
470
+ /**
471
+ * Extract AI metadata from defineSegment call.
472
+ */
473
+ function extractAIMetadata(
474
+ arg: ts.ObjectLiteralExpression,
475
+ warnings: string[]
476
+ ): AIMetadata | undefined {
477
+ const aiProp = findProperty(arg, "ai");
478
+ if (!aiProp || !ts.isObjectLiteralExpression(aiProp)) {
479
+ return undefined;
480
+ }
481
+
482
+ const ai: AIMetadata = {};
483
+
484
+ // Extract compositionPattern
485
+ const compositionPattern = extractStringProperty(aiProp, "compositionPattern");
486
+ if (compositionPattern && ['compound', 'simple', 'controlled'].includes(compositionPattern)) {
487
+ ai.compositionPattern = compositionPattern as AIMetadata['compositionPattern'];
488
+ }
489
+
490
+ // Extract subComponents array
491
+ const subComponents = extractStringArray(aiProp, "subComponents");
492
+ if (subComponents.length > 0) {
493
+ ai.subComponents = subComponents;
494
+ }
495
+
496
+ // Extract requiredChildren array
497
+ const requiredChildren = extractStringArray(aiProp, "requiredChildren");
498
+ if (requiredChildren.length > 0) {
499
+ ai.requiredChildren = requiredChildren;
500
+ }
501
+
502
+ // Extract commonPatterns array
503
+ const commonPatterns = extractStringArray(aiProp, "commonPatterns");
504
+ if (commonPatterns.length > 0) {
505
+ ai.commonPatterns = commonPatterns;
506
+ }
507
+
508
+ // Only return if we have any fields
509
+ if (Object.keys(ai).length > 0) {
510
+ return ai;
511
+ }
512
+
513
+ return undefined;
514
+ }
515
+
463
516
  /**
464
517
  * Extract a string property from an object literal.
465
518
  */
@@ -138,6 +138,16 @@ export const segmentGeneratedSchema = z.object({
138
138
  timestamp: z.string().datetime().optional(),
139
139
  });
140
140
 
141
+ /**
142
+ * Schema for AI-specific metadata for playground context generation
143
+ */
144
+ export const aiMetadataSchema = z.object({
145
+ compositionPattern: z.enum(['compound', 'simple', 'controlled']).optional(),
146
+ subComponents: z.array(z.string()).optional(),
147
+ requiredChildren: z.array(z.string()).optional(),
148
+ commonPatterns: z.array(z.string()).optional(),
149
+ });
150
+
141
151
  /**
142
152
  * Schema for recipe definitions
143
153
  */
@@ -158,6 +168,7 @@ export const segmentDefinitionSchema = z.object({
158
168
  relations: z.array(componentRelationSchema).optional(),
159
169
  variants: z.array(segmentVariantSchema), // Allow empty variants array
160
170
  contract: segmentContractSchema.optional(),
171
+ ai: aiMetadataSchema.optional(),
161
172
  _generated: segmentGeneratedSchema.optional(),
162
173
  });
163
174
 
package/src/core/types.ts CHANGED
@@ -314,6 +314,24 @@ export interface SegmentGenerated {
314
314
  timestamp?: string;
315
315
  }
316
316
 
317
+ /**
318
+ * AI-specific metadata for playground context generation
319
+ * Provides hints for AI code generation about component composition
320
+ */
321
+ export interface AIMetadata {
322
+ /** How this component is composed with others */
323
+ compositionPattern?: "compound" | "simple" | "controlled";
324
+
325
+ /** Sub-component names (without parent prefix, e.g., "Header" not "Card.Header") */
326
+ subComponents?: string[];
327
+
328
+ /** Sub-components that must be present for valid composition */
329
+ requiredChildren?: string[];
330
+
331
+ /** Common usage patterns as JSX strings for AI reference */
332
+ commonPatterns?: string[];
333
+ }
334
+
317
335
  /**
318
336
  * Complete segment definition
319
337
  */
@@ -339,6 +357,9 @@ export interface SegmentDefinition<TProps = unknown> {
339
357
  /** Agent-optimized contract metadata */
340
358
  contract?: SegmentContract;
341
359
 
360
+ /** AI-specific metadata for playground context generation */
361
+ ai?: AIMetadata;
362
+
342
363
  /** Provenance tracking (for generated segments) */
343
364
  _generated?: SegmentGenerated;
344
365
  }
@@ -706,6 +727,9 @@ export interface CompiledSegment {
706
727
  /** Agent-optimized contract metadata */
707
728
  contract?: SegmentContract;
708
729
 
730
+ /** AI-specific metadata for playground context generation */
731
+ ai?: AIMetadata;
732
+
709
733
  /** Provenance tracking (for generated segments) */
710
734
  _generated?: SegmentGenerated;
711
735
  }
@@ -7,15 +7,21 @@
7
7
 
8
8
  import { Command } from "commander";
9
9
  import pc from "picocolors";
10
+ import { readFileSync } from "node:fs";
11
+ import { fileURLToPath } from "node:url";
12
+ import { dirname, join } from "node:path";
10
13
  import { BRAND } from "../core/index.js";
11
14
  import { migrate } from "./migrate.js";
12
15
 
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const pkg = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf-8")) as { version: string };
18
+
13
19
  const program = new Command();
14
20
 
15
21
  program
16
22
  .name("segments-migrate")
17
23
  .description(`${BRAND.name} Storybook Migration Tool`)
18
- .version("0.0.1");
24
+ .version(pkg.version);
19
25
 
20
26
  program
21
27
  .command("migrate")
@@ -49,7 +49,7 @@ function getStyles(): string {
49
49
  --bg-warning: rgba(234, 179, 8, 0.1);
50
50
  --bg-error: rgba(239, 68, 68, 0.1);
51
51
  --border: #262626;
52
- --text: #fafafa;
52
+ --text: #f2f2f2;
53
53
  --text-secondary: #a1a1aa;
54
54
  --text-muted: #71717a;
55
55
  --accent: #8b5cf6;
@@ -61,7 +61,7 @@ function getStyles(): string {
61
61
  --bg-card: #141414;
62
62
  --bg-hover: #1a1a1a;
63
63
  --border: #262626;
64
- --text: #fafafa;
64
+ --text: #f2f2f2;
65
65
  --text-secondary: #a1a1aa;
66
66
  --text-muted: #71717a;
67
67
  --accent: #10b981;