@jay-framework/jay-stack-cli 0.25.4 → 0.25.5

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.
@@ -35,24 +35,28 @@ When running `jay-stack-cli setup` without `--interactive`, plugins that need us
35
35
 
36
36
  ```yaml
37
37
  setup-needs-answer:
38
- plugin: wix-server-client
39
- key: api-key
38
+ plugin: '@jay-framework/some-plugin'
39
+ key: apiKey
40
40
  type: input
41
41
  message: 'Enter your API key'
42
+ choices: # present only for select-type questions
43
+ - us: United States
42
44
  ```
43
45
 
44
- To provide the answer, create a YAML file and re-run:
46
+ To provide the answer, create a YAML file keyed by the `key` field and re-run:
45
47
 
46
48
  ```yaml
47
49
  # answers.yaml
48
- api-key: 'IST.abc123...'
50
+ apiKey: 'your-answer'
49
51
  ```
50
52
 
51
53
  ```bash
52
54
  jay-stack-cli setup --answers answers.yaml
53
55
  ```
54
56
 
55
- Repeat until all plugins report `configured`. The flow is iterative — each run may reveal the next question.
57
+ Repeat until all plugins report `configured`. The flow is iterative — each run may reveal the next question. The `key` is the stable join field between a question and its answer.
58
+
59
+ > **Exception — Wix login is not answerable via a file.** The Wix plugins' credential setup shells out to the Wix CLI for a browser-based OAuth login (`npx @wix/cli login`). In non-interactive mode it reports `needs-config` ("requires interactive mode") rather than a `setup-needs-answer:` — there is no key you can put in `answers.yaml`. A human must run `jay-stack-cli setup --interactive` in a real terminal once; after that the app secret, client ID, and site ID are fetched/derived automatically. `wix-deploy` also needs a live Wix CLI session at deploy time (`jay-stack run wix-deploy/deploy`) — re-run `npx @wix/cli login` if it reports the session is missing.
56
60
 
57
61
  ### Setup order
58
62
 
@@ -64,6 +68,68 @@ jay-stack-cli agent-kit # 2. Generate contracts and discovery data
64
68
  jay-stack-cli build # 3. Production build
