@jay-framework/stack-server-runtime 0.6.10 → 0.8.0
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 +121 -4
- package/dist/index.js +67 -7
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnyJayStackComponentDefinition, PageProps, AnySlowlyRenderResult, UrlParams, JayStackComponentDefinition, AnyFastRenderResult } from '@jay-framework/fullstack-component';
|
|
1
|
+
import { AnyJayStackComponentDefinition, PageProps, AnySlowlyRenderResult, UrlParams, JayStackComponentDefinition, AnyFastRenderResult, ServiceMarker } from '@jay-framework/fullstack-component';
|
|
2
2
|
import { JayComponentCore } from '@jay-framework/component';
|
|
3
3
|
import { ViteDevServer } from 'vite';
|
|
4
4
|
import { JayRoute } from '@jay-framework/stack-route-scanner';
|
|
@@ -21,11 +21,128 @@ declare class DevSlowlyChangingPhase implements SlowlyChangingPhase {
|
|
|
21
21
|
constructor(dontCacheSlowly: boolean);
|
|
22
22
|
runSlowlyForPage(pageParams: UrlParams, pageProps: PageProps, parts: Array<DevServerPagePart>): Promise<AnySlowlyRenderResult>;
|
|
23
23
|
}
|
|
24
|
-
declare function runLoadParams<StaticViewState extends object, ViewState extends object, Refs extends object,
|
|
25
|
-
declare function runSlowlyChangingRender<StaticViewState extends object, ViewState extends object, Refs extends object,
|
|
24
|
+
declare function runLoadParams<StaticViewState extends object, ViewState extends object, Refs extends object, Services extends Array<any>, Contexts extends Array<any>, PropsT extends object, Params extends UrlParams, CompCore extends JayComponentCore<PropsT, ViewState>>(compDefinition: JayStackComponentDefinition<StaticViewState, ViewState, Refs, Services, Contexts, PropsT, Params, CompCore>, services: Services): Promise<void>;
|
|
25
|
+
declare function runSlowlyChangingRender<StaticViewState extends object, ViewState extends object, Refs extends object, Services extends Array<any>, Contexts extends Array<any>, PropsT extends object, Params extends UrlParams, CompCore extends JayComponentCore<PropsT, ViewState>>(compDefinition: JayStackComponentDefinition<StaticViewState, ViewState, Refs, Services, Contexts, PropsT, Params, CompCore>): void;
|
|
26
26
|
|
|
27
27
|
declare function renderFastChangingData(pageParams: object, pageProps: PageProps, carryForward: object, parts: Array<DevServerPagePart>): Promise<AnyFastRenderResult>;
|
|
28
28
|
|
|
29
29
|
declare function generateClientScript(defaultViewState: object, fastCarryForward: object, parts: DevServerPagePart[], jayHtmlPath: string): string;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Service registry for Jay Stack server-side dependency injection.
|
|
33
|
+
*
|
|
34
|
+
* Services are global singletons (not hierarchical like client contexts) that provide
|
|
35
|
+
* infrastructure capabilities like database connections, API clients, etc.
|
|
36
|
+
*
|
|
37
|
+
* Note: ServiceMarker and createJayService are defined in @jay-framework/fullstack-component
|
|
38
|
+
* to avoid circular dependencies. This module contains only the runtime implementation.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Registers a service instance with the given marker.
|
|
43
|
+
* Typically called within an `onInit()` callback.
|
|
44
|
+
*
|
|
45
|
+
* @param marker - The service marker created with `createJayService()`
|
|
46
|
+
* @param service - The service instance to register
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* onInit(async () => {
|
|
51
|
+
* const db = await createDatabase();
|
|
52
|
+
* registerService(DATABASE_SERVICE, db);
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function registerService<ServiceType>(marker: ServiceMarker<ServiceType>, service: ServiceType): void;
|
|
57
|
+
/**
|
|
58
|
+
* Retrieves a registered service by its marker.
|
|
59
|
+
* Throws an error if the service is not found.
|
|
60
|
+
*
|
|
61
|
+
* @param marker - The service marker
|
|
62
|
+
* @returns The registered service instance
|
|
63
|
+
* @throws Error if service is not registered
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* onShutdown(async () => {
|
|
68
|
+
* const db = getService(DATABASE_SERVICE);
|
|
69
|
+
* await db?.close();
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
declare function getService<ServiceType>(marker: ServiceMarker<ServiceType>): ServiceType;
|
|
74
|
+
/**
|
|
75
|
+
* Checks if a service is registered.
|
|
76
|
+
*
|
|
77
|
+
* @param marker - The service marker
|
|
78
|
+
* @returns true if the service is registered
|
|
79
|
+
*/
|
|
80
|
+
declare function hasService<ServiceType>(marker: ServiceMarker<ServiceType>): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Clears all registered services.
|
|
83
|
+
* Internal API used by dev-server during hot reload.
|
|
84
|
+
*/
|
|
85
|
+
declare function clearServiceRegistry(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Resolves an array of service markers to their registered instances.
|
|
88
|
+
* Used by the runtime to inject services into render functions.
|
|
89
|
+
*
|
|
90
|
+
* @param serviceMarkers - Array of service markers to resolve
|
|
91
|
+
* @returns Array of resolved service instances
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const services = resolveServices([DATABASE_SERVICE, INVENTORY_SERVICE]);
|
|
96
|
+
* // Returns: [databaseInstance, inventoryInstance]
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function resolveServices(serviceMarkers: any[]): Array<any>;
|
|
100
|
+
type InitCallback = () => void | Promise<void>;
|
|
101
|
+
type ShutdownCallback = () => void | Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Registers a callback to be executed during service initialization.
|
|
104
|
+
* Multiple callbacks can be registered and will be executed in order.
|
|
105
|
+
*
|
|
106
|
+
* @param callback - Async or sync function to initialize services
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* onInit(async () => {
|
|
111
|
+
* const db = await connectToDatabase(process.env.DATABASE_URL);
|
|
112
|
+
* registerService(DATABASE_SERVICE, db);
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
declare function onInit(callback: InitCallback): void;
|
|
117
|
+
/**
|
|
118
|
+
* Registers a callback to be executed during service shutdown.
|
|
119
|
+
* Multiple callbacks can be registered. They execute in reverse order (LIFO).
|
|
120
|
+
*
|
|
121
|
+
* @param callback - Async or sync function to clean up services
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* onShutdown(async () => {
|
|
126
|
+
* const db = getService(DATABASE_SERVICE);
|
|
127
|
+
* await db?.close();
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function onShutdown(callback: ShutdownCallback): void;
|
|
132
|
+
/**
|
|
133
|
+
* Executes all registered init callbacks in order.
|
|
134
|
+
* Internal API called by dev-server on startup.
|
|
135
|
+
*/
|
|
136
|
+
declare function runInitCallbacks(): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Executes all registered shutdown callbacks in reverse order (LIFO).
|
|
139
|
+
* Internal API called by dev-server on shutdown/reload.
|
|
140
|
+
*/
|
|
141
|
+
declare function runShutdownCallbacks(): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Clears all registered lifecycle callbacks.
|
|
144
|
+
* Internal API used by dev-server during hot reload.
|
|
145
|
+
*/
|
|
146
|
+
declare function clearLifecycleCallbacks(): void;
|
|
147
|
+
|
|
148
|
+
export { DevSlowlyChangingPhase, type SlowlyChangingPhase, clearLifecycleCallbacks, clearServiceRegistry, generateClientScript, getService, hasService, loadPageParts, onInit, onShutdown, registerService, renderFastChangingData, resolveServices, runInitCallbacks, runLoadParams, runShutdownCallbacks, runSlowlyChangingRender };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,53 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { parseJayFile } from "@jay-framework/compiler-jay-html";
|
|
5
5
|
import { createRequire } from "module";
|
|
6
|
+
const serviceRegistry = /* @__PURE__ */ new Map();
|
|
7
|
+
function registerService(marker, service) {
|
|
8
|
+
serviceRegistry.set(marker, service);
|
|
9
|
+
}
|
|
10
|
+
function getService(marker) {
|
|
11
|
+
const service = serviceRegistry.get(marker);
|
|
12
|
+
if (service === void 0) {
|
|
13
|
+
const symbolKey = marker;
|
|
14
|
+
const serviceName = symbolKey.description || "Unknown service";
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Service '${serviceName}' not found. Did you register it in jay.init.ts?
|
|
17
|
+
Make sure to call: registerService(${serviceName.toUpperCase()}_SERVICE, ...)`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return service;
|
|
21
|
+
}
|
|
22
|
+
function hasService(marker) {
|
|
23
|
+
return serviceRegistry.has(marker);
|
|
24
|
+
}
|
|
25
|
+
function clearServiceRegistry() {
|
|
26
|
+
serviceRegistry.clear();
|
|
27
|
+
}
|
|
28
|
+
function resolveServices(serviceMarkers) {
|
|
29
|
+
return serviceMarkers.map((marker) => getService(marker));
|
|
30
|
+
}
|
|
31
|
+
const initCallbacks = [];
|
|
32
|
+
const shutdownCallbacks = [];
|
|
33
|
+
function onInit(callback) {
|
|
34
|
+
initCallbacks.push(callback);
|
|
35
|
+
}
|
|
36
|
+
function onShutdown(callback) {
|
|
37
|
+
shutdownCallbacks.push(callback);
|
|
38
|
+
}
|
|
39
|
+
async function runInitCallbacks() {
|
|
40
|
+
for (const callback of initCallbacks) {
|
|
41
|
+
await callback();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function runShutdownCallbacks() {
|
|
45
|
+
for (let i = shutdownCallbacks.length - 1; i >= 0; i--) {
|
|
46
|
+
await shutdownCallbacks[i]();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function clearLifecycleCallbacks() {
|
|
50
|
+
initCallbacks.length = 0;
|
|
51
|
+
shutdownCallbacks.length = 0;
|
|
52
|
+
}
|
|
6
53
|
function isLeftSideParamsSubsetOfRightSideParams(left, right) {
|
|
7
54
|
return Object.keys(left).reduce((prev, curr) => prev && left[curr] === right[curr], true);
|
|
8
55
|
}
|
|
@@ -21,7 +68,8 @@ class DevSlowlyChangingPhase {
|
|
|
21
68
|
for (const part of parts) {
|
|
22
69
|
const { compDefinition } = part;
|
|
23
70
|
if (compDefinition.loadParams) {
|
|
24
|
-
const
|
|
71
|
+
const services = resolveServices(compDefinition.services);
|
|
72
|
+
const compParams = compDefinition.loadParams(services);
|
|
25
73
|
if (!await findMatchingParams(pageParams, compParams))
|
|
26
74
|
return notFound();
|
|
27
75
|
}
|
|
@@ -31,9 +79,10 @@ class DevSlowlyChangingPhase {
|
|
|
31
79
|
for (const part of parts) {
|
|
32
80
|
const { compDefinition, key } = part;
|
|
33
81
|
if (compDefinition.slowlyRender) {
|
|
82
|
+
const services = resolveServices(compDefinition.services);
|
|
34
83
|
const slowlyRenderedPart = await compDefinition.slowlyRender(
|
|
35
84
|
{ ...pageProps, ...pageParams },
|
|
36
|
-
|
|
85
|
+
...services
|
|
37
86
|
);
|
|
38
87
|
if (slowlyRenderedPart.kind === "PartialRender") {
|
|
39
88
|
if (!key) {
|
|
@@ -50,8 +99,8 @@ class DevSlowlyChangingPhase {
|
|
|
50
99
|
return partialRender(slowlyViewState, carryForward);
|
|
51
100
|
}
|
|
52
101
|
}
|
|
53
|
-
async function runLoadParams(compDefinition,
|
|
54
|
-
compDefinition.loadParams(
|
|
102
|
+
async function runLoadParams(compDefinition, services) {
|
|
103
|
+
compDefinition.loadParams(services);
|
|
55
104
|
}
|
|
56
105
|
function runSlowlyChangingRender(compDefinition) {
|
|
57
106
|
}
|
|
@@ -62,9 +111,11 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
62
111
|
const { compDefinition, key } = part;
|
|
63
112
|
if (compDefinition.fastRender) {
|
|
64
113
|
const partSlowlyCarryForward = key ? carryForward[key] : carryForward;
|
|
114
|
+
const services = resolveServices(compDefinition.services);
|
|
65
115
|
const fastRenderedPart = await compDefinition.fastRender(
|
|
66
116
|
{ ...pageProps, ...pageParams },
|
|
67
|
-
|
|
117
|
+
partSlowlyCarryForward,
|
|
118
|
+
...services
|
|
68
119
|
);
|
|
69
120
|
if (fastRenderedPart.kind === "PartialRender") {
|
|
70
121
|
if (!key) {
|
|
@@ -114,12 +165,11 @@ const require2 = createRequire(import.meta.url);
|
|
|
114
165
|
async function loadPageParts(vite, route, pagesBase, jayRollupConfig) {
|
|
115
166
|
const exists = await fs.access(route.compPath, fs.constants.F_OK).then(() => true).catch(() => false);
|
|
116
167
|
const parts = [];
|
|
117
|
-
const pageCode = path.resolve(pagesBase, "./page.ts");
|
|
118
168
|
if (exists) {
|
|
119
169
|
const pageComponent = (await vite.ssrLoadModule(route.compPath)).page;
|
|
120
170
|
parts.push({
|
|
121
171
|
compDefinition: pageComponent,
|
|
122
|
-
clientImport: `import {page} from '${
|
|
172
|
+
clientImport: `import {page} from '${route.compPath}'`,
|
|
123
173
|
clientPart: `{comp: page.comp, contextMarkers: []}`
|
|
124
174
|
});
|
|
125
175
|
}
|
|
@@ -158,9 +208,19 @@ async function loadPageParts(vite, route, pagesBase, jayRollupConfig) {
|
|
|
158
208
|
}
|
|
159
209
|
export {
|
|
160
210
|
DevSlowlyChangingPhase,
|
|
211
|
+
clearLifecycleCallbacks,
|
|
212
|
+
clearServiceRegistry,
|
|
161
213
|
generateClientScript,
|
|
214
|
+
getService,
|
|
215
|
+
hasService,
|
|
162
216
|
loadPageParts,
|
|
217
|
+
onInit,
|
|
218
|
+
onShutdown,
|
|
219
|
+
registerService,
|
|
163
220
|
renderFastChangingData,
|
|
221
|
+
resolveServices,
|
|
222
|
+
runInitCallbacks,
|
|
164
223
|
runLoadParams,
|
|
224
|
+
runShutdownCallbacks,
|
|
165
225
|
runSlowlyChangingRender
|
|
166
226
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/stack-server-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"test:watch": "vitest"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@jay-framework/compiler-jay-html": "^0.
|
|
30
|
-
"@jay-framework/component": "^0.
|
|
31
|
-
"@jay-framework/fullstack-component": "^0.
|
|
32
|
-
"@jay-framework/runtime": "^0.
|
|
33
|
-
"@jay-framework/stack-route-scanner": "^0.
|
|
29
|
+
"@jay-framework/compiler-jay-html": "^0.8.0",
|
|
30
|
+
"@jay-framework/component": "^0.8.0",
|
|
31
|
+
"@jay-framework/fullstack-component": "^0.8.0",
|
|
32
|
+
"@jay-framework/runtime": "^0.8.0",
|
|
33
|
+
"@jay-framework/stack-route-scanner": "^0.8.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@jay-framework/dev-environment": "^0.
|
|
37
|
-
"@jay-framework/jay-cli": "^0.
|
|
38
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
36
|
+
"@jay-framework/dev-environment": "^0.8.0",
|
|
37
|
+
"@jay-framework/jay-cli": "^0.8.0",
|
|
38
|
+
"@jay-framework/stack-client-runtime": "^0.8.0",
|
|
39
39
|
"@types/express": "^5.0.2",
|
|
40
40
|
"@types/node": "^22.15.21",
|
|
41
41
|
"nodemon": "^3.0.3",
|