@refrakt-md/cli 0.4.0 → 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.
Files changed (47) hide show
  1. package/dist/bin.js +277 -9
  2. package/dist/bin.js.map +1 -1
  3. package/dist/commands/contracts.d.ts +6 -0
  4. package/dist/commands/contracts.d.ts.map +1 -0
  5. package/dist/commands/contracts.js +41 -0
  6. package/dist/commands/contracts.js.map +1 -0
  7. package/dist/commands/inspect.d.ts +33 -0
  8. package/dist/commands/inspect.d.ts.map +1 -0
  9. package/dist/commands/inspect.js +269 -0
  10. package/dist/commands/inspect.js.map +1 -0
  11. package/dist/commands/scaffold-css.d.ts +6 -0
  12. package/dist/commands/scaffold-css.d.ts.map +1 -0
  13. package/dist/commands/scaffold-css.js +113 -0
  14. package/dist/commands/scaffold-css.js.map +1 -0
  15. package/dist/commands/validate.d.ts +6 -0
  16. package/dist/commands/validate.d.ts.map +1 -0
  17. package/dist/commands/validate.js +70 -0
  18. package/dist/commands/validate.js.map +1 -0
  19. package/dist/commands/write.d.ts +7 -0
  20. package/dist/commands/write.d.ts.map +1 -1
  21. package/dist/commands/write.js +66 -10
  22. package/dist/commands/write.js.map +1 -1
  23. package/dist/config.d.ts +2 -1
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +30 -2
  26. package/dist/config.js.map +1 -1
  27. package/dist/lib/css-audit.d.ts +23 -0
  28. package/dist/lib/css-audit.d.ts.map +1 -0
  29. package/dist/lib/css-audit.js +99 -0
  30. package/dist/lib/css-audit.js.map +1 -0
  31. package/dist/lib/css-resolve.d.ts +20 -0
  32. package/dist/lib/css-resolve.d.ts.map +1 -0
  33. package/dist/lib/css-resolve.js +57 -0
  34. package/dist/lib/css-resolve.js.map +1 -0
  35. package/dist/lib/fixtures.d.ts +10 -0
  36. package/dist/lib/fixtures.d.ts.map +1 -0
  37. package/dist/lib/fixtures.js +356 -0
  38. package/dist/lib/fixtures.js.map +1 -0
  39. package/dist/lib/format.d.ts +35 -0
  40. package/dist/lib/format.d.ts.map +1 -0
  41. package/dist/lib/format.js +215 -0
  42. package/dist/lib/format.js.map +1 -0
  43. package/dist/lib/variants.d.ts +17 -0
  44. package/dist/lib/variants.d.ts.map +1 -0
  45. package/dist/lib/variants.js +32 -0
  46. package/dist/lib/variants.js.map +1 -0
  47. package/package.json +7 -3
