@auto-engineer/design-system-importer 0.4.8 → 0.5.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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-format.log +10 -8
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +14 -12
- package/.turbo/turbo-type-check.log +5 -4
- package/CHANGELOG.md +11 -0
- package/DEBUG.md +195 -0
- package/README.md +45 -18
- package/dist/FigmaComponentsBuilder.d.ts +1 -0
- package/dist/FigmaComponentsBuilder.d.ts.map +1 -1
- package/dist/FigmaComponentsBuilder.js +138 -26
- package/dist/FigmaComponentsBuilder.js.map +1 -1
- package/dist/cli-manifest.d.ts +3 -0
- package/dist/cli-manifest.d.ts.map +1 -0
- package/dist/cli-manifest.js +17 -0
- package/dist/cli-manifest.js.map +1 -0
- package/dist/commands/import-design-system.d.ts +8 -1
- package/dist/commands/import-design-system.d.ts.map +1 -1
- package/dist/commands/import-design-system.js +88 -5
- package/dist/commands/import-design-system.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -17
- package/dist/index.js.map +1 -1
- package/dist/utils/FilterLoader.d.ts.map +1 -1
- package/dist/utils/FilterLoader.js +84 -4
- package/dist/utils/FilterLoader.js.map +1 -1
- package/package.json +5 -6
- package/src/FigmaComponentsBuilder.ts +162 -29
- package/src/cli-manifest.ts +18 -0
- package/src/commands/import-design-system.ts +101 -5
- package/src/index.ts +125 -16
- package/src/utils/FilterLoader.ts +85 -4
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
import * as dotenv from 'dotenv';
|
|
2
2
|
import * as Figma from 'figma-api';
|
|
3
|
+
import createDebug from 'debug';
|
|
4
|
+
|
|
5
|
+
const debug = createDebug('design-system-importer:figma-builder');
|
|
6
|
+
const debugComponents = createDebug('design-system-importer:figma-builder:components');
|
|
7
|
+
const debugFilters = createDebug('design-system-importer:figma-builder:filters');
|
|
8
|
+
const debugAPI = createDebug('design-system-importer:figma-builder:api');
|
|
9
|
+
const debugTree = createDebug('design-system-importer:figma-builder:tree');
|
|
3
10
|
|
|
4
11
|
dotenv.config();
|
|
5
12
|
|
|
13
|
+
debug('Initializing FigmaComponentsBuilder module');
|
|
14
|
+
|
|
15
|
+
// Add timeout wrapper for Figma API calls
|
|
16
|
+
const withTimeout = <T>(promise: Promise<T>, timeoutMs: number = 10000): Promise<T> => {
|
|
17
|
+
return Promise.race([
|
|
18
|
+
promise,
|
|
19
|
+
new Promise<T>((_, reject) =>
|
|
20
|
+
setTimeout(() => reject(new Error(`Figma API request timed out after ${timeoutMs}ms`)), timeoutMs),
|
|
21
|
+
),
|
|
22
|
+
]);
|
|
23
|
+
};
|
|
24
|
+
|
|
6
25
|
const figmaApi = new Figma.Api({
|
|
7
26
|
personalAccessToken: process.env.FIGMA_PERSONAL_TOKEN as string,
|
|
8
27
|
});
|
|
28
|
+
debug('Figma API initialized with personal access token');
|
|
9
29
|
|
|
10
30
|
export interface FigmaComponent {
|
|
11
31
|
name: string;
|
|
@@ -26,47 +46,103 @@ interface FigmaNode {
|
|
|
26
46
|
export class FigmaComponentsBuilder {
|
|
27
47
|
components: FigmaComponent[] = [];
|
|
28
48
|
|
|
49
|
+
constructor() {
|
|
50
|
+
debug('FigmaComponentsBuilder instance created');
|
|
51
|
+
debugComponents('Initial components array: empty');
|
|
52
|
+
}
|
|
53
|
+
|
|
29
54
|
async withFigmaComponents() {
|
|
55
|
+
debugAPI('Fetching Figma components from file: %s', process.env.FIGMA_FILE_ID);
|
|
56
|
+
|
|
57
|
+
if (
|
|
58
|
+
process.env.FIGMA_PERSONAL_TOKEN?.trim() === '' ||
|
|
59
|
+
process.env.FIGMA_FILE_ID?.trim() === '' ||
|
|
60
|
+
process.env.FIGMA_PERSONAL_TOKEN === undefined ||
|
|
61
|
+
process.env.FIGMA_FILE_ID === undefined
|
|
62
|
+
) {
|
|
63
|
+
debugAPI('Missing Figma credentials. FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID not set');
|
|
64
|
+
console.warn('Skipping Figma import: Missing FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID in environment');
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
|
|
30
68
|
try {
|
|
69
|
+
debugAPI('Making API call to getFileComponents...');
|
|
31
70
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
32
|
-
const response = await figmaApi.getFileComponents({ file_key: process.env.FIGMA_FILE_ID });
|
|
71
|
+
const response = await withTimeout(figmaApi.getFileComponents({ file_key: process.env.FIGMA_FILE_ID }), 10000);
|
|
72
|
+
debugAPI('API response received');
|
|
33
73
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
34
74
|
if (response.meta.components.length > 0) {
|
|
35
75
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
36
|
-
|
|
76
|
+
debugComponents('Found %d components in Figma file', response.meta.components.length);
|
|
37
77
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
|
38
78
|
this.components = response.meta.components.map(
|
|
39
|
-
(component: { name: string; description: string; thumbnail_url: string }) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
79
|
+
(component: { name: string; description: string; thumbnail_url: string }) => {
|
|
80
|
+
debugComponents('Processing component: %s', component.name);
|
|
81
|
+
return {
|
|
82
|
+
name: component.name,
|
|
83
|
+
description: component.description,
|
|
84
|
+
thumbnail: component.thumbnail_url,
|
|
85
|
+
};
|
|
86
|
+
},
|
|
44
87
|
);
|
|
88
|
+
debugComponents('Successfully mapped %d components', this.components.length);
|
|
89
|
+
} else {
|
|
90
|
+
debugComponents('No components found in Figma file');
|
|
45
91
|
}
|
|
46
92
|
} catch (e) {
|
|
47
|
-
|
|
93
|
+
debugAPI('ERROR: Failed to fetch Figma components: %O', e);
|
|
94
|
+
console.error('Failed to fetch Figma components:', e);
|
|
48
95
|
}
|
|
96
|
+
debugComponents('withFigmaComponents complete, total components: %d', this.components.length);
|
|
49
97
|
return this;
|
|
50
98
|
}
|
|
51
99
|
|
|
52
100
|
async withFigmaComponentSets() {
|
|
101
|
+
debugAPI('Fetching Figma component sets from file: %s', process.env.FIGMA_FILE_ID);
|
|
102
|
+
|
|
103
|
+
if (
|
|
104
|
+
process.env.FIGMA_PERSONAL_TOKEN?.trim() === '' ||
|
|
105
|
+
process.env.FIGMA_FILE_ID?.trim() === '' ||
|
|
106
|
+
process.env.FIGMA_PERSONAL_TOKEN === undefined ||
|
|
107
|
+
process.env.FIGMA_FILE_ID === undefined
|
|
108
|
+
) {
|
|
109
|
+
debugAPI('Missing Figma credentials. FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID not set');
|
|
110
|
+
console.warn('Skipping Figma import: Missing FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID in environment');
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
53
114
|
try {
|
|
115
|
+
debugAPI('Making API call to getFileComponentSets...');
|
|
54
116
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
55
|
-
const response = await figmaApi.getFileComponentSets({ file_key: process.env.FIGMA_FILE_ID });
|
|
117
|
+
const response = await withTimeout(figmaApi.getFileComponentSets({ file_key: process.env.FIGMA_FILE_ID }), 10000);
|
|
118
|
+
debugAPI('API response received');
|
|
56
119
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
57
120
|
if (response.meta.component_sets.length > 0) {
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
122
|
+
debugComponents('Found %d component sets in Figma file', response.meta.component_sets.length);
|
|
58
123
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
|
59
124
|
this.components = response.meta.component_sets.map(
|
|
60
|
-
(component: { name: string; description: string; thumbnail_url: string }) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
(component: { name: string; description: string; thumbnail_url: string }) => {
|
|
126
|
+
debugComponents('Processing component set: %s', component.name);
|
|
127
|
+
const mapped = {
|
|
128
|
+
name: component.name,
|
|
129
|
+
description: component.description ?? 'N/A',
|
|
130
|
+
thumbnail: component.thumbnail_url ?? 'N/A',
|
|
131
|
+
};
|
|
132
|
+
debugComponents(' - Description: %s', mapped.description.substring(0, 50));
|
|
133
|
+
debugComponents(' - Has thumbnail: %s', mapped.thumbnail !== 'N/A');
|
|
134
|
+
return mapped;
|
|
135
|
+
},
|
|
65
136
|
);
|
|
137
|
+
debugComponents('Successfully mapped %d component sets', this.components.length);
|
|
138
|
+
} else {
|
|
139
|
+
debugComponents('No component sets found in Figma file');
|
|
66
140
|
}
|
|
67
141
|
} catch (e) {
|
|
68
|
-
|
|
142
|
+
debugAPI('ERROR: Failed to fetch Figma component sets: %O', e);
|
|
143
|
+
console.error('Failed to fetch Figma component sets:', e);
|
|
69
144
|
}
|
|
145
|
+
debugComponents('withFigmaComponentSets complete, total components: %d', this.components.length);
|
|
70
146
|
return this;
|
|
71
147
|
}
|
|
72
148
|
|
|
@@ -81,73 +157,122 @@ export class FigmaComponentsBuilder {
|
|
|
81
157
|
// }
|
|
82
158
|
|
|
83
159
|
withFilteredNamesForShadcn(): void {
|
|
160
|
+
debugFilters('Applying Shadcn name filter to %d components', this.components.length);
|
|
161
|
+
const originalCount = this.components.length;
|
|
84
162
|
this.components = this.components
|
|
85
163
|
.map((comp: FigmaComponent): FigmaComponent | null => {
|
|
86
|
-
if (!comp?.name)
|
|
164
|
+
if (!comp?.name) {
|
|
165
|
+
debugFilters('Skipping component with no name');
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
87
168
|
|
|
88
169
|
let str = comp.name.trim();
|
|
170
|
+
debugFilters('Processing component name: %s', str);
|
|
89
171
|
|
|
90
172
|
if (str.includes('/')) {
|
|
173
|
+
const original = str;
|
|
91
174
|
str = str.split('/')[0].trim();
|
|
175
|
+
debugFilters(' Split by /: %s -> %s', original, str);
|
|
92
176
|
} else {
|
|
177
|
+
const original = str;
|
|
93
178
|
str = str.split(' ')[0].trim();
|
|
179
|
+
debugFilters(' Split by space: %s -> %s', original, str);
|
|
94
180
|
}
|
|
95
181
|
|
|
96
182
|
if (str.length > 0) {
|
|
97
|
-
|
|
183
|
+
const capitalized = str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
184
|
+
const final = capitalized.toLowerCase();
|
|
185
|
+
debugFilters(' Normalized: %s -> %s', str, final);
|
|
186
|
+
return {
|
|
187
|
+
...comp,
|
|
188
|
+
name: final,
|
|
189
|
+
};
|
|
98
190
|
} else {
|
|
191
|
+
debugFilters(' Empty string after processing, skipping');
|
|
99
192
|
return null;
|
|
100
193
|
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
...comp,
|
|
104
|
-
name: str.toLowerCase(),
|
|
105
|
-
};
|
|
106
194
|
})
|
|
107
195
|
.filter((c: FigmaComponent | null): c is FigmaComponent => Boolean(c));
|
|
196
|
+
debugFilters('Shadcn filter complete: %d -> %d components', originalCount, this.components.length);
|
|
108
197
|
}
|
|
109
198
|
|
|
110
199
|
withFilter(filter: FilterFunctionType): void {
|
|
200
|
+
debugFilters('Applying custom filter function to %d components', this.components.length);
|
|
201
|
+
const originalCount = this.components.length;
|
|
111
202
|
try {
|
|
112
203
|
this.components = filter(this.components);
|
|
204
|
+
debugFilters('Custom filter applied successfully: %d -> %d components', originalCount, this.components.length);
|
|
113
205
|
} catch (e) {
|
|
206
|
+
debugFilters('ERROR: Failed to apply custom filter: %O', e);
|
|
114
207
|
console.error('Error applying custom filter:', e);
|
|
115
208
|
}
|
|
116
209
|
}
|
|
117
210
|
|
|
118
211
|
async withAllFigmaInstanceNames() {
|
|
212
|
+
debugAPI('Fetching all Figma instance names from file: %s', process.env.FIGMA_FILE_ID);
|
|
213
|
+
|
|
214
|
+
if (
|
|
215
|
+
process.env.FIGMA_PERSONAL_TOKEN?.trim() === '' ||
|
|
216
|
+
process.env.FIGMA_FILE_ID?.trim() === '' ||
|
|
217
|
+
process.env.FIGMA_PERSONAL_TOKEN === undefined ||
|
|
218
|
+
process.env.FIGMA_FILE_ID === undefined
|
|
219
|
+
) {
|
|
220
|
+
debugAPI('Missing Figma credentials. FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID not set');
|
|
221
|
+
console.warn('Skipping Figma import: Missing FIGMA_PERSONAL_TOKEN or FIGMA_FILE_ID in environment');
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
224
|
+
|
|
119
225
|
try {
|
|
120
226
|
/// ----
|
|
121
227
|
const usedComponentMap = new Map<string, { name: string; description: string; thumbnail: string }>();
|
|
228
|
+
debugTree('Created component map for tracking unique instances');
|
|
122
229
|
|
|
230
|
+
debugAPI('Making API call to getFile with depth: 1...');
|
|
123
231
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
124
|
-
const { document } = await
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
232
|
+
const { document } = await withTimeout(
|
|
233
|
+
figmaApi.getFile({
|
|
234
|
+
file_key: process.env.FIGMA_FILE_ID,
|
|
235
|
+
depth: 1,
|
|
236
|
+
}),
|
|
237
|
+
10000,
|
|
238
|
+
);
|
|
239
|
+
debugAPI('File document received, starting tree walk');
|
|
240
|
+
|
|
241
|
+
// eslint-disable-next-line complexity
|
|
242
|
+
function walkTree(node: FigmaNode, depth: number = 0) {
|
|
243
|
+
const indent = ' '.repeat(depth);
|
|
244
|
+
debugTree('%sVisiting node: %s (type: %s)', indent, node.name, node.type);
|
|
128
245
|
|
|
129
|
-
function walkTree(node: FigmaNode) {
|
|
130
246
|
if (node.type === 'INSTANCE' && Boolean(node.name)) {
|
|
131
247
|
if (!usedComponentMap.has(node.name)) {
|
|
248
|
+
debugTree('%s -> Found new instance: %s', indent, node.name);
|
|
132
249
|
usedComponentMap.set(node.name, {
|
|
133
250
|
name: node.name,
|
|
134
251
|
description: node.description ?? '',
|
|
135
252
|
thumbnail: node.thumbnail_url ?? '',
|
|
136
253
|
});
|
|
254
|
+
debugTree('%s Description: %s', indent, node.description ? 'present' : 'empty');
|
|
255
|
+
debugTree('%s Thumbnail: %s', indent, node.thumbnail_url ? 'present' : 'missing');
|
|
256
|
+
} else {
|
|
257
|
+
debugTree('%s -> Instance already tracked: %s', indent, node.name);
|
|
137
258
|
}
|
|
138
259
|
}
|
|
139
260
|
|
|
140
261
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
141
262
|
if (node.children) {
|
|
263
|
+
debugTree('%s Has %d children', indent, node.children.length);
|
|
142
264
|
for (const child of node.children) {
|
|
143
|
-
walkTree(child);
|
|
265
|
+
walkTree(child, depth + 1);
|
|
144
266
|
}
|
|
145
267
|
}
|
|
146
268
|
}
|
|
147
269
|
|
|
270
|
+
debugTree('Starting tree walk from document root');
|
|
148
271
|
walkTree(document);
|
|
272
|
+
debugTree('Tree walk complete');
|
|
149
273
|
|
|
150
274
|
this.components = Array.from(usedComponentMap.values());
|
|
275
|
+
debugComponents('Extracted %d unique component instances', this.components.length);
|
|
151
276
|
|
|
152
277
|
/// ----
|
|
153
278
|
|
|
@@ -196,12 +321,20 @@ export class FigmaComponentsBuilder {
|
|
|
196
321
|
// );
|
|
197
322
|
// }
|
|
198
323
|
} catch (e) {
|
|
199
|
-
|
|
324
|
+
debugAPI('ERROR: Failed to fetch Figma instance names: %O', e);
|
|
325
|
+
console.error('Failed to fetch Figma instance names:', e);
|
|
200
326
|
}
|
|
327
|
+
debugComponents('withAllFigmaInstanceNames complete, total components: %d', this.components.length);
|
|
201
328
|
return this;
|
|
202
329
|
}
|
|
203
330
|
|
|
204
331
|
build() {
|
|
332
|
+
debug('Building final component list');
|
|
333
|
+
debugComponents('Returning %d components', this.components.length);
|
|
334
|
+
if (this.components.length > 0) {
|
|
335
|
+
debugComponents('First component: %s', this.components[0].name);
|
|
336
|
+
debugComponents('Last component: %s', this.components[this.components.length - 1].name);
|
|
337
|
+
}
|
|
205
338
|
return this.components;
|
|
206
339
|
}
|
|
207
340
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CliManifest } from '@auto-engineer/cli/manifest-types';
|
|
2
|
+
|
|
3
|
+
export const CLI_MANIFEST: CliManifest = {
|
|
4
|
+
category: '@auto-engineer/design-system-importer',
|
|
5
|
+
commands: {
|
|
6
|
+
'import:design-system': {
|
|
7
|
+
handler: () => import('./commands/import-design-system'),
|
|
8
|
+
description: 'Import Figma design system',
|
|
9
|
+
usage: 'import:design-system <src> <mode> [filter]',
|
|
10
|
+
examples: ['$ auto import:design-system ./.context WITH_COMPONENT_SETS ./shadcn-filter.ts'],
|
|
11
|
+
args: [
|
|
12
|
+
{ name: 'src', description: 'Source directory for design system', required: true },
|
|
13
|
+
{ name: 'mode', description: 'Import mode (e.g., WITH_COMPONENT_SETS)', required: true },
|
|
14
|
+
{ name: 'filter', description: 'Optional filter file', required: false },
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type CommandHandler, type Command, type Event } from '@auto-engineer/message-bus';
|
|
2
2
|
import { importDesignSystemComponentsFromFigma, ImportStrategy, type FilterFunctionType } from '../index';
|
|
3
3
|
import { FilterLoader } from '../utils/FilterLoader';
|
|
4
|
+
import createDebug from 'debug';
|
|
5
|
+
|
|
6
|
+
const debug = createDebug('design-system-importer:command');
|
|
7
|
+
const debugFilter = createDebug('design-system-importer:command:filter');
|
|
8
|
+
const debugHandler = createDebug('design-system-importer:command:handler');
|
|
9
|
+
const debugResult = createDebug('design-system-importer:command:result');
|
|
4
10
|
|
|
5
11
|
export type ImportDesignSystemCommand = Command<
|
|
6
12
|
'ImportDesignSystem',
|
|
@@ -27,31 +33,51 @@ export type DesignSystemImportFailedEvent = Event<
|
|
|
27
33
|
>;
|
|
28
34
|
|
|
29
35
|
// Handler
|
|
30
|
-
|
|
36
|
+
// eslint-disable-next-line complexity
|
|
37
|
+
async function handleImportDesignSystemCommandInternal(
|
|
31
38
|
command: ImportDesignSystemCommand,
|
|
32
39
|
): Promise<DesignSystemImportedEvent | DesignSystemImportFailedEvent> {
|
|
33
40
|
const { outputDir, strategy, filterPath } = command.data;
|
|
34
41
|
|
|
42
|
+
debug('Handling ImportDesignSystemCommand');
|
|
43
|
+
debug(' Output directory: %s', outputDir);
|
|
44
|
+
debug(' Strategy: %s', strategy ?? 'default');
|
|
45
|
+
debug(' Filter path: %s', filterPath ?? 'none');
|
|
46
|
+
debug(' Request ID: %s', command.requestId);
|
|
47
|
+
debug(' Correlation ID: %s', command.correlationId ?? 'none');
|
|
48
|
+
|
|
35
49
|
try {
|
|
36
50
|
const resolvedStrategy = strategy ? ImportStrategy[strategy] : ImportStrategy.WITH_COMPONENT_SETS;
|
|
51
|
+
debugHandler('Resolved strategy: %s', resolvedStrategy);
|
|
37
52
|
|
|
38
53
|
let filterFn: FilterFunctionType | undefined;
|
|
39
54
|
let loader: FilterLoader | undefined;
|
|
40
55
|
if (typeof filterPath === 'string' && filterPath.trim().length > 0) {
|
|
56
|
+
debugFilter('Loading custom filter from: %s', filterPath);
|
|
41
57
|
try {
|
|
42
58
|
loader = new FilterLoader();
|
|
59
|
+
debugFilter('FilterLoader instance created');
|
|
43
60
|
filterFn = await loader.loadFilter(filterPath);
|
|
61
|
+
debugFilter('Filter function loaded successfully');
|
|
44
62
|
} catch (e) {
|
|
63
|
+
debugFilter('ERROR: Failed to load filter from %s: %O', filterPath, e);
|
|
45
64
|
console.warn(`Could not import filter from ${filterPath}. Skipping custom filter.`, e);
|
|
46
65
|
} finally {
|
|
47
|
-
if (loader)
|
|
66
|
+
if (loader) {
|
|
67
|
+
debugFilter('Cleaning up FilterLoader');
|
|
68
|
+
loader.cleanup();
|
|
69
|
+
}
|
|
48
70
|
}
|
|
71
|
+
} else {
|
|
72
|
+
debugFilter('No filter path provided, proceeding without custom filter');
|
|
49
73
|
}
|
|
50
74
|
|
|
75
|
+
debugHandler('Calling importDesignSystemComponentsFromFigma...');
|
|
51
76
|
await importDesignSystemComponentsFromFigma(outputDir, resolvedStrategy, filterFn);
|
|
77
|
+
debugHandler('Import completed successfully');
|
|
52
78
|
console.log(`Design system files processed to ${outputDir}`);
|
|
53
79
|
|
|
54
|
-
|
|
80
|
+
const successEvent: DesignSystemImportedEvent = {
|
|
55
81
|
type: 'DesignSystemImported',
|
|
56
82
|
data: {
|
|
57
83
|
outputDir,
|
|
@@ -60,11 +86,16 @@ export async function handleImportDesignSystemCommand(
|
|
|
60
86
|
requestId: command.requestId,
|
|
61
87
|
correlationId: command.correlationId,
|
|
62
88
|
};
|
|
89
|
+
debugResult('Returning success event: DesignSystemImported');
|
|
90
|
+
debugResult(' Output directory: %s', outputDir);
|
|
91
|
+
return successEvent;
|
|
63
92
|
} catch (error) {
|
|
64
93
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
94
|
+
debugHandler('ERROR: Design system import failed: %O', error);
|
|
95
|
+
debugResult('Error message: %s', errorMessage);
|
|
65
96
|
console.error('Error importing design system:', error);
|
|
66
97
|
|
|
67
|
-
|
|
98
|
+
const failureEvent: DesignSystemImportFailedEvent = {
|
|
68
99
|
type: 'DesignSystemImportFailed',
|
|
69
100
|
data: {
|
|
70
101
|
error: errorMessage,
|
|
@@ -74,17 +105,82 @@ export async function handleImportDesignSystemCommand(
|
|
|
74
105
|
requestId: command.requestId,
|
|
75
106
|
correlationId: command.correlationId,
|
|
76
107
|
};
|
|
108
|
+
debugResult('Returning failure event: DesignSystemImportFailed');
|
|
109
|
+
debugResult(' Error: %s', errorMessage);
|
|
110
|
+
debugResult(' Output directory: %s', outputDir);
|
|
111
|
+
return failureEvent;
|
|
77
112
|
}
|
|
78
113
|
}
|
|
79
114
|
|
|
80
115
|
export const importDesignSystemCommandHandler: CommandHandler<ImportDesignSystemCommand> = {
|
|
81
116
|
name: 'ImportDesignSystem',
|
|
82
117
|
handle: async (command: ImportDesignSystemCommand): Promise<void> => {
|
|
83
|
-
|
|
118
|
+
debug('CommandHandler executing for ImportDesignSystem');
|
|
119
|
+
const result = await handleImportDesignSystemCommandInternal(command);
|
|
84
120
|
if (result.type === 'DesignSystemImported') {
|
|
121
|
+
debug('Command handler completed: success');
|
|
85
122
|
console.log('Design system imported successfully');
|
|
86
123
|
} else {
|
|
124
|
+
debug('Command handler completed: failure - %s', result.data.error);
|
|
87
125
|
console.error(`Failed: ${result.data.error}`);
|
|
88
126
|
}
|
|
89
127
|
},
|
|
90
128
|
};
|
|
129
|
+
|
|
130
|
+
// CLI arguments interface
|
|
131
|
+
interface CliArgs {
|
|
132
|
+
_: string[];
|
|
133
|
+
strategy?: 'WITH_COMPONENTS' | 'WITH_COMPONENT_SETS' | 'WITH_ALL_FIGMA_INSTANCES';
|
|
134
|
+
filter?: string;
|
|
135
|
+
[key: string]: unknown;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Type guard to check if it's an ImportDesignSystemCommand
|
|
139
|
+
function isImportDesignSystemCommand(obj: unknown): obj is ImportDesignSystemCommand {
|
|
140
|
+
return (
|
|
141
|
+
typeof obj === 'object' &&
|
|
142
|
+
obj !== null &&
|
|
143
|
+
'type' in obj &&
|
|
144
|
+
'data' in obj &&
|
|
145
|
+
(obj as { type: unknown }).type === 'ImportDesignSystem'
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Default export for CLI usage
|
|
150
|
+
export default async (commandOrArgs: ImportDesignSystemCommand | CliArgs) => {
|
|
151
|
+
let command: ImportDesignSystemCommand;
|
|
152
|
+
|
|
153
|
+
if (isImportDesignSystemCommand(commandOrArgs)) {
|
|
154
|
+
command = commandOrArgs;
|
|
155
|
+
} else if ('outputDir' in commandOrArgs) {
|
|
156
|
+
// Handle message bus format
|
|
157
|
+
const args = commandOrArgs as { outputDir?: string; strategy?: string; filterPath?: string };
|
|
158
|
+
command = {
|
|
159
|
+
type: 'ImportDesignSystem' as const,
|
|
160
|
+
data: {
|
|
161
|
+
outputDir: args.outputDir ?? '.context',
|
|
162
|
+
strategy: args.strategy as keyof typeof ImportStrategy | undefined,
|
|
163
|
+
filterPath: args.filterPath,
|
|
164
|
+
},
|
|
165
|
+
timestamp: new Date(),
|
|
166
|
+
};
|
|
167
|
+
} else {
|
|
168
|
+
// Handle traditional CLI args format
|
|
169
|
+
command = {
|
|
170
|
+
type: 'ImportDesignSystem' as const,
|
|
171
|
+
data: {
|
|
172
|
+
outputDir: commandOrArgs._?.[0] ?? '.context',
|
|
173
|
+
strategy: commandOrArgs._?.[1] as keyof typeof ImportStrategy | undefined,
|
|
174
|
+
filterPath: commandOrArgs._?.[2],
|
|
175
|
+
},
|
|
176
|
+
timestamp: new Date(),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const result = await handleImportDesignSystemCommandInternal(command);
|
|
181
|
+
if (result.type === 'DesignSystemImported') {
|
|
182
|
+
console.log('Design system imported successfully');
|
|
183
|
+
} else {
|
|
184
|
+
console.error(`Failed: ${result.data.error}`);
|
|
185
|
+
}
|
|
186
|
+
};
|