@jay-framework/stack-server-runtime 0.16.0 → 0.16.2

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/dist/index.d.ts CHANGED
@@ -205,6 +205,8 @@ interface RegisteredActionBase {
205
205
  /** Optional metadata from .jay-action file (description, input/output schemas).
206
206
  * Actions with metadata are exposed to AI agents; those without are not. */
207
207
  metadata?: ActionMetadata;
208
+ /** Whether this action accepts file uploads (DL#131) */
209
+ acceptsFiles?: boolean;
208
210
  }
209
211
  /**
210
212
  * Registered request-response action entry.
@@ -895,17 +897,17 @@ declare class SlowRenderCache {
895
897
  * Get a cached pre-rendered jay-html entry by reading from disk.
896
898
  * Returns undefined if the cache file doesn't exist or has no metadata tag.
897
899
  */
898
- get(jayHtmlPath: string, params: Record<string, string>): Promise<SlowRenderCacheEntry | undefined>;
900
+ get(jayHtmlPath: string, params: Record<string, string>, routeDir?: string): Promise<SlowRenderCacheEntry | undefined>;
899
901
  /**
900
902
  * Store a pre-rendered jay-html entry.
901
903
  * Embeds metadata as a <script> tag and writes to disk.
902
904
  * Returns the full cache entry with stripped content.
903
905
  */
904
- set(jayHtmlPath: string, params: Record<string, string>, preRenderedJayHtml: string, slowViewState: object, carryForward: object): Promise<SlowRenderCacheEntry>;
906
+ set(jayHtmlPath: string, params: Record<string, string>, preRenderedJayHtml: string, slowViewState: object, carryForward: object, routeDir?: string): Promise<SlowRenderCacheEntry>;
905
907
  /**
906
908
  * Check if a pre-rendered entry exists for the given path and params
907
909
  */
908
- has(jayHtmlPath: string, params: Record<string, string>): Promise<boolean>;
910
+ has(jayHtmlPath: string, params: Record<string, string>, routeDir?: string): Promise<boolean>;
909
911
  /**
910
912
  * Invalidate all cached entries for a given jay-html source path.
911
913
  * Deletes cached files from disk.
package/dist/index.js CHANGED
@@ -204,6 +204,7 @@ new JayAtomicType("string");
204
204
  new JayAtomicType("number");
205
205
  new JayAtomicType("boolean");
206
206
  new JayAtomicType("Date");
207
+ new JayAtomicType("file");
207
208
  new JayAtomicType("Unknown");
208
209
  class JayObjectType {
209
210
  constructor(name, props) {
@@ -247,6 +248,9 @@ function jayTypeToJsonSchema(type) {
247
248
  if (name === "string" || name === "number" || name === "boolean") {
248
249
  return { type: name };
249
250
  }
251
+ if (name === "file") {
252
+ return { type: "string", description: "Binary file upload (JayFile)" };
253
+ }
250
254
  return { type: "string" };
251
255
  }
252
256
  if (isEnumType(type)) {
@@ -649,6 +653,17 @@ function buildFreezeScript(routePattern) {
649
653
  __jayDoFreeze();
650
654
  }
651
655
  });
656
+ }
657
+
658
+ // Targeted page reload: only reload if this page matches the changed route prefix
659
+ if (import.meta.hot) {
660
+ import.meta.hot.on('jay:page-reload', (data) => {
661
+ const prefix = data.routePrefix;
662
+ const pathname = window.location.pathname;
663
+ if (pathname === prefix || pathname.startsWith(prefix + '/')) {
664
+ window.location.reload();
665
+ }
666
+ });
652
667
  }`;
653
668
  }
654
669
  function buildAutomationWrap(options, mode) {
@@ -1114,11 +1129,12 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
1114
1129
  const exists = await fs$2.access(route.compPath, fs$2.constants.F_OK).then(() => true).catch(() => false);
1115
1130
  const parts = [];
1116
1131
  if (exists) {
1117
- const pageComponent = (await vite.ssrLoadModule(route.compPath)).page;
1132
+ const exportName = route.componentExport || "page";
1133
+ const pageComponent = (await vite.ssrLoadModule(route.compPath))[exportName];
1118
1134
  parts.push({
1119
1135
  compDefinition: pageComponent,
1120
- clientImport: `import {page} from '${route.compPath}'`,
1121
- clientPart: `{comp: page.comp, contextMarkers: page.contexts || []}`
1136
+ clientImport: `import {${exportName}} from '${route.compPath}'`,
1137
+ clientPart: `{comp: ${exportName}.comp, contextMarkers: ${exportName}.contexts || []}`
1122
1138
  });
1123
1139
  }
1124
1140
  const jayHtmlFilePath = options?.preRenderedPath ?? route.jayHtmlPath;
@@ -1295,7 +1311,8 @@ class ActionRegistry {
1295
1311
  method: action.method,
1296
1312
  cacheOptions: action.cacheOptions,
1297
1313
  services: action.services,
1298
- handler: action.handler
1314
+ handler: action.handler,
1315
+ ...action.acceptsFiles && { acceptsFiles: true }
1299
1316
  };
1300
1317
  this.actions.set(action.actionName, entry);
1301
1318
  }
@@ -1452,7 +1469,8 @@ class ActionRegistry {
1452
1469
  method: "POST",
1453
1470
  isStreaming: true,
1454
1471
  services: action.services,
1455
- handler: action.handler
1472
+ handler: action.handler,
1473
+ ...action.acceptsFiles && { acceptsFiles: true }
1456
1474
  };
1457
1475
  this.actions.set(action.actionName, entry);
1458
1476
  }
@@ -2192,8 +2210,8 @@ class SlowRenderCache {
2192
2210
  * Get a cached pre-rendered jay-html entry by reading from disk.
2193
2211
  * Returns undefined if the cache file doesn't exist or has no metadata tag.
2194
2212
  */
