@astryxdesign/cli 0.1.1-canary.7e591d0 → 0.1.1-canary.9846a62

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/cli",
3
- "version": "0.1.1-canary.7e591d0",
3
+ "version": "0.1.1-canary.9846a62",
4
4
  "displayName": "CLI",
5
5
  "description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
6
6
  "author": "Meta Open Source",
@@ -38,10 +38,6 @@
38
38
  "./api": {
39
39
  "types": "./src/types/api.d.ts",
40
40
  "import": "./src/api/index.mjs"
41
- },
42
- "./config": {
43
- "types": "./src/types/config.d.ts",
44
- "import": "./src/config.mjs"
45
41
  }
46
42
  },
47
43
  "files": [
@@ -55,13 +51,12 @@
55
51
  "@clack/prompts": "^1.5.1",
56
52
  "commander": "^12.1.0",
57
53
  "jiti": "^2.7.0",
58
- "jscodeshift": "^17.3.0",
59
- "zod": "^4.4.3"
54
+ "jscodeshift": "^17.3.0"
60
55
  },
61
56
  "peerDependencies": {
62
- "@astryxdesign/core": "0.1.1-canary.7e591d0",
63
- "@astryxdesign/lab": "0.1.1-canary.7e591d0",
64
- "@astryxdesign/theme-neutral": "0.1.1-canary.7e591d0"
57
+ "@astryxdesign/core": "0.1.1-canary.9846a62",
58
+ "@astryxdesign/lab": "0.1.1-canary.9846a62",
59
+ "@astryxdesign/theme-neutral": "0.1.1-canary.9846a62"
65
60
  },
66
61
  "peerDependenciesMeta": {
67
62
  "@astryxdesign/core": {
@@ -75,9 +70,9 @@
75
70
  }
76
71
  },
77
72
  "devDependencies": {
78
- "@astryxdesign/core": "0.1.1-canary.7e591d0",
79
- "@astryxdesign/lab": "0.1.1-canary.7e591d0",
80
- "@astryxdesign/theme-neutral": "0.1.1-canary.7e591d0"
73
+ "@astryxdesign/core": "0.1.1-canary.9846a62",
74
+ "@astryxdesign/lab": "0.1.1-canary.9846a62",
75
+ "@astryxdesign/theme-neutral": "0.1.1-canary.9846a62"
81
76
  },
