@jay-framework/stack-server-runtime 0.12.0 → 0.14.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 +243 -93
- package/dist/index.js +989 -272
- package/package.json +13 -12
package/dist/index.js
CHANGED
|
@@ -5,19 +5,19 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
7
|
import { notFound, partialRender, phaseOutput, isJayAction } from "@jay-framework/fullstack-component";
|
|
8
|
-
import fs$1 from "node:fs/promises";
|
|
9
|
-
import * as path from "node:path";
|
|
10
|
-
import path__default from "node:path";
|
|
11
|
-
import { parseJayFile, JAY_IMPORT_RESOLVER } from "@jay-framework/compiler-jay-html";
|
|
12
|
-
import { createRequire } from "module";
|
|
13
|
-
import * as fs from "node:fs";
|
|
14
|
-
import { createRequire as createRequire$1 } from "node:module";
|
|
15
8
|
import "prettier";
|
|
16
9
|
import "js-beautify";
|
|
17
|
-
import fs$
|
|
10
|
+
import fs$1 from "fs";
|
|
18
11
|
import path$1 from "path";
|
|
19
12
|
import YAML from "yaml";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
import { parseJayFile, JAY_IMPORT_RESOLVER, generateServerElementFile, discoverHeadlessInstances, parseAction } from "@jay-framework/compiler-jay-html";
|
|
15
|
+
import fs$2 from "node:fs/promises";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import path__default from "node:path";
|
|
20
18
|
import { getLogger } from "@jay-framework/logger";
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import { createRequire as createRequire$1 } from "node:module";
|
|
21
21
|
import crypto from "node:crypto";
|
|
22
22
|
const serviceRegistry = /* @__PURE__ */ new Map();
|
|
23
23
|
function registerService(marker, service) {
|
|
@@ -86,32 +86,42 @@ function clearClientInitData() {
|
|
|
86
86
|
function isLeftSideParamsSubsetOfRightSideParams(left, right) {
|
|
87
87
|
return Object.keys(left).reduce((prev, curr) => prev && left[curr] === right[curr], true);
|
|
88
88
|
}
|
|
89
|
-
async function findMatchingParams(search, searchTarget) {
|
|
90
|
-
for await (const paramsArray of searchTarget) {
|
|
91
|
-
if (paramsArray.find((params) => isLeftSideParamsSubsetOfRightSideParams(search, params)))
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
89
|
class DevSlowlyChangingPhase {
|
|
97
|
-
constructor(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
constructor() {
|
|
91
|
+
/** Cached loadParams results per route (jayHtmlPath → array of UrlParams[] per part) */
|
|
92
|
+
__publicField(this, "loadParamsCache", /* @__PURE__ */ new Map());
|
|
93
|
+
}
|
|
94
|
+
async runSlowlyForPage(pageParams, pageProps, parts, discoveredInstances, headlessInstanceComponents, jayHtmlPath) {
|
|
95
|
+
const loadParamsParts = parts.filter((p) => p.compDefinition.loadParams);
|
|
96
|
+
if (loadParamsParts.length > 0) {
|
|
97
|
+
let cachedParamsArray = jayHtmlPath ? this.loadParamsCache.get(jayHtmlPath) : void 0;
|
|
98
|
+
if (!cachedParamsArray) {
|
|
99
|
+
cachedParamsArray = [];
|
|
100
|
+
for (const part of loadParamsParts) {
|
|
101
|
+
const { compDefinition, contractInfo } = part;
|
|
102
|
+
const services = resolveServices(compDefinition.services);
|
|
103
|
+
const loadParamsArgs = contractInfo ? [
|
|
104
|
+
...services,
|
|
105
|
+
{
|
|
106
|
+
contractName: contractInfo.contractName,
|
|
107
|
+
metadata: contractInfo.metadata
|
|
108
|
+
}
|
|
109
|
+
] : services;
|
|
110
|
+
const compParams = compDefinition.loadParams(loadParamsArgs);
|
|
111
|
+
const collected = [];
|
|
112
|
+
for await (const batch of compParams) {
|
|
113
|
+
collected.push(...batch);
|
|
110
114
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
115
|
+
cachedParamsArray.push(collected);
|
|
116
|
+
}
|
|
117
|
+
if (jayHtmlPath) {
|
|
118
|
+
this.loadParamsCache.set(jayHtmlPath, cachedParamsArray);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const partParams of cachedParamsArray) {
|
|
122
|
+
if (!partParams.some((p) => isLeftSideParamsSubsetOfRightSideParams(pageParams, p))) {
|
|
114
123
|
return notFound();
|
|
124
|
+
}
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
127
|
let slowlyViewState = {};
|
|
@@ -144,15 +154,264 @@ class DevSlowlyChangingPhase {
|
|
|
144
154
|
return slowlyRenderedPart;
|
|
145
155
|
}
|
|
146
156
|
}
|
|
157
|
+
if (discoveredInstances && discoveredInstances.length > 0 && headlessInstanceComponents) {
|
|
158
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
159
|
+
for (const comp of headlessInstanceComponents) {
|
|
160
|
+
componentByContractName.set(comp.contractName, comp);
|
|
161
|
+
}
|
|
162
|
+
const instancePhaseData = {
|
|
163
|
+
discovered: [],
|
|
164
|
+
carryForwards: {}
|
|
165
|
+
};
|
|
166
|
+
const instanceSlowViewStates = {};
|
|
167
|
+
const instanceResolvedData = [];
|
|
168
|
+
for (const instance of discoveredInstances) {
|
|
169
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
170
|
+
if (!comp)
|
|
171
|
+
continue;
|
|
172
|
+
const coordKey = instance.coordinate.join("/");
|
|
173
|
+
const contractProps = comp.contract?.props ?? [];
|
|
174
|
+
const normalizedProps = {};
|
|
175
|
+
for (const [key, value] of Object.entries(instance.props)) {
|
|
176
|
+
const match = contractProps.find(
|
|
177
|
+
(p) => p.name.toLowerCase() === key.toLowerCase()
|
|
178
|
+
);
|
|
179
|
+
normalizedProps[match ? match.name : key] = value;
|
|
180
|
+
}
|
|
181
|
+
instancePhaseData.discovered.push({
|
|
182
|
+
contractName: instance.contractName,
|
|
183
|
+
props: normalizedProps,
|
|
184
|
+
coordinate: instance.coordinate
|
|
185
|
+
});
|
|
186
|
+
if (comp.compDefinition.slowlyRender) {
|
|
187
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
188
|
+
const slowResult = await comp.compDefinition.slowlyRender(
|
|
189
|
+
normalizedProps,
|
|
190
|
+
...services
|
|
191
|
+
);
|
|
192
|
+
if (slowResult.kind === "PhaseOutput") {
|
|
193
|
+
instanceSlowViewStates[coordKey] = slowResult.rendered;
|
|
194
|
+
instancePhaseData.carryForwards[coordKey] = slowResult.carryForward;
|
|
195
|
+
instanceResolvedData.push({
|
|
196
|
+
coordinate: instance.coordinate,
|
|
197
|
+
contract: comp.contract,
|
|
198
|
+
slowViewState: slowResult.rendered
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
carryForward.__instances = instancePhaseData;
|
|
204
|
+
carryForward.__instanceSlowViewStates = instanceSlowViewStates;
|
|
205
|
+
carryForward.__instanceResolvedData = instanceResolvedData;
|
|
206
|
+
}
|
|
147
207
|
return partialRender(slowlyViewState, carryForward);
|
|
148
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* Invalidate the cached loadParams result for a given route.
|
|
211
|
+
* Called when source files change (page.ts, .jay-contract, .jay-html).
|
|
212
|
+
*/
|
|
213
|
+
invalidateLoadParamsCache(jayHtmlPath) {
|
|
214
|
+
this.loadParamsCache.delete(jayHtmlPath);
|
|
215
|
+
}
|
|
149
216
|
}
|
|
150
217
|
async function runLoadParams(compDefinition, services) {
|
|
151
218
|
compDefinition.loadParams(services);
|
|
152
219
|
}
|
|
153
220
|
function runSlowlyChangingRender(compDefinition) {
|
|
154
221
|
}
|
|
155
|
-
|
|
222
|
+
var __defProp2 = Object.defineProperty;
|
|
223
|
+
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
224
|
+
var __publicField2 = (obj, key, value) => {
|
|
225
|
+
__defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
226
|
+
return value;
|
|
227
|
+
};
|
|
228
|
+
class JayAtomicType {
|
|
229
|
+
constructor(name) {
|
|
230
|
+
__publicField2(this, "kind", 0);
|
|
231
|
+
this.name = name;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
new JayAtomicType("string");
|
|
235
|
+
new JayAtomicType("number");
|
|
236
|
+
new JayAtomicType("boolean");
|
|
237
|
+
new JayAtomicType("Date");
|
|
238
|
+
new JayAtomicType("Unknown");
|
|
239
|
+
class JayObjectType {
|
|
240
|
+
constructor(name, props) {
|
|
241
|
+
__publicField2(this, "kind", 8);
|
|
242
|
+
this.name = name;
|
|
243
|
+
this.props = props;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
new JayObjectType("Error", {
|
|
247
|
+
message: new JayAtomicType("string"),
|
|
248
|
+
name: new JayAtomicType("string"),
|
|
249
|
+
stack: new JayAtomicType("string")
|
|
250
|
+
});
|
|
251
|
+
function isOptionalType(aType) {
|
|
252
|
+
return aType.kind === 13;
|
|
253
|
+
}
|
|
254
|
+
function isAtomicType(aType) {
|
|
255
|
+
return aType.kind === 0;
|
|
256
|
+
}
|
|
257
|
+
function isEnumType(aType) {
|
|
258
|
+
return aType.kind === 2;
|
|
259
|
+
}
|
|
260
|
+
function isImportedType(aType) {
|
|
261
|
+
return aType.kind === 4;
|
|
262
|
+
}
|
|
263
|
+
function isObjectType(aType) {
|
|
264
|
+
return aType.kind === 8;
|
|
265
|
+
}
|
|
266
|
+
function isArrayType(aType) {
|
|
267
|
+
return aType.kind === 9;
|
|
268
|
+
}
|
|
269
|
+
function jayTypeToJsonSchema(type) {
|
|
270
|
+
if (isOptionalType(type)) {
|
|
271
|
+
return jayTypeToJsonSchema(type.innerType);
|
|
272
|
+
}
|
|
273
|
+
if (isAtomicType(type)) {
|
|
274
|
+
const name = type.name.toLowerCase();
|
|
275
|
+
if (name === "string" || name === "number" || name === "boolean") {
|
|
276
|
+
return { type: name };
|
|
277
|
+
}
|
|
278
|
+
return { type: "string" };
|
|
279
|
+
}
|
|
280
|
+
if (isEnumType(type)) {
|
|
281
|
+
return { type: "string", enum: type.values };
|
|
282
|
+
}
|
|
283
|
+
if (isImportedType(type)) {
|
|
284
|
+
return { type: "object", description: `Contract: ${type.name}` };
|
|
285
|
+
}
|
|
286
|
+
if (isArrayType(type)) {
|
|
287
|
+
const itemSchema = jayTypeToJsonSchema(type.itemType);
|
|
288
|
+
if (itemSchema) {
|
|
289
|
+
return { type: "array", items: itemSchema };
|
|
290
|
+
}
|
|
291
|
+
return { type: "array" };
|
|
292
|
+
}
|
|
293
|
+
if (isObjectType(type)) {
|
|
294
|
+
const properties = {};
|
|
295
|
+
const required = [];
|
|
296
|
+
for (const [key, propType] of Object.entries(type.props)) {
|
|
297
|
+
const isOpt = isOptionalType(propType);
|
|
298
|
+
const schema = jayTypeToJsonSchema(propType);
|
|
299
|
+
if (schema) {
|
|
300
|
+
properties[key] = schema;
|
|
301
|
+
if (!isOpt) {
|
|
302
|
+
required.push(key);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
type: "object",
|
|
308
|
+
properties,
|
|
309
|
+
...required.length > 0 && { required }
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
var RuntimeMode = /* @__PURE__ */ ((RuntimeMode2) => {
|
|
315
|
+
RuntimeMode2["MainTrusted"] = "mainTrusted";
|
|
316
|
+
RuntimeMode2["MainSandbox"] = "mainSandbox";
|
|
317
|
+
RuntimeMode2["WorkerTrusted"] = "workerTrusted";
|
|
318
|
+
RuntimeMode2["WorkerSandbox"] = "workerSandbox";
|
|
319
|
+
return RuntimeMode2;
|
|
320
|
+
})(RuntimeMode || {});
|
|
321
|
+
const TS_EXTENSION = ".ts";
|
|
322
|
+
const JAY_QUERY_PREFIX = "?jay-";
|
|
323
|
+
const JAY_QUERY_HYDRATE = `${JAY_QUERY_PREFIX}hydrate`;
|
|
324
|
+
[
|
|
325
|
+
// Hydrate target
|
|
326
|
+
{
|
|
327
|
+
pattern: JAY_QUERY_HYDRATE,
|
|
328
|
+
buildEnv: "client",
|
|
329
|
+
isHydrate: true
|
|
330
|
+
},
|
|
331
|
+
// Build environments
|
|
332
|
+
{
|
|
333
|
+
pattern: `${JAY_QUERY_PREFIX}${"client"}`,
|
|
334
|
+
buildEnv: "client"
|
|
335
|
+
/* Client */
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
pattern: `${JAY_QUERY_PREFIX}${"server"}`,
|
|
339
|
+
buildEnv: "server"
|
|
340
|
+
/* Server */
|
|
341
|
+
},
|
|
342
|
+
// Runtime modes (with .ts suffix)
|
|
343
|
+
{
|
|
344
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}${TS_EXTENSION}`,
|
|
345
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}${TS_EXTENSION}`,
|
|
349
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}${TS_EXTENSION}`,
|
|
353
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
354
|
+
},
|
|
355
|
+
// Runtime modes (without .ts suffix)
|
|
356
|
+
{
|
|
357
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}`,
|
|
358
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}`,
|
|
362
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}`,
|
|
366
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
367
|
+
}
|
|
368
|
+
];
|
|
369
|
+
function checkValidationErrors(withValidations) {
|
|
370
|
+
const { validations } = withValidations;
|
|
371
|
+
if (validations.length > 0) {
|
|
372
|
+
throw new Error(validations.join("\n"));
|
|
373
|
+
}
|
|
374
|
+
return withValidations.val;
|
|
375
|
+
}
|
|
376
|
+
createRequire(import.meta.url);
|
|
377
|
+
function normalizeActionEntry(entry) {
|
|
378
|
+
if (typeof entry === "string") {
|
|
379
|
+
return { name: entry };
|
|
380
|
+
}
|
|
381
|
+
return { name: entry.name, action: entry.action };
|
|
382
|
+
}
|
|
383
|
+
function loadPluginManifest(pluginDir) {
|
|
384
|
+
const pluginYamlPath = path$1.join(pluginDir, "plugin.yaml");
|
|
385
|
+
if (!fs$1.existsSync(pluginYamlPath)) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
try {
|
|
389
|
+
const yamlContent = fs$1.readFileSync(pluginYamlPath, "utf-8");
|
|
390
|
+
return YAML.parse(yamlContent);
|
|
391
|
+
} catch (error) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function computeForEachInstanceKey(trackByValue, coordinateSuffix) {
|
|
396
|
+
return [trackByValue, coordinateSuffix].toString();
|
|
397
|
+
}
|
|
398
|
+
const s = createRequire(import.meta.url), e = s("typescript");
|
|
399
|
+
new Proxy(e, {
|
|
400
|
+
get(t, r) {
|
|
401
|
+
return t[r];
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
function resolvePathValue(obj, path2) {
|
|
405
|
+
return path2.split(".").reduce((current, segment) => current?.[segment], obj);
|
|
406
|
+
}
|
|
407
|
+
function resolveBinding(binding, item) {
|
|
408
|
+
const match = binding.match(/^\{(.+)\}$/);
|
|
409
|
+
if (match) {
|
|
410
|
+
return String(item[match[1]] ?? "");
|
|
411
|
+
}
|
|
412
|
+
return binding;
|
|
413
|
+
}
|
|
414
|
+
async function renderFastChangingData(pageParams, pageProps, carryForward, parts, instancePhaseData, forEachInstances, headlessInstanceComponents, mergedSlowViewState) {
|
|
156
415
|
let fastViewState = {};
|
|
157
416
|
let fastCarryForward = {};
|
|
158
417
|
for (const part of parts) {
|
|
@@ -185,12 +444,92 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
185
444
|
return fastRenderedPart;
|
|
186
445
|
}
|
|
187
446
|
}
|
|
447
|
+
const instanceViewStates = {};
|
|
448
|
+
const instanceCarryForwards = {};
|
|
449
|
+
if (instancePhaseData && headlessInstanceComponents) {
|
|
450
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
451
|
+
for (const comp of headlessInstanceComponents) {
|
|
452
|
+
componentByContractName.set(comp.contractName, comp);
|
|
453
|
+
}
|
|
454
|
+
for (const instance of instancePhaseData.discovered) {
|
|
455
|
+
const coordKey = instance.coordinate.join("/");
|
|
456
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
457
|
+
if (!comp || !comp.compDefinition.fastRender)
|
|
458
|
+
continue;
|
|
459
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
460
|
+
const cf = instancePhaseData.carryForwards[coordKey];
|
|
461
|
+
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(instance.props, cf, ...services) : await comp.compDefinition.fastRender(instance.props, ...services);
|
|
462
|
+
if (fastResult.kind === "PhaseOutput") {
|
|
463
|
+
const instanceSlowVS = carryForward?.__instanceSlowViewStates?.[coordKey];
|
|
464
|
+
instanceViewStates[coordKey] = instanceSlowVS ? { ...instanceSlowVS, ...fastResult.rendered } : fastResult.rendered;
|
|
465
|
+
if (fastResult.carryForward) {
|
|
466
|
+
instanceCarryForwards[coordKey] = fastResult.carryForward;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (forEachInstances && forEachInstances.length > 0 && headlessInstanceComponents) {
|
|
472
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
473
|
+
for (const comp of headlessInstanceComponents) {
|
|
474
|
+
componentByContractName.set(comp.contractName, comp);
|
|
475
|
+
}
|
|
476
|
+
const mergedForEachVS = { ...mergedSlowViewState || {}, ...fastViewState };
|
|
477
|
+
for (const instance of forEachInstances) {
|
|
478
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
479
|
+
if (!comp)
|
|
480
|
+
continue;
|
|
481
|
+
const items = resolvePathValue(mergedForEachVS, instance.forEachPath);
|
|
482
|
+
if (!Array.isArray(items))
|
|
483
|
+
continue;
|
|
484
|
+
const contractProps = comp.contract?.props ?? [];
|
|
485
|
+
const normalizePropName = (key) => contractProps.find((p) => p.name.toLowerCase() === key.toLowerCase())?.name ?? key;
|
|
486
|
+
for (const item of items) {
|
|
487
|
+
const trackByValue = String(item[instance.trackBy]);
|
|
488
|
+
const props = {};
|
|
489
|
+
for (const [propName, binding] of Object.entries(instance.propBindings)) {
|
|
490
|
+
props[normalizePropName(propName)] = resolveBinding(String(binding), item);
|
|
491
|
+
}
|
|
492
|
+
if (comp.compDefinition.fastRender) {
|
|
493
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
494
|
+
let slowVS = {};
|
|
495
|
+
let cf = {};
|
|
496
|
+
if (comp.compDefinition.slowlyRender) {
|
|
497
|
+
const slowResult = await comp.compDefinition.slowlyRender(
|
|
498
|
+
props,
|
|
499
|
+
...services
|
|
500
|
+
);
|
|
501
|
+
if (slowResult.kind === "PhaseOutput") {
|
|
502
|
+
slowVS = slowResult.rendered;
|
|
503
|
+
cf = slowResult.carryForward;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(props, cf, ...services) : await comp.compDefinition.fastRender(props, ...services);
|
|
507
|
+
if (fastResult.kind === "PhaseOutput") {
|
|
508
|
+
const coord = computeForEachInstanceKey(
|
|
509
|
+
trackByValue,
|
|
510
|
+
instance.coordinateSuffix
|
|
511
|
+
);
|
|
512
|
+
instanceViewStates[coord] = { ...slowVS, ...fastResult.rendered };
|
|
513
|
+
if (fastResult.carryForward) {
|
|
514
|
+
instanceCarryForwards[coord] = fastResult.carryForward;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (Object.keys(instanceViewStates).length > 0) {
|
|
522
|
+
fastViewState.__headlessInstances = instanceViewStates;
|
|
523
|
+
}
|
|
524
|
+
if (Object.keys(instanceCarryForwards).length > 0) {
|
|
525
|
+
fastCarryForward.__headlessInstances = instanceCarryForwards;
|
|
526
|
+
}
|
|
188
527
|
return Promise.resolve(phaseOutput(fastViewState, fastCarryForward));
|
|
189
528
|
}
|
|
190
|
-
function
|
|
529
|
+
function buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options) {
|
|
191
530
|
const { enableAutomation = true, slowViewState } = options;
|
|
192
531
|
const hasSlowViewState = slowViewState && Object.keys(slowViewState).length > 0;
|
|
193
|
-
const
|
|
532
|
+
const partImports = parts.length > 0 ? parts.map((part) => part.clientImport).join("\n") + "\n" : "";
|
|
194
533
|
const compositeParts = parts.length > 0 ? `[
|
|
195
534
|
${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
196
535
|
]` : "[]";
|
|
@@ -214,7 +553,7 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
214
553
|
const clientInitExecution = hasClientInit ? `
|
|
215
554
|
// Plugin client initialization (in dependency order)
|
|
216
555
|
${pluginClientInitCalls}
|
|
217
|
-
|
|
556
|
+
|
|
218
557
|
// Project client initialization
|
|
219
558
|
${projectInitCall}
|
|
220
559
|
` : "";
|
|
@@ -223,7 +562,28 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
223
562
|
import { deepMergeViewStates } from "@jay-framework/view-state-merge";` : `import { wrapWithAutomation, AUTOMATION_CONTEXT } from "@jay-framework/runtime-automation";
|
|
224
563
|
import { registerGlobalContext } from "@jay-framework/runtime";` : "";
|
|
225
564
|
const slowViewStateDecl = enableAutomation && hasSlowViewState ? `const slowViewState = ${JSON.stringify(slowViewState)};` : "";
|
|
226
|
-
|
|
565
|
+
return {
|
|
566
|
+
partImports,
|
|
567
|
+
compositeParts,
|
|
568
|
+
pluginClientInitImports,
|
|
569
|
+
projectInitImport,
|
|
570
|
+
clientInitExecution,
|
|
571
|
+
automationImport,
|
|
572
|
+
slowViewStateDecl
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
function buildAutomationWrap(options, mode) {
|
|
576
|
+
const { enableAutomation = true, slowViewState } = options;
|
|
577
|
+
const hasSlowViewState = slowViewState && Object.keys(slowViewState).length > 0;
|
|
578
|
+
const appendDom = mode === "client";
|
|
579
|
+
if (!enableAutomation) {
|
|
580
|
+
return appendDom ? `
|
|
581
|
+
target.appendChild(instance.element.dom);` : "";
|
|
582
|
+
}
|
|
583
|
+
const appendLine = appendDom ? `
|
|
584
|
+
target.appendChild(wrapped.element.dom);` : "";
|
|
585
|
+
if (hasSlowViewState) {
|
|
586
|
+
return `
|
|
227
587
|
// Wrap with automation for dev tooling
|
|
228
588
|
// Deep merge slow+fast ViewState so automation can see full page state
|
|
229
589
|
const fullViewState = deepMergeViewStates(slowViewState, {...viewState, ...fastCarryForward}, trackByMap);
|
|
@@ -231,14 +591,27 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
231
591
|
registerGlobalContext(AUTOMATION_CONTEXT, wrapped.automation);
|
|
232
592
|
window.__jay = window.__jay || {};
|
|
233
593
|
window.__jay.automation = wrapped.automation;
|
|
234
|
-
|
|
594
|
+
window.dispatchEvent(new Event('jay:automation-ready'));${appendLine}`;
|
|
595
|
+
}
|
|
596
|
+
return `
|
|
235
597
|
// Wrap with automation for dev tooling
|
|
236
598
|
const wrapped = wrapWithAutomation(instance);
|
|
237
599
|
registerGlobalContext(AUTOMATION_CONTEXT, wrapped.automation);
|
|
238
600
|
window.__jay = window.__jay || {};
|
|
239
601
|
window.__jay.automation = wrapped.automation;
|
|
240
|
-
|
|
241
|
-
|
|
602
|
+
window.dispatchEvent(new Event('jay:automation-ready'));${appendLine}`;
|
|
603
|
+
}
|
|
604
|
+
function generateClientScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
|
|
605
|
+
const {
|
|
606
|
+
partImports,
|
|
607
|
+
compositeParts,
|
|
608
|
+
pluginClientInitImports,
|
|
609
|
+
projectInitImport,
|
|
610
|
+
clientInitExecution,
|
|
611
|
+
automationImport,
|
|
612
|
+
slowViewStateDecl
|
|
613
|
+
} = buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options);
|
|
614
|
+
const automationWrap = buildAutomationWrap(options, "client");
|
|
242
615
|
return `<!doctype html>
|
|
243
616
|
<html lang="en">
|
|
244
617
|
<head>
|
|
@@ -254,7 +627,7 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
254
627
|
${pluginClientInitImports}
|
|
255
628
|
${projectInitImport}
|
|
256
629
|
import { render } from '${jayHtmlPath}';
|
|
257
|
-
${
|
|
630
|
+
${partImports}${slowViewStateDecl}
|
|
258
631
|
const viewState = ${JSON.stringify(defaultViewState)};
|
|
259
632
|
const fastCarryForward = ${JSON.stringify(fastCarryForward)};
|
|
260
633
|
const trackByMap = ${JSON.stringify(trackByMap)};
|
|
@@ -268,9 +641,171 @@ ${automationWrap}
|
|
|
268
641
|
</body>
|
|
269
642
|
</html>`;
|
|
270
643
|
}
|
|
644
|
+
const serverModuleCache = /* @__PURE__ */ new Map();
|
|
645
|
+
function invalidateServerElementCache(jayHtmlPath) {
|
|
646
|
+
if (serverModuleCache.delete(jayHtmlPath)) {
|
|
647
|
+
getLogger().info(`[SSR] Invalidated server element cache for ${jayHtmlPath}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function clearServerElementCache() {
|
|
651
|
+
serverModuleCache.clear();
|
|
652
|
+
}
|
|
653
|
+
async function generateSSRPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, viewState, jayHtmlImportPath, parts, carryForward, trackByMap = {}, clientInitData2 = {}, buildFolder, projectRoot, routeDir, tsConfigFilePath, projectInit, pluginInits = [], options = {}) {
|
|
654
|
+
const jayHtmlPath = path__default.join(jayHtmlDir, jayHtmlFilename);
|
|
655
|
+
let cached = serverModuleCache.get(jayHtmlPath);
|
|
656
|
+
if (!cached) {
|
|
657
|
+
cached = await compileAndLoadServerElement(
|
|
658
|
+
vite,
|
|
659
|
+
jayHtmlContent,
|
|
660
|
+
jayHtmlFilename,
|
|
661
|
+
jayHtmlDir,
|
|
662
|
+
buildFolder,
|
|
663
|
+
projectRoot,
|
|
664
|
+
routeDir,
|
|
665
|
+
tsConfigFilePath
|
|
666
|
+
);
|
|
667
|
+
serverModuleCache.set(jayHtmlPath, cached);
|
|
668
|
+
}
|
|
669
|
+
const htmlChunks = [];
|
|
670
|
+
const asyncPromises = [];
|
|
671
|
+
const ctx = {
|
|
672
|
+
write: (chunk) => {
|
|
673
|
+
htmlChunks.push(chunk);
|
|
674
|
+
},
|
|
675
|
+
onAsync: (promise, id, templates) => {
|
|
676
|
+
const asyncPromise = promise.then(
|
|
677
|
+
(val) => {
|
|
678
|
+
if (templates.resolved) {
|
|
679
|
+
return templates.resolved(val);
|
|
680
|
+
}
|
|
681
|
+
return "";
|
|
682
|
+
},
|
|
683
|
+
(err) => {
|
|
684
|
+
if (templates.rejected) {
|
|
685
|
+
return templates.rejected(err);
|
|
686
|
+
}
|
|
687
|
+
return "";
|
|
688
|
+
}
|
|
689
|
+
);
|
|
690
|
+
asyncPromises.push(asyncPromise);
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
cached.renderToStream(viewState, ctx);
|
|
694
|
+
const asyncResults = await Promise.all(asyncPromises);
|
|
695
|
+
const ssrHtml = htmlChunks.join("");
|
|
696
|
+
const asyncScripts = asyncResults.filter((r) => r !== "").join("");
|
|
697
|
+
const hydrationScript = generateHydrationScript(
|
|
698
|
+
viewState,
|
|
699
|
+
carryForward,
|
|
700
|
+
parts,
|
|
701
|
+
jayHtmlImportPath,
|
|
702
|
+
trackByMap,
|
|
703
|
+
clientInitData2,
|
|
704
|
+
projectInit,
|
|
705
|
+
pluginInits,
|
|
706
|
+
options
|
|
707
|
+
);
|
|
708
|
+
const headLinksHtml = cached.headLinks.map((link) => {
|
|
709
|
+
const attrs = Object.entries(link.attributes).map(([k, v]) => ` ${k}="${v}"`).join("");
|
|
710
|
+
return ` <link rel="${link.rel}" href="${link.href}"${attrs} />`;
|
|
711
|
+
}).join("\n");
|
|
712
|
+
const inlineCss = cached.css ? ` <style>
|
|
713
|
+
${cached.css}
|
|
714
|
+
</style>` : "";
|
|
715
|
+
const headExtras = [headLinksHtml, inlineCss].filter((_) => _).join("\n");
|
|
716
|
+
return `<!doctype html>
|
|
717
|
+
<html lang="en">
|
|
718
|
+
<head>
|
|
719
|
+
<meta charset="UTF-8" />
|
|
720
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
721
|
+
<title>Vite + TS</title>
|
|
722
|
+
${headExtras ? headExtras + "\n" : ""} </head>
|
|
723
|
+
<body>
|
|
724
|
+
<div id="target">${ssrHtml}</div>${asyncScripts}
|
|
725
|
+
${hydrationScript}
|
|
726
|
+
</body>
|
|
727
|
+
</html>`;
|
|
728
|
+
}
|
|
729
|
+
function rebaseRelativeImports(code, fromDir, toDir) {
|
|
730
|
+
return code.replace(/from "(\.\.\/[^"]+)"/g, (_match, relPath) => {
|
|
731
|
+
const absolutePath = path__default.resolve(fromDir, relPath);
|
|
732
|
+
let newRelPath = path__default.relative(toDir, absolutePath);
|
|
733
|
+
if (!newRelPath.startsWith(".")) {
|
|
734
|
+
newRelPath = "./" + newRelPath;
|
|
735
|
+
}
|
|
736
|
+
return `from "${newRelPath}"`;
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, buildFolder, projectRoot, routeDir, tsConfigFilePath) {
|
|
740
|
+
const jayFile = await parseJayFile(
|
|
741
|
+
jayHtmlContent,
|
|
742
|
+
jayHtmlFilename,
|
|
743
|
+
jayHtmlDir,
|
|
744
|
+
{ relativePath: tsConfigFilePath },
|
|
745
|
+
JAY_IMPORT_RESOLVER,
|
|
746
|
+
projectRoot
|
|
747
|
+
);
|
|
748
|
+
const parsedJayFile = checkValidationErrors(jayFile);
|
|
749
|
+
const pageName = jayHtmlFilename.replace(".jay-html", "");
|
|
750
|
+
const debugCoordinatePreprocessPath = path__default.join(
|
|
751
|
+
buildFolder,
|
|
752
|
+
"debug",
|
|
753
|
+
routeDir,
|
|
754
|
+
`${pageName}.coordinate-preprocess.jay-html`
|
|
755
|
+
);
|
|
756
|
+
const serverElementOptions = {
|
|
757
|
+
debugCoordinatePreprocessPath
|
|
758
|
+
};
|
|
759
|
+
const serverElementCode = checkValidationErrors(
|
|
760
|
+
generateServerElementFile(parsedJayFile, serverElementOptions)
|
|
761
|
+
);
|
|
762
|
+
const serverElementDir = path__default.join(buildFolder, "pre-rendered", routeDir);
|
|
763
|
+
await fs$2.mkdir(serverElementDir, { recursive: true });
|
|
764
|
+
const adjustedCode = rebaseRelativeImports(serverElementCode, jayHtmlDir, serverElementDir);
|
|
765
|
+
const serverElementFilename = jayHtmlFilename.replace(".jay-html", ".server-element.ts");
|
|
766
|
+
const serverElementPath = path__default.join(serverElementDir, serverElementFilename);
|
|
767
|
+
await fs$2.writeFile(serverElementPath, adjustedCode, "utf-8");
|
|
768
|
+
const serverModule = await vite.ssrLoadModule(serverElementPath);
|
|
769
|
+
return {
|
|
770
|
+
renderToStream: serverModule.renderToStream,
|
|
771
|
+
headLinks: parsedJayFile.headLinks,
|
|
772
|
+
css: parsedJayFile.css
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
function generateHydrationScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
|
|
776
|
+
const {
|
|
777
|
+
partImports,
|
|
778
|
+
compositeParts,
|
|
779
|
+
pluginClientInitImports,
|
|
780
|
+
projectInitImport,
|
|
781
|
+
clientInitExecution,
|
|
782
|
+
automationImport,
|
|
783
|
+
slowViewStateDecl
|
|
784
|
+
} = buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options);
|
|
785
|
+
const automationWrap = buildAutomationWrap(options, "hydrate");
|
|
786
|
+
const hydrateImportPath = `${jayHtmlPath}${JAY_QUERY_HYDRATE}`;
|
|
787
|
+
return `<script type="module">
|
|
788
|
+
import {hydrateCompositeJayComponent} from "@jay-framework/stack-client-runtime";
|
|
789
|
+
${automationImport}
|
|
790
|
+
${pluginClientInitImports}
|
|
791
|
+
${projectInitImport}
|
|
792
|
+
import { hydrate } from '${hydrateImportPath}';
|
|
793
|
+
${partImports}${slowViewStateDecl}
|
|
794
|
+
const viewState = ${JSON.stringify(defaultViewState)};
|
|
795
|
+
const fastCarryForward = ${JSON.stringify(fastCarryForward)};
|
|
796
|
+
const trackByMap = ${JSON.stringify(trackByMap)};
|
|
797
|
+
|
|
798
|
+
const target = document.getElementById('target');
|
|
799
|
+
const rootElement = target.firstElementChild;
|
|
800
|
+
const pageComp = hydrateCompositeJayComponent(hydrate, viewState, fastCarryForward, ${compositeParts}, trackByMap, rootElement);
|
|
801
|
+
${clientInitExecution}
|
|
802
|
+
const instance = pageComp({/* placeholder for page props */});
|
|
803
|
+
${automationWrap}
|
|
804
|
+
<\/script>`;
|
|
805
|
+
}
|
|
271
806
|
const require$3 = createRequire(import.meta.url);
|
|
272
807
|
async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfig, options) {
|
|
273
|
-
const exists = await fs$
|
|
808
|
+
const exists = await fs$2.access(route.compPath, fs$2.constants.F_OK).then(() => true).catch(() => false);
|
|
274
809
|
const parts = [];
|
|
275
810
|
if (exists) {
|
|
276
811
|
const pageComponent = (await vite.ssrLoadModule(route.compPath)).page;
|
|
@@ -281,7 +816,7 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
|
|
|
281
816
|
});
|
|
282
817
|
}
|
|
283
818
|
const jayHtmlFilePath = options?.preRenderedPath ?? route.jayHtmlPath;
|
|
284
|
-
const jayHtmlSource = (await fs$
|
|
819
|
+
const jayHtmlSource = options?.preRenderedContent ?? (await fs$2.readFile(jayHtmlFilePath)).toString();
|
|
285
820
|
const fileName = path__default.basename(route.jayHtmlPath);
|
|
286
821
|
const dirName = path__default.dirname(route.jayHtmlPath);
|
|
287
822
|
const jayHtmlWithValidations = await parseJayFile(
|
|
@@ -338,13 +873,16 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
|
|
|
338
873
|
contract: hi.contract,
|
|
339
874
|
contractPath: hi.contractPath
|
|
340
875
|
}));
|
|
876
|
+
const discoveryResult = headlessInstanceComponents.length > 0 ? discoverHeadlessInstances(jayHtmlSource) : { instances: [], forEachInstances: [], preRenderedJayHtml: jayHtmlSource };
|
|
341
877
|
return {
|
|
342
878
|
parts,
|
|
343
879
|
serverTrackByMap: jayHtml.serverTrackByMap,
|
|
344
880
|
clientTrackByMap: jayHtml.clientTrackByMap,
|
|
345
881
|
usedPackages,
|
|
346
882
|
headlessContracts,
|
|
347
|
-
headlessInstanceComponents
|
|
883
|
+
headlessInstanceComponents,
|
|
884
|
+
discoveredInstances: discoveryResult.instances,
|
|
885
|
+
forEachInstances: discoveryResult.forEachInstances
|
|
348
886
|
};
|
|
349
887
|
});
|
|
350
888
|
}
|
|
@@ -362,8 +900,14 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
362
900
|
if (!comp || !comp.compDefinition.slowlyRender) {
|
|
363
901
|
continue;
|
|
364
902
|
}
|
|
903
|
+
const contractProps = comp.contract?.props ?? [];
|
|
904
|
+
const normalizedProps = {};
|
|
905
|
+
for (const [key, value] of Object.entries(instance.props)) {
|
|
906
|
+
const match = contractProps.find((p) => p.name.toLowerCase() === key.toLowerCase());
|
|
907
|
+
normalizedProps[match ? match.name : key] = value;
|
|
908
|
+
}
|
|
365
909
|
const services = resolveServices(comp.compDefinition.services);
|
|
366
|
-
const slowResult = await comp.compDefinition.slowlyRender(
|
|
910
|
+
const slowResult = await comp.compDefinition.slowlyRender(normalizedProps, ...services);
|
|
367
911
|
if (slowResult.kind === "PhaseOutput") {
|
|
368
912
|
const coordKey = instance.coordinate.join("/");
|
|
369
913
|
resolvedData.push({
|
|
@@ -375,7 +919,7 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
375
919
|
carryForwards[coordKey] = slowResult.carryForward;
|
|
376
920
|
discoveredForFast.push({
|
|
377
921
|
contractName: instance.contractName,
|
|
378
|
-
props:
|
|
922
|
+
props: normalizedProps,
|
|
379
923
|
coordinate: instance.coordinate
|
|
380
924
|
});
|
|
381
925
|
}
|
|
@@ -389,6 +933,22 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
389
933
|
instancePhaseData: { discovered: discoveredForFast, carryForwards }
|
|
390
934
|
};
|
|
391
935
|
}
|
|
936
|
+
function validateForEachInstances(forEachInstances, headlessInstanceComponents) {
|
|
937
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
938
|
+
for (const comp of headlessInstanceComponents) {
|
|
939
|
+
componentByContractName.set(comp.contractName, comp);
|
|
940
|
+
}
|
|
941
|
+
const validations = [];
|
|
942
|
+
for (const instance of forEachInstances) {
|
|
943
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
944
|
+
if (comp?.compDefinition.slowlyRender) {
|
|
945
|
+
validations.push(
|
|
946
|
+
`<jay:${instance.contractName}> inside forEach has a slow rendering phase. Headless components with slow phases cannot be used inside forEach because forEach items are only known at request time, after slow rendering completes. Use slowForEach instead, or remove the slow phase from the component.`
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return validations;
|
|
951
|
+
}
|
|
392
952
|
class ActionRegistry {
|
|
393
953
|
constructor() {
|
|
394
954
|
__publicField(this, "actions", /* @__PURE__ */ new Map());
|
|
@@ -429,10 +989,38 @@ class ActionRegistry {
|
|
|
429
989
|
/**
|
|
430
990
|
* Gets all registered action names.
|
|
431
991
|
*
|
|
432
|
-
* @returns Array of registered action names
|
|
992
|
+
* @returns Array of registered action names
|
|
993
|
+
*/
|
|
994
|
+
getNames() {
|
|
995
|
+
return Array.from(this.actions.keys());
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Attaches metadata from a .jay-action file to a registered action.
|
|
999
|
+
* Called during action discovery when a plugin declares action metadata.
|
|
1000
|
+
*
|
|
1001
|
+
* @param actionName - The action name
|
|
1002
|
+
* @param metadata - Parsed ActionMetadata from .jay-action file
|
|
1003
|
+
*/
|
|
1004
|
+
setMetadata(actionName, metadata) {
|
|
1005
|
+
const action = this.actions.get(actionName);
|
|
1006
|
+
if (action) {
|
|
1007
|
+
action.metadata = metadata;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Gets all registered actions that have .jay-action metadata.
|
|
1012
|
+
* These are the actions that should be exposed to AI agents.
|
|
1013
|
+
*
|
|
1014
|
+
* @returns Array of { actionName, metadata } for actions with metadata
|
|
433
1015
|
*/
|
|
434
|
-
|
|
435
|
-
|
|
1016
|
+
getActionsWithMetadata() {
|
|
1017
|
+
const result = [];
|
|
1018
|
+
for (const action of this.actions.values()) {
|
|
1019
|
+
if (action.metadata) {
|
|
1020
|
+
result.push({ actionName: action.actionName, metadata: action.metadata });
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return result;
|
|
436
1024
|
}
|
|
437
1025
|
/**
|
|
438
1026
|
* Clears all registered actions.
|
|
@@ -536,102 +1124,62 @@ async function executeAction(actionName, input) {
|
|
|
536
1124
|
function getActionCacheHeaders(actionName) {
|
|
537
1125
|
return actionRegistry.getCacheHeaders(actionName);
|
|
538
1126
|
}
|
|
539
|
-
|
|
540
|
-
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
541
|
-
var __publicField2 = (obj, key, value) => {
|
|
542
|
-
__defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
543
|
-
return value;
|
|
544
|
-
};
|
|
545
|
-
class JayAtomicType {
|
|
546
|
-
constructor(name) {
|
|
547
|
-
__publicField2(this, "kind", 0);
|
|
548
|
-
this.name = name;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
new JayAtomicType("string");
|
|
552
|
-
new JayAtomicType("number");
|
|
553
|
-
new JayAtomicType("boolean");
|
|
554
|
-
new JayAtomicType("Date");
|
|
555
|
-
new JayAtomicType("Unknown");
|
|
556
|
-
class JayObjectType {
|
|
557
|
-
constructor(name, props) {
|
|
558
|
-
__publicField2(this, "kind", 8);
|
|
559
|
-
this.name = name;
|
|
560
|
-
this.props = props;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
new JayObjectType("Error", {
|
|
564
|
-
message: new JayAtomicType("string"),
|
|
565
|
-
name: new JayAtomicType("string"),
|
|
566
|
-
stack: new JayAtomicType("string")
|
|
567
|
-
});
|
|
568
|
-
var RuntimeMode = /* @__PURE__ */ ((RuntimeMode2) => {
|
|
569
|
-
RuntimeMode2["MainTrusted"] = "mainTrusted";
|
|
570
|
-
RuntimeMode2["MainSandbox"] = "mainSandbox";
|
|
571
|
-
RuntimeMode2["WorkerTrusted"] = "workerTrusted";
|
|
572
|
-
RuntimeMode2["WorkerSandbox"] = "workerSandbox";
|
|
573
|
-
return RuntimeMode2;
|
|
574
|
-
})(RuntimeMode || {});
|
|
575
|
-
const TS_EXTENSION = ".ts";
|
|
576
|
-
const JAY_QUERY_PREFIX = "?jay-";
|
|
577
|
-
[
|
|
578
|
-
// Build environments
|
|
579
|
-
{
|
|
580
|
-
pattern: `${JAY_QUERY_PREFIX}${"client"}`,
|
|
581
|
-
buildEnv: "client"
|
|
582
|
-
/* Client */
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
pattern: `${JAY_QUERY_PREFIX}${"server"}`,
|
|
586
|
-
buildEnv: "server"
|
|
587
|
-
/* Server */
|
|
588
|
-
},
|
|
589
|
-
// Runtime modes (with .ts suffix)
|
|
590
|
-
{
|
|
591
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}${TS_EXTENSION}`,
|
|
592
|
-
runtimeMode: RuntimeMode.MainSandbox
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}${TS_EXTENSION}`,
|
|
596
|
-
runtimeMode: RuntimeMode.WorkerTrusted
|
|
597
|
-
},
|
|
598
|
-
{
|
|
599
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}${TS_EXTENSION}`,
|
|
600
|
-
runtimeMode: RuntimeMode.WorkerSandbox
|
|
601
|
-
},
|
|
602
|
-
// Runtime modes (without .ts suffix)
|
|
603
|
-
{
|
|
604
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}`,
|
|
605
|
-
runtimeMode: RuntimeMode.MainSandbox
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}`,
|
|
609
|
-
runtimeMode: RuntimeMode.WorkerTrusted
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}`,
|
|
613
|
-
runtimeMode: RuntimeMode.WorkerSandbox
|
|
614
|
-
}
|
|
615
|
-
];
|
|
616
|
-
createRequire(import.meta.url);
|
|
617
|
-
function loadPluginManifest(pluginDir) {
|
|
618
|
-
const pluginYamlPath = path$1.join(pluginDir, "plugin.yaml");
|
|
619
|
-
if (!fs$2.existsSync(pluginYamlPath)) {
|
|
620
|
-
return null;
|
|
621
|
-
}
|
|
1127
|
+
function parseActionMetadata(yamlContent, fileName) {
|
|
622
1128
|
try {
|
|
623
|
-
const
|
|
624
|
-
|
|
1129
|
+
const parsed = parseAction(yamlContent, fileName);
|
|
1130
|
+
if (parsed.validations.length > 0) {
|
|
1131
|
+
getLogger().warn(
|
|
1132
|
+
`[ActionMetadata] ${fileName}: validation errors: ${parsed.validations.join(", ")}`
|
|
1133
|
+
);
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
if (!parsed.val) {
|
|
1137
|
+
getLogger().warn(`[ActionMetadata] ${fileName}: parsing returned no result`);
|
|
1138
|
+
return null;
|
|
1139
|
+
}
|
|
1140
|
+
const action = parsed.val;
|
|
1141
|
+
const inputJsonSchema = jayTypeToJsonSchema(action.inputType);
|
|
1142
|
+
let inputSchema;
|
|
1143
|
+
if (inputJsonSchema && inputJsonSchema.type === "object") {
|
|
1144
|
+
inputSchema = {
|
|
1145
|
+
type: "object",
|
|
1146
|
+
properties: inputJsonSchema.properties || {},
|
|
1147
|
+
...inputJsonSchema.required && inputJsonSchema.required.length > 0 && { required: inputJsonSchema.required }
|
|
1148
|
+
};
|
|
1149
|
+
} else {
|
|
1150
|
+
inputSchema = { type: "object", properties: {} };
|
|
1151
|
+
}
|
|
1152
|
+
const metadata = {
|
|
1153
|
+
name: action.name,
|
|
1154
|
+
description: action.description,
|
|
1155
|
+
inputSchema
|
|
1156
|
+
};
|
|
1157
|
+
if (action.outputType) {
|
|
1158
|
+
const outputJsonSchema = jayTypeToJsonSchema(action.outputType);
|
|
1159
|
+
if (outputJsonSchema) {
|
|
1160
|
+
metadata.outputSchema = outputJsonSchema;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return metadata;
|
|
625
1164
|
} catch (error) {
|
|
1165
|
+
getLogger().error(
|
|
1166
|
+
`[ActionMetadata] Failed to parse ${fileName}: ${error instanceof Error ? error.message : error}`
|
|
1167
|
+
);
|
|
626
1168
|
return null;
|
|
627
1169
|
}
|
|
628
1170
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
return
|
|
1171
|
+
function loadActionMetadata(filePath) {
|
|
1172
|
+
if (!fs.existsSync(filePath)) {
|
|
1173
|
+
getLogger().warn(`[ActionMetadata] File not found: ${filePath}`);
|
|
1174
|
+
return null;
|
|
633
1175
|
}
|
|
634
|
-
|
|
1176
|
+
const yamlContent = fs.readFileSync(filePath, "utf-8");
|
|
1177
|
+
const fileName = path.basename(filePath);
|
|
1178
|
+
return parseActionMetadata(yamlContent, fileName);
|
|
1179
|
+
}
|
|
1180
|
+
function resolveActionMetadataPath(actionPath, pluginDir) {
|
|
1181
|
+
return path.resolve(pluginDir, actionPath);
|
|
1182
|
+
}
|
|
635
1183
|
const require$2 = createRequire$1(import.meta.url);
|
|
636
1184
|
async function discoverAndRegisterActions(options) {
|
|
637
1185
|
const {
|
|
@@ -753,6 +1301,7 @@ async function discoverNpmPluginActions(projectRoot, registry, verbose, viteServ
|
|
|
753
1301
|
const actions = await registerNpmPluginActions(
|
|
754
1302
|
packageName,
|
|
755
1303
|
pluginConfig,
|
|
1304
|
+
pluginDir,
|
|
756
1305
|
registry,
|
|
757
1306
|
verbose,
|
|
758
1307
|
viteServer
|
|
@@ -776,7 +1325,25 @@ function tryResolvePluginYaml(packageName, projectRoot) {
|
|
|
776
1325
|
return null;
|
|
777
1326
|
}
|
|
778
1327
|
}
|
|
779
|
-
|
|
1328
|
+
function resolveNpmActionMetadataPath(actionPath, packageName, pluginDir) {
|
|
1329
|
+
if (!actionPath.startsWith(".")) {
|
|
1330
|
+
try {
|
|
1331
|
+
return require$2.resolve(`${packageName}/${actionPath}`, {
|
|
1332
|
+
paths: [pluginDir]
|
|
1333
|
+
});
|
|
1334
|
+
} catch {
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
const resolved = resolveActionMetadataPath(actionPath, pluginDir);
|
|
1338
|
+
if (fs.existsSync(resolved)) {
|
|
1339
|
+
return resolved;
|
|
1340
|
+
}
|
|
1341
|
+
getLogger().warn(
|
|
1342
|
+
`[Actions] Could not resolve .jay-action file "${actionPath}" for package "${packageName}"`
|
|
1343
|
+
);
|
|
1344
|
+
return null;
|
|
1345
|
+
}
|
|
1346
|
+
async function registerNpmPluginActions(packageName, pluginConfig, pluginDir, registry, verbose, viteServer) {
|
|
780
1347
|
const registeredActions = [];
|
|
781
1348
|
try {
|
|
782
1349
|
let pluginModule;
|
|
@@ -785,15 +1352,33 @@ async function registerNpmPluginActions(packageName, pluginConfig, registry, ver
|
|
|
785
1352
|
} else {
|
|
786
1353
|
pluginModule = await import(packageName);
|
|
787
1354
|
}
|
|
788
|
-
for (const
|
|
1355
|
+
for (const entry of pluginConfig.actions) {
|
|
1356
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
789
1357
|
const actionExport = pluginModule[actionName];
|
|
790
1358
|
if (actionExport && isJayAction(actionExport)) {
|
|
791
1359
|
registry.register(actionExport);
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1360
|
+
const registeredName = actionExport.actionName;
|
|
1361
|
+
registeredActions.push(registeredName);
|
|
1362
|
+
if (actionPath) {
|
|
1363
|
+
const metadataFilePath = resolveNpmActionMetadataPath(
|
|
1364
|
+
actionPath,
|
|
1365
|
+
packageName,
|
|
1366
|
+
pluginDir
|
|
796
1367
|
);
|
|
1368
|
+
if (metadataFilePath) {
|
|
1369
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
1370
|
+
if (metadata) {
|
|
1371
|
+
registry.setMetadata(registeredName, metadata);
|
|
1372
|
+
if (verbose) {
|
|
1373
|
+
getLogger().info(
|
|
1374
|
+
`[Actions] Loaded metadata for "${registeredName}" from ${actionPath}`
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
if (verbose) {
|
|
1381
|
+
getLogger().info(`[Actions] Registered NPM plugin action: ${registeredName}`);
|
|
797
1382
|
}
|
|
798
1383
|
} else {
|
|
799
1384
|
getLogger().warn(
|
|
@@ -841,15 +1426,27 @@ async function discoverPluginActions(pluginPath, projectRoot, registry = actionR
|
|
|
841
1426
|
} else {
|
|
842
1427
|
pluginModule = await import(modulePath);
|
|
843
1428
|
}
|
|
844
|
-
for (const
|
|
1429
|
+
for (const entry of pluginConfig.actions) {
|
|
1430
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
845
1431
|
const actionExport = pluginModule[actionName];
|
|
846
1432
|
if (actionExport && isJayAction(actionExport)) {
|
|
847
1433
|
registry.register(actionExport);
|
|
848
|
-
|
|
1434
|
+
const registeredName = actionExport.actionName;
|
|
1435
|
+
registeredActions.push(registeredName);
|
|
1436
|
+
if (actionPath) {
|
|
1437
|
+
const metadataFilePath = resolveActionMetadataPath(actionPath, pluginPath);
|
|
1438
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
1439
|
+
if (metadata) {
|
|
1440
|
+
registry.setMetadata(registeredName, metadata);
|
|
1441
|
+
if (verbose) {
|
|
1442
|
+
getLogger().info(
|
|
1443
|
+
`[Actions] Loaded metadata for "${registeredName}" from ${actionPath}`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
849
1448
|
if (verbose) {
|
|
850
|
-
getLogger().info(
|
|
851
|
-
`[Actions] Registered plugin action: ${actionExport.actionName}`
|
|
852
|
-
);
|
|
1449
|
+
getLogger().info(`[Actions] Registered plugin action: ${registeredName}`);
|
|
853
1450
|
}
|
|
854
1451
|
} else {
|
|
855
1452
|
getLogger().warn(
|
|
@@ -999,7 +1596,8 @@ async function discoverPluginsWithInit(options) {
|
|
|
999
1596
|
isLocal: scanned.isLocal,
|
|
1000
1597
|
initModule: initConfig.module,
|
|
1001
1598
|
initExport: initConfig.export,
|
|
1002
|
-
dependencies: scanned.dependencies
|
|
1599
|
+
dependencies: scanned.dependencies,
|
|
1600
|
+
global: scanned.manifest.global === true
|
|
1003
1601
|
});
|
|
1004
1602
|
if (verbose) {
|
|
1005
1603
|
getLogger().info(`[PluginInit] Found plugin with init: ${scanned.name}`);
|
|
@@ -1073,6 +1671,7 @@ function sortPluginsByDependencies(plugins) {
|
|
|
1073
1671
|
return sorted;
|
|
1074
1672
|
}
|
|
1075
1673
|
async function executePluginServerInits(plugins, viteServer, verbose = false) {
|
|
1674
|
+
const initErrors = /* @__PURE__ */ new Map();
|
|
1076
1675
|
for (const plugin of plugins) {
|
|
1077
1676
|
try {
|
|
1078
1677
|
let modulePath;
|
|
@@ -1106,11 +1705,14 @@ async function executePluginServerInits(plugins, viteServer, verbose = false) {
|
|
|
1106
1705
|
}
|
|
1107
1706
|
}
|
|
1108
1707
|
} catch (error) {
|
|
1708
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1709
|
+
initErrors.set(plugin.name, err);
|
|
1109
1710
|
getLogger().error(
|
|
1110
1711
|
`[PluginInit] Failed to execute server init for "${plugin.name}": ${error}`
|
|
1111
1712
|
);
|
|
1112
1713
|
}
|
|
1113
1714
|
}
|
|
1715
|
+
return initErrors;
|
|
1114
1716
|
}
|
|
1115
1717
|
function preparePluginClientInits(plugins) {
|
|
1116
1718
|
return plugins.map((plugin) => {
|
|
@@ -1129,16 +1731,8 @@ function preparePluginClientInits(plugins) {
|
|
|
1129
1731
|
};
|
|
1130
1732
|
});
|
|
1131
1733
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
(acc, key) => {
|
|
1135
|
-
acc[key] = params[key];
|
|
1136
|
-
return acc;
|
|
1137
|
-
},
|
|
1138
|
-
{}
|
|
1139
|
-
);
|
|
1140
|
-
return `${jayHtmlPath}:${JSON.stringify(sortedParams)}`;
|
|
1141
|
-
}
|
|
1734
|
+
const CACHE_TAG_START = '<script type="application/jay-cache">';
|
|
1735
|
+
const CACHE_TAG_END = "<\/script>";
|
|
1142
1736
|
function hashParams(params) {
|
|
1143
1737
|
const sortedParams = Object.keys(params).sort().reduce(
|
|
1144
1738
|
(acc, key) => {
|
|
@@ -1152,81 +1746,126 @@ function hashParams(params) {
|
|
|
1152
1746
|
return "";
|
|
1153
1747
|
return "_" + crypto.createHash("md5").update(json).digest("hex").substring(0, 8);
|
|
1154
1748
|
}
|
|
1749
|
+
function embedCacheMetadata(jayHtmlContent, slowViewState, carryForward, sourcePath) {
|
|
1750
|
+
const metadata = JSON.stringify({ slowViewState, carryForward, sourcePath });
|
|
1751
|
+
const cacheTag = `${CACHE_TAG_START}${metadata}${CACHE_TAG_END}`;
|
|
1752
|
+
const headMatch = jayHtmlContent.match(/<head[^>]*>/i);
|
|
1753
|
+
if (headMatch) {
|
|
1754
|
+
const insertPos = headMatch.index + headMatch[0].length;
|
|
1755
|
+
return jayHtmlContent.substring(0, insertPos) + "\n" + cacheTag + jayHtmlContent.substring(insertPos);
|
|
1756
|
+
}
|
|
1757
|
+
return `${cacheTag}
|
|
1758
|
+
${jayHtmlContent}`;
|
|
1759
|
+
}
|
|
1760
|
+
function extractCacheMetadata(fileContent) {
|
|
1761
|
+
const startIdx = fileContent.indexOf(CACHE_TAG_START);
|
|
1762
|
+
if (startIdx === -1)
|
|
1763
|
+
return void 0;
|
|
1764
|
+
const jsonStart = startIdx + CACHE_TAG_START.length;
|
|
1765
|
+
const endIdx = fileContent.indexOf(CACHE_TAG_END, jsonStart);
|
|
1766
|
+
if (endIdx === -1)
|
|
1767
|
+
return void 0;
|
|
1768
|
+
const jsonStr = fileContent.substring(jsonStart, endIdx);
|
|
1769
|
+
const metadata = JSON.parse(jsonStr);
|
|
1770
|
+
const tagEnd = endIdx + CACHE_TAG_END.length;
|
|
1771
|
+
const afterTag = fileContent[tagEnd] === "\n" ? tagEnd + 1 : tagEnd;
|
|
1772
|
+
const content = fileContent.substring(0, startIdx) + fileContent.substring(afterTag);
|
|
1773
|
+
return {
|
|
1774
|
+
content,
|
|
1775
|
+
slowViewState: metadata.slowViewState,
|
|
1776
|
+
carryForward: metadata.carryForward,
|
|
1777
|
+
sourcePath: metadata.sourcePath
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1155
1780
|
class SlowRenderCache {
|
|
1156
1781
|
/**
|
|
1157
1782
|
* @param cacheDir - Directory where pre-rendered jay-html files are stored
|
|
1158
1783
|
* @param pagesRoot - Root directory of the pages (for relative path calculation)
|
|
1159
1784
|
*/
|
|
1160
1785
|
constructor(cacheDir, pagesRoot) {
|
|
1161
|
-
|
|
1162
|
-
__publicField(this, "
|
|
1786
|
+
/** Maps source jay-html path → set of pre-rendered file paths (for invalidation) */
|
|
1787
|
+
__publicField(this, "pathToFiles", /* @__PURE__ */ new Map());
|
|
1163
1788
|
__publicField(this, "cacheDir");
|
|
1164
1789
|
__publicField(this, "pagesRoot");
|
|
1165
1790
|
this.cacheDir = cacheDir;
|
|
1166
1791
|
this.pagesRoot = pagesRoot;
|
|
1167
1792
|
}
|
|
1168
1793
|
/**
|
|
1169
|
-
* Get a cached pre-rendered jay-html entry
|
|
1794
|
+
* Get a cached pre-rendered jay-html entry by reading from disk.
|
|
1795
|
+
* Returns undefined if the cache file doesn't exist or has no metadata tag.
|
|
1170
1796
|
*/
|
|
1171
|
-
get(jayHtmlPath, params) {
|
|
1172
|
-
const
|
|
1173
|
-
|
|
1797
|
+
async get(jayHtmlPath, params) {
|
|
1798
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1799
|
+
let fileContent;
|
|
1800
|
+
try {
|
|
1801
|
+
fileContent = await fs$2.readFile(preRenderedPath, "utf-8");
|
|
1802
|
+
} catch {
|
|
1803
|
+
return void 0;
|
|
1804
|
+
}
|
|
1805
|
+
const extracted = extractCacheMetadata(fileContent);
|
|
1806
|
+
if (!extracted)
|
|
1807
|
+
return void 0;
|
|
1808
|
+
this.trackFile(jayHtmlPath, preRenderedPath);
|
|
1809
|
+
return {
|
|
1810
|
+
preRenderedPath,
|
|
1811
|
+
preRenderedContent: extracted.content,
|
|
1812
|
+
slowViewState: extracted.slowViewState,
|
|
1813
|
+
carryForward: extracted.carryForward,
|
|
1814
|
+
sourcePath: extracted.sourcePath
|
|
1815
|
+
};
|
|
1174
1816
|
}
|
|
1175
1817
|
/**
|
|
1176
|
-
* Store a pre-rendered jay-html entry
|
|
1177
|
-
*
|
|
1818
|
+
* Store a pre-rendered jay-html entry.
|
|
1819
|
+
* Embeds metadata as a <script> tag and writes to disk.
|
|
1820
|
+
* Returns the full cache entry with stripped content.
|
|
1178
1821
|
*/
|
|
1179
1822
|
async set(jayHtmlPath, params, preRenderedJayHtml, slowViewState, carryForward) {
|
|
1180
|
-
const
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
await fs$
|
|
1188
|
-
await fs$
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
}
|
|
1192
|
-
this.pathToKeys.get(jayHtmlPath).add(key);
|
|
1193
|
-
const entry = {
|
|
1823
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1824
|
+
const fileContent = embedCacheMetadata(
|
|
1825
|
+
preRenderedJayHtml,
|
|
1826
|
+
slowViewState,
|
|
1827
|
+
carryForward,
|
|
1828
|
+
jayHtmlPath
|
|
1829
|
+
);
|
|
1830
|
+
await fs$2.mkdir(path__default.dirname(preRenderedPath), { recursive: true });
|
|
1831
|
+
await fs$2.writeFile(preRenderedPath, fileContent, "utf-8");
|
|
1832
|
+
this.trackFile(jayHtmlPath, preRenderedPath);
|
|
1833
|
+
return {
|
|
1194
1834
|
preRenderedPath,
|
|
1835
|
+
preRenderedContent: preRenderedJayHtml,
|
|
1195
1836
|
slowViewState,
|
|
1196
1837
|
carryForward,
|
|
1197
|
-
createdAt: Date.now(),
|
|
1198
1838
|
sourcePath: jayHtmlPath
|
|
1199
1839
|
};
|
|
1200
|
-
this.cache.set(key, entry);
|
|
1201
|
-
return preRenderedPath;
|
|
1202
1840
|
}
|
|
1203
1841
|
/**
|
|
1204
1842
|
* Check if a pre-rendered entry exists for the given path and params
|
|
1205
1843
|
*/
|
|
1206
|
-
has(jayHtmlPath, params) {
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1844
|
+
async has(jayHtmlPath, params) {
|
|
1845
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1846
|
+
try {
|
|
1847
|
+
await fs$2.access(preRenderedPath);
|
|
1848
|
+
return true;
|
|
1849
|
+
} catch {
|
|
1850
|
+
return false;
|
|
1851
|
+
}
|
|
1209
1852
|
}
|
|
1210
1853
|
/**
|
|
1211
1854
|
* Invalidate all cached entries for a given jay-html source path.
|
|
1212
|
-
*
|
|
1213
|
-
* Also deletes the cached files from disk.
|
|
1855
|
+
* Deletes cached files from disk.
|
|
1214
1856
|
*/
|
|
1215
1857
|
async invalidate(jayHtmlPath) {
|
|
1216
|
-
const
|
|
1217
|
-
if (
|
|
1218
|
-
for (const
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
await fs$1.unlink(entry.preRenderedPath);
|
|
1223
|
-
} catch {
|
|
1224
|
-
}
|
|
1858
|
+
const files = this.pathToFiles.get(jayHtmlPath);
|
|
1859
|
+
if (files) {
|
|
1860
|
+
for (const filePath of files) {
|
|
1861
|
+
try {
|
|
1862
|
+
await fs$2.unlink(filePath);
|
|
1863
|
+
} catch {
|
|
1225
1864
|
}
|
|
1226
|
-
this.cache.delete(key);
|
|
1227
1865
|
}
|
|
1228
|
-
this.
|
|
1866
|
+
this.pathToFiles.delete(jayHtmlPath);
|
|
1229
1867
|
}
|
|
1868
|
+
await this.scanAndDeleteCacheFiles(jayHtmlPath);
|
|
1230
1869
|
}
|
|
1231
1870
|
/**
|
|
1232
1871
|
* Invalidate all entries that depend on a changed file.
|
|
@@ -1254,26 +1893,67 @@ class SlowRenderCache {
|
|
|
1254
1893
|
* Clear all cached entries and delete cached files from disk
|
|
1255
1894
|
*/
|
|
1256
1895
|
async clear() {
|
|
1257
|
-
for (const
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1896
|
+
for (const files of this.pathToFiles.values()) {
|
|
1897
|
+
for (const filePath of files) {
|
|
1898
|
+
try {
|
|
1899
|
+
await fs$2.unlink(filePath);
|
|
1900
|
+
} catch {
|
|
1901
|
+
}
|
|
1261
1902
|
}
|
|
1262
1903
|
}
|
|
1263
|
-
this.
|
|
1264
|
-
|
|
1904
|
+
this.pathToFiles.clear();
|
|
1905
|
+
try {
|
|
1906
|
+
await fs$2.rm(this.cacheDir, { recursive: true, force: true });
|
|
1907
|
+
} catch {
|
|
1908
|
+
}
|
|
1265
1909
|
}
|
|
1266
1910
|
/**
|
|
1267
|
-
* Get
|
|
1911
|
+
* Get all cached jay-html paths (for debugging/monitoring)
|
|
1268
1912
|
*/
|
|
1269
|
-
|
|
1270
|
-
return this.
|
|
1913
|
+
getCachedPaths() {
|
|
1914
|
+
return Array.from(this.pathToFiles.keys());
|
|
1271
1915
|
}
|
|
1272
1916
|
/**
|
|
1273
|
-
*
|
|
1917
|
+
* Compute the cache file path for a given jay-html path and params.
|
|
1274
1918
|
*/
|
|
1275
|
-
|
|
1276
|
-
|
|
1919
|
+
computeCachePath(jayHtmlPath, params) {
|
|
1920
|
+
const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
|
|
1921
|
+
const dir = path__default.dirname(relativePath);
|
|
1922
|
+
const basename = path__default.basename(relativePath, ".jay-html");
|
|
1923
|
+
const paramsHash = hashParams(params);
|
|
1924
|
+
const cacheFileName = `${basename}${paramsHash}.jay-html`;
|
|
1925
|
+
return path__default.join(this.cacheDir, dir, cacheFileName);
|
|
1926
|
+
}
|
|
1927
|
+
/**
|
|
1928
|
+
* Track a pre-rendered file path for invalidation.
|
|
1929
|
+
*/
|
|
1930
|
+
trackFile(jayHtmlPath, preRenderedPath) {
|
|
1931
|
+
if (!this.pathToFiles.has(jayHtmlPath)) {
|
|
1932
|
+
this.pathToFiles.set(jayHtmlPath, /* @__PURE__ */ new Set());
|
|
1933
|
+
}
|
|
1934
|
+
this.pathToFiles.get(jayHtmlPath).add(preRenderedPath);
|
|
1935
|
+
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Scan the cache directory for files matching a route and delete them.
|
|
1938
|
+
* Handles the startup case where pathToFiles is not populated from a previous session.
|
|
1939
|
+
*/
|
|
1940
|
+
async scanAndDeleteCacheFiles(jayHtmlPath) {
|
|
1941
|
+
const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
|
|
1942
|
+
const dir = path__default.dirname(relativePath);
|
|
1943
|
+
const basename = path__default.basename(relativePath, ".jay-html");
|
|
1944
|
+
const cacheSubDir = path__default.join(this.cacheDir, dir);
|
|
1945
|
+
try {
|
|
1946
|
+
const files = await fs$2.readdir(cacheSubDir);
|
|
1947
|
+
for (const file of files) {
|
|
1948
|
+
if (file.startsWith(basename) && file.endsWith(".jay-html")) {
|
|
1949
|
+
try {
|
|
1950
|
+
await fs$2.unlink(path__default.join(cacheSubDir, file));
|
|
1951
|
+
} catch {
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
} catch {
|
|
1956
|
+
}
|
|
1277
1957
|
}
|
|
1278
1958
|
}
|
|
1279
1959
|
const require2 = createRequire(import.meta.url);
|
|
@@ -1361,8 +2041,7 @@ async function executeDynamicGenerator(plugin, config, projectRoot, services, ve
|
|
|
1361
2041
|
if (verbose) {
|
|
1362
2042
|
getLogger().info(` Executing generator...`);
|
|
1363
2043
|
}
|
|
1364
|
-
|
|
1365
|
-
return result;
|
|
2044
|
+
return await generator.generate(...resolvedServices);
|
|
1366
2045
|
}
|
|
1367
2046
|
function resolveStaticContractPath(plugin, contractSpec, projectRoot) {
|
|
1368
2047
|
const { pluginPath, isLocal, packageName } = plugin;
|
|
@@ -1384,6 +2063,25 @@ function resolveStaticContractPath(plugin, contractSpec, projectRoot) {
|
|
|
1384
2063
|
return path.join(pluginPath, contractSpec);
|
|
1385
2064
|
}
|
|
1386
2065
|
}
|
|
2066
|
+
function resolveActionFilePath(actionPath, packageName, pluginPath, isLocal, projectRoot) {
|
|
2067
|
+
if (!isLocal && !actionPath.startsWith(".")) {
|
|
2068
|
+
try {
|
|
2069
|
+
return require2.resolve(`${packageName}/${actionPath}`, {
|
|
2070
|
+
paths: [projectRoot]
|
|
2071
|
+
});
|
|
2072
|
+
} catch {
|
|
2073
|
+
const possiblePaths = [
|
|
2074
|
+
path.join(pluginPath, "dist", actionPath),
|
|
2075
|
+
path.join(pluginPath, "lib", actionPath),
|
|
2076
|
+
path.join(pluginPath, actionPath)
|
|
2077
|
+
];
|
|
2078
|
+
const found = possiblePaths.find((p) => fs.existsSync(p));
|
|
2079
|
+
return found || null;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
const resolved = resolveActionMetadataPath(actionPath, pluginPath);
|
|
2083
|
+
return fs.existsSync(resolved) ? resolved : null;
|
|
2084
|
+
}
|
|
1387
2085
|
function toKebabCase(str) {
|
|
1388
2086
|
return str.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
1389
2087
|
}
|
|
@@ -1399,13 +2097,12 @@ function getJayStackVersion() {
|
|
|
1399
2097
|
async function materializeContracts(options, services = /* @__PURE__ */ new Map()) {
|
|
1400
2098
|
const {
|
|
1401
2099
|
projectRoot,
|
|
1402
|
-
outputDir = path.join(projectRoot, "
|
|
2100
|
+
outputDir = path.join(projectRoot, "agent-kit", "materialized-contracts"),
|
|
1403
2101
|
dynamicOnly = false,
|
|
1404
2102
|
pluginFilter,
|
|
1405
2103
|
verbose = false,
|
|
1406
2104
|
viteServer
|
|
1407
2105
|
} = options;
|
|
1408
|
-
const contracts = [];
|
|
1409
2106
|
const pluginsIndexMap = /* @__PURE__ */ new Map();
|
|
1410
2107
|
let staticCount = 0;
|
|
1411
2108
|
let dynamicCount = 0;
|
|
@@ -1429,6 +2126,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1429
2126
|
📦 Processing plugin: ${plugin.name}`);
|
|
1430
2127
|
}
|
|
1431
2128
|
const { manifest } = plugin;
|
|
2129
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
2130
|
+
if (!pluginsIndexMap.has(plugin.name)) {
|
|
2131
|
+
pluginsIndexMap.set(plugin.name, {
|
|
2132
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
2133
|
+
contracts: [],
|
|
2134
|
+
actions: []
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
1432
2137
|
if (!dynamicOnly && manifest.contracts) {
|
|
1433
2138
|
for (const contract of manifest.contracts) {
|
|
1434
2139
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1437,26 +2142,12 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1437
2142
|
projectRoot
|
|
1438
2143
|
);
|
|
1439
2144
|
const relativePath = path.relative(projectRoot, contractPath);
|
|
1440
|
-
const entry = {
|
|
1441
|
-
plugin: plugin.name,
|
|
1442
|
-
name: contract.name,
|
|
1443
|
-
type: "static",
|
|
1444
|
-
path: "./" + relativePath
|
|
1445
|
-
};
|
|
1446
|
-
contracts.push(entry);
|
|
1447
|
-
staticCount++;
|
|
1448
|
-
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1449
|
-
if (!pluginsIndexMap.has(plugin.name)) {
|
|
1450
|
-
pluginsIndexMap.set(plugin.name, {
|
|
1451
|
-
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1452
|
-
contracts: []
|
|
1453
|
-
});
|
|
1454
|
-
}
|
|
1455
2145
|
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1456
2146
|
name: contract.name,
|
|
1457
2147
|
type: "static",
|
|
1458
2148
|
path: "./" + relativePath
|
|
1459
2149
|
});
|
|
2150
|
+
staticCount++;
|
|
1460
2151
|
if (verbose) {
|
|
1461
2152
|
getLogger().info(` 📄 Static: ${contract.name}`);
|
|
1462
2153
|
}
|
|
@@ -1486,27 +2177,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1486
2177
|
const filePath = path.join(pluginOutputDir, fileName);
|
|
1487
2178
|
fs.writeFileSync(filePath, generated.yaml, "utf-8");
|
|
1488
2179
|
const relativePath = path.relative(projectRoot, filePath);
|
|
1489
|
-
const
|
|
1490
|
-
plugin: plugin.name,
|
|
2180
|
+
const contractEntry = {
|
|
1491
2181
|
name: fullName,
|
|
1492
2182
|
type: "dynamic",
|
|
1493
2183
|
path: "./" + relativePath,
|
|
1494
|
-
metadata: generated.metadata
|
|
2184
|
+
...generated.metadata && { metadata: generated.metadata }
|
|
1495
2185
|
};
|
|
1496
|
-
contracts.push(
|
|
2186
|
+
pluginsIndexMap.get(plugin.name).contracts.push(contractEntry);
|
|
1497
2187
|
dynamicCount++;
|
|
1498
|
-
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1499
|
-
if (!pluginsIndexMap.has(plugin.name)) {
|
|
1500
|
-
pluginsIndexMap.set(plugin.name, {
|
|
1501
|
-
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1502
|
-
contracts: []
|
|
1503
|
-
});
|
|
1504
|
-
}
|
|
1505
|
-
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1506
|
-
name: fullName,
|
|
1507
|
-
type: "dynamic",
|
|
1508
|
-
path: "./" + relativePath
|
|
1509
|
-
});
|
|
1510
2188
|
if (verbose) {
|
|
1511
2189
|
getLogger().info(` ⚡ Materialized: ${fullName}`);
|
|
1512
2190
|
}
|
|
@@ -1518,33 +2196,54 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1518
2196
|
}
|
|
1519
2197
|
}
|
|
1520
2198
|
}
|
|
2199
|
+
if (manifest.actions && Array.isArray(manifest.actions)) {
|
|
2200
|
+
for (const entry of manifest.actions) {
|
|
2201
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
2202
|
+
if (!actionPath)
|
|
2203
|
+
continue;
|
|
2204
|
+
const metadataFilePath = resolveActionFilePath(
|
|
2205
|
+
actionPath,
|
|
2206
|
+
plugin.packageName,
|
|
2207
|
+
plugin.pluginPath,
|
|
2208
|
+
plugin.isLocal,
|
|
2209
|
+
projectRoot
|
|
2210
|
+
);
|
|
2211
|
+
if (!metadataFilePath)
|
|
2212
|
+
continue;
|
|
2213
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
2214
|
+
if (!metadata)
|
|
2215
|
+
continue;
|
|
2216
|
+
const actionRelPath = path.relative(projectRoot, metadataFilePath);
|
|
2217
|
+
pluginsIndexMap.get(plugin.name).actions.push({
|
|
2218
|
+
name: metadata.name,
|
|
2219
|
+
description: metadata.description,
|
|
2220
|
+
path: "./" + actionRelPath.replace(/\\/g, "/")
|
|
2221
|
+
});
|
|
2222
|
+
if (verbose) {
|
|
2223
|
+
getLogger().info(` 🔧 Action: ${metadata.name} (${actionPath})`);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
1521
2227
|
}
|
|
1522
|
-
const index = {
|
|
1523
|
-
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1524
|
-
jay_stack_version: getJayStackVersion(),
|
|
1525
|
-
contracts
|
|
1526
|
-
};
|
|
1527
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
1528
|
-
const indexPath = path.join(outputDir, "contracts-index.yaml");
|
|
1529
|
-
fs.writeFileSync(indexPath, YAML.stringify(index), "utf-8");
|
|
1530
2228
|
const pluginsIndex = {
|
|
1531
|
-
|
|
1532
|
-
jay_stack_version: index.jay_stack_version,
|
|
2229
|
+
jay_stack_version: getJayStackVersion(),
|
|
1533
2230
|
plugins: Array.from(pluginsIndexMap.entries()).map(([name, data]) => ({
|
|
1534
2231
|
name,
|
|
1535
2232
|
path: data.path,
|
|
1536
|
-
contracts: data.contracts
|
|
2233
|
+
contracts: data.contracts,
|
|
2234
|
+
...data.actions.length > 0 && { actions: data.actions }
|
|
1537
2235
|
}))
|
|
1538
2236
|
};
|
|
1539
|
-
|
|
2237
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
2238
|
+
const agentKitDir = path.dirname(outputDir);
|
|
2239
|
+
const pluginsIndexPath = path.join(agentKitDir, "plugins-index.yaml");
|
|
1540
2240
|
fs.writeFileSync(pluginsIndexPath, YAML.stringify(pluginsIndex), "utf-8");
|
|
1541
2241
|
if (verbose) {
|
|
1542
2242
|
getLogger().info(`
|
|
1543
|
-
✅
|
|
1544
|
-
getLogger().info(`✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
2243
|
+
✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
1545
2244
|
}
|
|
1546
2245
|
return {
|
|
1547
|
-
|
|
2246
|
+
pluginsIndex,
|
|
1548
2247
|
staticCount,
|
|
1549
2248
|
dynamicCount,
|
|
1550
2249
|
outputDir
|
|
@@ -1552,7 +2251,7 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1552
2251
|
}
|
|
1553
2252
|
async function listContracts(options) {
|
|
1554
2253
|
const { projectRoot, dynamicOnly = false, pluginFilter } = options;
|
|
1555
|
-
const
|
|
2254
|
+
const pluginsMap = /* @__PURE__ */ new Map();
|
|
1556
2255
|
const plugins = await scanPlugins({
|
|
1557
2256
|
projectRoot,
|
|
1558
2257
|
includeDevDeps: true
|
|
@@ -1561,6 +2260,13 @@ async function listContracts(options) {
|
|
|
1561
2260
|
if (pluginFilter && plugin.name !== pluginFilter && pluginKey !== pluginFilter)
|
|
1562
2261
|
continue;
|
|
1563
2262
|
const { manifest } = plugin;
|
|
2263
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
2264
|
+
if (!pluginsMap.has(plugin.name)) {
|
|
2265
|
+
pluginsMap.set(plugin.name, {
|
|
2266
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
2267
|
+
contracts: []
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
1564
2270
|
if (!dynamicOnly && manifest.contracts) {
|
|
1565
2271
|
for (const contract of manifest.contracts) {
|
|
1566
2272
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1569,8 +2275,7 @@ async function listContracts(options) {
|
|
|
1569
2275
|
projectRoot
|
|
1570
2276
|
);
|
|
1571
2277
|
const relativePath = path.relative(projectRoot, contractPath);
|
|
1572
|
-
contracts.push({
|
|
1573
|
-
plugin: plugin.name,
|
|
2278
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1574
2279
|
name: contract.name,
|
|
1575
2280
|
type: "static",
|
|
1576
2281
|
path: "./" + relativePath
|
|
@@ -1580,8 +2285,7 @@ async function listContracts(options) {
|
|
|
1580
2285
|
if (manifest.dynamic_contracts) {
|
|
1581
2286
|
const dynamicConfigs = Array.isArray(manifest.dynamic_contracts) ? manifest.dynamic_contracts : [manifest.dynamic_contracts];
|
|
1582
2287
|
for (const config of dynamicConfigs) {
|
|
1583
|
-
contracts.push({
|
|
1584
|
-
plugin: plugin.name,
|
|
2288
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1585
2289
|
name: `${config.prefix}/*`,
|
|
1586
2290
|
type: "dynamic",
|
|
1587
2291
|
path: "(run materialization to generate)"
|
|
@@ -1590,9 +2294,12 @@ async function listContracts(options) {
|
|
|
1590
2294
|
}
|
|
1591
2295
|
}
|
|
1592
2296
|
return {
|
|
1593
|
-
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1594
2297
|
jay_stack_version: getJayStackVersion(),
|
|
1595
|
-
|
|
2298
|
+
plugins: Array.from(pluginsMap.entries()).map(([name, data]) => ({
|
|
2299
|
+
name,
|
|
2300
|
+
path: data.path,
|
|
2301
|
+
contracts: data.contracts
|
|
2302
|
+
}))
|
|
1596
2303
|
};
|
|
1597
2304
|
}
|
|
1598
2305
|
async function discoverPluginsWithSetup(options) {
|
|
@@ -1673,13 +2380,14 @@ async function executePluginSetup(plugin, options) {
|
|
|
1673
2380
|
return handler(context);
|
|
1674
2381
|
}
|
|
1675
2382
|
async function executePluginReferences(plugin, options) {
|
|
1676
|
-
const { projectRoot, force, viteServer } = options;
|
|
2383
|
+
const { projectRoot, force, initError, viteServer } = options;
|
|
1677
2384
|
const referencesDir = path.join(projectRoot, "agent-kit", "references", plugin.name);
|
|
1678
2385
|
const context = {
|
|
1679
2386
|
pluginName: plugin.name,
|
|
1680
2387
|
projectRoot,
|
|
1681
2388
|
referencesDir,
|
|
1682
2389
|
services: getServiceRegistry(),
|
|
2390
|
+
initError,
|
|
1683
2391
|
force
|
|
1684
2392
|
};
|
|
1685
2393
|
const handler = await loadHandler(
|
|
@@ -1726,9 +2434,12 @@ export {
|
|
|
1726
2434
|
DevSlowlyChangingPhase,
|
|
1727
2435
|
SlowRenderCache,
|
|
1728
2436
|
actionRegistry,
|
|
2437
|
+
buildAutomationWrap,
|
|
2438
|
+
buildScriptFragments,
|
|
1729
2439
|
clearActionRegistry,
|
|
1730
2440
|
clearClientInitData,
|
|
1731
2441
|
clearLifecycleCallbacks,
|
|
2442
|
+
clearServerElementCache,
|
|
1732
2443
|
clearServiceRegistry,
|
|
1733
2444
|
discoverAllPluginActions,
|
|
1734
2445
|
discoverAndRegisterActions,
|
|
@@ -1741,6 +2452,7 @@ export {
|
|
|
1741
2452
|
executePluginServerInits,
|
|
1742
2453
|
executePluginSetup,
|
|
1743
2454
|
generateClientScript,
|
|
2455
|
+
generateSSRPageHtml,
|
|
1744
2456
|
getActionCacheHeaders,
|
|
1745
2457
|
getClientInitData,
|
|
1746
2458
|
getClientInitDataForKey,
|
|
@@ -1750,15 +2462,19 @@ export {
|
|
|
1750
2462
|
getServiceRegistry,
|
|
1751
2463
|
hasAction,
|
|
1752
2464
|
hasService,
|
|
2465
|
+
invalidateServerElementCache,
|
|
1753
2466
|
listContracts,
|
|
2467
|
+
loadActionMetadata,
|
|
1754
2468
|
loadPageParts,
|
|
1755
2469
|
materializeContracts,
|
|
1756
2470
|
onInit,
|
|
1757
2471
|
onShutdown,
|
|
2472
|
+
parseActionMetadata,
|
|
1758
2473
|
preparePluginClientInits,
|
|
1759
2474
|
registerAction,
|
|
1760
2475
|
registerService,
|
|
1761
2476
|
renderFastChangingData,
|
|
2477
|
+
resolveActionMetadataPath,
|
|
1762
2478
|
resolveServices,
|
|
1763
2479
|
runInitCallbacks,
|
|
1764
2480
|
runLoadParams,
|
|
@@ -1767,5 +2483,6 @@ export {
|
|
|
1767
2483
|
scanPlugins,
|
|
1768
2484
|
setClientInitData,
|
|
1769
2485
|
slowRenderInstances,
|
|
1770
|
-
sortPluginsByDependencies
|
|
2486
|
+
sortPluginsByDependencies,
|
|
2487
|
+
validateForEachInstances
|
|
1771
2488
|
};
|