2195
- async get(jayHtmlPath, params) {
2196
- const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
2213
+ async get(jayHtmlPath, params, routeDir) {
2214
+ const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
2197
2215
  let fileContent;
2198
2216
  try {
2199
2217
  fileContent = await fs$2.readFile(preRenderedPath, "utf-8");
@@ -2217,8 +2235,8 @@ class SlowRenderCache {
2217
2235
  * Embeds metadata as a <script> tag and writes to disk.
2218
2236
  * Returns the full cache entry with stripped content.
2219
2237
  */
2220
- async set(jayHtmlPath, params, preRenderedJayHtml, slowViewState, carryForward) {
2221
- const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
2238
+ async set(jayHtmlPath, params, preRenderedJayHtml, slowViewState, carryForward, routeDir) {
2239
+ const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
2222
2240
  const fileContent = embedCacheMetadata(
2223
2241
  preRenderedJayHtml,
2224
2242
  slowViewState,
@@ -2239,8 +2257,8 @@ class SlowRenderCache {
2239
2257
  /**
2240
2258
  * Check if a pre-rendered entry exists for the given path and params
2241
2259
  */
2242
- async has(jayHtmlPath, params) {
2243
- const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
2260
+ async has(jayHtmlPath, params, routeDir) {
2261
+ const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
2244
2262
  try {
2245
2263
  await fs$2.access(preRenderedPath);
2246
2264
  return true;
@@ -2314,10 +2332,18 @@ class SlowRenderCache {
2314
2332
  /**
2315
2333
  * Compute the cache file path for a given jay-html path and params.
2316
2334
  */
2317
- computeCachePath(jayHtmlPath, params) {
2318
- const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
2319
- const dir = path__default.dirname(relativePath);
2320
- const basename = path__default.basename(relativePath, ".jay-html");
2335
+ computeCachePath(jayHtmlPath, params, routeDir) {
2336
+ let dir;
2337
+ if (routeDir) {
2338
+ dir = routeDir;
2339
+ } else {
2340
+ const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
2341
+ dir = relativePath.startsWith("..") ? path__default.join(
2342
+ "_plugins",
2343
+ crypto.createHash("md5").update(jayHtmlPath).digest("hex").slice(0, 12)
2344
+ ) : path__default.dirname(relativePath);
2345
+ }
2346
+ const basename = path__default.basename(jayHtmlPath, ".jay-html");
2321
2347
  const paramsHash = hashParams(params);
2322
2348
  const cacheFileName = `${basename}${paramsHash}.jay-html`;
2323
2349
  return path__default.join(this.cacheDir, dir, cacheFileName);
@@ -2337,8 +2363,11 @@ class SlowRenderCache {
2337
2363
  */
2338
2364
  async scanAndDeleteCacheFiles(jayHtmlPath) {
2339
2365
  const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
2340
- const dir = path__default.dirname(relativePath);
2341
- const basename = path__default.basename(relativePath, ".jay-html");
2366
+ const dir = relativePath.startsWith("..") ? path__default.join(
2367
+ "_plugins",
2368
+ crypto.createHash("md5").update(jayHtmlPath).digest("hex").slice(0, 12)
2369
+ ) : path__default.dirname(relativePath);
2370
+ const basename = path__default.basename(jayHtmlPath, ".jay-html");
2342
2371
  const cacheSubDir = path__default.join(this.cacheDir, dir);
2343
2372
  try {
2344
2373
  const files = await fs$2.readdir(cacheSubDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/stack-server-runtime",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.mts",
@@ -26,21 +26,21 @@
26
26
  "test:watch": "vitest"
27
27
  },
28
28
  "dependencies": {
29
- "@jay-framework/compiler-jay-html": "^0.16.0",
30
- "@jay-framework/compiler-shared": "^0.16.0",
31
- "@jay-framework/component": "^0.16.0",
32
- "@jay-framework/fullstack-component": "^0.16.0",
33
- "@jay-framework/logger": "^0.16.0",
34
- "@jay-framework/runtime": "^0.16.0",
35
- "@jay-framework/ssr-runtime": "^0.16.0",
36
- "@jay-framework/stack-route-scanner": "^0.16.0",
37
- "@jay-framework/view-state-merge": "^0.16.0",
29
+ "@jay-framework/compiler-jay-html": "^0.16.2",
30
+ "@jay-framework/compiler-shared": "^0.16.2",
31
+ "@jay-framework/component": "^0.16.2",
32
+ "@jay-framework/fullstack-component": "^0.16.2",
33
+ "@jay-framework/logger": "^0.16.2",
34
+ "@jay-framework/runtime": "^0.16.2",
35
+ "@jay-framework/ssr-runtime": "^0.16.2",
36
+ "@jay-framework/stack-route-scanner": "^0.16.2",
37
+ "@jay-framework/view-state-merge": "^0.16.2",
38
38
  "yaml": "^2.3.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@jay-framework/dev-environment": "^0.16.0",
42
- "@jay-framework/jay-cli": "^0.16.0",
43
- "@jay-framework/stack-client-runtime": "^0.16.0",
41
+ "@jay-framework/dev-environment": "^0.16.2",
42
+ "@jay-framework/jay-cli": "^0.16.2",
43
+ "@jay-framework/stack-client-runtime": "^0.16.2",
44
44
  "@types/express": "^5.0.2",
45
45
  "@types/node": "^22.15.21",
46
46
  "nodemon": "^3.0.3",