@jay-framework/jay-stack-cli 0.13.0 → 0.14.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.
|
@@ -26,7 +26,7 @@ There is no standalone "interactive" phase. Any tag with `type: interactive` (re
|
|
|
26
26
|
## Workflow
|
|
27
27
|
|
|
28
28
|
1. **Read this file** for overview and workflow
|
|
29
|
-
2. **Discover plugins** — read `
|
|
29
|
+
2. **Discover plugins** — read `plugins-index.yaml` to see available plugins, contracts, and actions.
|
|
30
30
|
3. **Read contracts** — read the `.jay-contract` files (paths from plugins-index) to understand data shapes, tag types, phases, and props.
|
|
31
31
|
4. **Read actions** — read `.jay-action` files (paths from plugins-index) to see action descriptions, input schemas, and output schemas. This tells you what data each action accepts and returns.
|
|
32
32
|
5. **Read references** — check `references/<plugin>/` for pre-generated discovery data (product catalogs, collection schemas, etc.). These are generated by `jay-stack agent-kit` and contain real data from the site.
|
|
@@ -50,7 +50,7 @@ There is no standalone "interactive" phase. Any tag with `type: interactive` (re
|
|
|
50
50
|
|
|
51
51
|
### 1. Discover plugins and contracts
|
|
52
52
|
|
|
53
|
-
Read `
|
|
53
|
+
Read `plugins-index.yaml`:
|
|
54
54
|
|
|
55
55
|
```yaml
|
|
56
56
|
plugins:
|
|
@@ -50,8 +50,7 @@ jay-stack agent-kit --no-references
|
|
|
50
50
|
|
|
51
51
|
Outputs:
|
|
52
52
|
|
|
53
|
-
- `
|
|
54
|
-
- `materialized-contracts/plugins-index.yaml`
|
|
53
|
+
- `plugins-index.yaml`
|
|
55
54
|
- `materialized-contracts/<plugin>/*.jay-contract` (dynamic contracts)
|
|
56
55
|
- `references/<plugin>/` — plugin reference data (product catalogs, collection schemas, etc.)
|
|
57
56
|
- Documentation files (INSTRUCTIONS.md and reference docs)
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Discovery: Plugins Index
|
|
4
4
|
|
|
5
|
-
After running `jay-stack agent-kit`, read `
|
|
5
|
+
After running `jay-stack agent-kit`, read `plugins-index.yaml`:
|
|
6
6
|
|
|
7
7
|
```yaml
|
|
8
|
-
materialized_at: '2026-02-09T...'
|
|
9
8
|
jay_stack_version: '1.0.0'
|
|
10
9
|
plugins:
|
|
11
10
|
- name: wix-stores
|
|
@@ -37,18 +36,6 @@ Fields:
|
|
|
37
36
|
- `actions[].description` — short description of what the action does
|
|
38
37
|
- `actions[].path` — path to the `.jay-action` file with full input/output schemas
|
|
39
38
|
|
|
40
|
-
## Discovery: Contracts Index
|
|
41
|
-
|
|
42
|
-
`materialized-contracts/contracts-index.yaml` lists all contracts across all plugins:
|
|
43
|
-
|
|
44
|
-
```yaml
|
|
45
|
-
contracts:
|
|
46
|
-
- plugin: wix-stores
|
|
47
|
-
name: product-page
|
|
48
|
-
type: static
|
|
49
|
-
path: ./node_modules/@wix/stores/lib/contracts/product-page.jay-contract
|
|
50
|
-
```
|
|
51
|
-
|
|
52
39
|
## Reading plugin.yaml
|
|
53
40
|
|
|
54
41
|
Each plugin has a `plugin.yaml` at its root (the `path` from plugins-index):
|
|
@@ -249,16 +236,16 @@ outputSchema:
|
|
|
249
236
|
|
|
250
237
|
Schemas use a compact type notation:
|
|
251
238
|
|
|
252
|
-
| Notation
|
|
253
|
-
|
|
|
254
|
-
| `propName: string`
|
|
255
|
-
| `propName?: number`
|
|
256
|
-
| `propName: boolean`
|
|
257
|
-
| `propName: enum(a \| b \| c)`
|
|
258
|
-
| `propName:` + nested block
|
|
259
|
-
| `propName:` + `- childProp: type` | Array of objects (YAML list)
|
|
260
|
-
| `propName: importedName`
|
|
261
|
-
| `- importedName`
|
|
239
|
+
| Notation | Meaning |
|
|
240
|
+
| --------------------------------- | -------------------------------------------------------- |
|
|
241
|
+
| `propName: string` | Required string property |
|
|
242
|
+
| `propName?: number` | Optional number property |
|
|
243
|
+
| `propName: boolean` | Required boolean |
|
|
244
|
+
| `propName: enum(a \| b \| c)` | Required enum |
|
|
245
|
+
| `propName:` + nested block | Nested object |
|
|
246
|
+
| `propName:` + `- childProp: type` | Array of objects (YAML list) |
|
|
247
|
+
| `propName: importedName` | Type from `import:` block (references a `.jay-contract`) |
|
|
248
|
+
| `- importedName` | Array of imported type |
|
|
262
249
|
|
|
263
250
|
### Using Action Metadata
|
|
264
251
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LogLevel } from '@jay-framework/logger';
|
|
2
2
|
import { PublishMessage, PublishResponse, SaveImageMessage, SaveImageResponse, HasImageMessage, HasImageResponse, GetProjectInfoMessage, GetProjectInfoResponse, ExportMessage, ExportResponse, ImportMessage, ImportResponse, ProjectPage, Plugin } from '@jay-framework/editor-protocol';
|
|
3
|
-
export {
|
|
3
|
+
export { MaterializeContractsOptions, MaterializeResult, PluginContractEntry, PluginsIndex, PluginsIndexEntry, listContracts, materializeContracts } from '@jay-framework/stack-server-runtime';
|
|
4
4
|
|
|
5
5
|
interface StartDevServerOptions {
|
|
6
6
|
projectPath?: string;
|
package/dist/index.js
CHANGED
|
@@ -2402,7 +2402,7 @@ async function startDevServer(options = {}) {
|
|
|
2402
2402
|
const resolvedConfig = getConfigWithDefaults(config);
|
|
2403
2403
|
const jayOptions = {
|
|
2404
2404
|
tsConfigFilePath: "./tsconfig.json",
|
|
2405
|
-
outputDir: "build
|
|
2405
|
+
outputDir: "build"
|
|
2406
2406
|
};
|
|
2407
2407
|
const app = express();
|
|
2408
2408
|
const devServerPort = await getPort({ port: resolvedConfig.devServer.portRange });
|
|
@@ -2441,7 +2441,6 @@ async function startDevServer(options = {}) {
|
|
|
2441
2441
|
pagesRootFolder: path.resolve(resolvedConfig.devServer.pagesBase),
|
|
2442
2442
|
projectRootFolder: process.cwd(),
|
|
2443
2443
|
publicBaseUrlPath: "/",
|
|
2444
|
-
dontCacheSlowly: false,
|
|
2445
2444
|
jayRollupConfig: jayOptions,
|
|
2446
2445
|
logLevel: options.logLevel
|
|
2447
2446
|
});
|
|
@@ -2934,13 +2933,206 @@ async function findJayFiles(dir) {
|
|
|
2934
2933
|
async function findContractFiles(dir) {
|
|
2935
2934
|
return await glob(`${dir}/**/*${JAY_CONTRACT_EXTENSION}`);
|
|
2936
2935
|
}
|
|
2936
|
+
function flattenContractTags(tags, prefix) {
|
|
2937
|
+
const result = [];
|
|
2938
|
+
for (const tag of tags) {
|
|
2939
|
+
const tagPath = prefix ? `${prefix}.${tag.tag}` : tag.tag;
|
|
2940
|
+
result.push({ path: tagPath, required: tag.required === true });
|
|
2941
|
+
if (tag.tags) {
|
|
2942
|
+
result.push(...flattenContractTags(tag.tags, tagPath));
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
return result;
|
|
2946
|
+
}
|
|
2947
|
+
function extractExpressions(text) {
|
|
2948
|
+
const results = [];
|
|
2949
|
+
const regex = /\{([^}]+)\}/g;
|
|
2950
|
+
let match;
|
|
2951
|
+
while ((match = regex.exec(text)) !== null) {
|
|
2952
|
+
results.push(match[1].trim());
|
|
2953
|
+
}
|
|
2954
|
+
return results;
|
|
2955
|
+
}
|
|
2956
|
+
function extractTagPath(expr) {
|
|
2957
|
+
let cleaned = expr.replace(/^!/, "").trim();
|
|
2958
|
+
cleaned = cleaned.split(/\s*[!=]==?\s*/)[0].trim();
|
|
2959
|
+
if (cleaned === "." || cleaned === "")
|
|
2960
|
+
return null;
|
|
2961
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(cleaned)) {
|
|
2962
|
+
return cleaned;
|
|
2963
|
+
}
|
|
2964
|
+
return null;
|
|
2965
|
+
}
|
|
2966
|
+
const SKIP_ATTRS = /* @__PURE__ */ new Set([
|
|
2967
|
+
"forEach",
|
|
2968
|
+
"if",
|
|
2969
|
+
"ref",
|
|
2970
|
+
"trackBy",
|
|
2971
|
+
"slowForEach",
|
|
2972
|
+
"jayIndex",
|
|
2973
|
+
"jayTrackBy",
|
|
2974
|
+
"when-resolved",
|
|
2975
|
+
"when-loading",
|
|
2976
|
+
"when-rejected",
|
|
2977
|
+
"accessor"
|
|
2978
|
+
]);
|
|
2979
|
+
function collectUsedTags(jayHtml) {
|
|
2980
|
+
const imports = jayHtml.headlessImports;
|
|
2981
|
+
const usedTags = /* @__PURE__ */ new Map();
|
|
2982
|
+
const keyMap = /* @__PURE__ */ new Map();
|
|
2983
|
+
for (let i = 0; i < imports.length; i++) {
|
|
2984
|
+
if (imports[i].contract) {
|
|
2985
|
+
usedTags.set(i, /* @__PURE__ */ new Set());
|
|
2986
|
+
if (imports[i].key) {
|
|
2987
|
+
keyMap.set(imports[i].key, i);
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
function markUsed(importIndex, tagPath) {
|
|
2992
|
+
usedTags.get(importIndex)?.add(tagPath);
|
|
2993
|
+
}
|
|
2994
|
+
function resolvePath(path2, scopes) {
|
|
2995
|
+
const dot = path2.indexOf(".");
|
|
2996
|
+
if (dot !== -1) {
|
|
2997
|
+
const key = path2.substring(0, dot);
|
|
2998
|
+
const idx = keyMap.get(key);
|
|
2999
|
+
if (idx !== void 0) {
|
|
3000
|
+
markUsed(idx, path2.substring(dot + 1));
|
|
3001
|
+
return;
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
if (scopes.length > 0) {
|
|
3005
|
+
const scope = scopes[scopes.length - 1];
|
|
3006
|
+
const full = scope.prefix ? `${scope.prefix}.${path2}` : path2;
|
|
3007
|
+
markUsed(scope.importIndex, full);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
function walkElement(element, scopes) {
|
|
3011
|
+
const tagName = element.rawTagName?.toLowerCase();
|
|
3012
|
+
let childScopes = scopes;
|
|
3013
|
+
if (tagName?.startsWith("jay:")) {
|
|
3014
|
+
const contractName = tagName.substring(4);
|
|
3015
|
+
const idx = imports.findIndex(
|
|
3016
|
+
(imp) => imp.contractName === contractName && imp.contract
|
|
3017
|
+
);
|
|
3018
|
+
if (idx !== -1) {
|
|
3019
|
+
childScopes = [...scopes, { importIndex: idx, prefix: "" }];
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
const forEachVal = element.getAttribute?.("forEach");
|
|
3023
|
+
if (forEachVal) {
|
|
3024
|
+
const fePath = extractTagPath(forEachVal);
|
|
3025
|
+
if (fePath) {
|
|
3026
|
+
resolvePath(fePath, childScopes);
|
|
3027
|
+
const dot = fePath.indexOf(".");
|
|
3028
|
+
if (dot !== -1) {
|
|
3029
|
+
const key = fePath.substring(0, dot);
|
|
3030
|
+
const idx = keyMap.get(key);
|
|
3031
|
+
if (idx !== void 0) {
|
|
3032
|
+
childScopes = [
|
|
3033
|
+
...childScopes,
|
|
3034
|
+
{ importIndex: idx, prefix: fePath.substring(dot + 1) }
|
|
3035
|
+
];
|
|
3036
|
+
}
|
|
3037
|
+
} else if (childScopes.length > 0) {
|
|
3038
|
+
const scope = childScopes[childScopes.length - 1];
|
|
3039
|
+
const newPrefix = scope.prefix ? `${scope.prefix}.${fePath}` : fePath;
|
|
3040
|
+
childScopes = [
|
|
3041
|
+
...childScopes,
|
|
3042
|
+
{ importIndex: scope.importIndex, prefix: newPrefix }
|
|
3043
|
+
];
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
if (tagName === "with-data") {
|
|
3048
|
+
const accessor = element.getAttribute?.("accessor");
|
|
3049
|
+
if (accessor && accessor !== "." && childScopes.length > 0) {
|
|
3050
|
+
resolvePath(accessor, childScopes);
|
|
3051
|
+
const scope = childScopes[childScopes.length - 1];
|
|
3052
|
+
const newPrefix = scope.prefix ? `${scope.prefix}.${accessor}` : accessor;
|
|
3053
|
+
childScopes = [
|
|
3054
|
+
...childScopes,
|
|
3055
|
+
{ importIndex: scope.importIndex, prefix: newPrefix }
|
|
3056
|
+
];
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
const ifVal = element.getAttribute?.("if");
|
|
3060
|
+
if (ifVal) {
|
|
3061
|
+
const ifPath = extractTagPath(ifVal);
|
|
3062
|
+
if (ifPath)
|
|
3063
|
+
resolvePath(ifPath, scopes);
|
|
3064
|
+
}
|
|
3065
|
+
const refVal = element.getAttribute?.("ref");
|
|
3066
|
+
if (refVal) {
|
|
3067
|
+
resolvePath(refVal, scopes);
|
|
3068
|
+
}
|
|
3069
|
+
const attrs = element.attributes ?? {};
|
|
3070
|
+
for (const [name, value] of Object.entries(attrs)) {
|
|
3071
|
+
if (SKIP_ATTRS.has(name))
|
|
3072
|
+
continue;
|
|
3073
|
+
for (const expr of extractExpressions(value)) {
|
|
3074
|
+
const p = extractTagPath(expr);
|
|
3075
|
+
if (p)
|
|
3076
|
+
resolvePath(p, scopes);
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
for (const child of element.childNodes ?? []) {
|
|
3080
|
+
if (child.nodeType === 3) {
|
|
3081
|
+
const text = child.rawText ?? child.text ?? "";
|
|
3082
|
+
for (const expr of extractExpressions(text)) {
|
|
3083
|
+
const p = extractTagPath(expr);
|
|
3084
|
+
if (p)
|
|
3085
|
+
resolvePath(p, childScopes);
|
|
3086
|
+
}
|
|
3087
|
+
} else if (child.nodeType === 1) {
|
|
3088
|
+
walkElement(child, childScopes);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
walkElement(jayHtml.body, []);
|
|
3093
|
+
return usedTags;
|
|
3094
|
+
}
|
|
3095
|
+
function analyzeTagCoverage(jayHtml, file) {
|
|
3096
|
+
const imports = jayHtml.headlessImports;
|
|
3097
|
+
const withContracts = imports.filter((imp) => imp.contract);
|
|
3098
|
+
if (withContracts.length === 0)
|
|
3099
|
+
return null;
|
|
3100
|
+
const usedTagsMap = collectUsedTags(jayHtml);
|
|
3101
|
+
const contracts = [];
|
|
3102
|
+
for (let i = 0; i < imports.length; i++) {
|
|
3103
|
+
const imp = imports[i];
|
|
3104
|
+
if (!imp.contract)
|
|
3105
|
+
continue;
|
|
3106
|
+
const allTags = flattenContractTags(imp.contract.tags);
|
|
3107
|
+
const usedSet = usedTagsMap.get(i) ?? /* @__PURE__ */ new Set();
|
|
3108
|
+
const expanded = new Set(usedSet);
|
|
3109
|
+
for (const usedPath of usedSet) {
|
|
3110
|
+
const segments = usedPath.split(".");
|
|
3111
|
+
for (let j = 1; j < segments.length; j++) {
|
|
3112
|
+
expanded.add(segments.slice(0, j).join("."));
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
const unused = allTags.filter((t) => !expanded.has(t.path));
|
|
3116
|
+
const requiredUnused = unused.filter((t) => t.required);
|
|
3117
|
+
contracts.push({
|
|
3118
|
+
key: imp.key,
|
|
3119
|
+
contractName: imp.contractName,
|
|
3120
|
+
totalTags: allTags.length,
|
|
3121
|
+
usedTags: allTags.length - unused.length,
|
|
3122
|
+
unusedTags: unused.map((t) => t.path),
|
|
3123
|
+
requiredUnusedTags: requiredUnused.map((t) => t.path)
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3126
|
+
return { file, contracts };
|
|
3127
|
+
}
|
|
2937
3128
|
async function validateJayFiles(options = {}) {
|
|
2938
3129
|
const config = loadConfig();
|
|
2939
3130
|
const resolvedConfig = getConfigWithDefaults(config);
|
|
2940
|
-
const projectRoot = process.cwd();
|
|
3131
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
2941
3132
|
const scanDir = options.path ? path.resolve(options.path) : path.resolve(resolvedConfig.devServer.pagesBase);
|
|
2942
3133
|
const errors = [];
|
|
2943
3134
|
const warnings = [];
|
|
3135
|
+
const coverage = [];
|
|
2944
3136
|
const jayHtmlFiles = await findJayFiles(scanDir);
|
|
2945
3137
|
const contractFiles = await findContractFiles(scanDir);
|
|
2946
3138
|
if (options.verbose) {
|
|
@@ -3006,6 +3198,10 @@ async function validateJayFiles(options = {}) {
|
|
|
3006
3198
|
}
|
|
3007
3199
|
continue;
|
|
3008
3200
|
}
|
|
3201
|
+
const fileCoverage = analyzeTagCoverage(parsedFile.val, relativePath);
|
|
3202
|
+
if (fileCoverage) {
|
|
3203
|
+
coverage.push(fileCoverage);
|
|
3204
|
+
}
|
|
3009
3205
|
const generatedFile = generateElementFile(
|
|
3010
3206
|
parsedFile.val,
|
|
3011
3207
|
RuntimeMode.MainTrusted,
|
|
@@ -3041,7 +3237,8 @@ async function validateJayFiles(options = {}) {
|
|
|
3041
3237
|
jayHtmlFilesScanned: jayHtmlFiles.length,
|
|
3042
3238
|
contractFilesScanned: contractFiles.length,
|
|
3043
3239
|
errors,
|
|
3044
|
-
warnings
|
|
3240
|
+
warnings,
|
|
3241
|
+
coverage
|
|
3045
3242
|
};
|
|
3046
3243
|
}
|
|
3047
3244
|
function printJayValidationResult(result, options) {
|
|
@@ -3070,6 +3267,29 @@ function printJayValidationResult(result, options) {
|
|
|
3070
3267
|
chalk.red(`${result.errors.length} error(s) found, ${validFiles} file(s) valid.`)
|
|
3071
3268
|
);
|
|
3072
3269
|
}
|
|
3270
|
+
if (result.coverage.length > 0) {
|
|
3271
|
+
logger.important("");
|
|
3272
|
+
logger.important("Tag Coverage:");
|
|
3273
|
+
for (const fileCov of result.coverage) {
|
|
3274
|
+
logger.important(` ${fileCov.file}`);
|
|
3275
|
+
for (const contract of fileCov.contracts) {
|
|
3276
|
+
const label = contract.key ? `${contract.key} (${contract.contractName})` : contract.contractName;
|
|
3277
|
+
logger.important(
|
|
3278
|
+
` ${label}: ${contract.usedTags}/${contract.totalTags} tags used`
|
|
3279
|
+
);
|
|
3280
|
+
if (contract.unusedTags.length > 0) {
|
|
3281
|
+
logger.important(chalk.gray(` Unused: ${contract.unusedTags.join(", ")}`));
|
|
3282
|
+
}
|
|
3283
|
+
if (contract.requiredUnusedTags.length > 0) {
|
|
3284
|
+
logger.important(
|
|
3285
|
+
chalk.yellow(
|
|
3286
|
+
` ⚠ Required unused: ${contract.requiredUnusedTags.join(", ")}`
|
|
3287
|
+
)
|
|
3288
|
+
);
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3073
3293
|
}
|
|
3074
3294
|
async function initializeServicesForCli(projectRoot, viteServer) {
|
|
3075
3295
|
const path2 = await import("node:path");
|
|
@@ -3553,12 +3773,14 @@ async function runMaterialize(projectRoot, options, defaultOutputRelative, keepV
|
|
|
3553
3773
|
services
|
|
3554
3774
|
);
|
|
3555
3775
|
if (options.yaml) {
|
|
3556
|
-
getLogger().important(YAML.stringify(result.
|
|
3776
|
+
getLogger().important(YAML.stringify(result.pluginsIndex));
|
|
3557
3777
|
} else {
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3778
|
+
const totalContracts = result.pluginsIndex.plugins.reduce(
|
|
3779
|
+
(sum, p) => sum + p.contracts.length,
|
|
3780
|
+
0
|
|
3561
3781
|
);
|
|
3782
|
+
getLogger().important(chalk.green(`
|
|
3783
|
+
✅ Materialized ${totalContracts} contracts`));
|
|
3562
3784
|
getLogger().important(` Static: ${result.staticCount}`);
|
|
3563
3785
|
getLogger().important(` Dynamic: ${result.dynamicCount}`);
|
|
3564
3786
|
getLogger().important(` Output: ${result.outputDir}`);
|
|
@@ -3670,21 +3892,15 @@ function printValidationResult(result, verbose) {
|
|
|
3670
3892
|
function printContractList(index) {
|
|
3671
3893
|
const logger = getLogger();
|
|
3672
3894
|
logger.important("\nAvailable Contracts:\n");
|
|
3673
|
-
const
|
|
3674
|
-
|
|
3675
|
-
const
|
|
3676
|
-
existing.push(contract);
|
|
3677
|
-
byPlugin.set(contract.plugin, existing);
|
|
3678
|
-
}
|
|
3679
|
-
for (const [plugin, contracts] of byPlugin) {
|
|
3680
|
-
logger.important(chalk.bold(`📦 ${plugin}`));
|
|
3681
|
-
for (const contract of contracts) {
|
|
3895
|
+
for (const plugin of index.plugins) {
|
|
3896
|
+
logger.important(chalk.bold(`📦 ${plugin.name}`));
|
|
3897
|
+
for (const contract of plugin.contracts) {
|
|
3682
3898
|
const typeIcon = contract.type === "static" ? "📄" : "⚡";
|
|
3683
3899
|
logger.important(` ${typeIcon} ${contract.name}`);
|
|
3684
3900
|
}
|
|
3685
3901
|
logger.important("");
|
|
3686
3902
|
}
|
|
3687
|
-
if (index.
|
|
3903
|
+
if (index.plugins.length === 0) {
|
|
3688
3904
|
logger.important(chalk.gray("No contracts found."));
|
|
3689
3905
|
}
|
|
3690
3906
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/jay-stack-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"test:watch": "vitest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@jay-framework/compiler-jay-html": "^0.
|
|
28
|
-
"@jay-framework/compiler-shared": "^0.
|
|
29
|
-
"@jay-framework/dev-server": "^0.
|
|
30
|
-
"@jay-framework/editor-server": "^0.
|
|
31
|
-
"@jay-framework/fullstack-component": "^0.
|
|
32
|
-
"@jay-framework/logger": "^0.
|
|
33
|
-
"@jay-framework/plugin-validator": "^0.
|
|
34
|
-
"@jay-framework/stack-server-runtime": "^0.
|
|
27
|
+
"@jay-framework/compiler-jay-html": "^0.14.0",
|
|
28
|
+
"@jay-framework/compiler-shared": "^0.14.0",
|
|
29
|
+
"@jay-framework/dev-server": "^0.14.0",
|
|
30
|
+
"@jay-framework/editor-server": "^0.14.0",
|
|
31
|
+
"@jay-framework/fullstack-component": "^0.14.0",
|
|
32
|
+
"@jay-framework/logger": "^0.14.0",
|
|
33
|
+
"@jay-framework/plugin-validator": "^0.14.0",
|
|
34
|
+
"@jay-framework/stack-server-runtime": "^0.14.0",
|
|
35
35
|
"chalk": "^4.1.2",
|
|
36
36
|
"commander": "^14.0.0",
|
|
37
37
|
"express": "^5.0.1",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"yaml": "^2.3.4"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@jay-framework/dev-environment": "^0.
|
|
43
|
+
"@jay-framework/dev-environment": "^0.14.0",
|
|
44
44
|
"@types/express": "^5.0.2",
|
|
45
45
|
"@types/node": "^22.15.21",
|
|
46
46
|
"nodemon": "^3.0.3",
|