@@ -0,0 +1,269 @@
1
+ import { getFixture } from '../lib/fixtures.js';
2
+ import { discoverVariants } from '../lib/variants.js';
3
+ import { parseCssFile, auditSelectors, collectAllSelectors, } from '../lib/css-audit.js';
4
+ import { resolveCssDir, readCssForBlock, readAllCss } from '../lib/css-resolve.js';
5
+ import { formatConfig, formatSelectors, formatInput, formatHtml, formatRuneList, buildJsonOutput, formatAuditResult, formatAuditSummary, buildAuditJson, heading, } from '../lib/format.js';
6
+ export async function inspectCommand(options, deps) {
7
+ const { runes, baseConfig, } = deps;
8
+ // --list mode: show all available runes
9
+ if (options.list) {
10
+ return listRunes(runes, options.json);
11
+ }
12
+ // Resolve theme config
13
+ const config = await resolveTheme(options.theme, baseConfig);
14
+ // --all --audit: full-theme audit
15
+ if (options.all && options.audit) {
16
+ return runFullAudit(config, runes, options, deps);
17
+ }
18
+ // --all without --audit: not supported yet
19
+ if (options.all) {
20
+ throw new Error('--all currently requires --audit. Use --list to see available runes.');
21
+ }
22
+ if (!options.runeName) {
23
+ throw new Error('Missing rune name. Use --list to see available runes.\n\nUsage: refrakt inspect <rune> [options]');
24
+ }
25
+ // Resolve the rune by name or alias
26
+ const rune = findRune(options.runeName, runes);
27
+ if (!rune) {
28
+ const available = Object.values(runes)
29
+ .map(r => ` ${r.name}${r.aliases.length > 0 ? ` (${r.aliases.join(', ')})` : ''}`)
30
+ .join('\n');
31
+ throw new Error(`Unknown rune "${options.runeName}"\n\nAvailable runes:\n${available}`);
32
+ }
33
+ // --audit mode for a single rune
34
+ if (options.audit) {
35
+ return runSingleAudit(rune, config, options, deps);
36
+ }
37
+ // Check for variant expansion (e.g., --type=all)
38
+ const schemaVariants = discoverVariants(rune.schema);
39
+ const expandAttr = findExpandAttr(options.flags, schemaVariants);
40
+ if (expandAttr) {
41
+ // Expand all variants for this attribute
42
+ const values = schemaVariants[expandAttr];
43
+ if (options.json) {
44
+ const results = [];
45
+ for (const value of values) {
46
+ const overrides = { ...options.flags, [expandAttr]: value };
47
+ results.push(inspectSingle(rune, config, overrides, deps));
48
+ }
49
+ console.log(JSON.stringify(results, null, 2));
50
+ }
51
+ else {
52
+ for (const value of values) {
53
+ console.log(heading(`Variant: ${expandAttr}=${value}`));
54
+ const overrides = { ...options.flags, [expandAttr]: value };
55
+ outputFormatted(rune, config, overrides, deps);
56
+ console.log('');
57
+ }
58
+ }
59
+ }
60
+ else {
61
+ // Single variant
62
+ if (options.json) {
63
+ const result = inspectSingle(rune, config, options.flags, deps);
64
+ console.log(JSON.stringify(result, null, 2));
65
+ }
66
+ else {
67
+ outputFormatted(rune, config, options.flags, deps);
68
+ }
69
+ }
70
+ }
71
+ /** Run audit for a single rune */
72
+ function runSingleAudit(rune, config, options, deps) {
73
+ const cssDir = resolveCssDir(options.cssDir);
74
+ if (!cssDir) {
75
+ throw new Error('No CSS directory found. Use --css <dir> to specify the path to rune CSS files.');
76
+ }
77
+ const runeTypeof = rune.type?.name;
78
+ const runeConfig = runeTypeof ? config.runes[runeTypeof] : undefined;
79
+ if (!runeConfig) {
80
+ throw new Error(`No engine config found for rune "${rune.name}". It may be a component-only rune without identity transform config.`);
81
+ }
82
+ // Read CSS for this block
83
+ const cssFile = readCssForBlock(cssDir, runeConfig.block);
84
+ const cssMatches = cssFile
85
+ ? parseCssFile(cssFile.content, cssFile.path)
86
+ : [];
87
+ // Collect all possible selectors across variants
88
+ const schemaVariants = discoverVariants(rune.schema);
89
+ const allSelectors = collectAllSelectors(rune.name, runeConfig.block, config.prefix, schemaVariants, runeConfig.contextModifiers, runeConfig.staticModifiers, (flags) => {
90
+ const { tree } = runPipeline(rune, config, flags, deps);
91
+ return deps.extractSelectors(tree, config.prefix);
92
+ });
93
+ const result = auditSelectors(rune.name, allSelectors, cssMatches);
94
+ if (options.json) {
95
+ console.log(JSON.stringify(buildAuditJson([result], options.theme), null, 2));
96
+ }
97
+ else {
98
+ console.log(formatAuditResult(result, options.theme));
99
+ }
100
+ }
101
+ /** Run audit for all runes in the theme */
102
+ function runFullAudit(config, runes, options, deps) {
103
+ const cssDir = resolveCssDir(options.cssDir);
104
+ if (!cssDir) {
105
+ throw new Error('No CSS directory found. Use --css <dir> to specify the path to rune CSS files.');
106
+ }
107
+ // Parse all CSS files upfront
108
+ const cssFiles = readAllCss(cssDir);
109
+ const allCssMatches = [];
110
+ for (const file of cssFiles) {
111
+ allCssMatches.push(...parseCssFile(file.content, file.path));
112
+ }
113
+ const results = [];
114
+ // Iterate over all runes that have engine config
115
+ for (const rune of Object.values(runes)) {
116
+ const runeTypeof = rune.type?.name;
117
+ const runeConfig = runeTypeof ? config.runes[runeTypeof] : undefined;
118
+ if (!runeConfig)
119
+ continue; // Skip runes without identity transform config
120
+ const schemaVariants = discoverVariants(rune.schema);
121
+ let allSelectors;
122
+ try {
123
+ allSelectors = collectAllSelectors(rune.name, runeConfig.block, config.prefix, schemaVariants, runeConfig.contextModifiers, runeConfig.staticModifiers, (flags) => {
124
+ const { tree } = runPipeline(rune, config, flags, deps);
125
+ return deps.extractSelectors(tree, config.prefix);
126
+ });
127
+ }
128
+ catch {
129
+ // Skip runes whose fixtures fail to transform
130
+ continue;
131
+ }
132
+ // Filter CSS matches to only those relevant to this rune's block
133
+ const blockPrefix = `.${config.prefix}-${runeConfig.block}`;
134
+ const relevantCss = allCssMatches.filter(m => m.selector.startsWith(blockPrefix) || m.selector.startsWith('[data-'));
135
+ results.push(auditSelectors(rune.name, allSelectors, relevantCss));
136
+ }
137
+ // Sort results: complete first, then partial, then not-started, alphabetically within each group
138
+ results.sort((a, b) => {
139
+ const order = { 'complete': 0, 'partial': 1, 'not-started': 2 };
140
+ const statusDiff = order[a.status] - order[b.status];
141
+ if (statusDiff !== 0)
142
+ return statusDiff;
143
+ return a.rune.localeCompare(b.rune);
144
+ });
145
+ if (options.json) {
146
+ console.log(JSON.stringify(buildAuditJson(results, options.theme), null, 2));
147
+ }
148
+ else {
149
+ console.log(formatAuditSummary(results, options.theme));
150
+ }
151
+ }
152
+ /** Run the full pipeline for a single rune variant and return structured data */
153
+ function inspectSingle(rune, config, flags, deps) {
154
+ const { tree, source } = runPipeline(rune, config, flags, deps);
155
+ const html = deps.renderToHtml(tree, { pretty: true });
156
+ const selectors = deps.extractSelectors(tree, config.prefix);
157
+ const runeTypeof = rune.type?.name;
158
+ const runeConfig = runeTypeof ? config.runes[runeTypeof] : undefined;
159
+ return buildJsonOutput({
160
+ rune: rune.name,
161
+ theme: 'base',
162
+ input: source,
163
+ config: runeConfig,
164
+ html,
165
+ selectors,
166
+ });
167
+ }
168
+ /** Run the full pipeline and output formatted text */
169
+ function outputFormatted(rune, config, flags, deps) {
170
+ const { tree, source } = runPipeline(rune, config, flags, deps);
171
+ const html = deps.renderToHtml(tree, { pretty: true });
172
+ const selectors = deps.extractSelectors(tree, config.prefix);
173
+ const runeTypeof = rune.type?.name;
174
+ console.log(heading('Input'));
175
+ console.log(formatInput(source));
176
+ if (runeTypeof) {
177
+ console.log(heading('Config Applied'));
178
+ console.log(formatConfig(runeTypeof, config));
179
+ }
180
+ console.log(heading('Output HTML'));
181
+ console.log(formatHtml(html));
182
+ console.log(heading('Selectors'));
183
+ console.log(formatSelectors(selectors));
184
+ }
185
+ /** Run the Markdoc parse → transform → serialize → identity transform pipeline */
186
+ function runPipeline(rune, config, flags, deps) {
187
+ const source = getFixture(rune.name, flags);
188
+ const ast = deps.Markdoc.parse(source);
189
+ const headings = deps.extractHeadings(ast);
190
+ const transformed = deps.Markdoc.transform(ast, {
191
+ tags: deps.tags,
192
+ nodes: deps.nodes,
193
+ variables: {
194
+ generatedIds: new Set(),
195
+ path: '/inspect.md',
196
+ headings,
197
+ __source: source,
198
+ },
199
+ });
200
+ const serialized = deps.serializeTree(transformed);
201
+ const identityTransform = deps.createTransform(config);
202
+ const tree = identityTransform(serialized);
203
+ return { tree, source };
204
+ }
205
+ /** List all available runes */
206
+ function listRunes(runes, json) {
207
+ const list = Object.values(runes).map(rune => ({
208
+ name: rune.name,
209
+ aliases: rune.aliases,
210
+ description: rune.description,
211
+ variants: discoverVariants(rune.schema),
212
+ }));
213
+ if (json) {
214
+ console.log(JSON.stringify(list, null, 2));
215
+ }
216
+ else {
217
+ console.log(heading('Available Runes'));
218
+ console.log('');
219
+ console.log(formatRuneList(list));
220
+ }
221
+ }
222
+ /** Find a rune by name or alias */
223
+ function findRune(name, runes) {
224
+ // Direct match on rune key
225
+ if (runes[name])
226
+ return runes[name];
227
+ // Search by name or alias
228
+ for (const rune of Object.values(runes)) {
229
+ if (rune.name === name || rune.aliases.includes(name)) {
230
+ return rune;
231
+ }
232
+ }
233
+ return undefined;
234
+ }
235
+ /** Check if any flag has value "all" and corresponds to a known variant */
236
+ function findExpandAttr(flags, variants) {
237
+ for (const [key, value] of Object.entries(flags)) {
238
+ if (value === 'all' && variants[key]) {
239
+ return key;
240
+ }
241
+ }
242
+ return null;
243
+ }
244
+ /** Resolve a theme name to a ThemeConfig */
245
+ async function resolveTheme(theme, baseConfig) {
246
+ if (theme === 'base')
247
+ return baseConfig;
248
+ // Try dynamic import — works for package names (e.g., '@refrakt-md/lumina')
249
+ // and file paths (e.g., './src/config.ts')
250
+ const importPath = theme.startsWith('.') || theme.startsWith('/')
251
+ ? (await import('node:path')).resolve(theme)
252
+ : theme + '/transform';
253
+ try {
254
+ const mod = await import(importPath);
255
+ // Look for common export names
256
+ const config = mod.themeConfig ?? mod.config ?? mod.default;
257
+ if (config && typeof config === 'object' && config.runes && config.prefix) {
258
+ return config;
259
+ }
260
+ console.error(`Warning: "${importPath}" does not export a valid ThemeConfig, using base config.\n`);
261
+ return baseConfig;
262
+ }
263
+ catch (err) {
264
+ console.error(`Warning: Could not load theme "${theme}" (${importPath}): ${err.message}\n`);
265
+ console.error(`Falling back to base config.\n`);
266
+ return baseConfig;
267
+ }
268
+ }
269
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACN,YAAY,EACZ,cAAc,EACd,mBAAmB,GAGnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACN,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,OAAO,GACP,MAAM,kBAAkB,CAAC;AA4B1B,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,OAAuB,EACvB,IAAiB;IAEjB,MAAM,EACL,KAAK,EACL,UAAU,GACV,GAAG,IAAI,CAAC;IAET,wCAAwC;IACxC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,uBAAuB;IACvB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAE7D,kCAAkC;IAClC,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClC,OAAO,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,2CAA2C;IAC3C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAC;IACrH,CAAC;IAED,oCAAoC;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aAClF,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,CAAC,QAAQ,0BAA0B,SAAS,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,iCAAiC;IACjC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,iDAAiD;IACjD,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAEjE,IAAI,UAAU,EAAE,CAAC;QAChB,yCAAyC;QACzC,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC5B,MAAM,SAAS,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC;gBAC5D,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACP,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;gBACxD,MAAM,SAAS,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC;gBAC5D,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;gBAC/C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;QACF,CAAC;IACF,CAAC;SAAM,CAAC;QACP,iBAAiB;QACjB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACP,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC;IACF,CAAC;AACF,CAAC;AAED,kCAAkC;AAClC,SAAS,cAAc,CACtB,IAAU,EACV,MAAmB,EACnB,OAAuB,EACvB,IAAiB;IAEjB,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACnG,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;IACnC,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,IAAI,uEAAuE,CAAC,CAAC;IACvI,CAAC;IAED,0BAA0B;IAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAuB,OAAO;QAC7C,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;QAC7C,CAAC,CAAC,EAAE,CAAC;IAEN,iDAAiD;IACjD,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,mBAAmB,CACvC,IAAI,CAAC,IAAI,EACT,UAAU,CAAC,KAAK,EAChB,MAAM,CAAC,MAAM,EACb,cAAc,EACd,UAAU,CAAC,gBAAgB,EAC3B,UAAU,CAAC,eAAe,EAC1B,CAAC,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC,CACD,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IAEnE,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACvD,CAAC;AACF,CAAC;AAED,2CAA2C;AAC3C,SAAS,YAAY,CACpB,MAAmB,EACnB,KAA2B,EAC3B,OAAuB,EACvB,IAAiB;IAEjB,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACnG,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,aAAa,GAAuB,EAAE,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC7B,aAAa,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,iDAAiD;IACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;QACnC,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,IAAI,CAAC,UAAU;YAAE,SAAS,CAAC,+CAA+C;QAE1E,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErD,IAAI,YAAsB,CAAC;QAC3B,IAAI,CAAC;YACJ,YAAY,GAAG,mBAAmB,CACjC,IAAI,CAAC,IAAI,EACT,UAAU,CAAC,KAAK,EAChB,MAAM,CAAC,MAAM,EACb,cAAc,EACd,UAAU,CAAC,gBAAgB,EAC3B,UAAU,CAAC,eAAe,EAC1B,CAAC,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;gBACxD,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACnD,CAAC,CACD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACR,8CAA8C;YAC9C,SAAS;QACV,CAAC;QAED,iEAAiE;QACjE,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QAC5D,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC5C,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CACrE,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,iGAAiG;IACjG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QAChE,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,UAAU,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QACxC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,SAAS,aAAa,CACrB,IAAU,EACV,MAAmB,EACnB,KAA6B,EAC7B,IAAiB;IAEjB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;IACnC,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAErE,OAAO,eAAe,CAAC;QACtB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,UAAU;QAClB,IAAI;QACJ,SAAS;KACT,CAAC,CAAC;AACJ,CAAC;AAED,sDAAsD;AACtD,SAAS,eAAe,CACvB,IAAU,EACV,MAAmB,EACnB,KAA6B,EAC7B,IAAiB;IAEjB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjC,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,kFAAkF;AAClF,SAAS,WAAW,CACnB,IAAU,EACV,MAAmB,EACnB,KAA6B,EAC7B,IAAiB;IAEjB,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE;YACV,YAAY,EAAE,IAAI,GAAG,EAAU;YAC/B,IAAI,EAAE,aAAa;YACnB,QAAQ;YACR,QAAQ,EAAE,MAAM;SAChB;KACD,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED,+BAA+B;AAC/B,SAAS,SAAS,CAAC,KAA2B,EAAE,IAAa;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;KACvC,CAAC,CAAC,CAAC;IAEJ,IAAI,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;AACF,CAAC;AAED,mCAAmC;AACnC,SAAS,QAAQ,CAAC,IAAY,EAAE,KAA2B;IAC1D,2BAA2B;IAC3B,IAAI,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpC,0BAA0B;IAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,2EAA2E;AAC3E,SAAS,cAAc,CAAC,KAA6B,EAAE,QAAkC;IACxF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,KAAK,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,OAAO,GAAG,CAAC;QACZ,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,4CAA4C;AAC5C,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,UAAuB;IACjE,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IAExC,4EAA4E;IAC5E,2CAA2C;IAC3C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAChE,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QAC5C,CAAC,CAAC,KAAK,GAAG,YAAY,CAAC;IAExB,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,+BAA+B;QAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC;QAC5D,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC3E,OAAO,MAAqB,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,aAAa,UAAU,6DAA6D,CAAC,CAAC;QACpG,OAAO,UAAU,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,kCAAkC,KAAK,MAAM,UAAU,MAAO,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACvG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAChD,OAAO,UAAU,CAAC;IACnB,CAAC;AACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ScaffoldCssOptions {
2
+ outputDir: string;
3
+ force: boolean;
4
+ }
5
+ export declare function scaffoldCssCommand(opts: ScaffoldCssOptions): void;
6
+ //# sourceMappingURL=scaffold-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-css.d.ts","sourceRoot":"","sources":["../../src/commands/scaffold-css.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CACf;AAYD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAyDjE"}
@@ -0,0 +1,113 @@
1
+ import { writeFileSync, existsSync, mkdirSync } from 'fs';
2
+ import { join, resolve } from 'path';
3
+ import { generateStructureContract } from '@refrakt-md/transform';
4
+ import { baseConfig } from '@refrakt-md/theme-base';
5
+ export function scaffoldCssCommand(opts) {
6
+ const contract = generateStructureContract(baseConfig);
7
+ const outputDir = resolve(opts.outputDir);
8
+ if (!existsSync(outputDir)) {
9
+ mkdirSync(outputDir, { recursive: true });
10
+ }
11
+ // Group runes by block name (e.g., Tier and FeaturedTier both use 'tier')
12
+ const blockMap = new Map();
13
+ for (const [runeName, runeContract] of Object.entries(contract.runes)) {
14
+ const existing = blockMap.get(runeContract.block);
15
+ if (existing) {
16
+ existing.runeNames.push(runeName);
17
+ Object.assign(existing.modifiers, runeContract.modifiers ?? {});
18
+ Object.assign(existing.contextModifiers, runeContract.contextModifiers ?? {});
19
+ existing.staticModifiers.push(...(runeContract.staticModifiers ?? []));
20
+ Object.assign(existing.elements, runeContract.elements ?? {});
21
+ }
22
+ else {
23
+ blockMap.set(runeContract.block, {
24
+ runeNames: [runeName],
25
+ block: runeContract.block,
26
+ modifiers: { ...(runeContract.modifiers ?? {}) },
27
+ contextModifiers: { ...(runeContract.contextModifiers ?? {}) },
28
+ staticModifiers: [...(runeContract.staticModifiers ?? [])],
29
+ elements: { ...(runeContract.elements ?? {}) },
30
+ });
31
+ }
32
+ }
33
+ let created = 0;
34
+ let skipped = 0;
35
+ for (const [blockName, merged] of blockMap) {
36
+ const fileName = `${blockName}.css`;
37
+ const filePath = join(outputDir, fileName);
38
+ if (existsSync(filePath) && !opts.force) {
39
+ skipped++;
40
+ continue;
41
+ }
42
+ const css = generateBlockCss(merged, contract.prefix);
43
+ writeFileSync(filePath, css);
44
+ created++;
45
+ }
46
+ console.log(`Scaffold CSS: ${created} files created, ${skipped} skipped (already exist)`);
47
+ if (skipped > 0 && !opts.force) {
48
+ console.log('Use --force to overwrite existing files');
49
+ }
50
+ if (created > 0) {
51
+ console.log(`Output directory: ${outputDir}`);
52
+ }
53
+ }
54
+ function generateBlockCss(merged, prefix) {
55
+ const block = `${prefix}-${merged.block}`;
56
+ const label = merged.runeNames.join(', ');
57
+ const lines = [];
58
+ lines.push(`/* ${label} rune${merged.runeNames.length > 1 ? 's' : ''} */`);
59
+ lines.push('');
60
+ // Root block
61
+ lines.push(`.${block} {`);
62
+ lines.push('');
63
+ lines.push('}');
64
+ // Modifier selectors
65
+ if (Object.keys(merged.modifiers).length > 0) {
66
+ lines.push('');
67
+ lines.push(`/* Modifiers */`);
68
+ for (const [modName, mod] of Object.entries(merged.modifiers)) {
69
+ if (mod.default) {
70
+ lines.push(`.${block}--${mod.default} {`);
71
+ lines.push('');
72
+ lines.push('}');
73
+ }
74
+ lines.push(`/* ${modName}: ${mod.classPattern} [${mod.dataAttribute}] */`);
75
+ }
76
+ }
77
+ // Context modifier selectors
78
+ if (Object.keys(merged.contextModifiers).length > 0) {
79
+ lines.push('');
80
+ lines.push(`/* Context modifiers */`);
81
+ for (const [parent, ctx] of Object.entries(merged.contextModifiers)) {
82
+ lines.push(`/* When inside ${parent}: */`);
83
+ lines.push(`${ctx.selector} {`);
84
+ lines.push('');
85
+ lines.push('}');
86
+ }
87
+ }
88
+ // Static modifier selectors
89
+ if (merged.staticModifiers.length > 0) {
90
+ lines.push('');
91
+ lines.push(`/* Static modifiers */`);
92
+ for (const mod of merged.staticModifiers) {
93
+ lines.push(`${mod.selector} {`);
94
+ lines.push('');
95
+ lines.push('}');
96
+ }
97
+ }
98
+ // Element selectors
99
+ if (Object.keys(merged.elements).length > 0) {
100
+ lines.push('');
101
+ lines.push(`/* Elements */`);
102
+ for (const [elName, el] of Object.entries(merged.elements)) {
103
+ const condNote = el.condition ? ` (conditional: ${el.condition})` : '';
104
+ lines.push(`/* ${elName} — <${el.tag}> from ${el.source}${condNote} */`);
105
+ lines.push(`${el.selector} {`);
106
+ lines.push('');
107
+ lines.push('}');
108
+ }
109
+ }
110
+ lines.push('');
111
+ return lines.join('\n');
112
+ }
113
+ //# sourceMappingURL=scaffold-css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-css.js","sourceRoot":"","sources":["../../src/commands/scaffold-css.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface ValidateOptions {
2
+ configPath?: string;
3
+ manifestPath?: string;
4
+ }
5
+ export declare function validateCommand(opts: ValidateOptions): void;
6
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA4C3D"}
@@ -0,0 +1,70 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import { validateThemeConfig, validateManifest } from '@refrakt-md/transform';
4
+ import { baseConfig } from '@refrakt-md/theme-base';
5
+ export function validateCommand(opts) {
6
+ let hasErrors = false;
7
+ // Validate theme config
8
+ if (opts.configPath) {
9
+ const absPath = resolve(opts.configPath);
10
+ if (!existsSync(absPath)) {
11
+ console.error(`Error: Config file not found: ${absPath}`);
12
+ process.exit(1);
13
+ }
14
+ // For now, only JSON configs are supported via CLI.
15
+ // TypeScript configs require dynamic import which needs the module to be built.
16
+ const raw = JSON.parse(readFileSync(absPath, 'utf-8'));
17
+ console.log('Validating theme config...');
18
+ const result = validateThemeConfig(raw);
19
+ printResult('Theme config', result);
20
+ if (!result.valid)
21
+ hasErrors = true;
22
+ }
23
+ else {
24
+ // Validate the base config as a sanity check
25
+ console.log('Validating base theme config...');
26
+ const result = validateThemeConfig(baseConfig);
27
+ printResult('Base theme config', result);
28
+ if (!result.valid)
29
+ hasErrors = true;
30
+ }
31
+ // Validate manifest
32
+ if (opts.manifestPath) {
33
+ const absPath = resolve(opts.manifestPath);
34
+ if (!existsSync(absPath)) {
35
+ console.error(`Error: Manifest file not found: ${absPath}`);
36
+ process.exit(1);
37
+ }
38
+ const raw = JSON.parse(readFileSync(absPath, 'utf-8'));
39
+ console.log('\nValidating manifest...');
40
+ const result = validateManifest(raw);
41
+ printResult('Manifest', result);
42
+ if (!result.valid)
43
+ hasErrors = true;
44
+ }
45
+ if (hasErrors) {
46
+ process.exit(1);
47
+ }
48
+ }
49
+ function printResult(label, result) {
50
+ if (result.valid && result.warnings.length === 0) {
51
+ console.log(` ${label}: OK`);
52
+ return;
53
+ }
54
+ if (result.errors.length > 0) {
55
+ console.log(` ${label}: FAIL (${result.errors.length} error${result.errors.length === 1 ? '' : 's'})`);
56
+ for (const err of result.errors) {
57
+ console.log(` ERROR ${err.path}: ${err.message}`);
58
+ }
59
+ }
60
+ else {
61
+ console.log(` ${label}: OK`);
62
+ }
63
+ if (result.warnings.length > 0) {
64
+ console.log(` ${result.warnings.length} warning${result.warnings.length === 1 ? '' : 's'}:`);
65
+ for (const warn of result.warnings) {
66
+ console.log(` WARN ${warn.path}: ${warn.message}`);
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,15 @@ import type { AIProvider } from '@refrakt-md/ai';
2
2
  export interface WriteOptions {
3
3
  prompt: string;
4
4
  provider: AIProvider;
5
+ providerName: string;
6
+ modelName: string;
5
7
  model?: string;
6
8
  output?: string;
9
+ outputDir?: string;
7
10
  }
11
+ export declare function splitFiles(raw: string): Array<{
12
+ path: string;
13
+ content: string;
14
+ }>;
8
15
  export declare function writeCommand(options: WriteOptions): Promise<void>;
9
16
  //# sourceMappingURL=write.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,gBAAgB,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BvE"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,gBAAgB,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAYD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8BhF;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDvE"}
@@ -1,25 +1,81 @@
1
- import { writeFileSync } from 'node:fs';
2
- import { generateSystemPrompt } from '@refrakt-md/ai';
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { generateSystemPrompt, writePrompt } from '@refrakt-md/ai';
3
4
  import { runes } from '@refrakt-md/runes';
5
+ function log(message) {
6
+ process.stderr.write(message);
7
+ }
8
+ function wordCount(text) {
9
+ return text.split(/\s+/).filter(Boolean).length;
10
+ }
11
+ const FILE_MARKER = /^--- FILE: (.+) ---$/gm;
12
+ export function splitFiles(raw) {
13
+ const files = [];
14
+ const markers = [];
15
+ let match;
16
+ while ((match = FILE_MARKER.exec(raw)) !== null) {
17
+ markers.push({ path: match[1].trim(), index: match.index + match[0].length });
18
+ }
19
+ if (markers.length === 0) {
20
+ return [];
21
+ }
22
+ for (let i = 0; i < markers.length; i++) {
23
+ const filePath = markers[i].path;
24
+ if (filePath.includes('..')) {
25
+ throw new Error(`Invalid file path "${filePath}": parent traversal is not allowed`);
26
+ }
27
+ const start = markers[i].index;
28
+ const nextMarkerPos = i + 1 < markers.length
29
+ ? raw.indexOf(`--- FILE: ${markers[i + 1].path} ---`, start)
30
+ : raw.length;
31
+ const content = raw.slice(start, nextMarkerPos).replace(/^\n/, '').replace(/\n$/, '');
32
+ files.push({ path: filePath, content: content + '\n' });
33
+ }
34
+ return files;
35
+ }
4
36
  export async function writeCommand(options) {
5
- const { prompt, provider, model, output } = options;
6
- const systemPrompt = generateSystemPrompt(runes);
37
+ const { prompt, provider, providerName, modelName, model, output, outputDir } = options;
38
+ log(`Using ${providerName} (${modelName})\n`);
39
+ const multiFile = !!outputDir;
40
+ const systemPrompt = generateSystemPrompt(runes) + writePrompt({ multiFile });
7
41
  const messages = [
8
42
  { role: 'system', content: systemPrompt },
9
43
  { role: 'user', content: prompt },
10
44
  ];
11
45
  let content = '';
46
+ if (output || outputDir) {
47
+ log('Generating...');
48
+ }
12
49
  for await (const chunk of provider.complete({ messages, model })) {
13
- if (output) {
14
- content += chunk;
15
- }
16
- else {
50
+ content += chunk;
51
+ if (!output && !outputDir) {
17
52
  process.stdout.write(chunk);
18
53
  }
19
54
  }
20
- if (output) {
55
+ if (outputDir) {
56
+ const files = splitFiles(content);
57
+ const words = wordCount(content);
58
+ if (files.length === 0) {
59
+ log(`\rGenerating... done (${words.toLocaleString()} words)\n`);
60
+ const fallbackPath = path.join(outputDir, 'index.md');
61
+ mkdirSync(outputDir, { recursive: true });
62
+ writeFileSync(fallbackPath, content);
63
+ log(`Written to ${fallbackPath}\n`);
64
+ return;
65
+ }
66
+ log(`\rGenerating... done (${words.toLocaleString()} words, ${files.length} files)\n`);
67
+ for (const file of files) {
68
+ const fullPath = path.join(outputDir, file.path);
69
+ mkdirSync(path.dirname(fullPath), { recursive: true });
70
+ writeFileSync(fullPath, file.content);
71
+ log(` ${fullPath}\n`);
72
+ }
73
+ }
74
+ else if (output) {
75
+ const words = wordCount(content);
76
+ log(`\rGenerating... done (${words.toLocaleString()} words)\n`);
21
77
  writeFileSync(output, content);
22
- process.stderr.write(`Written to ${output}\n`);
78
+ log(`Written to ${output}\n`);
23
79
  }
24
80
  else {
25
81
  process.stdout.write('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAU1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACvD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAEpD,MAAM,YAAY,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAc;QAC3B,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;QACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;KACjC,CAAC;IAEF,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAClE,IAAI,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,KAAK,CAAC;QAClB,CAAC;aAAM,CAAC;YACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACZ,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,MAAM,IAAI,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"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"}