82
77
  "scripts": {
83
78
  "astryx": "node bin/astryx.mjs",
@@ -5,28 +5,19 @@
5
5
  */
6
6
 
7
7
  import {loadConfig} from '../lib/config.mjs';
8
- import {
9
- scanAllPackages,
10
- findComponentInPackages,
11
- } from '../lib/package-scanner.mjs';
8
+ import {scanAllPackages, findComponentInPackages} from '../lib/package-scanner.mjs';
12
9
  import {loadDocs} from '../lib/component-loader.mjs';
13
10
  import {levenshteinDistance} from '../lib/string-utils.mjs';
14
11
  import {AstryxError} from './error.mjs';
15
12
  import {ERROR_CODES} from '../lib/error-codes.mjs';
16
13
 
17
14
  function validateDocs(docs) {
18
- if (!docs || typeof docs !== 'object')
19
- return 'docs export is missing or not an object';
20
- if (typeof docs.name !== 'string' || !docs.name)
21
- return 'docs.name is missing or not a string';
22
- if (!docs.usage || typeof docs.usage.description !== 'string')
23
- return 'docs.usage.description is missing or not a string';
24
- if (docs.props && !Array.isArray(docs.props))
25
- return 'docs.props must be an array';
26
- if (docs.components && !Array.isArray(docs.components))
27
- return 'docs.components must be an array';
28
- if (docs.usage?.bestPractices && !Array.isArray(docs.usage.bestPractices))
29
- return 'docs.usage.bestPractices must be an array';
15
+ if (!docs || typeof docs !== 'object') return 'docs export is missing or not an object';
16
+ if (typeof docs.name !== 'string' || !docs.name) return 'docs.name is missing or not a string';
17
+ if (!docs.usage || typeof docs.usage.description !== 'string') return 'docs.usage.description is missing or not a string';
18
+ if (docs.props && !Array.isArray(docs.props)) return 'docs.props must be an array';
19
+ if (docs.components && !Array.isArray(docs.components)) return 'docs.components must be an array';
20
+ if (docs.usage?.bestPractices && !Array.isArray(docs.usage.bestPractices)) return 'docs.usage.bestPractices must be an array';
30
21
  return null;
31
22
  }
32
23
 
@@ -41,7 +32,7 @@ function validateDocs(docs) {
41
32
  export async function discover(query, options = {}) {
42
33
  const {lang = null, zh = false} = options;
43
34
  const config = await loadConfig();
44
- const toEntry = pkg => ({
35
+ const toEntry = (pkg) => ({
45
36
  name: pkg.name,
46
37
  category: pkg.category,
47
38
  components: pkg.components,
@@ -50,14 +41,11 @@ export async function discover(query, options = {}) {
50
41
  displayName: pkg.displayName,
51
42
  });
52
43
 
53
- const explicitPackages = (config.loadedIntegrations ?? [])
54
- .map(integration => integration.package)
55
- .filter(Boolean);
56
- if (config.packages.length === 0 && explicitPackages.length === 0) {
44
+ if (config.packages.length === 0) {
57
45
  return {type: 'discover.list', data: [], meta: {configured: false}};
58
46
  }
59
47
 
60
- const packages = scanAllPackages(config.packages, explicitPackages);
48
+ const packages = scanAllPackages(config.packages);
61
49
 
62
50
  if (packages.length === 0) {
63
51
  return {type: 'discover.list', data: [], meta: {configured: true}};
@@ -73,10 +61,7 @@ export async function discover(query, options = {}) {
73
61
  if (slashIdx > 0) {
74
62
  const pkgName = query.slice(0, slashIdx);
75
63
  const compName = query.slice(slashIdx + 1);
76
- return await resolveComponentDocs(packages, compName, pkgName, {
77
- lang,
78
- zh,
79
- });
64
+ return await resolveComponentDocs(packages, compName, pkgName, {lang, zh});
80
65
  }
81
66
 
82
67
  const pkg = packages.find(p => p.name === query);
@@ -114,16 +99,7 @@ export async function discover(query, options = {}) {
114
99
  }
115
100
 
116
101
  if (substringMatches.length > 1) {
117
- return {
118
- type: 'discover.search',
119
- data: {
120
- query,
121
- matches: substringMatches.map(m => ({
122
- package: m.pkg.name,
123
- component: m.comp,
124
- })),
125
- },
126
- };
102
+ return {type: 'discover.search', data: {query, matches: substringMatches.map(m => ({package: m.pkg.name, component: m.comp}))}};
127
103
  }
128
104
 
129
105
  // Fuzzy fallback
@@ -134,10 +110,7 @@ export async function discover(query, options = {}) {
134
110
  }
135
111
  }
136
112
  const fuzzyMatches = allComponents
137
- .map(item => ({
138
- ...item,
139
- distance: levenshteinDistance(lower, item.comp.toLowerCase()),
140
- }))
113
+ .map(item => ({...item, distance: levenshteinDistance(lower, item.comp.toLowerCase())}))
141
114
  .filter(m => m.distance <= 3)
142
115
  .sort((a, b) => a.distance - b.distance)
143
116
  .slice(0, 5);
@@ -145,46 +118,30 @@ export async function discover(query, options = {}) {
145
118
  if (fuzzyMatches.length > 0) {
146
119
  throw new AstryxError(
147
120
  `"${query}" not found`,
148
- fuzzyMatches.map(m => ({
149
- name: m.pkg.name + '/' + m.comp,
150
- reason: 'similar name',
151
- })),
121
+ fuzzyMatches.map(m => ({name: m.pkg.name + '/' + m.comp, reason: 'similar name'})),
152
122
  ERROR_CODES.ERR_NOT_FOUND,
153
123
  );
154
124
  }
155
125
 
156
- throw new AstryxError(
157
- `"${query}" not found in any package`,
158
- undefined,
159
- ERROR_CODES.ERR_NOT_FOUND,
160
- );
126
+ throw new AstryxError(`"${query}" not found in any package`, undefined, ERROR_CODES.ERR_NOT_FOUND);
161
127
  }
162
128
 
163
129
  async function resolveComponentDocs(packages, compName, pkgName, {lang, zh}) {
164
130
  const pkg = packages.find(p => p.name === pkgName);
165
- if (!pkg)
166
- throw new AstryxError(
167
- `Package "${pkgName}" not found`,
168
- undefined,
169
- ERROR_CODES.ERR_UNKNOWN_PACKAGE,
170
- );
131
+ if (!pkg) throw new AstryxError(`Package "${pkgName}" not found`, undefined, ERROR_CODES.ERR_UNKNOWN_PACKAGE);
171
132
 
172
133
  const result = findComponentInPackages([pkg], compName);
173
134
  if (!result) {
174
135
  const lower = compName.toLowerCase();
175
136
  const hits = pkg.components.filter(c => c.toLowerCase().includes(lower));
176
- const suggestions =
177
- hits.length > 0
178
- ? hits
179
- : pkg.components
180
- .map(c => ({
181
- name: c,
182
- distance: levenshteinDistance(lower, c.toLowerCase()),
183
- }))
184
- .filter(m => m.distance <= 3)
185
- .sort((a, b) => a.distance - b.distance)
186
- .slice(0, 5)
187
- .map(m => m.name);
137
+ const suggestions = hits.length > 0
138
+ ? hits
139
+ : pkg.components
140
+ .map(c => ({name: c, distance: levenshteinDistance(lower, c.toLowerCase())}))
141
+ .filter(m => m.distance <= 3)
142
+ .sort((a, b) => a.distance - b.distance)
143
+ .slice(0, 5)
144
+ .map(m => m.name);
188
145
  throw new AstryxError(
189
146
  `Component "${compName}" not found in ${pkgName}`,
190
147
  suggestions.map(s => ({name: s, reason: 'similar name'})),
@@ -200,18 +157,9 @@ async function loadAndValidate(result, {lang, zh}) {
200
157
  try {
201
158
  docs = await loadDocs(result.docPath, {zh, lang});
202
159
  } catch (e) {
203
- throw new AstryxError(
204
- `Failed to load docs for ${result.componentName}: ${e.message}`,
205
- undefined,
206
- ERROR_CODES.ERR_INVALID_DOC,
207
- );
160
+ throw new AstryxError(`Failed to load docs for ${result.componentName}: ${e.message}`, undefined, ERROR_CODES.ERR_INVALID_DOC);
208
161
  }
209
162
  const err = validateDocs(docs);
210
- if (err)
211
- throw new AstryxError(
212
- `Invalid docs for ${result.componentName}: ${err}`,
213
- undefined,
214
- ERROR_CODES.ERR_INVALID_DOC,
215
- );
163
+ if (err) throw new AstryxError(`Invalid docs for ${result.componentName}: ${err}`, undefined, ERROR_CODES.ERR_INVALID_DOC);
216
164
  return {type: 'discover.detail.doc', data: docs};
217
165
  }
@@ -7,11 +7,7 @@
7
7
  import * as fs from 'node:fs';
8
8
  import * as path from 'node:path';
9
9
  import {CLI_ROOT, discoverExternalPackages} from '../utils/paths.mjs';
10
- import {
11
- assertWithin,
12
- isFilePathArg,
13
- PathSafetyError,
14
- } from '../utils/path-safety.mjs';
10
+ import {assertWithin, isFilePathArg, PathSafetyError} from '../utils/path-safety.mjs';
15
11
  import {AstryxError} from './error.mjs';
16
12
  import {ERROR_CODES} from '../lib/error-codes.mjs';
17
13
  import {loadConfig} from '../lib/config.mjs';
@@ -27,7 +23,7 @@ const BLOCKS_DIR = path.join(TEMPLATES_DIR, 'blocks');
27
23
  * or not. Mirrors apps/docsite/public/template-assets/placeholder.svg.
28
24
  */
29
25
  const PLACEHOLDER_IMAGE =
30
- 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20400%20300%22%20preserveAspectRatio%3D%22xMidYMid%20slice%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23f5f6f8%22%2F%3E%3Cg%20transform%3D%22translate%28200%20150%29%22%20fill%3D%22none%22%20stroke%3D%22%23c2cad6%22%20stroke-width%3D%225%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22-44%22%20y%3D%22-44%22%20width%3D%2288%22%20height%3D%2288%22%20rx%3D%2216%22%2F%3E%3Ccircle%20cx%3D%2218%22%20cy%3D%22-18%22%20r%3D%222.5%22%20fill%3D%22%23c2cad6%22%20stroke%3D%22none%22%2F%3E%3Cpath%20d%3D%22M-34%2030%20L-8%200%20L10%2018%20L20%208%20L34%2024%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E';
26
+ "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20400%20300%22%20preserveAspectRatio%3D%22xMidYMid%20slice%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23f5f6f8%22%2F%3E%3Cg%20transform%3D%22translate%28200%20150%29%22%20fill%3D%22none%22%20stroke%3D%22%23c2cad6%22%20stroke-width%3D%225%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22-44%22%20y%3D%22-44%22%20width%3D%2288%22%20height%3D%2288%22%20rx%3D%2216%22%2F%3E%3Ccircle%20cx%3D%2218%22%20cy%3D%22-18%22%20r%3D%222.5%22%20fill%3D%22%23c2cad6%22%20stroke%3D%22none%22%2F%3E%3Cpath%20d%3D%22M-34%2030%20L-8%200%20L10%2018%20L20%208%20L34%2024%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E";
31
27
 
32
28
  /**
33
29
  * Demo-image sources to strip from scaffolded projects — Meta's lookaside CDN
@@ -64,12 +60,9 @@ export {discoverAll as discoverTemplates};
64
60
  export function listTemplates() {
65
61
  const all = [];
66
62
  if (fs.existsSync(PAGES_DIR)) {
67
- all.push(
68
- ...fs
69
- .readdirSync(PAGES_DIR, {withFileTypes: true})
70
- .filter(e => e.isDirectory())
71
- .map(e => e.name),
72
- );
63
+ all.push(...fs.readdirSync(PAGES_DIR, {withFileTypes: true})
64
+ .filter(e => e.isDirectory())
65
+ .map(e => e.name));
73
66
  }
74
67
  return all.sort();
75
68
  }
@@ -90,8 +83,7 @@ function findDocFiles(dir, pattern) {
90
83
 
91
84
  async function discoverPages() {
92
85
  if (!fs.existsSync(PAGES_DIR)) return [];
93
- const dirs = fs
94
- .readdirSync(PAGES_DIR, {withFileTypes: true})
86
+ const dirs = fs.readdirSync(PAGES_DIR, {withFileTypes: true})
95
87
  .filter(e => e.isDirectory());
96
88
 
97
89
  const templates = [];
@@ -146,11 +138,7 @@ async function discoverBlocks() {
146
138
  * @param {string} [cwd]
147
139
  */
148
140
  async function discoverExternalBlocks(cwd = process.cwd()) {
149
- const config = await loadConfig(cwd);
150
- const integrationPackages = (config.loadedIntegrations ?? [])
151
- .map(integration => integration.package)
152
- .filter(Boolean);
153
- const externals = [...discoverExternalPackages(cwd), ...integrationPackages];
141
+ const externals = discoverExternalPackages(cwd);
154
142
  const blocks = [];
155
143
 
156
144
  for (const ext of externals) {
@@ -205,7 +193,9 @@ async function discoverAll() {
205
193
  export async function findRelatedBlocks(componentName, cwd) {
206
194
  const blocks = await discoverAllBlocks(cwd);
207
195
  return blocks.filter(b =>
208
- b.componentsUsed.some(c => c.toLowerCase() === componentName.toLowerCase()),
196
+ b.componentsUsed.some(c =>
197
+ c.toLowerCase() === componentName.toLowerCase(),
198
+ ),
209
199
  );
210
200
  }
211
201
 
@@ -228,7 +218,7 @@ export async function findShowcase(componentName, cwd, options) {
228
218
  return true;
229
219
  });
230
220
 
231
- const toResult = b => ({
221
+ const toResult = (b) => ({
232
222
  name: b.name,
233
223
  aspectRatio: b.aspectRatio,
234
224
  filePath: b.filePath,
@@ -252,14 +242,8 @@ export async function findShowcase(componentName, cwd, options) {
252
242
  }
253
243
 
254
244
  const UBIQUITOUS = new Set([
255
- 'Text',
256
- 'Heading',
257
- 'Button',
258
- 'HStack',
259
- 'VStack',
260
- 'Link',
261
- 'StackItem',
262
- 'Icon',
245
+ 'Text', 'Heading', 'Button', 'HStack', 'VStack', 'Link',
246
+ 'StackItem', 'Icon',
263
247
  ]);
264
248
 
265
249
  export function extractComponents(pagePath) {
@@ -275,60 +259,26 @@ export function extractComponents(pagePath) {
275
259
  while ((m = tagRegex.exec(src)) !== null) {
276
260
  matches.push(m[2]);
277
261
  }
278
- return [
279
- ...new Set(
280
- matches
281
- .filter(n => !['Theme', 'ThemeProvider'].includes(n))
282
- .filter(n => !UBIQUITOUS.has(n))
283
- .map(n =>
284
- n.replace(
285
- /(Item|Section|Header|Content|Footer|Panel|Heading|CollapseButton|Column|Sortable|Selection|Group|Source)$/,
286
- '',
287
- ),
288
- )
289
- .filter(Boolean),
290
- ),
291
- ].sort();
262
+ return [...new Set(
263
+ matches
264
+ .filter(n => !['Theme', 'ThemeProvider'].includes(n))
265
+ .filter(n => !UBIQUITOUS.has(n))
266
+ .map(n => n.replace(/(Item|Section|Header|Content|Footer|Panel|Heading|CollapseButton|Column|Sortable|Selection|Group|Source)$/, ''))
267
+ .filter(Boolean),
268
+ )].sort();
292
269
  }
293
270
 
294
271
  const STRUCTURAL = new Set([
295
- 'AppShell',
296
- 'Layout',
297
- 'LayoutHeader',
298
- 'LayoutContent',
299
- 'LayoutPanel',
300
- 'LayoutFooter',
301
- 'Card',
302
- 'Section',
303
- 'Grid',
304
- 'GridSpan',
305
- 'List',
306
- 'Table',
307
- 'TabList',
308
- 'Toolbar',
309
- 'SideNav',
310
- 'TopNav',
311
- 'Dialog',
312
- 'FormLayout',
313
- 'Center',
272
+ 'AppShell', 'Layout', 'LayoutHeader', 'LayoutContent', 'LayoutPanel',
273
+ 'LayoutFooter', 'Card', 'Section', 'Grid', 'GridSpan', 'List',
274
+ 'Table', 'TabList', 'Toolbar', 'SideNav', 'TopNav', 'Dialog',
275
+ 'FormLayout', 'Center',
314
276
  ]);
315
277
 
316
278
  const SPATIAL_PROPS = [
317
- 'padding',
318
- 'contentPadding',
319
- 'gap',
320
- 'rowGap',
321
- 'columnGap',
322
- 'columns',
323
- 'minChildWidth',
324
- 'hasDivider',
325
- 'defaultHasDividers',
326
- 'variant',
327
- 'density',
328
- 'role',
329
- 'height',
330
- 'width',
331
- 'maxWidth',
279
+ 'padding', 'contentPadding', 'gap', 'rowGap', 'columnGap',
280
+ 'columns', 'minChildWidth', 'hasDivider', 'defaultHasDividers',
281
+ 'variant', 'density', 'role', 'height', 'width', 'maxWidth',
332
282
  ];
333
283
 
334
284
  /**
@@ -396,18 +346,11 @@ function extractSkeleton(source) {
396
346
  for (let i = 0; i < lines.length; i++) {
397
347
  const t = lines[i].trim();
398
348
 
399
- if (t.match(/^export\s+default\s+function/)) {
400
- inDefaultExport = true;
401
- continue;
402
- }
403
- if (inDefaultExport && t.match(/^return\s*\(/)) {
404
- capturing = true;
405
- continue;
406
- }
349
+ if (t.match(/^export\s+default\s+function/)) { inDefaultExport = true; continue; }
350
+ if (inDefaultExport && t.match(/^return\s*\(/)) { capturing = true; continue; }
407
351
  if (!capturing) continue;
408
352
  if (out.length >= MAX_LINES) {
409
- if (!out[out.length - 1]?.includes('...'))
410
- out.push(' '.repeat(depth) + '...');
353
+ if (!out[out.length - 1]?.includes('...')) out.push(' '.repeat(depth) + '...');
411
354
  continue;
412
355
  }
413
356
 
@@ -429,9 +372,7 @@ function extractSkeleton(source) {
429
372
  const hasSpatialProps = props.length > 0;
430
373
  const propStr = hasSpatialProps ? ' ' + props.join(' ') : '';
431
374
  const isVStack = comp === 'VStack' || comp === 'HStack';
432
- const isSelfClosing = tagText.match(
433
- new RegExp('<' + tagName + '[^>]*/>', 's'),
434
- );
375
+ const isSelfClosing = tagText.match(new RegExp('<' + tagName + '[^>]*/>', 's'));
435
376
 
436
377
  if (isVStack && !hasSpatialProps) continue;
437
378
 
@@ -458,18 +399,13 @@ function extractSkeleton(source) {
458
399
  continue;
459
400
  }
460
401
 
461
- const slotMatch = t.match(
462
- /^(header|content|footer|start|end|sideNav|topNav)\s*=\s*\{/,
463
- );
402
+ const slotMatch = t.match(/^(header|content|footer|start|end|sideNav|topNav)\s*=\s*\{/);
464
403
  if (slotMatch) {
465
404
  out.push(' '.repeat(depth) + `/* ${slotMatch[1]}: */`);
466
405
  continue;
467
406
  }
468
407
 
469
- if (
470
- t.startsWith('<div') &&
471
- (t.includes('padding') || t.includes('maxWidth') || t.includes('gap:'))
472
- ) {
408
+ if (t.startsWith('<div') && (t.includes('padding') || t.includes('maxWidth') || t.includes('gap:'))) {
473
409
  const styleProps = [];
474
410
  const divText = lines.slice(i, Math.min(i + 5, lines.length)).join(' ');
475
411
  const pp = divText.match(/padding[^:]*:\s*['"]?([^'"},)]+)/);
@@ -509,7 +445,7 @@ export async function getTemplateById(id, options = {}) {
509
445
  'Add a template.get function to astryx.config.mjs:\n\n' +
510
446
  ' export default {\n' +
511
447
  ' template: {\n' +
512
- ' get: async (id) => { /* return template source string */ },\n' +
448
+ " get: async (id) => { /* return template source string */ },\n" +
513
449
  ' },\n' +
514
450
  ' };',
515
451
  undefined,
@@ -522,11 +458,7 @@ export async function getTemplateById(id, options = {}) {
522
458
  source = await getter(id);
523
459
  } catch (err) {
524
460
  const detail = err instanceof Error ? err.message : String(err);
525
- throw new AstryxError(
526
- `template.get("${id}") threw an error: ${detail}`,
527
- undefined,
528
- ERROR_CODES.ERR_TEMPLATE_GET,
529
- );
461
+ throw new AstryxError(`template.get("${id}") threw an error: ${detail}`, undefined, ERROR_CODES.ERR_TEMPLATE_GET);
530
462
  }
531
463
 
532
464
  if (source == null) {
@@ -568,14 +500,7 @@ export async function getTemplateById(id, options = {}) {
568
500
  * @returns {Promise<{type: string, data: unknown}>}
569
501
  */
570
502
  export async function template(name, options = {}) {
571
- const {
572
- list = false,
573
- skeleton = false,
574
- show = false,
575
- targetPath,
576
- type,
577
- cwd = process.cwd(),
578
- } = options;
503
+ const {list = false, skeleton = false, show = false, targetPath, type, cwd = process.cwd()} = options;
579
504
  const templates = await discoverAll();
580
505
 
581
506
  if (list || (!name && !skeleton)) {
@@ -612,11 +537,7 @@ export async function template(name, options = {}) {
612
537
  );
613
538
  }
614
539
  if (!fs.existsSync(match.filePath)) {
615
- throw new AstryxError(
616
- `No source file found for template "${name}"`,
617
- undefined,
618
- ERROR_CODES.ERR_NO_SOURCE,
619
- );
540
+ throw new AstryxError(`No source file found for template "${name}"`, undefined, ERROR_CODES.ERR_NO_SOURCE);
620
541
  }
621
542
  const src = fs.readFileSync(match.filePath, 'utf-8');
622
543
  return {
@@ -631,11 +552,7 @@ export async function template(name, options = {}) {
631
552
  }
632
553
 
633
554
  if (!fs.existsSync(match.filePath)) {
634
- throw new AstryxError(
635
- `No source file found for template "${name}"`,
636
- undefined,
637
- ERROR_CODES.ERR_NO_SOURCE,
638
- );
555
+ throw new AstryxError(`No source file found for template "${name}"`, undefined, ERROR_CODES.ERR_NO_SOURCE);
639
556
  }
640
557
 
641
558
  if (show || !targetPath) {
@@ -662,11 +579,7 @@ export async function template(name, options = {}) {
662
579
  });
663
580
  } catch (err) {
664
581
  if (err instanceof PathSafetyError) {
665
- throw new AstryxError(
666
- err.message,
667
- undefined,
668
- ERROR_CODES.ERR_PATH_TRAVERSAL,
669
- );
582
+ throw new AstryxError(err.message, undefined, ERROR_CODES.ERR_PATH_TRAVERSAL);
670
583
  }
671
584
  throw err;
672
585
  }
@@ -683,8 +596,9 @@ export async function template(name, options = {}) {
683
596
  outputFilePath = resolvedTarget;
684
597
  } else {
685
598
  outputDir = resolvedTarget;
686
- outputFileName =
687
- match.type === 'block' ? path.basename(match.filePath) : 'page.tsx';
599
+ outputFileName = match.type === 'block'
600
+ ? path.basename(match.filePath)
601
+ : 'page.tsx';
688
602
  outputFilePath = path.join(outputDir, outputFileName);
689
603
  }
690
604
 
@@ -699,11 +613,6 @@ export async function template(name, options = {}) {
699
613
  const relOutput = path.relative(cwd, outputDir) || '.';
700
614
  return {
701
615
  type: 'template.copy',
702
- data: {
703
- template: name,
704
- outputDir: relOutput,
705
- fileName: outputFileName,
706
- filesCopied: 1,
707
- },
616
+ data: {template: name, outputDir: relOutput, fileName: outputFileName, filesCopied: 1},
708
617
  };
709
618
  }
@@ -132,7 +132,7 @@ export function registerGapReport(program) {
132
132
  .action(async () => {
133
133
  p.intro('Gap report setup');
134
134
 
135
- const config = await loadGapReportConfig();
135
+ const config = loadGapReportConfig();
136
136
  const currentMode = !config.enabled
137
137
  ? 'disabled'
138
138
  : config.command
@@ -252,14 +252,9 @@ export function registerGapReport(program) {
252
252
  return;
253
253
  }
254
254
 
255
- const config = await loadGapReportConfig();
255
+ const config = loadGapReportConfig();
256
256
  if (!config.enabled) {
257
- if (json)
258
- return jsonError(
259
- 'Gap reporting is disabled',
260
- undefined,
261
- ERROR_CODES.ERR_GAP_REPORT_FAILED,
262
- );
257
+ if (json) return jsonError('Gap reporting is disabled', undefined, ERROR_CODES.ERR_GAP_REPORT_FAILED);
263
258
  humanLog(
264
259
  `Gap reporting is disabled (ASTRYX_GAP_REPORT=off or astryx.config.mjs).\n` +
265
260
  `Run \`${getRunPrefix()} astryx gap-report setup\` to configure.`,
@@ -300,7 +295,7 @@ export function registerGapReport(program) {
300
295
  return;
301
296
  }
302
297
 
303
- const preview = await buildGapReportPreview({
298
+ const preview = buildGapReportPreview({
304
299
  component: options.component,
305
300
  category: options.category,
306
301
  intention: options.reason,
@@ -331,7 +326,7 @@ export function registerGapReport(program) {
331
326
  }
332
327
 
333
328
  try {
334
- const url = await createGapReport({
329
+ const url = createGapReport({
335
330
  component: options.component,
336
331
  category: options.category,
337
332
  intention: options.reason,
@@ -348,9 +343,7 @@ export function registerGapReport(program) {
348
343
  humanLog('\nGap reporting is disabled via configuration.\n');
349
344
  }
350
345
  } catch (err) {
351
- cliError(`Filing gap report failed: ${err.message}`, {
352
- code: ERROR_CODES.ERR_GAP_REPORT_FAILED,
353
- });
346
+ cliError(`Filing gap report failed: ${err.message}`, {code: ERROR_CODES.ERR_GAP_REPORT_FAILED});
354
347
  return;
355
348
  }
356
349
  return;
@@ -393,8 +386,7 @@ export function registerGapReport(program) {
393
386
  placeholder:
394
387
  'e.g. "Need a compact variant for use in dense data tables"',
395
388
  validate: val => {
396
- if (!val.trim())
397
- return 'Please describe what you were trying to do';
389
+ if (!val.trim()) return 'Please describe what you were trying to do';
398
390
  },
399
391
  }),
400
392
  );
@@ -414,7 +406,7 @@ export function registerGapReport(program) {
414
406
  source: 'interactive',
415
407
  };
416
408
 
417
- const preview = await buildGapReportPreview(previewArgs);
409
+ const preview = buildGapReportPreview(previewArgs);
418
410
 
419
411
  // Always show the user exactly what would be filed before sending.
420
412
  p.note(
@@ -448,7 +440,7 @@ export function registerGapReport(program) {
448
440
  s.start('Filing gap report');
449
441
 
450
442
  try {
451
- const url = await createGapReport(previewArgs);
443
+ const url = createGapReport(previewArgs);
452
444
  s.stop(url ? 'Gap report filed' : 'Gap reporting is disabled');
453
445
  if (url) {
454
446
  p.log.success(url);