65
69
  ```
66
70
 
71
+ ## Running in cloud / remote environments
72
+
73
+ Running the dev server behind a cloud preview proxy (sandboxes, Codespaces, Gitpod, etc.) has three
74
+ non-obvious requirements.
75
+
76
+ ### 1. Allow the proxy's host (Vite host check)
77
+
78
+ The dev server runs Vite in middleware mode, and Vite's host check 403s any request whose `Host` header
79
+ isn't `localhost` ("Blocked request. This host is not allowed."). Allow the external host via `.jay`:
80
+
81
+ ```yaml
82
+ # .jay
83
+ devServer:
84
+ allowedHosts:
85
+ - .mysandbox.dev # Vite host-suffix syntax — matches any subdomain
86
+ # or, to disable the check entirely (dev only):
87
+ # allowedHosts: true
88
+ ```
89
+
90
+ Platforms that already set Vite's `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` env var (comma-separated
91
+ hosts, or `true`) need **no** `.jay` change — the dev server reads and merges it. Do **not** add a
92
+ `src/pages/vite.config.ts` to work around this; use the config above (DL#220).
93
+
94
+ > HMR over a proxy may additionally need Vite's `server.hmr` client settings — not required for serving
95
+ > pages, only for live reload through the proxy.
96
+
97
+ ### 2. Binding and port
98
+
99
+ `jay-stack-cli dev` takes **no** `--port` / `--host` flags. The Express server binds all interfaces, so
100
+ the container is reachable as-is; set the port in `.jay` (`devServer.portRange`, e.g. `[3000, 3000]` to
101
+ pin it).
102
+
103
+ ### 3. Credentials are read from files, not env vars
104
+
105
+ Plugins read credentials from files written by `setup`, not from `process.env`. Wix, for example, uses
106
+ `config/.wix.yaml` (backend services) and `wix.config.json` (deploy target) — both gitignored. A
107
+ container that only has secrets as env vars must **materialize them into those files before** starting
108
+ the dev server (e.g. a startup script that writes `config/.wix.yaml` from `WIX_*` env vars). Putting
109
+ `WIX_*` under a compose `environment:` block does **not** configure the plugins.
110
+
111
+ ### 4. AIditor (visual editor) in a container
112
+
113
+ The `/aiditor` route runs an agent **server-side** via the Claude Agent SDK, so the environment running
114
+ the dev server — not the user's laptop — must have Claude Code available:
115
+
116
+ - **Install the `claude` CLI in the image.** It is not part of the Node base image.
117
+ - **Provide `ANTHROPIC_API_KEY` as a secret/env var.** `claude login` is interactive and cannot complete
118
+ headless, so in a container the API key is the only viable auth. (Locally, `claude login` also works.)
119
+ - **It's dev-only.** The `/aiditor` route is served by the dev server; it is excluded from production
120
+ deploy (`--exclude-plugins aiditor`). If you don't need visual editing in a given environment, you can
121
+ ignore it — the rest of the site scaffolds, builds, runs, and deploys without it; only the `/aiditor`
122
+ route's agent stays inert when the CLI/key are absent.
123
+
124
+ A cloud platform that boots the dev server but neither installs the CLI nor injects the key will serve a
125
+ working site with a non-functional `/aiditor` — the single most common surprise. Install both, or
126
+ document that visual editing is unavailable there.
127
+
128
+ ### Health / shutdown (containers)
129
+
130
+ Run with `--test-mode` to expose `GET /_jay/health` (readiness probe) and `POST /_jay/shutdown` (graceful
131
+ stop) — the sanctioned hooks for container healthchecks and lifecycle, instead of signal-guessing.
132
+
67
133
  ## Guides
68
134
 
69
135
  | File | Topic |
@@ -486,6 +486,10 @@ async function loadProductionPageParts(route, pageModule, jayHtmlContent, projec
486
486
  const ci = headlessImport.contract ? { contractName: headlessImport.contract.name, metadata: headlessImport.metadata } : void 0;
487
487
  parts.push({
488
488
  key: headlessImport.key,
489
+ // DL#221 post-merge fix: the component's module is its global identity — keys the
490
+ // build-time loadParams cache so two routes reusing the same ref `key` for different
491
+ // components don't collide (the ref `key` is page-local).
492
+ modulePath,
489
493
  compDefinition: headlessCompDef,
490
494
  clientImport: "",
491
495
  clientPart: "",
@@ -823,6 +827,11 @@ async function parseViteManifest(outputDir, packages) {
823
827
  await fs.rm(viteManifestPath, { force: true });
824
828
  return manifest;
825
829
  }
830
+ function loadParamsCacheKey(rawRoute, part) {
831
+ const propsKey = JSON.stringify(part.headlessProps ?? {});
832
+ if (part.key) return `headless:${part.modulePath ?? part.key}:${propsKey}`;
833
+ return `page:${rawRoute}:${propsKey}`;
834
+ }
826
835
  function crossProductParams(parts) {
827
836
  if (parts.length === 0) return [];
828
837
  if (parts.length === 1) return parts[0].values;
@@ -1487,8 +1496,7 @@ async function buildVersion(options) {
1487
1496
  if (partsWithLoadParams.length === 0) continue;
1488
1497
  const paramParts = [];
1489
1498
  for (const part of partsWithLoadParams) {
1490
- const propsKey = JSON.stringify(part.headlessProps ?? {});
1491
- const cacheKey = `${part.key ?? ""}:${propsKey}`;
1499
+ const cacheKey = loadParamsCacheKey(route.rawRoute, part);
1492
1500
  if (!loadParamsCache.has(cacheKey)) {
1493
1501
  logger.important(`[Build] Loading params for ${route.rawRoute}...`);
1494
1502
  const partParams = [];
@@ -1796,6 +1804,7 @@ export {
1796
1804
  discoverActions,
1797
1805
  discoverServerEntries,
1798
1806
  generateRouteHydrationEntry,
1807
+ loadParamsCacheKey,
1799
1808
  loadProductionPageParts,
1800
1809
  materializeRouteParams,
1801
1810
  scanPluginRoutes,
package/dist/index.d.ts CHANGED
@@ -25,6 +25,20 @@ interface JayConfig {
25
25
  componentsBase?: string;
26
26
  publicFolder?: string;
27
27
  configBase?: string;
28
+ /**
29
+ * Hosts the dev server's Vite host-check accepts, beyond localhost. Use Vite's host-suffix
30
+ * syntax (`.example.dev` matches any subdomain), or `true` to disable the check entirely
31
+ * (dev only — e.g. cloud preview sandboxes). Merged with the
32
+ * `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` env var. Absent → Vite's localhost-only default.
33
+ * (DL#220)
34
+ */
35
+ allowedHosts?: string[] | true;
36
+ /**
37
+ * Inject source-editing dev markers (`jay-dev-src` / `jay-dev-item`) so the source-editing
38
+ * inspector can map a rendered pixel back to its jay-html source (DL#219). Off by default —
39
+ * the markers change rendered output, so enable only for AIditor / source-editing sessions.
40
+ */
41
+ sourceEditing?: boolean;
28
42
  };
29
43
  site?: {
30
44
  baseUrl?: string;
package/dist/index.js CHANGED
@@ -65,7 +65,11 @@ function getConfigWithDefaults(config) {
65
65
  pagesBase: config.devServer?.pagesBase || DEFAULT_CONFIG.devServer.pagesBase,
66
66
  componentsBase: config.devServer?.componentsBase || DEFAULT_CONFIG.devServer.componentsBase,
67
67
  publicFolder: config.devServer?.publicFolder || DEFAULT_CONFIG.devServer.publicFolder,
68
- configBase: config.devServer?.configBase || DEFAULT_CONFIG.devServer.configBase
68
+ configBase: config.devServer?.configBase || DEFAULT_CONFIG.devServer.configBase,
69
+ // No default — absent means Vite's localhost-only host check (DL#220).
70
+ allowedHosts: config.devServer?.allowedHosts,
71
+ // Default off — source-editing markers (DL#219) only for opt-in sessions.
72
+ sourceEditing: config.devServer?.sourceEditing
69
73
  },
70
74
  site: config.site
71
75
  };
@@ -220,7 +224,9 @@ async function startDevServer(options = {}) {
220
224
  publicBaseUrlPath: "/",
221
225
  jayRollupConfig: jayOptions,
222
226
  logLevel: options.logLevel,
223
- httpServer
227
+ httpServer,
228
+ allowedHosts: resolvedConfig.devServer.allowedHosts,
229
+ sourceEditing: resolvedConfig.devServer.sourceEditing
224
230
  });
225
231
  app.use(server);
226
232
  const publicPath = path$1.resolve(resolvedConfig.devServer.publicFolder);
@@ -7548,7 +7554,7 @@ async function runBuild(projectPath, options) {
7548
7554
  }
7549
7555
  const ctx = await resolveProductionContext(projectPath, options.version);
7550
7556
  await generateDefinitionFiles(ctx);
7551
- const { buildVersion } = await import("./index-B5oavmfA.js");
7557
+ const { buildVersion } = await import("./index-_Gyf630q.js");
7552
7558
  await buildVersion({
7553
7559
  version: ctx.version,
7554
7560
  projectRoot: ctx.resolvedPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/jay-stack-cli",
3
- "version": "0.25.4",
3
+ "version": "0.25.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -25,18 +25,18 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@inquirer/prompts": "^8.5.2",
28
- "@jay-framework/compiler-inline-composition": "^0.25.4",
29
- "@jay-framework/compiler-jay-html": "^0.25.4",
30
- "@jay-framework/compiler-shared": "^0.25.4",
31
- "@jay-framework/dev-server": "^0.25.4",
32
- "@jay-framework/fullstack-component": "^0.25.4",
33
- "@jay-framework/logger": "^0.25.4",
34
- "@jay-framework/plugin-validator": "^0.25.4",
35
- "@jay-framework/production-build": "^0.25.4",
36
- "@jay-framework/production-server": "^0.25.4",
37
- "@jay-framework/stack-route-scanner": "^0.25.4",
38
- "@jay-framework/stack-server-build": "^0.25.4",
39
- "@jay-framework/stack-server-runtime": "^0.25.4",
28
+ "@jay-framework/compiler-inline-composition": "^0.25.5",
29
+ "@jay-framework/compiler-jay-html": "^0.25.5",
30
+ "@jay-framework/compiler-shared": "^0.25.5",
31
+ "@jay-framework/dev-server": "^0.25.5",
32
+ "@jay-framework/fullstack-component": "^0.25.5",
33
+ "@jay-framework/logger": "^0.25.5",
34
+ "@jay-framework/plugin-validator": "^0.25.5",
35
+ "@jay-framework/production-build": "^0.25.5",
36
+ "@jay-framework/production-server": "^0.25.5",
37
+ "@jay-framework/stack-route-scanner": "^0.25.5",
38
+ "@jay-framework/stack-server-build": "^0.25.5",
39
+ "@jay-framework/stack-server-runtime": "^0.25.5",
40
40
  "chalk": "^4.1.2",
41
41
  "commander": "^14.0.0",
42
42
  "express": "^5.0.1",
@@ -47,7 +47,7 @@
47
47
  "yaml": "^2.3.4"
48
48
  },
49
49
  "devDependencies": {
50
- "@jay-framework/dev-environment": "^0.25.4",
50
+ "@jay-framework/dev-environment": "^0.25.5",
51
51
  "@types/express": "^5.0.2",
52
52
  "@types/node": "^22.15.21",
53
53
  "nodemon": "^3.0.3",