@jay-framework/stack-server-runtime 0.15.3 → 0.15.4

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
@@ -539,6 +539,15 @@ interface PluginClientInitInfo {
539
539
  */
540
540
  declare function preparePluginClientInits(plugins: PluginWithInit[]): PluginClientInitInfo[];
541
541
 
542
+ /**
543
+ * Generate JS code to reconstruct Promise.resolve()/Promise.reject() for async ViewState properties.
544
+ * JSON.stringify drops Promise objects, so this emits assignments that recreate them from tracked outcomes.
545
+ */
546
+ declare function generatePromiseReconstruction(outcomes: Array<{
547
+ id: string;
548
+ status: 'resolved' | 'rejected';
549
+ value: any;
550
+ }>): string;
542
551
  /**
543
552
  * Information needed to generate client init script for the project.
544
553
  */
@@ -583,7 +592,21 @@ declare function buildScriptFragments(parts: DevServerPagePart[], clientInitData
583
592
  * @param mode - 'client' appends to DOM; 'hydrate' skips appendChild (DOM already present)
584
593
  */
585
594
  declare function buildAutomationWrap(options: GenerateClientScriptOptions, mode: 'client' | 'hydrate'): string;
586
- declare function generateClientScript(defaultViewState: object, fastCarryForward: object, parts: DevServerPagePart[], jayHtmlPath: string, trackByMap?: TrackByMap, clientInitData?: Record<string, Record<string, any>>, projectInit?: ProjectClientInitInfo, pluginInits?: PluginClientInitInfo[], options?: GenerateClientScriptOptions): string;
595
+ /**
596
+ * Resolve all top-level Promise values in a ViewState object.
597
+ * Returns the ViewState with Promises replaced by their resolved values,
598
+ * plus a list of outcomes for reconstructing Promise.resolve()/Promise.reject()
599
+ * in the client script.
600
+ */
601
+ declare function resolveViewStatePromises(viewState: object): Promise<{
602
+ resolved: object;
603
+ outcomes: Array<{
604
+ id: string;
605
+ status: 'resolved' | 'rejected';
606
+ value: any;
607
+ }>;
608
+ }>;
609
+ declare function generateClientScript(defaultViewState: object, fastCarryForward: object, parts: DevServerPagePart[], jayHtmlPath: string, trackByMap?: TrackByMap, clientInitData?: Record<string, Record<string, any>>, projectInit?: ProjectClientInitInfo, pluginInits?: PluginClientInitInfo[], options?: GenerateClientScriptOptions): Promise<string>;
587
610
 
588
611
  /**
589
612
  * Invalidate the cached server element module for a jay-html file.
@@ -1127,4 +1150,4 @@ declare function executePluginReferences(plugin: PluginWithReferences, options:
1127
1150
  verbose?: boolean;
1128
1151
  }): Promise<PluginReferencesResult>;
1129
1152
 
1130
- export { type ActionDiscoveryOptions, type ActionDiscoveryResult, type ActionErrorResponse, type ActionExecutionResult, type ActionIndexEntry, type ActionMetadata, ActionRegistry, type ActionSchema, type DevServerPagePart, DevSlowlyChangingPhase, type GenerateClientScriptOptions, type HeadlessInstanceComponent, type InstancePhaseData, type InstanceSlowRenderResult, type LoadedPageParts, type MaterializeContractsOptions, type MaterializeResult, type PluginActionDiscoveryOptions, type PluginClientInitInfo, type PluginContractEntry, type PluginInitDiscoveryOptions, type PluginReferencesContext, type PluginReferencesHandler, type PluginReferencesResult, type PluginScanOptions, type PluginSetupContext, type PluginSetupHandler, type PluginSetupResult, type PluginWithInit, type PluginWithReferences, type PluginWithSetup, type PluginsIndex, type PluginsIndexEntry, type ProjectClientInitInfo, type RegisteredAction, type ScannedPlugin, type ScriptFragments, SlowRenderCache, type SlowRenderCacheEntry, type SlowlyChangingPhase, type ViteSSRLoader, actionRegistry, buildAutomationWrap, buildScriptFragments, clearActionRegistry, clearClientInitData, clearLifecycleCallbacks, clearServerElementCache, clearServiceRegistry, discoverAllPluginActions, discoverAndRegisterActions, discoverPluginActions, discoverPluginsWithInit, discoverPluginsWithReferences, discoverPluginsWithSetup, executeAction, executePluginReferences, executePluginServerInits, executePluginSetup, generateClientScript, generateSSRPageHtml, getActionCacheHeaders, getClientInitData, getClientInitDataForKey, getRegisteredAction, getRegisteredActionNames, getService, getServiceRegistry, hasAction, hasService, invalidateServerElementCache, listContracts, loadActionMetadata, loadPageParts, materializeContracts, onInit, onShutdown, parseActionMetadata, preparePluginClientInits, registerAction, registerService, renderFastChangingData, resolveActionMetadataPath, resolveServices, runInitCallbacks, runLoadParams, runShutdownCallbacks, runSlowlyChangingRender, scanPlugins, setClientInitData, slowRenderInstances, sortPluginsByDependencies, validateForEachInstances };
1153
+ export { type ActionDiscoveryOptions, type ActionDiscoveryResult, type ActionErrorResponse, type ActionExecutionResult, type ActionIndexEntry, type ActionMetadata, ActionRegistry, type ActionSchema, type DevServerPagePart, DevSlowlyChangingPhase, type GenerateClientScriptOptions, type HeadlessInstanceComponent, type InstancePhaseData, type InstanceSlowRenderResult, type LoadedPageParts, type MaterializeContractsOptions, type MaterializeResult, type PluginActionDiscoveryOptions, type PluginClientInitInfo, type PluginContractEntry, type PluginInitDiscoveryOptions, type PluginReferencesContext, type PluginReferencesHandler, type PluginReferencesResult, type PluginScanOptions, type PluginSetupContext, type PluginSetupHandler, type PluginSetupResult, type PluginWithInit, type PluginWithReferences, type PluginWithSetup, type PluginsIndex, type PluginsIndexEntry, type ProjectClientInitInfo, type RegisteredAction, type ScannedPlugin, type ScriptFragments, SlowRenderCache, type SlowRenderCacheEntry, type SlowlyChangingPhase, type ViteSSRLoader, actionRegistry, buildAutomationWrap, buildScriptFragments, clearActionRegistry, clearClientInitData, clearLifecycleCallbacks, clearServerElementCache, clearServiceRegistry, discoverAllPluginActions, discoverAndRegisterActions, discoverPluginActions, discoverPluginsWithInit, discoverPluginsWithReferences, discoverPluginsWithSetup, executeAction, executePluginReferences, executePluginServerInits, executePluginSetup, generateClientScript, generatePromiseReconstruction, generateSSRPageHtml, getActionCacheHeaders, getClientInitData, getClientInitDataForKey, getRegisteredAction, getRegisteredActionNames, getService, getServiceRegistry, hasAction, hasService, invalidateServerElementCache, listContracts, loadActionMetadata, loadPageParts, materializeContracts, onInit, onShutdown, parseActionMetadata, preparePluginClientInits, registerAction, registerService, renderFastChangingData, resolveActionMetadataPath, resolveServices, resolveViewStatePromises, runInitCallbacks, runLoadParams, runShutdownCallbacks, runSlowlyChangingRender, scanPlugins, setClientInitData, slowRenderInstances, sortPluginsByDependencies, validateForEachInstances };
package/dist/index.js CHANGED
@@ -483,6 +483,18 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
483
483
  }
484
484
  return Promise.resolve(phaseOutput(fastViewState, fastCarryForward));
485
485
  }
486
+ function generatePromiseReconstruction(outcomes) {
487
+ if (outcomes.length === 0)
488
+ return "";
489
+ return outcomes.map((outcome) => {
490
+ if (outcome.status === "resolved") {
491
+ return ` viewState[${JSON.stringify(outcome.id)}] = Promise.resolve(${JSON.stringify(outcome.value)});`;
492
+ } else {
493
+ const errMsg = outcome.value?.message ?? "Unknown error";
494
+ return ` viewState[${JSON.stringify(outcome.id)}] = Promise.reject(new Error(${JSON.stringify(errMsg)}));`;
495
+ }
496
+ }).join("\n") + "\n";
497
+ }
486
498
  function buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options) {
487
499
  const { enableAutomation = true, slowViewState } = options;
488
500
  const hasSlowViewState = slowViewState && Object.keys(slowViewState).length > 0;
@@ -558,7 +570,34 @@ function buildAutomationWrap(options, mode) {
558
570
  window.__jay.automation = wrapped.automation;
559
571
  window.dispatchEvent(new Event('jay:automation-ready'));${appendLine}`;
560
572
  }
561
- function generateClientScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
573
+ async function resolveViewStatePromises(viewState) {
574
+ const entries = Object.entries(viewState);
575
+ const hasPromises = entries.some(([, v]) => v instanceof Promise);
576
+ if (!hasPromises)
577
+ return { resolved: viewState, outcomes: [] };
578
+ const result = { ...viewState };
579
+ const outcomes = [];
580
+ for (const [key, value] of entries) {
581
+ if (value instanceof Promise) {
582
+ try {
583
+ const val = await value;
584
+ result[key] = val;
585
+ outcomes.push({ id: key, status: "resolved", value: val });
586
+ } catch (err) {
587
+ delete result[key];
588
+ outcomes.push({
589
+ id: key,
590
+ status: "rejected",
591
+ value: { message: err?.message ?? String(err) }
592
+ });
593
+ }
594
+ }
595
+ }
596
+ return { resolved: result, outcomes };
597
+ }
598
+ async function generateClientScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
599
+ const { resolved, outcomes } = await resolveViewStatePromises(defaultViewState);
600
+ defaultViewState = resolved;
562
601
  const {
563
602
  partImports,
564
603
  compositeParts,
@@ -586,7 +625,7 @@ function generateClientScript(defaultViewState, fastCarryForward, parts, jayHtml
586
625
  import { render } from '${jayHtmlPath}';
587
626
  ${partImports}${slowViewStateDecl}
588
627
  const viewState = ${JSON.stringify(defaultViewState)};
589
- const fastCarryForward = ${JSON.stringify(fastCarryForward)};
628
+ ${generatePromiseReconstruction(outcomes)} const fastCarryForward = ${JSON.stringify(fastCarryForward)};
590
629
  const trackByMap = ${JSON.stringify(trackByMap)};
591
630
  ${clientInitExecution}
592
631
  const target = document.getElementById('target');
@@ -598,6 +637,10 @@ ${automationWrap}
598
637
  </body>
599
638
  </html>`;
600
639
  }
640
+ function asyncSwapScript(id, html) {
641
+ const escapedHtml = html.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
642
+ return `<script>(function(){var t=document.querySelector('[jay-async="${id}:pending"]');if(t){var d=document.createElement('div');d.innerHTML='${escapedHtml}';t.replaceWith(d.firstChild);}window.__jay&&window.__jay.hydrateAsync&&window.__jay.hydrateAsync('${id}');})()<\/script>`;
643
+ }
601
644
  const serverModuleCache = /* @__PURE__ */ new Map();
602
645
  function invalidateServerElementCache(jayHtmlPath) {
603
646
  if (serverModuleCache.delete(jayHtmlPath)) {
@@ -625,6 +668,7 @@ async function generateSSRPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtm
625
668
  }
626
669
  const htmlChunks = [];
627
670
  const asyncPromises = [];
671
+ const asyncOutcomes = [];
628
672
  const ctx = {
629
673
  write: (chunk) => {
630
674
  htmlChunks.push(chunk);
@@ -632,14 +676,20 @@ async function generateSSRPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtm
632
676
  onAsync: (promise, id, templates) => {
633
677
  const asyncPromise = promise.then(
634
678
  (val) => {
679
+ asyncOutcomes.push({ id, status: "resolved", value: val });
635
680
  if (templates.resolved) {
636
- return templates.resolved(val);
681
+ return asyncSwapScript(id, templates.resolved(val));
637
682
  }
638
683
  return "";
639
684
  },
640
685
  (err) => {
686
+ asyncOutcomes.push({
687
+ id,
688
+ status: "rejected",
689
+ value: { message: err?.message ?? String(err) }
690
+ });
641
691
  if (templates.rejected) {
642
- return templates.rejected(err);
692
+ return asyncSwapScript(id, templates.rejected(err));
643
693
  }
644
694
  return "";
645
695
  }
@@ -660,7 +710,8 @@ async function generateSSRPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtm
660
710
  clientInitData2,
661
711
  projectInit,
662
712
  pluginInits,
663
- options
713
+ options,
714
+ asyncOutcomes
664
715
  );
665
716
  const headLinksHtml = cached.headLinks.map((link) => {
666
717
  const attrs = Object.entries(link.attributes).map(([k, v]) => ` ${k}="${v}"`).join("");
@@ -733,7 +784,7 @@ async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename
733
784
  css: parsedJayFile.css
734
785
  };
735
786
  }
736
- function generateHydrationScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
787
+ function generateHydrationScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}, asyncOutcomes = []) {
737
788
  const {
738
789
  partImports,
739
790
  compositeParts,
@@ -753,7 +804,7 @@ function generateHydrationScript(defaultViewState, fastCarryForward, parts, jayH
753
804
  import { hydrate } from '${hydrateImportPath}';
754
805
  ${partImports}${slowViewStateDecl}
755
806
  const viewState = ${JSON.stringify(defaultViewState)};
756
- const fastCarryForward = ${JSON.stringify(fastCarryForward)};
807
+ ${generatePromiseReconstruction(asyncOutcomes)} const fastCarryForward = ${JSON.stringify(fastCarryForward)};
757
808
  const trackByMap = ${JSON.stringify(trackByMap)};
758
809
 
759
810
  const target = document.getElementById('target');
@@ -2402,6 +2453,7 @@ export {
2402
2453
  executePluginServerInits,
2403
2454
  executePluginSetup,
2404
2455
  generateClientScript,
2456
+ generatePromiseReconstruction,
2405
2457
  generateSSRPageHtml,
2406
2458
  getActionCacheHeaders,
2407
2459
  getClientInitData,
@@ -2426,6 +2478,7 @@ export {
2426
2478
  renderFastChangingData,
2427
2479
  resolveActionMetadataPath,
2428
2480
  resolveServices,
2481
+ resolveViewStatePromises,
2429
2482
  runInitCallbacks,
2430
2483
  runLoadParams,
2431
2484
  runShutdownCallbacks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/stack-server-runtime",
3
- "version": "0.15.3",
3
+ "version": "0.15.4",
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.15.3",
30
- "@jay-framework/compiler-shared": "^0.15.3",
31
- "@jay-framework/component": "^0.15.3",
32
- "@jay-framework/fullstack-component": "^0.15.3",
33
- "@jay-framework/logger": "^0.15.3",
34
- "@jay-framework/runtime": "^0.15.3",
35
- "@jay-framework/ssr-runtime": "^0.15.3",
36
- "@jay-framework/stack-route-scanner": "^0.15.3",
37
- "@jay-framework/view-state-merge": "^0.15.3",
29
+ "@jay-framework/compiler-jay-html": "^0.15.4",
30
+ "@jay-framework/compiler-shared": "^0.15.4",
31
+ "@jay-framework/component": "^0.15.4",
32
+ "@jay-framework/fullstack-component": "^0.15.4",
33
+ "@jay-framework/logger": "^0.15.4",
34
+ "@jay-framework/runtime": "^0.15.4",
35
+ "@jay-framework/ssr-runtime": "^0.15.4",
36
+ "@jay-framework/stack-route-scanner": "^0.15.4",
37
+ "@jay-framework/view-state-merge": "^0.15.4",
38
38
  "yaml": "^2.3.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@jay-framework/dev-environment": "^0.15.3",
42
- "@jay-framework/jay-cli": "^0.15.3",
43
- "@jay-framework/stack-client-runtime": "^0.15.3",
41
+ "@jay-framework/dev-environment": "^0.15.4",
42
+ "@jay-framework/jay-cli": "^0.15.4",
43
+ "@jay-framework/stack-client-runtime": "^0.15.4",
44
44
  "@types/express": "^5.0.2",
45
45
  "@types/node": "^22.15.21",
46
46
  "nodemon": "^3.0.3",