@jay-framework/jay-stack-cli 0.24.1 → 0.24.3
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/agent-kit-template/designer/validation-guide.md +32 -1
- package/agent-kit-template/developer/dev-server-service.md +7 -7
- package/agent-kit-template/developer/routing.md +1 -1
- package/agent-kit-template/plugin/actions-guide.md +10 -0
- package/agent-kit-template/plugin/commands-guide.md +15 -0
- package/agent-kit-template/plugin/contracts-guide.md +7 -0
- package/agent-kit-template/plugin/dev-server-service.md +7 -7
- package/agent-kit-template/plugin/plugin-routes.md +43 -2
- package/agent-kit-template/plugin/plugin-structure.md +101 -15
- package/agent-kit-template/plugin/setup-guide.md +7 -4
- package/agent-kit-template/plugin/validation.md +22 -4
- package/dist/index-B9vCxAZ1.js +1602 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1676 -241
- package/package.json +12 -10
|
@@ -22,12 +22,17 @@ The validator processes each `.jay-html` file with:
|
|
|
22
22
|
|
|
23
23
|
So a warning about an `<img>` might come from a headfull component's template, not your page template. A CSS warning might come from a linked stylesheet.
|
|
24
24
|
|
|
25
|
+
## Errors vs Warnings
|
|
26
|
+
|
|
27
|
+
- **Errors** block the build. They must be fixed — there is no way to suppress them.
|
|
28
|
+
- **Warnings** must be either fixed or explicitly suppressed. Do not ignore warnings — each one has a clear resolution path (add the missing attribute, or suppress via `<script type="application/jay-validations">`).
|
|
29
|
+
|
|
25
30
|
## How to Read Warnings
|
|
26
31
|
|
|
27
32
|
Each warning has:
|
|
28
33
|
|
|
29
34
|
- **Message** — what was found and why it matters
|
|
30
|
-
- **Suggestion** — how to fix it
|
|
35
|
+
- **Suggestion** — how to fix it, and how to suppress it if the warning is intentional
|
|
31
36
|
- **Element** — which HTML element triggered it (some include the full tag with attributes)
|
|
32
37
|
|
|
33
38
|
### Acting on Warnings
|
|
@@ -74,6 +79,32 @@ For design-system token warnings, add `/* design-system: allow */` as a comment
|
|
|
74
79
|
padding: 96px 0; /* design-system: allow */
|
|
75
80
|
```
|
|
76
81
|
|
|
82
|
+
### Page-level validation overrides
|
|
83
|
+
|
|
84
|
+
For page-level warnings that can't be fixed by adding an attribute (e.g., "no LCP image" on a text-first page), use a `<script type="application/jay-validations">` tag in the `<head>`:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<head>
|
|
88
|
+
<script type="application/jay-validations">
|
|
89
|
+
seo:
|
|
90
|
+
no-lcp-image: true
|
|
91
|
+
</script>
|
|
92
|
+
</head>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The YAML body is keyed by plugin name. Each plugin defines its own suppressible rules. This tag is a build-time directive — it's parsed during validation and never rendered in the page output.
|
|
96
|
+
|
|
97
|
+
Multiple plugins can be configured in one tag:
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<script type="application/jay-validations">
|
|
101
|
+
seo:
|
|
102
|
+
no-lcp-image: true
|
|
103
|
+
design-system:
|
|
104
|
+
allow-undefined-vars: true
|
|
105
|
+
</script>
|
|
106
|
+
```
|
|
107
|
+
|
|
77
108
|
### When you can't suppress
|
|
78
109
|
|
|
79
110
|
If a warning comes from dynamic content (`{post.content}`) or a generated file, you can't suppress it in the template. This is a validator limitation — the warning is a false positive. Don't loop trying to fix it.
|
|
@@ -96,15 +96,15 @@ These APIs are also exposed via the editor protocol (Socket.IO) for design board
|
|
|
96
96
|
// Server emits: { type: 'routeParamsBatch', route: '...', params: [], hasMore: false }
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
###
|
|
99
|
+
### Frozen Page Refresh (Dev)
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
In development, **full-page** frozen views (`?_jay_freeze=<id>` in iframe or tab) self-reload when jay-html or CSS changes — same `jay:page-reload` Hot Module Replacement (HMR) path as live pages. No host application wiring required. Saved ViewState is preserved across reload.
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
Fragment format (`format=fragment` for shadow DOM embedders) does **not** auto-reload; those hosts must re-fetch the fragment.
|
|
104
|
+
|
|
105
|
+
### Freeze Changed Event (Fragment Hosts)
|
|
106
|
+
|
|
107
|
+
The `freezeChanged` socket event was described for design board fragment refresh but is **not** emitted by the current dev server. Fragment embedders should re-fetch on file changes themselves, or wait for a future fetch-and-swap protocol. Dev full-page frozen views do not need this event.
|
|
108
108
|
|
|
109
109
|
## Iframe / Embed Mode
|
|
110
110
|
|
|
@@ -87,7 +87,7 @@ The script body is YAML. Values are passed to the component as props alongside r
|
|
|
87
87
|
</script>
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
> **Note:** `<script type="application/jay-params">` is
|
|
90
|
+
> **Note:** `<script type="application/jay-params">` is no longer supported — it is silently ignored by the route scanner and reported as an error by `jay-stack validate`. Move param values into the headless component's script tag body.
|
|
91
91
|
|
|
92
92
|
## Page Files
|
|
93
93
|
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Actions provide RPC-style server endpoints for client-to-server communication.
|
|
4
4
|
|
|
5
|
+
> **Actions are compiler-free and live on the `.` entry.** They run in production, so their handlers
|
|
6
|
+
> must not import the compiler (`@jay-framework/compiler-*`). A handler that needs the compiler is
|
|
7
|
+
> either a [CLI command](commands-guide.md) or a **`devOnly` action** (see below) — not a regular
|
|
8
|
+
> action. `validate-plugin`'s leak scan fails a compiler import in `dist/index.js`.
|
|
9
|
+
>
|
|
10
|
+
> **`devOnly` actions** (`actions[].devOnly: true`) — browser-callable handlers for settings/admin
|
|
11
|
+
> pages that may use the compiler and are **excluded from production**. Their handlers live in the
|
|
12
|
+
> `./tools` entry (`lib/tools.ts`), and the dev server registers them normally. See the settings-page
|
|
13
|
+
> pattern in [plugin-routes.md](plugin-routes.md).
|
|
14
|
+
|
|
5
15
|
## makeJayAction — Mutations (POST)
|
|
6
16
|
|
|
7
17
|
```typescript
|
|
@@ -75,6 +75,21 @@ commands:
|
|
|
75
75
|
command: commands/upload-public.jay-command
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
### 4. Export from `./tools`
|
|
79
|
+
|
|
80
|
+
Commands are the **tools** primitive — they load only from the `./tools` entry (`lib/tools.ts`), which
|
|
81
|
+
may use the compiler. Re-export each command handler there, and add the `./tools` export to
|
|
82
|
+
`package.json`:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// lib/tools.ts (./tools) — toolchain-only, compiler allowed
|
|
86
|
+
export { uploadPublic } from './commands/upload-public.js';
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Do **not** re-export commands from `lib/index.ts` — the serve entry must stay compiler-free. (An
|
|
90
|
+
operation that must be callable from a browser page is an [action](actions-guide.md), not a command;
|
|
91
|
+
if it also needs the compiler, mark the action `devOnly`.)
|
|
92
|
+
|
|
78
93
|
## `CONSOLE_CONTEXT` Service
|
|
79
94
|
|
|
80
95
|
A framework-provided service with project info and a logger:
|
|
@@ -4,6 +4,13 @@ For the full contract syntax, decision tree, and examples, see the shared [Contr
|
|
|
4
4
|
|
|
5
5
|
This file covers plugin-specific contract concerns. Contracts (`.jay-contract` files) are the source of truth for a component's data shape. Define the contract before implementing the component.
|
|
6
6
|
|
|
7
|
+
> **Interactive components need a `./client` export.** If a component built from this contract declares
|
|
8
|
+
> an interactive phase (`.withInteractive(...)`) — or the plugin declares `contexts` — the package
|
|
9
|
+
> must expose a `./client` export (`./dist/index.client.js`) for browser hydration. `validate-plugin`
|
|
10
|
+
> detects interactivity by scanning the built server bundle and errors if `./client` is missing.
|
|
11
|
+
> Server-only (slow/fast) component plugins need no `./client`. See
|
|
12
|
+
> [plugin-structure.md](plugin-structure.md).
|
|
13
|
+
|
|
7
14
|
## Basic Structure
|
|
8
15
|
|
|
9
16
|
```yaml
|
|
@@ -107,15 +107,15 @@ These APIs are also exposed via the editor protocol (Socket.IO) for design board
|
|
|
107
107
|
// Server emits: { type: 'routeParamsBatch', route: '...', params: [], hasMore: false }
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
###
|
|
110
|
+
### Frozen Page Refresh (Dev)
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
In development, **full-page** frozen views (`?_jay_freeze=<id>` in iframe or tab) self-reload when jay-html or CSS changes — same `jay:page-reload` Hot Module Replacement (HMR) path as live pages. No host application wiring required. Saved ViewState is preserved across reload.
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
Fragment format (`format=fragment` for shadow DOM embedders) does **not** auto-reload; those hosts must re-fetch the fragment.
|
|
115
|
+
|
|
116
|
+
### Freeze Changed Event (Fragment Hosts)
|
|
117
|
+
|
|
118
|
+
The `freezeChanged` socket event was described for design board fragment refresh but is **not** emitted by the current dev server. Fragment embedders should re-fetch on file changes themselves, or wait for a future fetch-and-swap protocol. Dev full-page frozen views do not need this event.
|
|
119
119
|
|
|
120
120
|
## Iframe / Embed Mode
|
|
121
121
|
|
|
@@ -149,7 +149,7 @@ There is no enforced convention — just pick a prefix that's unique and descrip
|
|
|
149
149
|
|
|
150
150
|
## Dev-only routes
|
|
151
151
|
|
|
152
|
-
Some plugin pages are **dev-server tooling** — internal dashboards, QA fixtures, builder settings UIs. Mark them with `devOnly: true` so
|
|
152
|
+
Some plugin pages are **dev-server tooling** — internal dashboards, QA fixtures, builder settings UIs. Mark them with `devOnly: true` so they are served by the dev server, distinguishable via `listRoutes()`, and **excluded from production builds** (not compiled, not in the route manifest).
|
|
153
153
|
|
|
154
154
|
```yaml
|
|
155
155
|
routes:
|
|
@@ -168,7 +168,48 @@ routes:
|
|
|
168
168
|
| `listRoutes()` / `RouteInfo` | Includes route with `devOnly: true` |
|
|
169
169
|
| Page navigation UIs | **Consumer choice** — tools may filter `devOnly` routes from pickers |
|
|
170
170
|
| Routes loaded by explicit path | **Unaffected** — embed/host tools pass a known route URL |
|
|
171
|
-
| Production build | **
|
|
171
|
+
| Production build | **Excluded** — the route is not compiled or bundled |
|
|
172
|
+
| Component entry (compiler) | Resolved from **`./tools`** when the page uses the compiler |
|
|
173
|
+
|
|
174
|
+
## Settings pages (devOnly route + devOnly actions)
|
|
175
|
+
|
|
176
|
+
A common pattern: a `devOnly` route whose interactive form calls plugin server handlers to run
|
|
177
|
+
analysis, rebuild a catalog, etc. Because a settings page runs in the browser it invokes handlers via
|
|
178
|
+
the **action RPC** — so these handlers must be **actions**, not CLI commands. When the handler uses the
|
|
179
|
+
compiler (e.g. it parses jay-html), mark the action **`devOnly: true`**: its handler then lives in
|
|
180
|
+
`./tools` (compiler allowed) and is excluded from production alongside the route.
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
routes:
|
|
184
|
+
- path: /my-plugin/settings
|
|
185
|
+
jayHtml: ./dist/pages/settings/page.jay-html
|
|
186
|
+
component: mySettingsPage
|
|
187
|
+
devOnly: true
|
|
188
|
+
actions:
|
|
189
|
+
- name: runAnalysis
|
|
190
|
+
action: run-analysis.jay-action
|
|
191
|
+
devOnly: true # handler in ./tools, may use the compiler, excluded from production
|
|
192
|
+
- name: fontFallback
|
|
193
|
+
action: font-fallback.jay-action # normal production action — compiler-free, stays on `.`
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// lib/tools.ts (./tools) — compiler allowed, never in the production serve bundle
|
|
198
|
+
export { runAnalysis } from './actions/run-analysis.js'; // uses the compiler
|
|
199
|
+
export { mySettingsPage } from './pages/settings/page.js';
|
|
200
|
+
|
|
201
|
+
// lib/index.ts (.) — compiler-free serve entry
|
|
202
|
+
export { fontFallback } from './actions/font-fallback.js';
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- The dev server registers **all** actions (devOnly from `./tools`, regular from `.`) and serves the
|
|
206
|
+
route end-to-end with the compiler present.
|
|
207
|
+
- Production build **excludes** the `devOnly` route (not compiled) and **skips** `devOnly` actions
|
|
208
|
+
(not registered/dispatchable). A compiler-using action left **without** `devOnly` would leak the
|
|
209
|
+
compiler into `dist/index.js` and fail the leak scan — that is the signal to mark it `devOnly` (or
|
|
210
|
+
reclassify it as a command).
|
|
211
|
+
- `devOnly` is orthogonal to compiler use: a compiler-free admin action can still be `devOnly` purely
|
|
212
|
+
to keep it out of production.
|
|
172
213
|
|
|
173
214
|
### Standalone access
|
|
174
215
|
|
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
A plugin provides headless components, contracts, and actions. It can be a standalone npm package or inline within a project.
|
|
4
4
|
|
|
5
|
+
## Capabilities & the runtime/tools split
|
|
6
|
+
|
|
7
|
+
A plugin package runs code in two very different phases, and they must **not** share one module graph:
|
|
8
|
+
|
|
9
|
+
- **Serve-time (runtime)** — headless components, production routes, **server actions**, the client
|
|
10
|
+
bundle, global `init`. Loaded on the production request path. **Must stay compiler-free** — the
|
|
11
|
+
serve bundle ships to production.
|
|
12
|
+
- **Tools-time** — validators, **CLI commands**, agent-kit generators, `setup` handlers, and
|
|
13
|
+
`devOnly` route components/actions. Run only under the Jay toolchain (`jay-stack
|
|
14
|
+
validate`/`agent-kit`/`setup`/`run`, dev server). These **may** use the compiler.
|
|
15
|
+
|
|
16
|
+
**Actions vs commands** — the load-bearing distinction:
|
|
17
|
+
|
|
18
|
+
- **Actions** are the _serving_ primitive: request-time handlers that run in production. They live on
|
|
19
|
+
the `.` entry and **must be compiler-free**.
|
|
20
|
+
- **CLI commands** are the _tools_ primitive: invoked under the toolchain. They live on `./tools` and
|
|
21
|
+
**may use the compiler**.
|
|
22
|
+
|
|
23
|
+
Rule of thumb: **if a handler needs the compiler, it is a command (or a `devOnly` action), not a
|
|
24
|
+
regular action.**
|
|
25
|
+
|
|
26
|
+
### Capability → required export
|
|
27
|
+
|
|
28
|
+
Derive a plugin's required `package.json` exports from the capabilities it declares:
|
|
29
|
+
|
|
30
|
+
| Capability (plugin.yaml) | Needs `./client`? | Handler/export loaded from |
|
|
31
|
+
| --------------------------- | -------------------------- | ------------------------------- |
|
|
32
|
+
| `contracts` | only if interactive phase | `.` (+ `./<contract>` per item) |
|
|
33
|
+
| `dynamic_contracts` | only if interactive phase | `.` |
|
|
34
|
+
| `routes` | only if interactive phase | `.` (or `./tools` if `devOnly`) |
|
|
35
|
+
| `contexts` | ✅ always (client by def.) | `.`, `./client` |
|
|
36
|
+
| `actions` | ❌ | `.` (or `./tools` if `devOnly`) |
|
|
37
|
+
| `services`, `init` / global | ❌ | `.` |
|
|
38
|
+
| `validators` | ❌ | **`./tools`** |
|
|
39
|
+
| `commands` | ❌ | **`./tools`** |
|
|
40
|
+
| `agentkit` / `setup` | ❌ | **`./tools`** |
|
|
41
|
+
|
|
42
|
+
Rules `jay-stack validate-plugin` enforces:
|
|
43
|
+
|
|
44
|
+
- **≥1 capability.** A plugin declaring none is flagged (a `global: true` plugin counts iff it exports
|
|
45
|
+
a resolvable `init`/`setup` handler).
|
|
46
|
+
- **`./tools` required** iff any tools capability (`validators`, `commands`, `agentkit`, `setup`) or a
|
|
47
|
+
`devOnly` action is declared.
|
|
48
|
+
- **`./client` required** iff a provided component has an interactive phase, or `contexts` is declared.
|
|
49
|
+
Server-only and tools-only plugins need no `./client`.
|
|
50
|
+
- **Leak scan:** `dist/index.js` (the `.` entry) must contain no `@jay-framework/compiler-` import.
|
|
51
|
+
|
|
5
52
|
## plugin.yaml
|
|
6
53
|
|
|
7
54
|
The plugin manifest declares all contracts, actions, services, contexts, and configuration:
|
|
@@ -125,6 +172,10 @@ tags:
|
|
|
125
172
|
|
|
126
173
|
- `name` — Action name (used with `jay-stack action <plugin>/<action>`)
|
|
127
174
|
- `action` — Path to `.jay-action` metadata file
|
|
175
|
+
- `devOnly` — (optional, boolean) When `true`, the action's handler lives in `./tools` (compiler
|
|
176
|
+
allowed), is served by the dev server, and is **excluded from production builds**. Use for
|
|
177
|
+
settings-page / admin handlers. A non-`devOnly` action's handler must be compiler-free on `.`. See
|
|
178
|
+
[plugin-routes.md](plugin-routes.md) for the settings-page pattern.
|
|
128
179
|
|
|
129
180
|
### Webhook Entry Fields
|
|
130
181
|
|
|
@@ -177,6 +228,9 @@ services:
|
|
|
177
228
|
- `css` — (optional) Path to the page's CSS file
|
|
178
229
|
- `component` — Path to the page component (relative to plugin root, or exported member name for NPM)
|
|
179
230
|
- `description` — What this page does
|
|
231
|
+
- `devOnly` — (optional, boolean) When `true`, the route is dev-server tooling (e.g. a settings UI):
|
|
232
|
+
served by the dev server, **excluded from production builds**. A `devOnly` route whose page
|
|
233
|
+
component uses the compiler resolves its component from `./tools`.
|
|
180
234
|
|
|
181
235
|
Plugin routes are served by the dev server alongside project routes. If a project defines the same route path, the project's page takes precedence.
|
|
182
236
|
|
|
@@ -193,7 +247,7 @@ Commands are CLI operations run via `jay-stack run`. Use `makeCliCommand()` to c
|
|
|
193
247
|
- `handler` — Export name (NPM plugins) or relative path (local plugins) to the validator function
|
|
194
248
|
- `description` — (optional) What this validator checks
|
|
195
249
|
|
|
196
|
-
**NPM plugins:** `handler` is the export name from the
|
|
250
|
+
**NPM plugins:** `handler` is the export name from the **`./tools`** entry (e.g., `validateMediaOptimization`). The function must be exported from `lib/tools.ts` — **never re-export a validator (or any compiler-using handler) from `lib/index.ts`**, or the compiler leaks into the serve bundle.
|
|
197
251
|
**Local plugins:** `handler` is a relative path to the module (e.g., `./validators/media-validator`). The module must export a `validate` function.
|
|
198
252
|
|
|
199
253
|
Validators run during `jay-stack validate` against every parsed jay-html file in the project. See [validation.md](validation.md) for implementation details.
|
|
@@ -204,7 +258,7 @@ Validators run during `jay-stack validate` against every parsed jay-html file in
|
|
|
204
258
|
- `agentkit` — Export name (NPM) or relative path (local) for `jay-stack agent-kit`. Generates discovery data: add-menu catalogs, reference files, skills, thumbnails.
|
|
205
259
|
- `description` — (optional, top-level) Human-readable description of what setup validates
|
|
206
260
|
|
|
207
|
-
**NPM plugins:** `setup` and `agentkit` are export names from the
|
|
261
|
+
**NPM plugins:** `setup` and `agentkit` are export names from the **`./tools`** entry (`lib/tools.ts`) — they are tools-time handlers and may use the compiler.
|
|
208
262
|
**Local plugins:** relative paths to the handler modules.
|
|
209
263
|
|
|
210
264
|
`jay-stack validate-plugin` checks that declared handlers exist and are correctly exported.
|
|
@@ -263,21 +317,29 @@ my-project/
|
|
|
263
317
|
|
|
264
318
|
See `examples/jay-stack/fake-shop` for a working example.
|
|
265
319
|
|
|
266
|
-
##
|
|
320
|
+
## Entry Points
|
|
267
321
|
|
|
268
|
-
Jay plugins
|
|
322
|
+
Jay plugins run in three contexts. The build produces up to three bundles:
|
|
269
323
|
|
|
270
|
-
- **Server** (`dist/index.js
|
|
271
|
-
|
|
324
|
+
- **Server / serve** (`dist/index.js`, `.`) — actions, services, SSR rendering, `init()`. Loaded on
|
|
325
|
+
the production request path. **Compiler-free.** Built with `vite build --ssr`.
|
|
326
|
+
- **Client** (`dist/index.client.js`, `./client`) — components for hydration, context tokens,
|
|
327
|
+
`init()`. Built with `vite build`.
|
|
328
|
+
- **Tools** (`dist/tools.js`, `./tools`) — validators, commands, agent-kit/setup handlers, and any
|
|
329
|
+
`devOnly` route component/action. **Compiler-allowed** (toolchain-only, never in a serve bundle).
|
|
330
|
+
Built alongside the server bundle (`vite build --ssr`).
|
|
272
331
|
|
|
273
|
-
Create
|
|
332
|
+
Create the entry files:
|
|
274
333
|
|
|
275
|
-
| File | Exports
|
|
276
|
-
| --------------------- |
|
|
277
|
-
| `lib/index.ts` | Actions, services, components (SSR), init, service markers |
|
|
278
|
-
| `lib/index.client.ts` | Components (hydration), context markers, init
|
|
334
|
+
| File | Exports |
|
|
335
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
336
|
+
| `lib/index.ts` | Actions, services, components (SSR), init, service markers — **compiler-free** |
|
|
337
|
+
| `lib/index.client.ts` | Components (hydration), context markers, init |
|
|
338
|
+
| `lib/tools.ts` | Validators, commands, agent-kit/setup handlers, `devOnly` route components + actions — **compiler OK** |
|
|
279
339
|
|
|
280
|
-
Actions and service providers are server-only. Components appear in **both**
|
|
340
|
+
Actions and service providers are server-only. Components appear in **both** `index.ts` and
|
|
341
|
+
`index.client.ts`. **`index.ts` must never import `tools.ts`** — that is what keeps the compiler out of
|
|
342
|
+
the serve bundle. A validator-only or tools-only plugin may have a near-empty `index.ts`.
|
|
281
343
|
|
|
282
344
|
## Build Scripts
|
|
283
345
|
|
|
@@ -289,7 +351,7 @@ Actions and service providers are server-only. Components appear in **both** ent
|
|
|
289
351
|
"build:client": "vite build",
|
|
290
352
|
"build:server": "vite build --ssr",
|
|
291
353
|
"build:copy-assets": "cp lib/*.jay-contract* dist/",
|
|
292
|
-
"build:types": "tsup lib/index.ts lib/index.client.ts --dts-only --format esm",
|
|
354
|
+
"build:types": "tsup lib/index.ts lib/index.client.ts lib/tools.ts --dts-only --format esm",
|
|
293
355
|
"validate": "jay-stack-cli validate-plugin",
|
|
294
356
|
"clean": "rimraf dist"
|
|
295
357
|
}
|
|
@@ -313,7 +375,12 @@ export default defineConfig(({ isSsrBuild }) => ({
|
|
|
313
375
|
emptyOutDir: false,
|
|
314
376
|
lib: {
|
|
315
377
|
entry: isSsrBuild
|
|
316
|
-
? {
|
|
378
|
+
? {
|
|
379
|
+
index: resolve(__dirname, 'lib/index.ts'),
|
|
380
|
+
// Tools entry (compiler-allowed, toolchain-only). Omit if the plugin has no
|
|
381
|
+
// validators/commands/agentkit/setup/devOnly surfaces.
|
|
382
|
+
tools: resolve(__dirname, 'lib/tools.ts'),
|
|
383
|
+
}
|
|
317
384
|
: { 'index.client': resolve(__dirname, 'lib/index.client.ts') },
|
|
318
385
|
formats: ['es'],
|
|
319
386
|
},
|
|
@@ -325,6 +392,9 @@ export default defineConfig(({ isSsrBuild }) => ({
|
|
|
325
392
|
'@jay-framework/stack-server-runtime',
|
|
326
393
|
'@jay-framework/reactive',
|
|
327
394
|
'@jay-framework/runtime',
|
|
395
|
+
// Externalize the compiler namespace: any leak into `.` then shows up as a literal
|
|
396
|
+
// import string in dist/index.js, which validate-plugin's leak scan catches.
|
|
397
|
+
/^@jay-framework\/compiler-/,
|
|
328
398
|
],
|
|
329
399
|
},
|
|
330
400
|
},
|
|
@@ -349,6 +419,10 @@ For NPM packages, declare exports for both server and client entry points:
|
|
|
349
419
|
"types": "./dist/index.client.d.ts",
|
|
350
420
|
"default": "./dist/index.client.js"
|
|
351
421
|
},
|
|
422
|
+
"./tools": {
|
|
423
|
+
"types": "./dist/tools.d.ts",
|
|
424
|
+
"default": "./dist/tools.js"
|
|
425
|
+
},
|
|
352
426
|
"./plugin.yaml": "./plugin.yaml",
|
|
353
427
|
"./my-contract.jay-contract": "./dist/my-contract.jay-contract"
|
|
354
428
|
},
|
|
@@ -356,7 +430,19 @@ For NPM packages, declare exports for both server and client entry points:
|
|
|
356
430
|
}
|
|
357
431
|
```
|
|
358
432
|
|
|
359
|
-
|
|
433
|
+
- The `.` export handles server-side rendering and action execution — it must be **compiler-free**.
|
|
434
|
+
- The `./client` export is required **only** when a component has an interactive phase or the plugin
|
|
435
|
+
declares `contexts` (browser-side hydration / client contexts).
|
|
436
|
+
- The `./tools` export is required **only** when the plugin declares a tools capability (`validators`,
|
|
437
|
+
`commands`, `agentkit`, `setup`) or a `devOnly` action — those handlers load exclusively from
|
|
438
|
+
`./tools`.
|
|
439
|
+
|
|
440
|
+
### compiler-\* dependencies
|
|
441
|
+
|
|
442
|
+
If `./tools` uses the compiler (`@jay-framework/compiler-jay-html`, `compiler-shared`), declare those
|
|
443
|
+
packages as **`peerDependencies`** (provided by the toolchain at tools time) plus **`devDependencies`**
|
|
444
|
+
(so the plugin's own build/test resolve them). Never put them in `dependencies` — that would pull the
|
|
445
|
+
compiler into runtime installs.
|
|
360
446
|
|
|
361
447
|
## Plugin-Contributed Agent-Kit Guides
|
|
362
448
|
|
|
@@ -23,7 +23,7 @@ agentkit: generateMyAgentKit # export name (NPM) or ./path (local) — optional
|
|
|
23
23
|
description: Validate credentials and install config # optional, top-level
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
**NPM plugins:** `setup` and `agentkit` are export names from the
|
|
26
|
+
**NPM plugins:** `setup` and `agentkit` are export names from the **`./tools`** entry (`lib/tools.ts`). They are tools-time handlers (may use the compiler) and load only from `./tools` — do not re-export them from `lib/index.ts`, or the compiler can leak into the serve bundle.
|
|
27
27
|
**Local plugins:** relative paths to handler modules (e.g. `agentkit: ./agentkit` — export `agentkit` or `default` from that module).
|
|
28
28
|
|
|
29
29
|
`jay-stack validate-plugin` checks that declared handlers exist and are correctly exported.
|
|
@@ -266,13 +266,16 @@ See [aiditor-settings-guide.md](aiditor-settings-guide.md) for the full checklis
|
|
|
266
266
|
|
|
267
267
|
## Exporting Handlers
|
|
268
268
|
|
|
269
|
-
For NPM plugins, export handlers from the
|
|
269
|
+
For NPM plugins, export setup/agent-kit handlers from the **`./tools`** entry (they may use the
|
|
270
|
+
compiler and must stay out of the serve bundle):
|
|
270
271
|
|
|
271
272
|
```typescript
|
|
272
|
-
// lib/
|
|
273
|
+
// lib/tools.ts (./tools) — compiler allowed, toolchain-only
|
|
273
274
|
export { setupMyPlugin } from './setup.js';
|
|
274
275
|
export { generateMyAgentKit } from './agentkit.js';
|
|
275
|
-
|
|
276
|
+
|
|
277
|
+
// lib/index.ts (.) — serve entry, compiler-free
|
|
278
|
+
// ... components, actions, services, init (NOT setup/agentkit)
|
|
276
279
|
```
|
|
277
280
|
|
|
278
281
|
For local plugins, use relative paths in `plugin.yaml` and export `agentkit` or `default` from the handler module.
|
|
@@ -43,6 +43,24 @@ jay-stack validate-plugin -v
|
|
|
43
43
|
- Component export names are valid strings (not file paths)
|
|
44
44
|
- Action metadata files (`.jay-action`) exist
|
|
45
45
|
|
|
46
|
+
### Capability-aware structure
|
|
47
|
+
|
|
48
|
+
`validate-plugin` derives required exports from the capabilities the plugin declares (see the
|
|
49
|
+
capability matrix in [plugin-structure.md](plugin-structure.md)):
|
|
50
|
+
|
|
51
|
+
- **≥1 capability** — a plugin declaring none is warned (a `global: true` plugin counts iff it exports
|
|
52
|
+
a resolvable `init`/`setup` handler).
|
|
53
|
+
- **`./tools` required** iff any tools capability (`validators`, `commands`, `agentkit`, `setup`) or a
|
|
54
|
+
`devOnly` action is declared — those handlers load only from `./tools`. Validator/setup/agentkit
|
|
55
|
+
handler names are checked against the **`./tools`** entry, not `.`.
|
|
56
|
+
- **`./client` required** iff a component has an interactive phase (detected by scanning the built
|
|
57
|
+
server `.` bundle for the interactive mark) or `contexts` is declared. Server-only and tools-only
|
|
58
|
+
plugins need no `./client`.
|
|
59
|
+
- **Leak scan** — the serve entry `dist/index.js` must contain no `@jay-framework/compiler-` import.
|
|
60
|
+
A compiler-using handler re-exported from `index.ts` fails this check; move it to `lib/tools.ts`.
|
|
61
|
+
- **`devOnly`** — `actions[].devOnly` / `routes[].devOnly` must be booleans; a `devOnly` action
|
|
62
|
+
requires the `./tools` export.
|
|
63
|
+
|
|
46
64
|
### Type Generation
|
|
47
65
|
|
|
48
66
|
- Contracts compile to valid TypeScript types
|
|
@@ -133,20 +151,20 @@ Plugins can provide custom jay-html validation rules that run during `jay-stack
|
|
|
133
151
|
```yaml
|
|
134
152
|
validators:
|
|
135
153
|
- name: media-optimization
|
|
136
|
-
handler: validateMediaOptimization # export name from
|
|
154
|
+
handler: validateMediaOptimization # export name from the ./tools entry
|
|
137
155
|
description: Ensures media URLs use resize parameters
|
|
138
156
|
```
|
|
139
157
|
|
|
140
158
|
**Handler format:**
|
|
141
159
|
|
|
142
|
-
- **NPM plugins** — `handler` is an export name from the
|
|
160
|
+
- **NPM plugins** — `handler` is an export name from the **`./tools`** entry (e.g., `validateMediaOptimization`). The function must be exported from `lib/tools.ts`. **Never re-export a validator from `lib/index.ts`** — validators use compiler APIs (`walkElements`, `parseTemplateParts`, …), and re-exporting from the serve entry pulls the compiler into the production bundle (caught by the leak scan).
|
|
143
161
|
- **Local plugins** (`src/plugins/`) — `handler` is a relative path to the module (e.g., `./validators/media-validator`). The module must export a `validate` function.
|
|
144
162
|
|
|
145
|
-
`jay-stack validate-plugin` checks that the handler exists and is correctly exported
|
|
163
|
+
`jay-stack validate-plugin` checks that the handler exists and is correctly exported from `./tools`.
|
|
146
164
|
|
|
147
165
|
### Writing a Validator
|
|
148
166
|
|
|
149
|
-
Export the validator function from the
|
|
167
|
+
Export the validator function from the **`./tools`** entry (`lib/tools.ts`, for NPM) or from the handler module (for local):
|
|
150
168
|
|
|
151
169
|
```typescript
|
|
152
170
|
import type { JayHtmlValidatorFn, JayHtmlValidationFinding } from '@jay-framework/compiler-shared';
|