rtgl 0.0.38 → 1.0.0-rc1

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 (2) hide show
  1. package/cli.js +67 -16
  2. package/package.json +2 -2
package/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { build, scaffold, watch, examples } from "@rettangoli/fe/cli";
3
+ import { build, check, scaffold, watch, examples } from "@rettangoli/fe/cli";
4
4
  import { generate, report, accept } from "@rettangoli/vt/cli";
5
5
  import { buildSite, watchSite, screenshotCommand, initSite } from "@rettangoli/sites/cli";
6
6
  import { buildSvg } from "@rettangoli/ui/cli";
@@ -25,11 +25,14 @@ function readConfig() {
25
25
  const configContent = readFileSync(configPath, "utf8");
26
26
  return yaml.load(configContent);
27
27
  } catch (error) {
28
- console.error("Error reading config file:", error.message);
29
- return null;
28
+ throw new Error(`Error reading config file "${configPath}": ${error.message}`);
30
29
  }
31
30
  }
32
31
 
32
+ function collectValues(value, previous = []) {
33
+ return [...previous, value];
34
+ }
35
+
33
36
  const program = new Command();
34
37
 
35
38
  program
@@ -103,6 +106,41 @@ Examples:
103
106
  build(options);
104
107
  });
105
108
 
109
+ feCommand
110
+ .command("check")
111
+ .description("Validate frontend component file contracts")
112
+ .option("--format <format>", "Output format: text or json", "text")
113
+ .addHelpText(
114
+ "after",
115
+ `
116
+
117
+ Examples:
118
+ $ rettangoli fe check
119
+ $ rettangoli fe check --format json
120
+ `,
121
+ )
122
+ .action((options) => {
123
+ const config = readConfig();
124
+
125
+ if (!config) {
126
+ throw new Error("rettangoli.config.yaml not found");
127
+ }
128
+
129
+ if (!config.fe?.dirs?.length) {
130
+ throw new Error("fe.dirs not found or empty in config");
131
+ }
132
+
133
+ const missingDirs = config.fe.dirs.filter(
134
+ (dir) => !existsSync(resolve(process.cwd(), dir)),
135
+ );
136
+ if (missingDirs.length > 0) {
137
+ throw new Error(`Directories do not exist: ${missingDirs.join(", ")}`);
138
+ }
139
+
140
+ options.dirs = config.fe.dirs;
141
+ check(options);
142
+ });
143
+
106
144
  feCommand
107
145
  .command("scaffold")
108
146
  .description("Scaffold UI components")
@@ -195,10 +233,14 @@ vtCommand
195
233
  .command("generate")
196
234
  .description("Generate visualizations")
197
235
  .option("--skip-screenshots", "Skip screenshot generation")
198
- .option("--screenshot-wait-time <time>", "Wait time between screenshots", parseInt, 0)
199
- .option("--concurrency <number>", "Number of concurrent screenshots", parseInt, 12)
200
- .option("--wait-event <name>", "Custom event name to wait for instead of networkidle (e.g., vt:ready)")
201
- .action((options) => {
236
+ .option("--concurrency <number>", "Number of parallel capture workers", parseInt)
237
+ .option("--timeout <ms>", "Global capture timeout in ms", parseInt)
238
+ .option("--wait-event <name>", "Custom event name to mark page ready (uses event wait strategy)")
239
+ .option("--folder <path>", "Run only specs under folder prefix (repeatable)", collectValues, [])
240
+ .option("--group <section-key>", "Run only one section key from vt.sections (repeatable)", collectValues, [])
241
+ .option("--item <spec-path>", "Run only one spec path relative to vt/specs (repeatable)", collectValues, [])
242
+ .option("--headed", "Run Playwright in headed mode")
243
+ .action(async (options) => {
202
244
  console.log(`rtgl v${packageJson.version}`);
203
245
  const config = readConfig();
204
246
 
@@ -208,17 +250,23 @@ vtCommand
208
250
 
209
251
  // Use vt.path from config, default to 'vt'
210
252
  options.vtPath = config.vt?.path || "vt";
253
+ if (options.headed) {
254
+ options.headless = false;
255
+ }
211
256
 
212
- generate(options);
257
+ await generate(options);
213
258
  });
214
259
 
215
260
  vtCommand
216
261
  .command("report")
217
262
  .description("Create reports")
218
- .option("--compare-method <method>", "Comparison method: pixelmatch or md5", "pixelmatch")
219
- .option("--color-threshold <number>", "Color threshold for pixelmatch (0-1)", parseFloat, 0.1)
220
- .option("--diff-threshold <number>", "Max diff pixels percentage to pass (0-100)", parseFloat, 0.3)
221
- .action((options) => {
263
+ .option("--compare-method <method>", "Comparison method: pixelmatch or md5")
264
+ .option("--color-threshold <number>", "Color threshold for pixelmatch (0-1)", parseFloat)
265
+ .option("--diff-threshold <number>", "Max diff pixels percentage to pass (0-100)", parseFloat)
266
+ .option("--folder <path>", "Compare only screenshots under folder prefix (repeatable)", collectValues, [])
267
+ .option("--group <section-key>", "Compare only one section key from vt.sections (repeatable)", collectValues, [])
268
+ .option("--item <spec-path>", "Compare only one spec path relative to vt/specs (repeatable)", collectValues, [])
269
+ .action(async (options) => {
222
270
  const config = readConfig();
223
271
 
224
272
  if (!config) {
@@ -226,18 +274,21 @@ vtCommand
226
274
  }
227
275
 
228
276
  const vtPath = config.vt?.path || "vt";
229
- report({
277
+ await report({
230
278
  vtPath,
231
279
  compareMethod: options.compareMethod,
232
280
  colorThreshold: options.colorThreshold,
233
281
  diffThreshold: options.diffThreshold,
282
+ folder: options.folder,
283
+ group: options.group,
284
+ item: options.item,
234
285
  });
235
286
  });
236
287
 
237
288
  vtCommand
238
289
  .command("accept")
239
290
  .description("Accept changes")
240
- .action(() => {
291
+ .action(async () => {
241
292
  const config = readConfig();
242
293
 
243
294
  if (!config) {
@@ -245,7 +296,7 @@ vtCommand
245
296
  }
246
297
 
247
298
  const vtPath = config.vt?.path || "vt";
248
- accept({ vtPath });
299
+ await accept({ vtPath });
249
300
  });
250
301
 
251
302
  const sitesCommand = program.command("sites").description("Rettangoli Sites");
@@ -349,4 +400,4 @@ Examples:
349
400
  buildSvg(options);
350
401
  });
351
402
 
352
- program.parse();
403
+ await program.parseAsync();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rtgl",
3
- "version": "0.0.38",
3
+ "version": "1.0.0-rc1",
4
4
  "description": "CLI tool for Rettangoli - A frontend framework and development toolkit",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,7 +49,7 @@
49
49
  "js-yaml": "^4.1.0",
50
50
  "@rettangoli/fe": "0.0.14",
51
51
  "@rettangoli/sites": "0.2.7",
52
- "@rettangoli/vt": "0.0.14",
52
+ "@rettangoli/vt": "1.0.0-rc1",
53
53
  "@rettangoli/ui": "0.1.31"
54
54
  }
55
55
  }