@jay-framework/jay-stack-cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -10
- package/dist/index.js +166 -3
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -14,16 +14,68 @@ npm install @jay-framework/stack-cli
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
-
###
|
|
17
|
+
### Commands
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
#### `jay-stack dev [path]`
|
|
20
|
+
|
|
21
|
+
Start the development server:
|
|
20
22
|
|
|
21
23
|
```bash
|
|
22
|
-
|
|
24
|
+
jay-stack dev # Start dev server in current directory
|
|
25
|
+
jay-stack dev ./my-project # Start dev server in specified directory
|
|
23
26
|
```
|
|
24
27
|
|
|
25
28
|
This will start both the development server and editor server with default configuration.
|
|
26
29
|
|
|
30
|
+
#### `jay-stack validate [path]`
|
|
31
|
+
|
|
32
|
+
Validate all `.jay-html` and `.jay-contract` files in the project without creating output files:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
jay-stack validate # Validate files in pagesBase from config
|
|
36
|
+
jay-stack validate ./src/pages # Validate files in specified directory
|
|
37
|
+
jay-stack validate --verbose # Show per-file validation status
|
|
38
|
+
jay-stack validate --json # Output results as JSON (for CI/tooling)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This command is useful for:
|
|
42
|
+
|
|
43
|
+
- **CI pipelines**: Returns exit code 1 on validation errors
|
|
44
|
+
- **Development workflow**: Quick syntax checking without running the dev server
|
|
45
|
+
- **Vite integration**: Validate generated `.jay-html` files
|
|
46
|
+
|
|
47
|
+
Example output:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
✅ Jay Stack validation successful!
|
|
51
|
+
|
|
52
|
+
Scanned 12 .jay-html files, 5 .jay-contract files
|
|
53
|
+
No errors found.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or with errors:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
❌ Jay Stack validation failed
|
|
60
|
+
|
|
61
|
+
Errors:
|
|
62
|
+
❌ src/pages/product/page.jay-html
|
|
63
|
+
jay file should have exactly one jay-data script, found 2
|
|
64
|
+
|
|
65
|
+
1 error(s) found, 11 file(s) valid.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### `jay-stack validate-plugin [path]`
|
|
69
|
+
|
|
70
|
+
Validate a Jay Stack plugin package:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
jay-stack validate-plugin # Validate plugin in current directory
|
|
74
|
+
jay-stack validate-plugin ./my-plugin # Validate plugin in specified directory
|
|
75
|
+
jay-stack validate-plugin --verbose # Show detailed validation output
|
|
76
|
+
jay-stack validate-plugin --strict # Treat warnings as errors (for CI)
|
|
77
|
+
```
|
|
78
|
+
|
|
27
79
|
### Configuration
|
|
28
80
|
|
|
29
81
|
The CLI uses a `.jay` configuration file (YAML format) to customize port ranges for both servers. Create a `.jay` file in your project root:
|
|
@@ -143,15 +195,29 @@ The CLI is built using:
|
|
|
143
195
|
- **get-port** - Automatic port discovery
|
|
144
196
|
- **Vite** - Build tool integration
|
|
145
197
|
|
|
146
|
-
##
|
|
198
|
+
## CLI Reference
|
|
199
|
+
|
|
200
|
+
| Command | Description |
|
|
201
|
+
| ---------------------------------- | ---------------------------------------- |
|
|
202
|
+
| `jay-stack dev [path]` | Start the development server |
|
|
203
|
+
| `jay-stack validate [path]` | Validate jay-html and jay-contract files |
|
|
204
|
+
| `jay-stack validate-plugin [path]` | Validate a plugin package |
|
|
205
|
+
|
|
206
|
+
### Validate Command Options
|
|
207
|
+
|
|
208
|
+
| Option | Description |
|
|
209
|
+
| --------------- | ------------------------------- |
|
|
210
|
+
| `-v, --verbose` | Show per-file validation status |
|
|
211
|
+
| `--json` | Output results as JSON |
|
|
147
212
|
|
|
148
|
-
|
|
213
|
+
### Validate-Plugin Command Options
|
|
149
214
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
215
|
+
| Option | Description |
|
|
216
|
+
| ------------------ | -------------------------------------- |
|
|
217
|
+
| `-v, --verbose` | Show detailed validation output |
|
|
218
|
+
| `--strict` | Treat warnings as errors (for CI) |
|
|
219
|
+
| `--local` | Validate local plugins in src/plugins/ |
|
|
220
|
+
| `--generate-types` | Generate .d.ts files for contracts |
|
|
155
221
|
|
|
156
222
|
## Related Packages
|
|
157
223
|
|
package/dist/index.js
CHANGED
|
@@ -4,14 +4,15 @@ import { mkDevServer } from "@jay-framework/dev-server";
|
|
|
4
4
|
import { createEditorServer } from "@jay-framework/editor-server";
|
|
5
5
|
import getPort from "get-port";
|
|
6
6
|
import path from "path";
|
|
7
|
-
import fs from "fs";
|
|
7
|
+
import fs, { promises } from "fs";
|
|
8
8
|
import YAML from "yaml";
|
|
9
9
|
import { parse } from "node-html-parser";
|
|
10
10
|
import { createRequire } from "module";
|
|
11
|
-
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, parseContract, ContractTagType } from "@jay-framework/compiler-jay-html";
|
|
12
|
-
import { JAY_CONTRACT_EXTENSION, JAY_EXTENSION, JayAtomicType, JayEnumType, loadPluginManifest } from "@jay-framework/compiler-shared";
|
|
11
|
+
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, parseContract, ContractTagType, generateElementFile } from "@jay-framework/compiler-jay-html";
|
|
12
|
+
import { JAY_CONTRACT_EXTENSION, JAY_EXTENSION, JayAtomicType, JayEnumType, loadPluginManifest, RuntimeMode, GenerateTarget } from "@jay-framework/compiler-shared";
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import chalk from "chalk";
|
|
15
|
+
import { glob } from "glob";
|
|
15
16
|
const DEFAULT_CONFIG = {
|
|
16
17
|
devServer: {
|
|
17
18
|
portRange: [3e3, 3100],
|
|
@@ -1459,6 +1460,148 @@ async function validateDynamicContracts(context, result) {
|
|
|
1459
1460
|
}
|
|
1460
1461
|
}
|
|
1461
1462
|
}
|
|
1463
|
+
async function findJayFiles(dir) {
|
|
1464
|
+
return await glob(`${dir}/**/*${JAY_EXTENSION}`);
|
|
1465
|
+
}
|
|
1466
|
+
async function findContractFiles(dir) {
|
|
1467
|
+
return await glob(`${dir}/**/*${JAY_CONTRACT_EXTENSION}`);
|
|
1468
|
+
}
|
|
1469
|
+
async function validateJayFiles(options = {}) {
|
|
1470
|
+
const config = loadConfig();
|
|
1471
|
+
const resolvedConfig = getConfigWithDefaults(config);
|
|
1472
|
+
const projectRoot = process.cwd();
|
|
1473
|
+
const scanDir = options.path ? path.resolve(options.path) : path.resolve(resolvedConfig.devServer.pagesBase);
|
|
1474
|
+
const errors = [];
|
|
1475
|
+
const warnings = [];
|
|
1476
|
+
const jayHtmlFiles = await findJayFiles(scanDir);
|
|
1477
|
+
const contractFiles = await findContractFiles(scanDir);
|
|
1478
|
+
if (options.verbose) {
|
|
1479
|
+
console.log(chalk.gray(`Scanning directory: ${scanDir}`));
|
|
1480
|
+
console.log(chalk.gray(`Found ${jayHtmlFiles.length} .jay-html files`));
|
|
1481
|
+
console.log(chalk.gray(`Found ${contractFiles.length} .jay-contract files
|
|
1482
|
+
`));
|
|
1483
|
+
}
|
|
1484
|
+
for (const contractFile of contractFiles) {
|
|
1485
|
+
const relativePath = path.relative(projectRoot, contractFile);
|
|
1486
|
+
try {
|
|
1487
|
+
const content = await promises.readFile(contractFile, "utf-8");
|
|
1488
|
+
const result = parseContract(content, path.basename(contractFile));
|
|
1489
|
+
if (result.validations.length > 0) {
|
|
1490
|
+
for (const validation of result.validations) {
|
|
1491
|
+
errors.push({
|
|
1492
|
+
file: relativePath,
|
|
1493
|
+
message: validation,
|
|
1494
|
+
stage: "parse"
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
if (options.verbose) {
|
|
1498
|
+
console.log(chalk.red(`❌ ${relativePath}`));
|
|
1499
|
+
}
|
|
1500
|
+
} else if (options.verbose) {
|
|
1501
|
+
console.log(chalk.green(`✓ ${relativePath}`));
|
|
1502
|
+
}
|
|
1503
|
+
} catch (error) {
|
|
1504
|
+
errors.push({
|
|
1505
|
+
file: relativePath,
|
|
1506
|
+
message: error.message,
|
|
1507
|
+
stage: "parse"
|
|
1508
|
+
});
|
|
1509
|
+
if (options.verbose) {
|
|
1510
|
+
console.log(chalk.red(`❌ ${relativePath}`));
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
for (const jayFile of jayHtmlFiles) {
|
|
1515
|
+
const relativePath = path.relative(projectRoot, jayFile);
|
|
1516
|
+
const filename = path.basename(jayFile.replace(JAY_EXTENSION, ""));
|
|
1517
|
+
const dirname = path.dirname(jayFile);
|
|
1518
|
+
try {
|
|
1519
|
+
const content = await promises.readFile(jayFile, "utf-8");
|
|
1520
|
+
const parsedFile = await parseJayFile(
|
|
1521
|
+
content,
|
|
1522
|
+
filename,
|
|
1523
|
+
dirname,
|
|
1524
|
+
{},
|
|
1525
|
+
JAY_IMPORT_RESOLVER,
|
|
1526
|
+
projectRoot
|
|
1527
|
+
);
|
|
1528
|
+
if (parsedFile.validations.length > 0) {
|
|
1529
|
+
for (const validation of parsedFile.validations) {
|
|
1530
|
+
errors.push({
|
|
1531
|
+
file: relativePath,
|
|
1532
|
+
message: validation,
|
|
1533
|
+
stage: "parse"
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
if (options.verbose) {
|
|
1537
|
+
console.log(chalk.red(`❌ ${relativePath}`));
|
|
1538
|
+
}
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
const generatedFile = generateElementFile(
|
|
1542
|
+
parsedFile.val,
|
|
1543
|
+
RuntimeMode.MainTrusted,
|
|
1544
|
+
GenerateTarget.jay
|
|
1545
|
+
);
|
|
1546
|
+
if (generatedFile.validations.length > 0) {
|
|
1547
|
+
for (const validation of generatedFile.validations) {
|
|
1548
|
+
errors.push({
|
|
1549
|
+
file: relativePath,
|
|
1550
|
+
message: validation,
|
|
1551
|
+
stage: "generate"
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
if (options.verbose) {
|
|
1555
|
+
console.log(chalk.red(`❌ ${relativePath}`));
|
|
1556
|
+
}
|
|
1557
|
+
} else if (options.verbose) {
|
|
1558
|
+
console.log(chalk.green(`✓ ${relativePath}`));
|
|
1559
|
+
}
|
|
1560
|
+
} catch (error) {
|
|
1561
|
+
errors.push({
|
|
1562
|
+
file: relativePath,
|
|
1563
|
+
message: error.message,
|
|
1564
|
+
stage: "parse"
|
|
1565
|
+
});
|
|
1566
|
+
if (options.verbose) {
|
|
1567
|
+
console.log(chalk.red(`❌ ${relativePath}`));
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
return {
|
|
1572
|
+
valid: errors.length === 0,
|
|
1573
|
+
jayHtmlFilesScanned: jayHtmlFiles.length,
|
|
1574
|
+
contractFilesScanned: contractFiles.length,
|
|
1575
|
+
errors,
|
|
1576
|
+
warnings
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
function printJayValidationResult(result, options) {
|
|
1580
|
+
if (options.json) {
|
|
1581
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
console.log("");
|
|
1585
|
+
if (result.valid) {
|
|
1586
|
+
console.log(chalk.green("✅ Jay Stack validation successful!\n"));
|
|
1587
|
+
console.log(
|
|
1588
|
+
`Scanned ${result.jayHtmlFilesScanned} .jay-html files, ${result.contractFilesScanned} .jay-contract files`
|
|
1589
|
+
);
|
|
1590
|
+
console.log("No errors found.");
|
|
1591
|
+
} else {
|
|
1592
|
+
console.log(chalk.red("❌ Jay Stack validation failed\n"));
|
|
1593
|
+
console.log("Errors:");
|
|
1594
|
+
for (const error of result.errors) {
|
|
1595
|
+
console.log(chalk.red(` ❌ ${error.file}`));
|
|
1596
|
+
console.log(chalk.gray(` ${error.message}`));
|
|
1597
|
+
console.log("");
|
|
1598
|
+
}
|
|
1599
|
+
const validFiles = result.jayHtmlFilesScanned + result.contractFilesScanned - result.errors.length;
|
|
1600
|
+
console.log(
|
|
1601
|
+
chalk.red(`${result.errors.length} error(s) found, ${validFiles} file(s) valid.`)
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1462
1605
|
const program = new Command();
|
|
1463
1606
|
program.name("jay-stack").description("Jay Stack CLI - Development server and plugin validation").version("0.9.0");
|
|
1464
1607
|
program.command("dev [path]").description("Start the Jay Stack development server").action(async (path2, options) => {
|
|
@@ -1471,6 +1614,26 @@ program.command("dev [path]").description("Start the Jay Stack development serve
|
|
|
1471
1614
|
process.exit(1);
|
|
1472
1615
|
}
|
|
1473
1616
|
});
|
|
1617
|
+
program.command("validate [path]").description("Validate all .jay-html and .jay-contract files in the project").option("-v, --verbose", "Show per-file validation status").option("--json", "Output results as JSON").action(async (scanPath, options) => {
|
|
1618
|
+
try {
|
|
1619
|
+
const result = await validateJayFiles({
|
|
1620
|
+
path: scanPath,
|
|
1621
|
+
verbose: options.verbose,
|
|
1622
|
+
json: options.json
|
|
1623
|
+
});
|
|
1624
|
+
printJayValidationResult(result, options);
|
|
1625
|
+
if (!result.valid) {
|
|
1626
|
+
process.exit(1);
|
|
1627
|
+
}
|
|
1628
|
+
} catch (error) {
|
|
1629
|
+
if (options.json) {
|
|
1630
|
+
console.log(JSON.stringify({ valid: false, error: error.message }, null, 2));
|
|
1631
|
+
} else {
|
|
1632
|
+
console.error(chalk.red("Validation error:"), error.message);
|
|
1633
|
+
}
|
|
1634
|
+
process.exit(1);
|
|
1635
|
+
}
|
|
1636
|
+
});
|
|
1474
1637
|
program.command("validate-plugin [path]").description("Validate a Jay Stack plugin package").option("--local", "Validate local plugins in src/plugins/").option("-v, --verbose", "Show detailed validation output").option("--strict", "Treat warnings as errors (for CI)").option("--generate-types", "Generate .d.ts files for contracts").action(async (pluginPath, options) => {
|
|
1475
1638
|
try {
|
|
1476
1639
|
const result = await validatePlugin({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/jay-stack-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,16 +23,19 @@
|
|
|
23
23
|
"test:watch": "vitest"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@jay-framework/
|
|
27
|
-
"@jay-framework/
|
|
28
|
-
"@jay-framework/
|
|
26
|
+
"@jay-framework/compiler-jay-html": "^0.11.0",
|
|
27
|
+
"@jay-framework/compiler-shared": "^0.11.0",
|
|
28
|
+
"@jay-framework/dev-server": "^0.11.0",
|
|
29
|
+
"@jay-framework/editor-server": "^0.11.0",
|
|
30
|
+
"@jay-framework/plugin-validator": "^0.11.0",
|
|
29
31
|
"chalk": "^4.1.2",
|
|
30
32
|
"commander": "^14.0.0",
|
|
31
33
|
"express": "^5.0.1",
|
|
34
|
+
"glob": "^10.3.10",
|
|
32
35
|
"vite": "^5.0.11"
|
|
33
36
|
},
|
|
34
37
|
"devDependencies": {
|
|
35
|
-
"@jay-framework/dev-environment": "^0.
|
|
38
|
+
"@jay-framework/dev-environment": "^0.11.0",
|
|
36
39
|
"@types/express": "^5.0.2",
|
|
37
40
|
"@types/node": "^22.15.21",
|
|
38
41
|
"nodemon": "^3.0.3",
|