@jay-framework/jay-stack-cli 0.11.0 โ 0.12.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 +58 -0
- package/agent-kit-template/INSTRUCTIONS.md +116 -0
- package/agent-kit-template/cli-commands.md +229 -0
- package/agent-kit-template/contracts-and-plugins.md +229 -0
- package/agent-kit-template/jay-html-syntax.md +312 -0
- package/agent-kit-template/project-structure.md +242 -0
- package/agent-kit-template/routing.md +112 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +708 -160
- package/package.json +13 -8
package/README.md
CHANGED
|
@@ -27,6 +27,57 @@ jay-stack dev ./my-project # Start dev server in specified directory
|
|
|
27
27
|
|
|
28
28
|
This will start both the development server and editor server with default configuration.
|
|
29
29
|
|
|
30
|
+
##### Test Mode
|
|
31
|
+
|
|
32
|
+
For automated testing, CI pipelines, and smoke tests, use the `--test-mode` flag:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
jay-stack dev --test-mode # Enable test endpoints
|
|
36
|
+
jay-stack dev --timeout 60 # Auto-shutdown after 60 seconds (implies --test-mode)
|
|
37
|
+
jay-stack dev --test-mode --timeout 120 # Both options
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Test mode enables special endpoints for reliable server management:
|
|
41
|
+
|
|
42
|
+
| Endpoint | Method | Description |
|
|
43
|
+
| ---------------- | ------ | ----------------------------------------------------------------------- |
|
|
44
|
+
| `/_jay/health` | GET | Returns `{"status":"ready","port":3300,"editorPort":3301,"uptime":5.2}` |
|
|
45
|
+
| `/_jay/shutdown` | POST | Gracefully shuts down the server, returns `{"status":"shutting_down"}` |
|
|
46
|
+
|
|
47
|
+
**Example smoke test workflow:**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Start server with 2-minute timeout
|
|
51
|
+
jay-stack dev --test-mode --timeout 120 &
|
|
52
|
+
|
|
53
|
+
# Wait for health endpoint
|
|
54
|
+
for i in {1..30}; do
|
|
55
|
+
if curl -s http://localhost:3300/_jay/health | grep -q "ready"; then
|
|
56
|
+
break
|
|
57
|
+
fi
|
|
58
|
+
sleep 1
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
# Run your tests
|
|
62
|
+
curl -s http://localhost:3300/products/ | grep -q "<!doctype html"
|
|
63
|
+
|
|
64
|
+
# Clean shutdown
|
|
65
|
+
curl -X POST http://localhost:3300/_jay/shutdown
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
When test mode is enabled, the startup output includes the test endpoints:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
๐ Jay Stack dev server started successfully!
|
|
72
|
+
๐ฑ Dev Server: http://localhost:3300
|
|
73
|
+
๐จ Editor Server: http://localhost:3301 (ID: init)
|
|
74
|
+
๐ Pages directory: ./src/pages
|
|
75
|
+
๐งช Test Mode: enabled
|
|
76
|
+
Health: http://localhost:3300/_jay/health
|
|
77
|
+
Shutdown: curl -X POST http://localhost:3300/_jay/shutdown
|
|
78
|
+
Timeout: 60s
|
|
79
|
+
```
|
|
80
|
+
|
|
30
81
|
#### `jay-stack validate [path]`
|
|
31
82
|
|
|
32
83
|
Validate all `.jay-html` and `.jay-contract` files in the project without creating output files:
|
|
@@ -203,6 +254,13 @@ The CLI is built using:
|
|
|
203
254
|
| `jay-stack validate [path]` | Validate jay-html and jay-contract files |
|
|
204
255
|
| `jay-stack validate-plugin [path]` | Validate a plugin package |
|
|
205
256
|
|
|
257
|
+
### Dev Command Options
|
|
258
|
+
|
|
259
|
+
| Option | Description |
|
|
260
|
+
| ------------------ | -------------------------------------------------------- |
|
|
261
|
+
| `--test-mode` | Enable test endpoints (`/_jay/health`, `/_jay/shutdown`) |
|
|
262
|
+
| `--timeout <secs>` | Auto-shutdown after N seconds (implies `--test-mode`) |
|
|
263
|
+
|
|
206
264
|
### Validate Command Options
|
|
207
265
|
|
|
208
266
|
| Option | Description |
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Jay Stack Agent Kit
|
|
2
|
+
|
|
3
|
+
This folder contains everything you need to create jay-html pages for a jay-stack application.
|
|
4
|
+
|
|
5
|
+
## What is Jay Stack?
|
|
6
|
+
|
|
7
|
+
Jay Stack is a full-stack framework where:
|
|
8
|
+
|
|
9
|
+
- **Plugins** provide headless components (data + interactions, no UI)
|
|
10
|
+
- **Contracts** define the data shape and interaction points of each component
|
|
11
|
+
- **jay-html** templates provide the UI that binds to contract data
|
|
12
|
+
- **Rendering phases** determine when data is available (build-time, request-time, client-side)
|
|
13
|
+
|
|
14
|
+
Your job is to create `.jay-html` pages that bind to the data and interactions defined by contracts.
|
|
15
|
+
|
|
16
|
+
## Rendering Phases
|
|
17
|
+
|
|
18
|
+
| Phase | When | Use For |
|
|
19
|
+
| -------------------- | ------------------ | ------------------------------------------------- |
|
|
20
|
+
| **slow** | Build time (SSG) | Static content, SEO data, pre-rendered lists |
|
|
21
|
+
| **fast** | Request time (SSR) | Per-request data (prices, stock, personalization) |
|
|
22
|
+
| **fast+interactive** | Request + client | Data that also updates on the client |
|
|
23
|
+
|
|
24
|
+
There is no standalone "interactive" phase. Any tag with `type: interactive` (refs/interactions) is automatically `fast+interactive`. Tags without an explicit phase are available in all phases.
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
1. **Read this file** for overview and workflow
|
|
29
|
+
2. **Discover plugins** โ read `materialized-contracts/plugins-index.yaml` to see available plugins and their contracts. Read `materialized-contracts/contracts-index.yaml` for the full contract list.
|
|
30
|
+
3. **Read plugin.yaml** โ for each plugin, read its `plugin.yaml` (at the path from plugins-index) to see contract descriptions and available **actions** (e.g., `searchProducts`, `getCategories`).
|
|
31
|
+
4. **Read contracts** โ read the `.jay-contract` files to understand data shapes, tag types, phases, and props.
|
|
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.
|
|
33
|
+
6. **Discover data** โ run `jay-stack params <plugin>/<contract>` for SSG route params, `jay-stack action <plugin>/<action>` for data discovery (action names come from plugin.yaml). Use reference files (step 5) first when available โ they're faster than running CLI commands.
|
|
34
|
+
7. **Create pages** โ write `.jay-html` files under `src/pages/` following directory-based routing.
|
|
35
|
+
8. **Validate** โ run `jay-stack validate` to check for errors.
|
|
36
|
+
9. **Test** โ run `jay-stack dev --test-mode` and verify pages render.
|
|
37
|
+
|
|
38
|
+
## Reference Docs
|
|
39
|
+
|
|
40
|
+
| File | Topic |
|
|
41
|
+
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
42
|
+
| [project-structure.md](project-structure.md) | Project layout, styling patterns (CSS themes, design tokens), configuration files |
|
|
43
|
+
| [jay-html-syntax.md](jay-html-syntax.md) | Jay-HTML template syntax: data binding, conditions, loops, headless components |
|
|
44
|
+
| [routing.md](routing.md) | Directory-based routing: page structure, dynamic routes, route priority |
|
|
45
|
+
| [contracts-and-plugins.md](contracts-and-plugins.md) | Reading contracts, plugin.yaml, and the materialized indexes |
|
|
46
|
+
| [cli-commands.md](cli-commands.md) | CLI commands: setup, validate, params, action, dev server |
|
|
47
|
+
| `references/<plugin>/` | Pre-generated discovery data: product catalogs, collection schemas (from `jay-stack agent-kit`) |
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### 1. Discover plugins and contracts
|
|
52
|
+
|
|
53
|
+
Read `materialized-contracts/plugins-index.yaml`:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
plugins:
|
|
57
|
+
- name: wix-stores
|
|
58
|
+
path: ./node_modules/@wix/stores
|
|
59
|
+
contracts:
|
|
60
|
+
- name: product-page
|
|
61
|
+
type: static
|
|
62
|
+
path: ./node_modules/@wix/stores/lib/contracts/product-page.jay-contract
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Read a contract
|
|
66
|
+
|
|
67
|
+
The `.jay-contract` file at the path from the index defines the data shape:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
name: ProductWidget
|
|
71
|
+
props:
|
|
72
|
+
- name: productId
|
|
73
|
+
type: string
|
|
74
|
+
required: true
|
|
75
|
+
tags:
|
|
76
|
+
- tag: name
|
|
77
|
+
type: data
|
|
78
|
+
dataType: string
|
|
79
|
+
phase: slow
|
|
80
|
+
- tag: inStock
|
|
81
|
+
type: variant
|
|
82
|
+
dataType: boolean
|
|
83
|
+
phase: fast+interactive
|
|
84
|
+
- tag: addToCart
|
|
85
|
+
type: interactive
|
|
86
|
+
elementType: HTMLButtonElement
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. Create a page
|
|
90
|
+
|
|
91
|
+
Create `src/pages/page.jay-html`:
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<html>
|
|
95
|
+
<head>
|
|
96
|
+
<script
|
|
97
|
+
type="application/jay-headless"
|
|
98
|
+
plugin="wix-stores"
|
|
99
|
+
contract="product-page"
|
|
100
|
+
key="product"
|
|
101
|
+
></script>
|
|
102
|
+
</head>
|
|
103
|
+
<body>
|
|
104
|
+
<h1>{product.name}</h1>
|
|
105
|
+
<span if="product.inStock">In Stock</span>
|
|
106
|
+
<button ref="product.addToCart">Add to Cart</button>
|
|
107
|
+
</body>
|
|
108
|
+
</html>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4. Validate and run
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
jay-stack validate
|
|
115
|
+
jay-stack dev
|
|
116
|
+
```
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# CLI Commands Reference
|
|
2
|
+
|
|
3
|
+
## jay-stack setup
|
|
4
|
+
|
|
5
|
+
Run plugin setup. Plugins can create configuration files, generate reference data, and validate their prerequisites.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Run setup for all installed plugins
|
|
9
|
+
jay-stack setup
|
|
10
|
+
|
|
11
|
+
# Run setup for a specific plugin
|
|
12
|
+
jay-stack setup wix-stores
|
|
13
|
+
|
|
14
|
+
# Re-run setup (e.g., after config change)
|
|
15
|
+
jay-stack setup wix-data --force
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Plugins declare their setup handler in `plugin.yaml`. Setup does two things:
|
|
19
|
+
|
|
20
|
+
1. **Config templates**: Creates `config/<plugin>.yaml` with placeholder credentials if missing
|
|
21
|
+
2. **Credential validation**: Attempts to initialize services, reports success or failure
|
|
22
|
+
|
|
23
|
+
Reference data (product catalogs, collection schemas) is generated by `jay-stack agent-kit`, not by setup.
|
|
24
|
+
|
|
25
|
+
Run this after installing new plugins, before `jay-stack agent-kit`.
|
|
26
|
+
|
|
27
|
+
## jay-stack agent-kit
|
|
28
|
+
|
|
29
|
+
Materialize contracts, generate discovery indexes, and produce plugin reference data. Run this after setup.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Default: writes to agent-kit/
|
|
33
|
+
jay-stack agent-kit
|
|
34
|
+
|
|
35
|
+
# Custom output directory for contracts
|
|
36
|
+
jay-stack agent-kit --output my-output/
|
|
37
|
+
|
|
38
|
+
# List contracts without writing files
|
|
39
|
+
jay-stack agent-kit --list
|
|
40
|
+
|
|
41
|
+
# Filter to specific plugin
|
|
42
|
+
jay-stack agent-kit --plugin wix-stores
|
|
43
|
+
|
|
44
|
+
# Force re-materialization
|
|
45
|
+
jay-stack agent-kit --force
|
|
46
|
+
|
|
47
|
+
# Skip reference data generation
|
|
48
|
+
jay-stack agent-kit --no-references
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Outputs:
|
|
52
|
+
|
|
53
|
+
- `materialized-contracts/contracts-index.yaml`
|
|
54
|
+
- `materialized-contracts/plugins-index.yaml`
|
|
55
|
+
- `materialized-contracts/<plugin>/*.jay-contract` (dynamic contracts)
|
|
56
|
+
- `references/<plugin>/` โ plugin reference data (product catalogs, collection schemas, etc.)
|
|
57
|
+
- Documentation files (INSTRUCTIONS.md and reference docs)
|
|
58
|
+
|
|
59
|
+
## jay-stack validate
|
|
60
|
+
|
|
61
|
+
Validate all `.jay-html` and `.jay-contract` files.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Validate entire project
|
|
65
|
+
jay-stack validate
|
|
66
|
+
|
|
67
|
+
# Validate a specific path
|
|
68
|
+
jay-stack validate src/pages/products/
|
|
69
|
+
|
|
70
|
+
# Verbose (per-file status)
|
|
71
|
+
jay-stack validate -v
|
|
72
|
+
|
|
73
|
+
# JSON output
|
|
74
|
+
jay-stack validate --json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Example output:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
โ
Jay Stack validation successful!
|
|
81
|
+
Scanned 5 .jay-html files, 3 .jay-contract files
|
|
82
|
+
No errors found.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
On failure:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
โ Jay Stack validation failed
|
|
89
|
+
|
|
90
|
+
Errors:
|
|
91
|
+
โ src/pages/products/page.jay-html
|
|
92
|
+
Unknown ref "nonExistentRef" - not found in contract
|
|
93
|
+
|
|
94
|
+
1 error(s) found, 7 file(s) valid.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Always run validate after creating or editing jay-html and contract files.
|
|
98
|
+
|
|
99
|
+
## jay-stack params
|
|
100
|
+
|
|
101
|
+
Discover load param values for SSG route generation.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Discover slug values for product pages
|
|
105
|
+
jay-stack params wix-stores/product-page
|
|
106
|
+
|
|
107
|
+
# YAML output
|
|
108
|
+
jay-stack params wix-stores/product-page --yaml
|
|
109
|
+
|
|
110
|
+
# Verbose
|
|
111
|
+
jay-stack params wix-stores/product-page -v
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Format: `<plugin-name>/<contract-name>`
|
|
115
|
+
|
|
116
|
+
Example output:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
[
|
|
120
|
+
{ "slug": "ceramic-flower-vase" },
|
|
121
|
+
{ "slug": "blue-running-shoes" },
|
|
122
|
+
{ "slug": "organic-cotton-tshirt" }
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
โ
Found 3 param combination(s)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Use this to discover what param values exist for dynamic routes like `[slug]`. Only works on contracts whose component has `loadParams`.
|
|
129
|
+
|
|
130
|
+
## jay-stack action
|
|
131
|
+
|
|
132
|
+
Run a plugin action from the CLI. Use to discover data for populating pages.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Run with default input
|
|
136
|
+
jay-stack action wix-stores/searchProducts
|
|
137
|
+
|
|
138
|
+
# Run with input
|
|
139
|
+
jay-stack action wix-stores/searchProducts --input '{"query": "shoes", "limit": 5}'
|
|
140
|
+
|
|
141
|
+
# YAML output
|
|
142
|
+
jay-stack action wix-stores/getCategories --yaml
|
|
143
|
+
|
|
144
|
+
# Verbose
|
|
145
|
+
jay-stack action wix-stores/getProductBySlug --input '{"slug": "blue-shirt"}' -v
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Format: `<plugin-name>/<action-name>`
|
|
149
|
+
|
|
150
|
+
Action names are listed in the plugin's `plugin.yaml` under `actions:`.
|
|
151
|
+
|
|
152
|
+
Example output:
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"items": [
|
|
157
|
+
{ "_id": "prod-1", "name": "Blue Shirt", "slug": "blue-shirt", "price": 29.99 },
|
|
158
|
+
{ "_id": "prod-2", "name": "Red Hat", "slug": "red-hat", "price": 19.99 }
|
|
159
|
+
],
|
|
160
|
+
"totalCount": 2
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
If not found, lists available actions:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
โ Action "badName" not found.
|
|
168
|
+
Available actions: searchProducts, getProductBySlug, getCategories
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## jay-stack dev
|
|
172
|
+
|
|
173
|
+
Start the development server.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Normal dev mode
|
|
177
|
+
jay-stack dev
|
|
178
|
+
|
|
179
|
+
# Test mode (enables health/shutdown endpoints)
|
|
180
|
+
jay-stack dev --test-mode
|
|
181
|
+
|
|
182
|
+
# Auto-timeout (implies test mode)
|
|
183
|
+
jay-stack dev --timeout 60
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Test mode endpoints
|
|
187
|
+
|
|
188
|
+
| Endpoint | Method | Response |
|
|
189
|
+
| ---------------- | ------ | --------------------------------------------------------------- |
|
|
190
|
+
| `/_jay/health` | GET | `{"status":"ready","port":3300,"editorPort":3301,"uptime":5.2}` |
|
|
191
|
+
| `/_jay/shutdown` | POST | `{"status":"shutting_down"}` |
|
|
192
|
+
|
|
193
|
+
### Wait for server ready
|
|
194
|
+
|
|
195
|
+
Poll the health endpoint:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Bash
|
|
199
|
+
for i in {1..30}; do
|
|
200
|
+
curl -s http://localhost:3300/_jay/health | grep -q "ready" && break
|
|
201
|
+
sleep 1
|
|
202
|
+
done
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// TypeScript
|
|
207
|
+
async function waitForServer(timeout = 30000): Promise<string> {
|
|
208
|
+
const start = Date.now();
|
|
209
|
+
while (Date.now() - start < timeout) {
|
|
210
|
+
try {
|
|
211
|
+
const res = await fetch('http://localhost:3300/_jay/health');
|
|
212
|
+
if (res.ok) {
|
|
213
|
+
const { port } = await res.json();
|
|
214
|
+
return `http://localhost:${port}`;
|
|
215
|
+
}
|
|
216
|
+
} catch {
|
|
217
|
+
/* not ready */
|
|
218
|
+
}
|
|
219
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
220
|
+
}
|
|
221
|
+
throw new Error('Server not ready');
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Shutdown
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
curl -X POST http://localhost:3300/_jay/shutdown
|
|
229
|
+
```
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Contracts and Plugins
|
|
2
|
+
|
|
3
|
+
## Discovery: Plugins Index
|
|
4
|
+
|
|
5
|
+
After running `jay-stack agent-kit`, read `materialized-contracts/plugins-index.yaml`:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
materialized_at: '2026-02-09T...'
|
|
9
|
+
jay_stack_version: '1.0.0'
|
|
10
|
+
plugins:
|
|
11
|
+
- name: wix-stores
|
|
12
|
+
path: ./node_modules/@wix/stores
|
|
13
|
+
contracts:
|
|
14
|
+
- name: product-page
|
|
15
|
+
type: static
|
|
16
|
+
path: ./node_modules/@wix/stores/lib/contracts/product-page.jay-contract
|
|
17
|
+
- name: product-search
|
|
18
|
+
type: static
|
|
19
|
+
path: ./node_modules/@wix/stores/lib/contracts/product-search.jay-contract
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Fields:
|
|
23
|
+
|
|
24
|
+
- `name` โ plugin name (use in `plugin="..."` attributes in jay-html)
|
|
25
|
+
- `path` โ path to plugin root (relative to project root)
|
|
26
|
+
- `contracts[].name` โ contract name (use in `contract="..."` attributes)
|
|
27
|
+
- `contracts[].type` โ `static` (defined in source) or `dynamic` (generated at runtime)
|
|
28
|
+
- `contracts[].path` โ path to the `.jay-contract` file you can read
|
|
29
|
+
|
|
30
|
+
## Discovery: Contracts Index
|
|
31
|
+
|
|
32
|
+
`materialized-contracts/contracts-index.yaml` lists all contracts across all plugins:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
contracts:
|
|
36
|
+
- plugin: wix-stores
|
|
37
|
+
name: product-page
|
|
38
|
+
type: static
|
|
39
|
+
path: ./node_modules/@wix/stores/lib/contracts/product-page.jay-contract
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Reading plugin.yaml
|
|
43
|
+
|
|
44
|
+
Each plugin has a `plugin.yaml` at its root (the `path` from plugins-index):
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
name: wix-stores
|
|
48
|
+
contracts:
|
|
49
|
+
- name: product-page
|
|
50
|
+
contract: product-page.jay-contract
|
|
51
|
+
component: productPage
|
|
52
|
+
description: Complete headless product page with server-side rendering
|
|
53
|
+
- name: product-search
|
|
54
|
+
contract: product-search.jay-contract
|
|
55
|
+
component: productSearch
|
|
56
|
+
description: Headless product search page
|
|
57
|
+
actions:
|
|
58
|
+
- searchProducts
|
|
59
|
+
- getProductBySlug
|
|
60
|
+
- getCategories
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Key fields:
|
|
64
|
+
|
|
65
|
+
- `contracts[].name` โ use in `contract="..."` in jay-html
|
|
66
|
+
- `contracts[].description` โ what the component does (helps you decide which to use)
|
|
67
|
+
- `actions[]` โ action names you can run with `jay-stack action <plugin>/<action>`
|
|
68
|
+
|
|
69
|
+
## Reading .jay-contract Files
|
|
70
|
+
|
|
71
|
+
Contracts define the data shape (ViewState), interaction points (Refs), and rendering phases.
|
|
72
|
+
|
|
73
|
+
### Tag Types
|
|
74
|
+
|
|
75
|
+
| Type | Purpose | Jay-HTML Usage |
|
|
76
|
+
| --------------------------------- | -------------------------------- | --------------------------------- |
|
|
77
|
+
| `data` | Read-only data value | `{tagName}` binding |
|
|
78
|
+
| `variant` | Enum or boolean for conditions | `if="tagName===value"` |
|
|
79
|
+
| `interactive` | Element ref for user interaction | `ref="tagName"` |
|
|
80
|
+
| `[data, interactive]` | Both data and interactive | `{tagName}` + `ref="tagName"` |
|
|
81
|
+
| `sub-contract` | Nested object | `{parent.child}` |
|
|
82
|
+
| `sub-contract` + `repeated: true` | Array for loops | `forEach="tagName" trackBy="..."` |
|
|
83
|
+
|
|
84
|
+
### Phases
|
|
85
|
+
|
|
86
|
+
| Phase | When | Example |
|
|
87
|
+
| ------------------ | ------------------------ | ----------------------------------------- |
|
|
88
|
+
| `slow` | Build time (SSG) | Product name, description, static content |
|
|
89
|
+
| `fast` | Request time (SSR) | Live pricing, stock status |
|
|
90
|
+
| `fast+interactive` | Request + client updates | Price that updates on variant selection |
|
|
91
|
+
| _(no phase)_ | All phases | Available everywhere |
|
|
92
|
+
|
|
93
|
+
### Props
|
|
94
|
+
|
|
95
|
+
Components that accept props:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
props:
|
|
99
|
+
- name: productId
|
|
100
|
+
type: string
|
|
101
|
+
required: true
|
|
102
|
+
description: The ID of the product to display
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use in jay-html: `<jay:contract-name productId="value">`.
|
|
106
|
+
|
|
107
|
+
### Params
|
|
108
|
+
|
|
109
|
+
Page components with dynamic routes:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
params:
|
|
113
|
+
slug: string
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Params are always strings. Discover values with `jay-stack params`.
|
|
117
|
+
|
|
118
|
+
### Linked Sub-Contracts
|
|
119
|
+
|
|
120
|
+
A sub-contract can reference another contract file:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
- tag: mediaGallery
|
|
124
|
+
type: sub-contract
|
|
125
|
+
phase: fast+interactive
|
|
126
|
+
link: ./media-gallery # refers to media-gallery.jay-contract in same directory
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Read the linked file to see the nested tags.
|
|
130
|
+
|
|
131
|
+
## Contract Examples
|
|
132
|
+
|
|
133
|
+
**Simple component with props:**
|
|
134
|
+
|
|
135
|
+
```yaml
|
|
136
|
+
name: ProductWidget
|
|
137
|
+
props:
|
|
138
|
+
- name: productId
|
|
139
|
+
type: string
|
|
140
|
+
required: true
|
|
141
|
+
tags:
|
|
142
|
+
- tag: name
|
|
143
|
+
type: data
|
|
144
|
+
dataType: string
|
|
145
|
+
phase: slow
|
|
146
|
+
- tag: price
|
|
147
|
+
type: data
|
|
148
|
+
dataType: number
|
|
149
|
+
phase: slow
|
|
150
|
+
- tag: inStock
|
|
151
|
+
type: variant
|
|
152
|
+
dataType: boolean
|
|
153
|
+
phase: fast+interactive
|
|
154
|
+
- tag: addToCart
|
|
155
|
+
type: interactive
|
|
156
|
+
elementType: HTMLButtonElement
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Page with nested loops:**
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
name: product-page
|
|
163
|
+
tags:
|
|
164
|
+
- tag: productName
|
|
165
|
+
type: data
|
|
166
|
+
dataType: string
|
|
167
|
+
- tag: price
|
|
168
|
+
type: data
|
|
169
|
+
dataType: string
|
|
170
|
+
phase: fast+interactive
|
|
171
|
+
- tag: addToCartButton
|
|
172
|
+
type: interactive
|
|
173
|
+
elementType: HTMLButtonElement
|
|
174
|
+
- tag: options
|
|
175
|
+
type: sub-contract
|
|
176
|
+
repeated: true
|
|
177
|
+
trackBy: _id
|
|
178
|
+
tags:
|
|
179
|
+
- tag: _id
|
|
180
|
+
type: data
|
|
181
|
+
dataType: string
|
|
182
|
+
- tag: name
|
|
183
|
+
type: data
|
|
184
|
+
dataType: string
|
|
185
|
+
- tag: choices
|
|
186
|
+
type: sub-contract
|
|
187
|
+
repeated: true
|
|
188
|
+
trackBy: choiceId
|
|
189
|
+
tags:
|
|
190
|
+
- tag: choiceId
|
|
191
|
+
type: data
|
|
192
|
+
dataType: string
|
|
193
|
+
- tag: name
|
|
194
|
+
type: data
|
|
195
|
+
dataType: string
|
|
196
|
+
- tag: isSelected
|
|
197
|
+
type: variant
|
|
198
|
+
dataType: boolean
|
|
199
|
+
phase: fast+interactive
|
|
200
|
+
- tag: choiceButton
|
|
201
|
+
type: interactive
|
|
202
|
+
elementType: HTMLButtonElement
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## From Contract to Jay-HTML
|
|
206
|
+
|
|
207
|
+
### Step by step
|
|
208
|
+
|
|
209
|
+
1. **Read the contract** โ identify tags, their types, and phases
|
|
210
|
+
2. **Map `data` tags** โ `{tagName}` bindings
|
|
211
|
+
3. **Map `variant` tags** โ `if="tagName===value"` conditions
|
|
212
|
+
4. **Map `interactive` tags** โ `ref="tagName"` on appropriate element types
|
|
213
|
+
5. **Map `sub-contract` + `repeated: true`** โ `forEach="tagName" trackBy="..."` loops
|
|
214
|
+
6. **Map nested `sub-contract`** โ dotted paths or nested context inside forEach
|
|
215
|
+
7. **Respect phases** โ don't assume fast-only data is available at build time
|
|
216
|
+
|
|
217
|
+
### Quick mapping
|
|
218
|
+
|
|
219
|
+
| Contract Tag | Jay-HTML |
|
|
220
|
+
| ---------------------------------------------------------------- | --------------------------------------------- |
|
|
221
|
+
| `{tag: title, type: data}` | `<h1>{title}</h1>` |
|
|
222
|
+
| `{tag: active, type: variant, dataType: boolean}` | `<span if="active">Active</span>` |
|
|
223
|
+
| `{tag: status, type: variant, dataType: "enum (A \| B)"}` | `<div if="status===A">...</div>` |
|
|
224
|
+
| `{tag: btn, type: interactive, elementType: HTMLButtonElement}` | `<button ref="btn">Click</button>` |
|
|
225
|
+
| `{tag: link, type: interactive, elementType: HTMLAnchorElement}` | `<a ref="link">Go</a>` |
|
|
226
|
+
| `{tag: input, type: interactive, elementType: HTMLInputElement}` | `<input ref="input" value="{val}" />` |
|
|
227
|
+
| `{tag: sel, type: interactive, elementType: HTMLSelectElement}` | `<select ref="sel">...</select>` |
|
|
228
|
+
| `{tag: items, type: sub-contract, repeated: true, trackBy: id}` | `<div forEach="items" trackBy="id">...</div>` |
|
|
229
|
+
| `{tag: detail, type: sub-contract}` | `{detail.fieldName}` |
|