@jay-framework/production-server 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.
@@ -6,236 +6,8 @@ import path from "node:path";
6
6
  import { renderFastChangingData, headMetaToHeadTags, mergeHeadTags, serializeHeadTags, getClientInitData, actionRegistry, setClientInitData } from "@jay-framework/stack-server-runtime";
7
7
  import { deepMergeViewStates } from "@jay-framework/view-state-merge";
8
8
  import { asyncSwapScript } from "@jay-framework/ssr-runtime";
9
- import { createRequire } from "node:module";
10
- import { getLogger } from "@jay-framework/logger";
11
- import { parseJayFile, JAY_IMPORT_RESOLVER, injectHeadfullFSTemplates, assignCoordinatesToJayHtml, discoverHeadlessInstances } from "@jay-framework/compiler-jay-html";
12
- import { checkValidationErrors } from "@jay-framework/compiler-shared";
13
9
  import { isJayAction, isJayStreamAction } from "@jay-framework/fullstack-component";
14
- const require$1 = createRequire(import.meta.url);
15
- async function loadProductionPageParts(route, pageModule, jayHtmlContent, projectRoot, tsConfigFilePath, serverBuildDir) {
16
- const exportName = route.componentExport || "page";
17
- const compDefinition = pageModule[exportName] ?? pageModule.default;
18
- const parts = compDefinition ? [{ compDefinition, clientImport: "", clientPart: "" }] : [];
19
- const dirName = path.dirname(route.jayHtmlPath);
20
- const fileName = path.basename(route.jayHtmlPath);
21
- const jayHtmlWithValidations = await parseJayFile(
22
- jayHtmlContent,
23
- fileName,
24
- dirName,
25
- { relativePath: tsConfigFilePath },
26
- JAY_IMPORT_RESOLVER,
27
- projectRoot
28
- );
29
- const jayHtml = checkValidationErrors(jayHtmlWithValidations);
30
- const headlessInstanceComponents = [];
31
- const keyedPartModules = [];
32
- const headlessModuleInfos = [];
33
- const headlessImports = jayHtml.headlessImports ?? [];
34
- getLogger().info(
35
- `[Build] headlessImports for ${fileName}: ${headlessImports.length}, keys: ${Object.keys(jayHtml).join(",")}`
36
- );
37
- for (const headlessImport of headlessImports) {
38
- const module = headlessImport.codeLink.module;
39
- const name = headlessImport.codeLink.names[0].name;
40
- const isLocalModule = module[0] === "." || module[0] === "/";
41
- let modulePath;
42
- if (isLocalModule) {
43
- const sourcePath = path.resolve(dirName, module);
44
- if (serverBuildDir) {
45
- const relativeToSrc = path.relative(path.join(projectRoot, "src"), sourcePath);
46
- let compiledPath = path.join(serverBuildDir, relativeToSrc);
47
- compiledPath = compiledPath.replace(/\.ts$/, ".js");
48
- if (!compiledPath.endsWith(".js")) {
49
- const indexPath = path.join(compiledPath, "index.js");
50
- try {
51
- await fs.access(indexPath);
52
- compiledPath = indexPath;
53
- } catch {
54
- compiledPath += ".js";
55
- }
56
- }
57
- modulePath = compiledPath;
58
- } else {
59
- modulePath = sourcePath;
60
- }
61
- } else {
62
- modulePath = module;
63
- }
64
- let headlessCompDef;
65
- if (headlessImport.structural) {
66
- continue;
67
- } else {
68
- const resolvedModulePath = isLocalModule ? modulePath : require$1.resolve(module, { paths: [dirName] });
69
- const headlessModule = await import(resolvedModulePath);
70
- headlessCompDef = headlessModule[name];
71
- }
72
- if (headlessImport.key) {
73
- const clientModulePath = isLocalModule ? path.resolve(dirName, module) : `${module}/client`;
74
- const ci = headlessImport.contract ? { contractName: headlessImport.contract.name, metadata: headlessImport.metadata } : void 0;
75
- parts.push({
76
- key: headlessImport.key,
77
- compDefinition: headlessCompDef,
78
- clientImport: "",
79
- clientPart: "",
80
- contractInfo: ci,
81
- headlessProps: headlessImport.headlessProps
82
- });
83
- const hasClientComp = !!headlessCompDef?.fastRender || !!headlessCompDef?.hasInteractive;
84
- if (!headlessImport.structural && hasClientComp) {
85
- keyedPartModules.push({
86
- key: headlessImport.key,
87
- modulePath: clientModulePath,
88
- exportName: name
89
- });
90
- }
91
- headlessModuleInfos.push({
92
- modulePath,
93
- exportName: name,
94
- isLocal: isLocalModule,
95
- key: headlessImport.key,
96
- contractInfo: ci,
97
- headlessProps: headlessImport.headlessProps,
98
- structural: headlessImport.structural
99
- });
100
- }
101
- if (!headlessImport.key && headlessImport.contract) {
102
- headlessInstanceComponents.push({
103
- contractName: headlessImport.contractName,
104
- compDefinition: headlessCompDef,
105
- contract: headlessImport.contract
106
- });
107
- headlessModuleInfos.push({
108
- modulePath,
109
- exportName: name,
110
- isLocal: isLocalModule,
111
- contractName: headlessImport.contractName,
112
- propNames: headlessImport.contract.props?.map((p) => p.name) ?? [],
113
- structural: headlessImport.structural
114
- });
115
- }
116
- }
117
- const headlessContracts = (jayHtml.headlessImports ?? []).filter((hi) => hi.contract && hi.key).map((hi) => ({
118
- key: hi.key,
119
- contract: hi.contract,
120
- contractPath: hi.contractPath
121
- }));
122
- const jayHtmlForDiscovery = injectHeadfullFSTemplates(
123
- jayHtmlContent,
124
- dirName,
125
- JAY_IMPORT_RESOLVER
126
- );
127
- let discoveredInstances = [];
128
- let forEachInstances = [];
129
- if (headlessInstanceComponents.length > 0) {
130
- const contractNames = new Set(headlessInstanceComponents.map((c) => c.contractName));
131
- const withCoords = assignCoordinatesToJayHtml(jayHtmlForDiscovery, contractNames);
132
- const discovery = discoverHeadlessInstances(withCoords);
133
- discoveredInstances = discovery.instances;
134
- forEachInstances = discovery.forEachInstances;
135
- }
136
- return {
137
- parts,
138
- headlessContracts,
139
- headlessInstanceComponents,
140
- discoveredInstances,
141
- forEachInstances,
142
- keyedPartModules,
143
- headlessModuleInfos,
144
- serverTrackByMap: jayHtml.serverTrackByMap,
145
- clientTrackByMap: jayHtml.clientTrackByMap
146
- };
147
- }
148
- function buildPagePartsConfig(pageParts, pageServerModule, pageExportName, buildDir, pageIsPlugin = false) {
149
- const parts = [];
150
- if (pageServerModule) {
151
- parts.push({
152
- modulePath: pageServerModule,
153
- exportName: pageExportName,
154
- source: pageIsPlugin ? "npm" : "local"
155
- });
156
- }
157
- for (const info of pageParts.headlessModuleInfos) {
158
- if (info.key) {
159
- parts.push({
160
- modulePath: info.isLocal ? path.relative(buildDir, info.modulePath) : info.modulePath,
161
- exportName: info.exportName,
162
- source: info.isLocal ? "local" : "npm",
163
- key: info.key,
164
- contractInfo: info.contractInfo,
165
- headlessProps: info.headlessProps
166
- });
167
- }
168
- }
169
- const instanceComponents = [];
170
- for (const info of pageParts.headlessModuleInfos) {
171
- if (info.contractName) {
172
- instanceComponents.push({
173
- modulePath: info.structural ? "" : info.isLocal ? path.relative(buildDir, info.modulePath) : info.modulePath,
174
- exportName: info.exportName,
175
- source: info.isLocal ? "local" : "npm",
176
- contractName: info.contractName,
177
- propNames: info.propNames ?? [],
178
- ...info.structural ? { structural: true } : {}
179
- });
180
- }
181
- }
182
- return {
183
- parts,
184
- instanceComponents,
185
- forEachInstances: pageParts.forEachInstances.map((fi) => ({
186
- contractName: fi.contractName,
187
- forEachPath: fi.forEachPath,
188
- trackBy: fi.trackBy,
189
- propBindings: fi.propBindings,
190
- coordinateSuffix: fi.coordinateSuffix
191
- }))
192
- };
193
- }
194
- async function loadPagePartsFromConfig(configPath, artifacts) {
195
- const config = await artifacts.readPagePartsConfig(configPath);
196
- async function importModule(entry) {
197
- if (!entry.modulePath) {
198
- throw new Error(
199
- `Empty modulePath in page-parts.json for "${entry.exportName}" (source: ${entry.source}). Rebuild required.`
200
- );
201
- }
202
- return artifacts.loadModule(entry.modulePath, entry.source === "local");
203
- }
204
- const parts = [];
205
- for (const entry of config.parts) {
206
- const mod = await importModule(entry);
207
- parts.push({
208
- compDefinition: mod[entry.exportName] ?? mod.default,
209
- key: entry.key,
210
- clientImport: "",
211
- clientPart: "",
212
- contractInfo: entry.contractInfo,
213
- headlessProps: entry.headlessProps
214
- });
215
- }
216
- const headlessInstanceComponents = [];
217
- for (const entry of config.instanceComponents) {
218
- const serveTimeContract = {
219
- props: entry.propNames.map((name) => ({ name }))
220
- };
221
- if (entry.structural) continue;
222
- const mod = await importModule(entry);
223
- headlessInstanceComponents.push({
224
- contractName: entry.contractName,
225
- compDefinition: mod[entry.exportName] ?? mod.default,
226
- contract: serveTimeContract
227
- });
228
- }
229
- return {
230
- parts,
231
- headlessContracts: [],
232
- headlessInstanceComponents,
233
- discoveredInstances: [],
234
- forEachInstances: config.forEachInstances,
235
- keyedPartModules: [],
236
- headlessModuleInfos: []
237
- };
238
- }
10
+ import { getLogger } from "@jay-framework/logger";
239
11
  class FilesystemArtifactStore {
240
12
  constructor(basePath) {
241
13
  __publicField(this, "manifestCache");
@@ -365,6 +137,51 @@ function buildImportMap(sharedManifest, publicBasePath, sharedDir = "shared") {
365
137
  }
366
138
  return imports;
367
139
  }
140
+ async function loadPagePartsFromConfig(configPath, artifacts) {
141
+ const config = await artifacts.readPagePartsConfig(configPath);
142
+ async function importModule(entry) {
143
+ if (!entry.modulePath) {
144
+ throw new Error(
145
+ `Empty modulePath in page-parts.json for "${entry.exportName}" (source: ${entry.source}). Rebuild required.`
146
+ );
147
+ }
148
+ return artifacts.loadModule(entry.modulePath, entry.source === "local");
149
+ }
150
+ const parts = [];
151
+ for (const entry of config.parts) {
152
+ const mod = await importModule(entry);
153
+ parts.push({
154
+ compDefinition: mod[entry.exportName] ?? mod.default,
155
+ key: entry.key,
156
+ clientImport: "",
157
+ clientPart: "",
158
+ contractInfo: entry.contractInfo,
159
+ headlessProps: entry.headlessProps
160
+ });
161
+ }
162
+ const headlessInstanceComponents = [];
163
+ for (const entry of config.instanceComponents) {
164
+ const serveTimeContract = {
165
+ props: entry.propNames.map((name) => ({ name }))
166
+ };
167
+ if (entry.structural) continue;
168
+ const mod = await importModule(entry);
169
+ headlessInstanceComponents.push({
170
+ contractName: entry.contractName,
171
+ compDefinition: mod[entry.exportName] ?? mod.default,
172
+ contract: serveTimeContract
173
+ });
174
+ }
175
+ return {
176
+ parts,
177
+ headlessContracts: [],
178
+ headlessInstanceComponents,
179
+ discoveredInstances: [],
180
+ forEachInstances: config.forEachInstances,
181
+ keyedPartModules: [],
182
+ headlessModuleInfos: []
183
+ };
184
+ }
368
185
  const pagePartsCache = /* @__PURE__ */ new Map();
369
186
  async function getPageParts(route, artifacts, cachePath) {
370
187
  const cacheKey = route.pattern;
@@ -457,7 +274,8 @@ async function fetchPageRequest(match, manifest, requestUrl, artifacts, staticBa
457
274
  importMap["jay-route-hydrate"] = `${staticBaseUrl}${route.routeHydratePath}`;
458
275
  }
459
276
  const clientBundleUrl = route.routeClientBundlePath ? `${staticBaseUrl}${route.routeClientBundlePath}` : `${staticBaseUrl}${instance.clientBundlePath}`;
460
- const preloadUrls = [...Object.values(importMap), clientBundleUrl];
277
+ const sharedPreloads = route.sharedDeps ? route.sharedDeps.map((dep) => importMap[dep]).filter(Boolean) : Object.values(importMap);
278
+ const preloadUrls = [...sharedPreloads, clientBundleUrl];
461
279
  const modulePreloads = preloadUrls.map((url) => ` <link rel="modulepreload" href="${url}" />`).join("\n");
462
280
  const cssUrl = instance.clientCssPath ? `${staticBaseUrl}${instance.clientCssPath}` : "";
463
281
  const cssPreload = cssUrl ? ` <link rel="preload" href="${cssUrl}" as="style" />` : "";
@@ -807,9 +625,8 @@ export {
807
625
  isActionRequest as d,
808
626
  registerActionsFromModules as e,
809
627
  fetchActionRequest as f,
810
- buildPagePartsConfig as g,
811
628
  initializeServices as i,
812
- loadProductionPageParts as l,
629
+ loadPagePartsFromConfig as l,
813
630
  matchRequest as m,
814
631
  registerActionsFromManifest as r
815
632
  };
@@ -1,6 +1,5 @@
1
1
  import * as _jay_framework_ssr_runtime from '@jay-framework/ssr-runtime';
2
- import { JayHtmlHeadMeta } from '@jay-framework/compiler-shared';
3
- import { ActionRegistry } from '@jay-framework/stack-server-runtime';
2
+ import { JayHtmlHeadMeta, DevServerPagePart, HeadlessInstanceComponent, ForEachHeadlessInstance, ActionRegistry } from '@jay-framework/stack-server-runtime';
4
3
 
5
4
  interface RouteManifest {
6
5
  version: string;
@@ -38,6 +37,8 @@ interface RouteEntry {
38
37
  instances: InstanceEntry[];
39
38
  isPlugin?: boolean;
40
39
  pluginName?: string;
40
+ /** Shared chunk package names this route's hydrate script imports (DL#177). */
41
+ sharedDeps?: string[];
41
42
  /** When true, dev-server tooling route (future: excluded from production builds). */
42
43
  devOnly?: boolean;
43
44
  }
@@ -90,7 +91,7 @@ interface PageModule {
90
91
  interface PagePartsConfigEntry {
91
92
  modulePath: string;
92
93
  exportName: string;
93
- source: 'npm' | 'local';
94
+ source: 'local' | 'npm';
94
95
  structural?: boolean;
95
96
  }
96
97
  interface PagePartsConfig {
@@ -114,6 +115,16 @@ interface PagePartsConfig {
114
115
  coordinateSuffix: string;
115
116
  }>;
116
117
  }
118
+ interface ProductionPageParts {
119
+ parts: DevServerPagePart[];
120
+ headlessContracts: any[];
121
+ headlessInstanceComponents: HeadlessInstanceComponent[];
122
+ discoveredInstances: any[];
123
+ forEachInstances: ForEachHeadlessInstance[];
124
+ keyedPartModules: any[];
125
+ headlessModuleInfos: any[];
126
+ }
127
+ declare function loadPagePartsFromConfig(configPath: string, artifacts: ArtifactStore): Promise<ProductionPageParts>;
117
128
 
118
129
  /**
119
130
  * Interface for reading build artifacts at serve time (DL#143).
@@ -187,4 +198,4 @@ interface PreImportedPlugin {
187
198
  declare function initializeServicesFromModules(plugins: PreImportedPlugin[], label: string): Promise<void>;
188
199
  declare function initializeServices(buildDir: string, projectRoot: string, label: string): Promise<void>;
189
200
 
190
- export { type ActionEntry as A, type BuildOptions as B, type CacheEntry as C, FilesystemArtifactStore as F, type InstanceEntry as I, type MatchResult as M, type PageModule as P, type RouteManifest as R, type ServerElementModule as S, type RouteEntry as a, type ArtifactStore as b, type BuildMetadata as c, type PluginEntry as d, type PreImportedPlugin as e, type RouteSegment as f, fetchActionRequest as g, fetchPageRequest as h, fetchStaticFile as i, initializeServices as j, initializeServicesFromModules as k, isActionRequest as l, matchRequest as m, registerActionsFromModules as n, registerActionsFromManifest as r };
201
+ export { type ActionEntry as A, type BuildMetadata as B, type CacheEntry as C, FilesystemArtifactStore as F, type InstanceEntry as I, type MatchResult as M, type PageModule as P, type RouteManifest as R, type ServerElementModule as S, type RouteEntry as a, type ArtifactStore as b, type BuildOptions as c, type PluginEntry as d, type PreImportedPlugin as e, type RouteSegment as f, fetchActionRequest as g, fetchPageRequest as h, fetchStaticFile as i, initializeServices as j, initializeServicesFromModules as k, isActionRequest as l, loadPagePartsFromConfig as m, matchRequest as n, registerActionsFromModules as o, registerActionsFromManifest as r };
@@ -1,4 +1,3 @@
1
- export { b as ArtifactStore, C as CacheEntry, F as FilesystemArtifactStore, I as InstanceEntry, M as MatchResult, e as PreImportedPlugin, a as RouteEntry, R as RouteManifest, S as ServerElementModule, g as fetchActionRequest, h as fetchPageRequest, i as fetchStaticFile, j as initializeServices, k as initializeServicesFromModules, l as isActionRequest, m as matchRequest, r as registerActionsFromManifest, n as registerActionsFromModules } from './serve-index-cRXZm8vQ.js';
1
+ export { b as ArtifactStore, C as CacheEntry, F as FilesystemArtifactStore, I as InstanceEntry, M as MatchResult, e as PreImportedPlugin, a as RouteEntry, R as RouteManifest, S as ServerElementModule, g as fetchActionRequest, h as fetchPageRequest, i as fetchStaticFile, j as initializeServices, k as initializeServicesFromModules, l as isActionRequest, n as matchRequest, r as registerActionsFromManifest, o as registerActionsFromModules } from './serve-index-B45QVQoo.js';
2
2
  import '@jay-framework/ssr-runtime';
3
- import '@jay-framework/compiler-shared';
4
3
  import '@jay-framework/stack-server-runtime';
@@ -1,4 +1,4 @@
1
- import { F, f, a, b, i, c, d, m, r, e } from "./init-services-Dy2SiHzw.js";
1
+ import { F, f, a, b, i, c, d, m, r, e } from "./init-services-CnM6IinC.js";
2
2
  export {
3
3
  F as FilesystemArtifactStore,
4
4
  f as fetchActionRequest,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/production-server",
3
- "version": "0.24.1",
3
+ "version": "0.24.3",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,20 +30,14 @@
30
30
  "test:watch": "vitest"
31
31
  },
32
32
  "dependencies": {
33
- "@jay-framework/compiler-jay-html": "^0.24.1",
34
- "@jay-framework/compiler-jay-stack": "^0.24.1",
35
- "@jay-framework/compiler-shared": "^0.24.1",
36
- "@jay-framework/fullstack-component": "^0.24.1",
37
- "@jay-framework/logger": "^0.24.1",
38
- "@jay-framework/ssr-runtime": "^0.24.1",
39
- "@jay-framework/stack-route-scanner": "^0.24.1",
40
- "@jay-framework/stack-server-runtime": "^0.24.1",
41
- "@jay-framework/view-state-merge": "^0.24.1",
42
- "@jay-framework/vite-plugin": "^0.24.1",
43
- "vite": "^5.0.11"
33
+ "@jay-framework/fullstack-component": "^0.24.3",
34
+ "@jay-framework/logger": "^0.24.3",
35
+ "@jay-framework/ssr-runtime": "^0.24.3",
36
+ "@jay-framework/stack-server-runtime": "^0.24.3",
37
+ "@jay-framework/view-state-merge": "^0.24.3"
44
38
  },
45
39
  "devDependencies": {
46
- "@jay-framework/dev-environment": "^0.24.1",
40
+ "@jay-framework/dev-environment": "^0.24.3",
47
41
  "@types/node": "^22.15.21",
48
42
  "rimraf": "^5.0.5",
49
43
  "tsup": "^8.0.1",