@dsai-io/tools 0.0.1

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.
@@ -0,0 +1,546 @@
1
+ /**
2
+ * Configuration type definitions for @dsai-io/tools
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ /**
7
+ * Root configuration object
8
+ */
9
+ interface DsaiConfig {
10
+ /** Token build configuration */
11
+ tokens?: TokensConfig;
12
+ /** Icon generation configuration */
13
+ icons?: IconsConfig;
14
+ /** Global settings */
15
+ global?: GlobalConfig;
16
+ }
17
+ /**
18
+ * Global settings applied across all modules
19
+ */
20
+ interface GlobalConfig {
21
+ /** Working directory (default: process.cwd()) */
22
+ cwd?: string;
23
+ /** Enable debug logging */
24
+ debug?: boolean;
25
+ /** Log level: 'silent' | 'error' | 'warn' | 'info' | 'debug' */
26
+ logLevel?: LogLevel;
27
+ }
28
+ /**
29
+ * Log level options
30
+ */
31
+ type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
32
+ /**
33
+ * Output format types
34
+ */
35
+ type OutputFormat = 'css' | 'scss' | 'js' | 'ts' | 'json' | 'android' | 'ios';
36
+ /**
37
+ * Token build configuration
38
+ */
39
+ interface TokensConfig {
40
+ /**
41
+ * Token source type
42
+ * - 'theme': Use combined theme.json from Figma
43
+ * - 'collections': Use individual collection files
44
+ * - Custom path: Direct path to token files
45
+ * @default 'theme'
46
+ */
47
+ source?: 'theme' | 'collections' | string;
48
+ /**
49
+ * Directory containing Figma export files
50
+ * Relative to config file location
51
+ * @default 'figma-exports'
52
+ */
53
+ sourceDir?: string;
54
+ /**
55
+ * Directory containing token collection files
56
+ * Relative to config file location
57
+ * @default 'collections'
58
+ */
59
+ collectionsDir?: string;
60
+ /**
61
+ * Input file patterns/globs for finding Figma exports
62
+ * Allows enterprises to use their own naming conventions
63
+ * @example ['theme.json', '*-tokens.json', 'figma-variables-*.json']
64
+ * @default ['theme.json', 'tokens.json', '*.tokens.json']
65
+ */
66
+ sourcePatterns?: string[];
67
+ /**
68
+ * Mapping of Figma collection names to local file paths
69
+ * Useful when teams export collections separately
70
+ * @example { 'primitives': './tokens/colors.json', 'semantic': './tokens/semantic.json' }
71
+ */
72
+ collectionMapping?: Record<string, string>;
73
+ /**
74
+ * Output directory for built tokens (applies to all formats by default)
75
+ * Relative to config file location
76
+ * @default 'dist'
77
+ */
78
+ outputDir?: string;
79
+ /**
80
+ * Per-format output directories (overrides outputDir for specific formats)
81
+ * Allows CSS to go one place, SCSS another, JS another
82
+ * @example { css: 'dist/css', scss: 'src/styles/tokens', js: 'dist/js', ts: 'src/tokens' }
83
+ */
84
+ outputDirs?: Partial<Record<OutputFormat, string>>;
85
+ /**
86
+ * Output file naming pattern per format
87
+ * Use {name}, {theme}, {format} placeholders
88
+ * @example { css: 'tokens-{theme}.css', scss: '_tokens-{theme}.scss' }
89
+ * @default { css: 'tokens.css', scss: '_tokens.scss', js: 'tokens.js', ts: 'tokens.ts' }
90
+ */
91
+ outputFileNames?: Partial<Record<OutputFormat, string>>;
92
+ /**
93
+ * CSS custom property prefix
94
+ * @default '--dsai-'
95
+ */
96
+ prefix?: string;
97
+ /**
98
+ * Output formats to generate
99
+ * @default ['css', 'scss', 'js', 'ts', 'json']
100
+ */
101
+ formats?: OutputFormat[];
102
+ /**
103
+ * Additional SCSS directories to include/merge with token SCSS output
104
+ * These stylesheets will be combined with the generated token files
105
+ * @example ['src/styles/overrides', 'src/styles/custom-mixins']
106
+ */
107
+ additionalScssDirectories?: string[];
108
+ /**
109
+ * Additional CSS directories to include/merge with token CSS output
110
+ * These stylesheets will be combined with the generated token files
111
+ * @example ['src/styles/base', 'src/styles/utilities']
112
+ */
113
+ additionalCssDirectories?: string[];
114
+ /**
115
+ * Order in which to merge additional stylesheets
116
+ * - 'before': User styles come before generated tokens
117
+ * - 'after': User styles come after generated tokens (default)
118
+ * @default 'after'
119
+ */
120
+ mergeOrder?: 'before' | 'after';
121
+ /**
122
+ * Whether to create combined bundle files
123
+ * When true, creates tokens-bundle.css and _tokens-bundle.scss
124
+ * @default false
125
+ */
126
+ createBundle?: boolean;
127
+ /**
128
+ * Custom file to import at the top of generated SCSS files
129
+ * Useful for SCSS variables, mixins, or functions needed by tokens
130
+ * @example '_variables.scss' or 'path/to/custom-base.scss'
131
+ */
132
+ scssImportHeader?: string;
133
+ /** Theme mode settings */
134
+ themes?: ThemesConfig;
135
+ /** Custom Style Dictionary transforms */
136
+ transforms?: CustomTransform[];
137
+ /** Custom Style Dictionary formats */
138
+ customFormats?: CustomFormat[];
139
+ /** Custom Style Dictionary preprocessors */
140
+ preprocessors?: CustomPreprocessor[];
141
+ /** Custom Style Dictionary filters */
142
+ filters?: CustomFilter[];
143
+ /**
144
+ * Hook called before token build starts
145
+ * @param config Resolved configuration
146
+ * @returns Modified config or undefined
147
+ */
148
+ onBuildStart?: (config: ResolvedConfig) => Promise<Partial<TokensConfig> | undefined>;
149
+ /**
150
+ * Hook called after each format is generated
151
+ * @param format The format just generated
152
+ * @param outputPath Path to the generated file
153
+ * @param content The generated content
154
+ * @returns Modified content or undefined
155
+ */
156
+ onFormatComplete?: (format: OutputFormat, outputPath: string, content: string) => Promise<string | undefined>;
157
+ /**
158
+ * Hook called after all formats are generated, before bundling
159
+ * @param outputs Map of format to file paths
160
+ */
161
+ onAllFormatsComplete?: (outputs: Map<OutputFormat, string[]>) => Promise<void>;
162
+ /**
163
+ * Hook called after build completes (including bundling)
164
+ * @param summary Build summary with all output paths
165
+ */
166
+ onBuildComplete?: (summary: BuildSummary) => Promise<void>;
167
+ /**
168
+ * Include token references in output
169
+ * @default true
170
+ */
171
+ outputReferences?: boolean;
172
+ /**
173
+ * Base font size for px to rem conversion
174
+ * @default 16
175
+ */
176
+ baseFontSize?: number;
177
+ /**
178
+ * Generate separate files per theme
179
+ * @default false
180
+ */
181
+ separateThemeFiles?: boolean;
182
+ /**
183
+ * Watch source files for changes and rebuild automatically
184
+ * @default false
185
+ */
186
+ watch?: boolean;
187
+ /**
188
+ * Directories to watch in addition to sourceDir (for watch mode)
189
+ * @example ['src/styles', 'design-tokens']
190
+ */
191
+ watchDirectories?: string[];
192
+ /**
193
+ * Build pipeline configuration
194
+ * Controls which steps run and their paths
195
+ */
196
+ pipeline?: TokensBuildPipeline;
197
+ }
198
+ /**
199
+ * Build pipeline step names
200
+ */
201
+ type BuildPipelineStep = 'validate' | 'transform' | 'style-dictionary' | 'sync' | 'sass-theme' | 'sass-theme-minified' | 'postprocess' | 'sass-utilities' | 'sass-utilities-minified' | 'bundle';
202
+ /**
203
+ * Build pipeline paths configuration
204
+ */
205
+ interface BuildPipelinePaths {
206
+ /** Source file for sync step (Style Dictionary JS output) */
207
+ syncSource?: string;
208
+ /** Target file for sync step */
209
+ syncTarget?: string;
210
+ /** SCSS theme input file */
211
+ sassThemeInput?: string;
212
+ /** CSS theme output file */
213
+ sassThemeOutput?: string;
214
+ /** CSS theme minified output file */
215
+ sassThemeMinifiedOutput?: string;
216
+ /** SCSS utilities input file */
217
+ sassUtilitiesInput?: string;
218
+ /** CSS utilities output file */
219
+ sassUtilitiesOutput?: string;
220
+ /** CSS utilities minified output file */
221
+ sassUtilitiesMinifiedOutput?: string;
222
+ }
223
+ /**
224
+ * Build pipeline configuration
225
+ */
226
+ interface TokensBuildPipeline {
227
+ /**
228
+ * Steps to include in the build.
229
+ * Order matters - steps run in sequence.
230
+ * Default includes all steps for full @dsai-io/tokens build.
231
+ * Simpler packages can use subset like ['validate', 'transform', 'style-dictionary']
232
+ */
233
+ steps?: BuildPipelineStep[];
234
+ /**
235
+ * Paths configuration for build steps
236
+ */
237
+ paths?: BuildPipelinePaths;
238
+ /**
239
+ * Style Dictionary config file name
240
+ * @default 'sd.config.mjs'
241
+ */
242
+ styleDictionaryConfig?: string;
243
+ }
244
+ /**
245
+ * Build summary returned after build completes
246
+ */
247
+ interface BuildSummary {
248
+ /** Total build duration in ms */
249
+ duration: number;
250
+ /** Map of format to generated file paths */
251
+ outputs: Record<OutputFormat, string[]>;
252
+ /** Bundle file paths (if createBundle is true) */
253
+ bundles?: {
254
+ css?: string;
255
+ scss?: string;
256
+ };
257
+ /** Warnings generated during build */
258
+ warnings: string[];
259
+ /** Token statistics */
260
+ stats: {
261
+ totalTokens: number;
262
+ tokensByType: Record<string, number>;
263
+ themes: string[];
264
+ };
265
+ }
266
+ /**
267
+ * Theme configuration
268
+ */
269
+ interface ThemesConfig {
270
+ /**
271
+ * Auto-detect available modes from Figma export
272
+ * @default true
273
+ */
274
+ autoDetect?: boolean;
275
+ /**
276
+ * Default theme mode (uses :root selector)
277
+ * @default 'Light'
278
+ */
279
+ default?: string;
280
+ /**
281
+ * Modes to ignore during build
282
+ * @default []
283
+ */
284
+ ignoreModes?: string[];
285
+ /**
286
+ * CSS selector patterns for themes
287
+ */
288
+ selectorPattern?: ThemeSelectorPattern;
289
+ }
290
+ /**
291
+ * Theme selector pattern configuration
292
+ */
293
+ interface ThemeSelectorPattern {
294
+ /**
295
+ * Selector for default theme
296
+ * @default ':root'
297
+ */
298
+ default?: string;
299
+ /**
300
+ * Selector pattern for other themes
301
+ * Use {mode} as placeholder for mode name
302
+ * @default '[data-dsai-theme="{mode}"]'
303
+ */
304
+ others?: string;
305
+ }
306
+ /**
307
+ * Custom Style Dictionary transform
308
+ */
309
+ interface CustomTransform {
310
+ /** Unique transform name */
311
+ name: string;
312
+ /** Transform type: 'name' | 'value' | 'attribute' */
313
+ type: 'name' | 'value' | 'attribute';
314
+ /** Filter function to determine which tokens to transform */
315
+ filter?: (token: TokenData) => boolean;
316
+ /** Transform function */
317
+ transform: (token: TokenData, options?: TransformOptions) => unknown;
318
+ }
319
+ /**
320
+ * Custom Style Dictionary format
321
+ */
322
+ interface CustomFormat {
323
+ /** Unique format name */
324
+ name: string;
325
+ /** Format function */
326
+ format: (args: FormatArgs) => string;
327
+ }
328
+ /**
329
+ * Custom Style Dictionary preprocessor
330
+ */
331
+ interface CustomPreprocessor {
332
+ /** Unique preprocessor name */
333
+ name: string;
334
+ /** Preprocessor function */
335
+ preprocessor: (dictionary: Dictionary) => Dictionary;
336
+ }
337
+ /**
338
+ * Custom Style Dictionary filter
339
+ */
340
+ interface CustomFilter {
341
+ /** Unique filter name */
342
+ name: string;
343
+ /** Filter function */
344
+ filter: (token: TokenData) => boolean;
345
+ }
346
+ /**
347
+ * Token data structure (Style Dictionary compatible)
348
+ */
349
+ interface TokenData {
350
+ name: string;
351
+ value: unknown;
352
+ $value?: unknown;
353
+ type?: string;
354
+ $type?: string;
355
+ path: string[];
356
+ original: unknown;
357
+ comment?: string;
358
+ description?: string;
359
+ $description?: string;
360
+ $extensions?: Record<string, unknown>;
361
+ $scopes?: string[];
362
+ attributes?: Record<string, unknown>;
363
+ }
364
+ /**
365
+ * Transform options
366
+ */
367
+ interface TransformOptions {
368
+ basePxFontSize?: number;
369
+ prefix?: string;
370
+ }
371
+ /**
372
+ * Format function arguments
373
+ */
374
+ interface FormatArgs {
375
+ dictionary: Dictionary;
376
+ options: Record<string, unknown>;
377
+ platform: Platform;
378
+ file: FileConfig;
379
+ }
380
+ /**
381
+ * Dictionary type
382
+ */
383
+ interface Dictionary {
384
+ allTokens: TokenData[];
385
+ tokens: Record<string, unknown>;
386
+ unfilteredTokens: Record<string, unknown>;
387
+ }
388
+ /**
389
+ * Platform configuration
390
+ */
391
+ interface Platform {
392
+ transformGroup?: string;
393
+ transforms?: string[];
394
+ buildPath?: string;
395
+ files?: FileConfig[];
396
+ options?: Record<string, unknown>;
397
+ }
398
+ /**
399
+ * File configuration
400
+ */
401
+ interface FileConfig {
402
+ destination: string;
403
+ format: string;
404
+ filter?: string | ((token: TokenData) => boolean);
405
+ options?: Record<string, unknown>;
406
+ }
407
+ /**
408
+ * Icon framework options
409
+ */
410
+ type IconFramework = 'react' | 'vue' | 'svelte' | 'web-components';
411
+ /**
412
+ * Icon generation configuration
413
+ */
414
+ interface IconsConfig {
415
+ /**
416
+ * Source directory containing SVG icons
417
+ * @default 'icons'
418
+ */
419
+ sourceDir?: string;
420
+ /**
421
+ * Output directory for generated components
422
+ * @default 'dist/icons'
423
+ */
424
+ outputDir?: string;
425
+ /**
426
+ * Framework for generated components
427
+ * @default 'react'
428
+ */
429
+ framework?: IconFramework;
430
+ /**
431
+ * Generate TypeScript files
432
+ * @default true
433
+ */
434
+ typescript?: boolean;
435
+ /**
436
+ * Optimize SVGs with SVGO
437
+ * @default true
438
+ */
439
+ optimize?: boolean;
440
+ /**
441
+ * Icon component prefix
442
+ * @default 'Icon'
443
+ */
444
+ prefix?: string;
445
+ }
446
+ /**
447
+ * Resolved themes config with all defaults applied
448
+ */
449
+ interface ResolvedThemesConfig {
450
+ autoDetect: boolean;
451
+ default: string;
452
+ ignoreModes: string[];
453
+ selectorPattern: Required<ThemeSelectorPattern>;
454
+ }
455
+ /**
456
+ * Resolved tokens config with all defaults applied
457
+ */
458
+ interface ResolvedTokensConfig {
459
+ source: string;
460
+ sourceDir: string;
461
+ collectionsDir: string;
462
+ sourcePatterns: string[];
463
+ collectionMapping: Record<string, string>;
464
+ outputDir: string;
465
+ outputDirs: Partial<Record<OutputFormat, string>>;
466
+ outputFileNames: Record<OutputFormat, string>;
467
+ prefix: string;
468
+ formats: OutputFormat[];
469
+ additionalScssDirectories: string[];
470
+ additionalCssDirectories: string[];
471
+ mergeOrder: 'before' | 'after';
472
+ createBundle: boolean;
473
+ scssImportHeader?: string;
474
+ themes: ResolvedThemesConfig;
475
+ transforms: CustomTransform[];
476
+ customFormats: CustomFormat[];
477
+ preprocessors: CustomPreprocessor[];
478
+ filters: CustomFilter[];
479
+ onBuildStart?: TokensConfig['onBuildStart'];
480
+ onFormatComplete?: TokensConfig['onFormatComplete'];
481
+ onAllFormatsComplete?: TokensConfig['onAllFormatsComplete'];
482
+ onBuildComplete?: TokensConfig['onBuildComplete'];
483
+ outputReferences: boolean;
484
+ baseFontSize: number;
485
+ separateThemeFiles: boolean;
486
+ watch: boolean;
487
+ watchDirectories: string[];
488
+ pipeline?: TokensBuildPipeline;
489
+ }
490
+ /**
491
+ * Resolved icons config with all defaults applied
492
+ */
493
+ interface ResolvedIconsConfig {
494
+ sourceDir: string;
495
+ outputDir: string;
496
+ framework: IconFramework;
497
+ typescript: boolean;
498
+ optimize: boolean;
499
+ prefix: string;
500
+ }
501
+ /**
502
+ * Resolved global config with all defaults applied
503
+ */
504
+ interface ResolvedGlobalConfig {
505
+ cwd: string;
506
+ debug: boolean;
507
+ logLevel: LogLevel;
508
+ }
509
+ /**
510
+ * Fully resolved configuration with all defaults applied
511
+ */
512
+ interface ResolvedConfig {
513
+ tokens: ResolvedTokensConfig;
514
+ icons: ResolvedIconsConfig;
515
+ global: ResolvedGlobalConfig;
516
+ /** Absolute path to config file (if loaded from file) */
517
+ configPath?: string;
518
+ /** Absolute path to config directory */
519
+ configDir: string;
520
+ }
521
+ /**
522
+ * Options for loading configuration
523
+ */
524
+ interface LoadConfigOptions {
525
+ /** Working directory to search from */
526
+ cwd?: string;
527
+ /** Explicit config file path */
528
+ configPath?: string;
529
+ /** Override values (highest priority) */
530
+ overrides?: Partial<DsaiConfig>;
531
+ /** Skip config file loading (use defaults + overrides only) */
532
+ skipFile?: boolean;
533
+ }
534
+ /**
535
+ * Config loading result
536
+ */
537
+ interface LoadConfigResult {
538
+ /** Resolved configuration */
539
+ config: ResolvedConfig;
540
+ /** Path to loaded config file (if any) */
541
+ configPath?: string;
542
+ /** Warnings during loading */
543
+ warnings: string[];
544
+ }
545
+
546
+ export type { BuildSummary as B, CustomTransform as C, DsaiConfig as D, FormatArgs as F, GlobalConfig as G, IconsConfig as I, LoadConfigOptions as L, OutputFormat as O, Platform as P, ResolvedConfig as R, TokensConfig as T, ThemesConfig as a, ThemeSelectorPattern as b, ResolvedGlobalConfig as c, ResolvedTokensConfig as d, ResolvedIconsConfig as e, ResolvedThemesConfig as f, CustomFormat as g, CustomPreprocessor as h, CustomFilter as i, TokenData as j, TransformOptions as k, Dictionary as l, FileConfig as m, LoadConfigResult as n, LogLevel as o, IconFramework as p };
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@dsai-io/tools",
3
+ "version": "0.0.1",
4
+ "description": "Build tooling and CLI for DSAi Design System",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "dsai": "./bin/dsai-tools.mjs",
11
+ "dsai-tools": "./bin/dsai-tools.mjs"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ },
19
+ "./config": {
20
+ "types": "./dist/config/index.d.ts",
21
+ "import": "./dist/config/index.js",
22
+ "require": "./dist/config/index.cjs"
23
+ },
24
+ "./tokens": {
25
+ "types": "./dist/tokens/index.d.ts",
26
+ "import": "./dist/tokens/index.js",
27
+ "require": "./dist/tokens/index.cjs"
28
+ },
29
+ "./icons": {
30
+ "types": "./dist/icons/index.d.ts",
31
+ "import": "./dist/icons/index.js",
32
+ "require": "./dist/icons/index.cjs"
33
+ },
34
+ "./cli": {
35
+ "types": "./dist/cli/index.d.ts",
36
+ "import": "./dist/cli/index.js",
37
+ "require": "./dist/cli/index.cjs"
38
+ }
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "bin",
43
+ "templates"
44
+ ],
45
+ "scripts": {
46
+ "build": "tsup",
47
+ "build:watch": "tsup --watch",
48
+ "dev": "tsup --watch",
49
+ "test": "jest",
50
+ "lint": "eslint src --ext .ts",
51
+ "lint:fix": "eslint src --ext .ts --fix",
52
+ "typecheck": "tsc --noEmit",
53
+ "generate-schema": "node scripts/generate-schema.mjs"
54
+ },
55
+ "keywords": [
56
+ "design-tokens",
57
+ "design-system",
58
+ "cli",
59
+ "style-dictionary",
60
+ "build-tools",
61
+ "dsai"
62
+ ],
63
+ "license": "UNLICENSED",
64
+ "engines": {
65
+ "node": ">=22.0.0"
66
+ },
67
+ "dependencies": {
68
+ "commander": "^14.0.2",
69
+ "cosmiconfig": "^9.0.0",
70
+ "deepmerge": "^4.3.1",
71
+ "fast-glob": "^3.3.3",
72
+ "ora": "^9.0.0",
73
+ "picocolors": "^1.1.1",
74
+ "svgo": "^4.0.0",
75
+ "zod": "^3.25.0"
76
+ },
77
+ "devDependencies": {
78
+ "@clack/prompts": "^0.11.0",
79
+ "@types/node": "^22.15.30",
80
+ "@types/prompts": "^2.4.9",
81
+ "style-dictionary": "^5.1.1",
82
+ "tsup": "^8.5.1",
83
+ "typescript": "^5.9.3",
84
+ "zod-to-json-schema": "^3.25.0"
85
+ },
86
+ "peerDependencies": {
87
+ "style-dictionary": "^5.1.1"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "style-dictionary": {
91
+ "optional": true
92
+ }
93
+ },
94
+ "publishConfig": {
95
+ "access": "restricted"
96
+ }
97
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "./dsai-config.schema.json",
3
+ "tokens": {
4
+ "source": "theme",
5
+ "sourceDir": "figma-exports",
6
+ "sourcePatterns": ["theme.json", "tokens.json", "*.tokens.json"],
7
+ "outputDir": "dist",
8
+ "formats": ["css", "scss", "js", "ts", "json"],
9
+ "prefix": "--dsai-",
10
+ "themes": {
11
+ "autoDetect": true,
12
+ "default": "Light",
13
+ "selectorPattern": {
14
+ "default": ":root",
15
+ "others": "[data-dsai-theme=\"{mode}\"]"
16
+ }
17
+ },
18
+ "outputReferences": true,
19
+ "baseFontSize": 16,
20
+ "separateThemeFiles": false,
21
+ "watch": false
22
+ },
23
+ "icons": {
24
+ "sourceDir": "icons",
25
+ "outputDir": "src/components/icons",
26
+ "framework": "react",
27
+ "typescript": true,
28
+ "optimize": true,
29
+ "prefix": "Icon",
30
+ "exportIndex": true,
31
+ "generateSprite": false
32
+ },
33
+ "global": {
34
+ "debug": false,
35
+ "logLevel": "info"
36
+ }
37
+ }