@jay-framework/stack-server-runtime 0.13.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 +164 -106
- package/dist/index.js +789 -357
- 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, parseAction } 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
|
}
|
|
@@ -551,200 +1095,35 @@ class ActionRegistry {
|
|
|
551
1095
|
const parts = [];
|
|
552
1096
|
if (maxAge !== void 0) {
|
|
553
1097
|
parts.push(`max-age=${maxAge}`);
|
|
554
|
-
}
|
|
555
|
-
if (staleWhileRevalidate !== void 0) {
|
|
556
|
-
parts.push(`stale-while-revalidate=${staleWhileRevalidate}`);
|
|
557
|
-
}
|
|
558
|
-
return parts.length > 0 ? parts.join(", ") : void 0;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
const actionRegistry = new ActionRegistry();
|
|
562
|
-
function registerAction(action) {
|
|
563
|
-
actionRegistry.register(action);
|
|
564
|
-
}
|
|
565
|
-
function getRegisteredAction(actionName) {
|
|
566
|
-
return actionRegistry.get(actionName);
|
|
567
|
-
}
|
|
568
|
-
function hasAction(actionName) {
|
|
569
|
-
return actionRegistry.has(actionName);
|
|
570
|
-
}
|
|
571
|
-
function getRegisteredActionNames() {
|
|
572
|
-
return actionRegistry.getNames();
|
|
573
|
-
}
|
|
574
|
-
function clearActionRegistry() {
|
|
575
|
-
actionRegistry.clear();
|
|
576
|
-
}
|
|
577
|
-
async function executeAction(actionName, input) {
|
|
578
|
-
return actionRegistry.execute(actionName, input);
|
|
579
|
-
}
|
|
580
|
-
function getActionCacheHeaders(actionName) {
|
|
581
|
-
return actionRegistry.getCacheHeaders(actionName);
|
|
582
|
-
}
|
|
583
|
-
var __defProp2 = Object.defineProperty;
|
|
584
|
-
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
585
|
-
var __publicField2 = (obj, key, value) => {
|
|
586
|
-
__defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
587
|
-
return value;
|
|
588
|
-
};
|
|
589
|
-
class JayAtomicType {
|
|
590
|
-
constructor(name) {
|
|
591
|
-
__publicField2(this, "kind", 0);
|
|
592
|
-
this.name = name;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
new JayAtomicType("string");
|
|
596
|
-
new JayAtomicType("number");
|
|
597
|
-
new JayAtomicType("boolean");
|
|
598
|
-
new JayAtomicType("Date");
|
|
599
|
-
new JayAtomicType("Unknown");
|
|
600
|
-
class JayObjectType {
|
|
601
|
-
constructor(name, props) {
|
|
602
|
-
__publicField2(this, "kind", 8);
|
|
603
|
-
this.name = name;
|
|
604
|
-
this.props = props;
|
|
1098
|
+
}
|
|
1099
|
+
if (staleWhileRevalidate !== void 0) {
|
|
1100
|
+
parts.push(`stale-while-revalidate=${staleWhileRevalidate}`);
|
|
1101
|
+
}
|
|
1102
|
+
return parts.length > 0 ? parts.join(", ") : void 0;
|
|
605
1103
|
}
|
|
606
1104
|
}
|
|
607
|
-
new
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
stack: new JayAtomicType("string")
|
|
611
|
-
});
|
|
612
|
-
function isOptionalType(aType) {
|
|
613
|
-
return aType.kind === 13;
|
|
614
|
-
}
|
|
615
|
-
function isAtomicType(aType) {
|
|
616
|
-
return aType.kind === 0;
|
|
617
|
-
}
|
|
618
|
-
function isEnumType(aType) {
|
|
619
|
-
return aType.kind === 2;
|
|
1105
|
+
const actionRegistry = new ActionRegistry();
|
|
1106
|
+
function registerAction(action) {
|
|
1107
|
+
actionRegistry.register(action);
|
|
620
1108
|
}
|
|
621
|
-
function
|
|
622
|
-
return
|
|
1109
|
+
function getRegisteredAction(actionName) {
|
|
1110
|
+
return actionRegistry.get(actionName);
|
|
623
1111
|
}
|
|
624
|
-
function
|
|
625
|
-
return
|
|
1112
|
+
function hasAction(actionName) {
|
|
1113
|
+
return actionRegistry.has(actionName);
|
|
626
1114
|
}
|
|
627
|
-
function
|
|
628
|
-
return
|
|
1115
|
+
function getRegisteredActionNames() {
|
|
1116
|
+
return actionRegistry.getNames();
|
|
629
1117
|
}
|
|
630
|
-
function
|
|
631
|
-
|
|
632
|
-
return jayTypeToJsonSchema(type.innerType);
|
|
633
|
-
}
|
|
634
|
-
if (isAtomicType(type)) {
|
|
635
|
-
const name = type.name.toLowerCase();
|
|
636
|
-
if (name === "string" || name === "number" || name === "boolean") {
|
|
637
|
-
return { type: name };
|
|
638
|
-
}
|
|
639
|
-
return { type: "string" };
|
|
640
|
-
}
|
|
641
|
-
if (isEnumType(type)) {
|
|
642
|
-
return { type: "string", enum: type.values };
|
|
643
|
-
}
|
|
644
|
-
if (isImportedType(type)) {
|
|
645
|
-
return { type: "object", description: `Contract: ${type.name}` };
|
|
646
|
-
}
|
|
647
|
-
if (isArrayType(type)) {
|
|
648
|
-
const itemSchema = jayTypeToJsonSchema(type.itemType);
|
|
649
|
-
if (itemSchema) {
|
|
650
|
-
return { type: "array", items: itemSchema };
|
|
651
|
-
}
|
|
652
|
-
return { type: "array" };
|
|
653
|
-
}
|
|
654
|
-
if (isObjectType(type)) {
|
|
655
|
-
const properties = {};
|
|
656
|
-
const required = [];
|
|
657
|
-
for (const [key, propType] of Object.entries(type.props)) {
|
|
658
|
-
const isOpt = isOptionalType(propType);
|
|
659
|
-
const schema = jayTypeToJsonSchema(propType);
|
|
660
|
-
if (schema) {
|
|
661
|
-
properties[key] = schema;
|
|
662
|
-
if (!isOpt) {
|
|
663
|
-
required.push(key);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
return {
|
|
668
|
-
type: "object",
|
|
669
|
-
properties,
|
|
670
|
-
...required.length > 0 && { required }
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
return null;
|
|
1118
|
+
function clearActionRegistry() {
|
|
1119
|
+
actionRegistry.clear();
|
|
674
1120
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
RuntimeMode2["MainSandbox"] = "mainSandbox";
|
|
678
|
-
RuntimeMode2["WorkerTrusted"] = "workerTrusted";
|
|
679
|
-
RuntimeMode2["WorkerSandbox"] = "workerSandbox";
|
|
680
|
-
return RuntimeMode2;
|
|
681
|
-
})(RuntimeMode || {});
|
|
682
|
-
const TS_EXTENSION = ".ts";
|
|
683
|
-
const JAY_QUERY_PREFIX = "?jay-";
|
|
684
|
-
[
|
|
685
|
-
// Build environments
|
|
686
|
-
{
|
|
687
|
-
pattern: `${JAY_QUERY_PREFIX}${"client"}`,
|
|
688
|
-
buildEnv: "client"
|
|
689
|
-
/* Client */
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
pattern: `${JAY_QUERY_PREFIX}${"server"}`,
|
|
693
|
-
buildEnv: "server"
|
|
694
|
-
/* Server */
|
|
695
|
-
},
|
|
696
|
-
// Runtime modes (with .ts suffix)
|
|
697
|
-
{
|
|
698
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}${TS_EXTENSION}`,
|
|
699
|
-
runtimeMode: RuntimeMode.MainSandbox
|
|
700
|
-
},
|
|
701
|
-
{
|
|
702
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}${TS_EXTENSION}`,
|
|
703
|
-
runtimeMode: RuntimeMode.WorkerTrusted
|
|
704
|
-
},
|
|
705
|
-
{
|
|
706
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}${TS_EXTENSION}`,
|
|
707
|
-
runtimeMode: RuntimeMode.WorkerSandbox
|
|
708
|
-
},
|
|
709
|
-
// Runtime modes (without .ts suffix)
|
|
710
|
-
{
|
|
711
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}`,
|
|
712
|
-
runtimeMode: RuntimeMode.MainSandbox
|
|
713
|
-
},
|
|
714
|
-
{
|
|
715
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}`,
|
|
716
|
-
runtimeMode: RuntimeMode.WorkerTrusted
|
|
717
|
-
},
|
|
718
|
-
{
|
|
719
|
-
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}`,
|
|
720
|
-
runtimeMode: RuntimeMode.WorkerSandbox
|
|
721
|
-
}
|
|
722
|
-
];
|
|
723
|
-
createRequire(import.meta.url);
|
|
724
|
-
function normalizeActionEntry(entry) {
|
|
725
|
-
if (typeof entry === "string") {
|
|
726
|
-
return { name: entry };
|
|
727
|
-
}
|
|
728
|
-
return { name: entry.name, action: entry.action };
|
|
1121
|
+
async function executeAction(actionName, input) {
|
|
1122
|
+
return actionRegistry.execute(actionName, input);
|
|
729
1123
|
}
|
|
730
|
-
function
|
|
731
|
-
|
|
732
|
-
if (!fs$2.existsSync(pluginYamlPath)) {
|
|
733
|
-
return null;
|
|
734
|
-
}
|
|
735
|
-
try {
|
|
736
|
-
const yamlContent = fs$2.readFileSync(pluginYamlPath, "utf-8");
|
|
737
|
-
return YAML.parse(yamlContent);
|
|
738
|
-
} catch (error) {
|
|
739
|
-
return null;
|
|
740
|
-
}
|
|
1124
|
+
function getActionCacheHeaders(actionName) {
|
|
1125
|
+
return actionRegistry.getCacheHeaders(actionName);
|
|
741
1126
|
}
|
|
742
|
-
const s = createRequire(import.meta.url), e = s("typescript");
|
|
743
|
-
new Proxy(e, {
|
|
744
|
-
get(t, r) {
|
|
745
|
-
return t[r];
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
1127
|
function parseActionMetadata(yamlContent, fileName) {
|
|
749
1128
|
try {
|
|
750
1129
|
const parsed = parseAction(yamlContent, fileName);
|
|
@@ -1352,16 +1731,8 @@ function preparePluginClientInits(plugins) {
|
|
|
1352
1731
|
};
|
|
1353
1732
|
});
|
|
1354
1733
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
(acc, key) => {
|
|
1358
|
-
acc[key] = params[key];
|
|
1359
|
-
return acc;
|
|
1360
|
-
},
|
|
1361
|
-
{}
|
|
1362
|
-
);
|
|
1363
|
-
return `${jayHtmlPath}:${JSON.stringify(sortedParams)}`;
|
|
1364
|
-
}
|
|
1734
|
+
const CACHE_TAG_START = '<script type="application/jay-cache">';
|
|
1735
|
+
const CACHE_TAG_END = "<\/script>";
|
|
1365
1736
|
function hashParams(params) {
|
|
1366
1737
|
const sortedParams = Object.keys(params).sort().reduce(
|
|
1367
1738
|
(acc, key) => {
|
|
@@ -1375,81 +1746,126 @@ function hashParams(params) {
|
|
|
1375
1746
|
return "";
|
|
1376
1747
|
return "_" + crypto.createHash("md5").update(json).digest("hex").substring(0, 8);
|
|
1377
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
|
+
}
|
|
1378
1780
|
class SlowRenderCache {
|
|
1379
1781
|
/**
|
|
1380
1782
|
* @param cacheDir - Directory where pre-rendered jay-html files are stored
|
|
1381
1783
|
* @param pagesRoot - Root directory of the pages (for relative path calculation)
|
|
1382
1784
|
*/
|
|
1383
1785
|
constructor(cacheDir, pagesRoot) {
|
|
1384
|
-
|
|
1385
|
-
__publicField(this, "
|
|
1786
|
+
/** Maps source jay-html path → set of pre-rendered file paths (for invalidation) */
|
|
1787
|
+
__publicField(this, "pathToFiles", /* @__PURE__ */ new Map());
|
|
1386
1788
|
__publicField(this, "cacheDir");
|
|
1387
1789
|
__publicField(this, "pagesRoot");
|
|
1388
1790
|
this.cacheDir = cacheDir;
|
|
1389
1791
|
this.pagesRoot = pagesRoot;
|
|
1390
1792
|
}
|
|
1391
1793
|
/**
|
|
1392
|
-
* 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.
|
|
1393
1796
|
*/
|
|
1394
|
-
get(jayHtmlPath, params) {
|
|
1395
|
-
const
|
|
1396
|
-
|
|
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
|
+
};
|
|
1397
1816
|
}
|
|
1398
1817
|
/**
|
|
1399
|
-
* Store a pre-rendered jay-html entry
|
|
1400
|
-
*
|
|
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.
|
|
1401
1821
|
*/
|
|
1402
1822
|
async set(jayHtmlPath, params, preRenderedJayHtml, slowViewState, carryForward) {
|
|
1403
|
-
const
|
|
1404
|
-
const
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
await fs$
|
|
1411
|
-
await fs$
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
this.pathToKeys.get(jayHtmlPath).add(key);
|
|
1416
|
-
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 {
|
|
1417
1834
|
preRenderedPath,
|
|
1835
|
+
preRenderedContent: preRenderedJayHtml,
|
|
1418
1836
|
slowViewState,
|
|
1419
1837
|
carryForward,
|
|
1420
|
-
createdAt: Date.now(),
|
|
1421
1838
|
sourcePath: jayHtmlPath
|
|
1422
1839
|
};
|
|
1423
|
-
this.cache.set(key, entry);
|
|
1424
|
-
return preRenderedPath;
|
|
1425
1840
|
}
|
|
1426
1841
|
/**
|
|
1427
1842
|
* Check if a pre-rendered entry exists for the given path and params
|
|
1428
1843
|
*/
|
|
1429
|
-
has(jayHtmlPath, params) {
|
|
1430
|
-
const
|
|
1431
|
-
|
|
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
|
+
}
|
|
1432
1852
|
}
|
|
1433
1853
|
/**
|
|
1434
1854
|
* Invalidate all cached entries for a given jay-html source path.
|
|
1435
|
-
*
|
|
1436
|
-
* Also deletes the cached files from disk.
|
|
1855
|
+
* Deletes cached files from disk.
|
|
1437
1856
|
*/
|
|
1438
1857
|
async invalidate(jayHtmlPath) {
|
|
1439
|
-
const
|
|
1440
|
-
if (
|
|
1441
|
-
for (const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
await fs$1.unlink(entry.preRenderedPath);
|
|
1446
|
-
} catch {
|
|
1447
|
-
}
|
|
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 {
|
|
1448
1864
|
}
|
|
1449
|
-
this.cache.delete(key);
|
|
1450
1865
|
}
|
|
1451
|
-
this.
|
|
1866
|
+
this.pathToFiles.delete(jayHtmlPath);
|
|
1452
1867
|
}
|
|
1868
|
+
await this.scanAndDeleteCacheFiles(jayHtmlPath);
|
|
1453
1869
|
}
|
|
1454
1870
|
/**
|
|
1455
1871
|
* Invalidate all entries that depend on a changed file.
|
|
@@ -1477,26 +1893,67 @@ class SlowRenderCache {
|
|
|
1477
1893
|
* Clear all cached entries and delete cached files from disk
|
|
1478
1894
|
*/
|
|
1479
1895
|
async clear() {
|
|
1480
|
-
for (const
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
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
|
+
}
|
|
1484
1902
|
}
|
|
1485
1903
|
}
|
|
1486
|
-
this.
|
|
1487
|
-
|
|
1904
|
+
this.pathToFiles.clear();
|
|
1905
|
+
try {
|
|
1906
|
+
await fs$2.rm(this.cacheDir, { recursive: true, force: true });
|
|
1907
|
+
} catch {
|
|
1908
|
+
}
|
|
1488
1909
|
}
|
|
1489
1910
|
/**
|
|
1490
|
-
* Get
|
|
1911
|
+
* Get all cached jay-html paths (for debugging/monitoring)
|
|
1491
1912
|
*/
|
|
1492
|
-
|
|
1493
|
-
return this.
|
|
1913
|
+
getCachedPaths() {
|
|
1914
|
+
return Array.from(this.pathToFiles.keys());
|
|
1494
1915
|
}
|
|
1495
1916
|
/**
|
|
1496
|
-
*
|
|
1917
|
+
* Compute the cache file path for a given jay-html path and params.
|
|
1497
1918
|
*/
|
|
1498
|
-
|
|
1499
|
-
|
|
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
|
+
}
|
|
1500
1957
|
}
|
|
1501
1958
|
}
|
|
1502
1959
|
const require2 = createRequire(import.meta.url);
|
|
@@ -1640,13 +2097,12 @@ function getJayStackVersion() {
|
|
|
1640
2097
|
async function materializeContracts(options, services = /* @__PURE__ */ new Map()) {
|
|
1641
2098
|
const {
|
|
1642
2099
|
projectRoot,
|
|
1643
|
-
outputDir = path.join(projectRoot, "
|
|
2100
|
+
outputDir = path.join(projectRoot, "agent-kit", "materialized-contracts"),
|
|
1644
2101
|
dynamicOnly = false,
|
|
1645
2102
|
pluginFilter,
|
|
1646
2103
|
verbose = false,
|
|
1647
2104
|
viteServer
|
|
1648
2105
|
} = options;
|
|
1649
|
-
const contracts = [];
|
|
1650
2106
|
const pluginsIndexMap = /* @__PURE__ */ new Map();
|
|
1651
2107
|
let staticCount = 0;
|
|
1652
2108
|
let dynamicCount = 0;
|
|
@@ -1670,6 +2126,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1670
2126
|
📦 Processing plugin: ${plugin.name}`);
|
|
1671
2127
|
}
|
|
1672
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
|
+
}
|
|
1673
2137
|
if (!dynamicOnly && manifest.contracts) {
|
|
1674
2138
|
for (const contract of manifest.contracts) {
|
|
1675
2139
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1678,27 +2142,12 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1678
2142
|
projectRoot
|
|
1679
2143
|
);
|
|
1680
2144
|
const relativePath = path.relative(projectRoot, contractPath);
|
|
1681
|
-
const entry = {
|
|
1682
|
-
plugin: plugin.name,
|
|
1683
|
-
name: contract.name,
|
|
1684
|
-
type: "static",
|
|
1685
|
-
path: "./" + relativePath
|
|
1686
|
-
};
|
|
1687
|
-
contracts.push(entry);
|
|
1688
|
-
staticCount++;
|
|
1689
|
-
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1690
|
-
if (!pluginsIndexMap.has(plugin.name)) {
|
|
1691
|
-
pluginsIndexMap.set(plugin.name, {
|
|
1692
|
-
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1693
|
-
contracts: [],
|
|
1694
|
-
actions: []
|
|
1695
|
-
});
|
|
1696
|
-
}
|
|
1697
2145
|
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1698
2146
|
name: contract.name,
|
|
1699
2147
|
type: "static",
|
|
1700
2148
|
path: "./" + relativePath
|
|
1701
2149
|
});
|
|
2150
|
+
staticCount++;
|
|
1702
2151
|
if (verbose) {
|
|
1703
2152
|
getLogger().info(` 📄 Static: ${contract.name}`);
|
|
1704
2153
|
}
|
|
@@ -1728,28 +2177,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1728
2177
|
const filePath = path.join(pluginOutputDir, fileName);
|
|
1729
2178
|
fs.writeFileSync(filePath, generated.yaml, "utf-8");
|
|
1730
2179
|
const relativePath = path.relative(projectRoot, filePath);
|
|
1731
|
-
const
|
|
1732
|
-
plugin: plugin.name,
|
|
2180
|
+
const contractEntry = {
|
|
1733
2181
|
name: fullName,
|
|
1734
2182
|
type: "dynamic",
|
|
1735
2183
|
path: "./" + relativePath,
|
|
1736
|
-
metadata: generated.metadata
|
|
2184
|
+
...generated.metadata && { metadata: generated.metadata }
|
|
1737
2185
|
};
|
|
1738
|
-
contracts.push(
|
|
2186
|
+
pluginsIndexMap.get(plugin.name).contracts.push(contractEntry);
|
|
1739
2187
|
dynamicCount++;
|
|
1740
|
-
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1741
|
-
if (!pluginsIndexMap.has(plugin.name)) {
|
|
1742
|
-
pluginsIndexMap.set(plugin.name, {
|
|
1743
|
-
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1744
|
-
contracts: [],
|
|
1745
|
-
actions: []
|
|
1746
|
-
});
|
|
1747
|
-
}
|
|
1748
|
-
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1749
|
-
name: fullName,
|
|
1750
|
-
type: "dynamic",
|
|
1751
|
-
path: "./" + relativePath
|
|
1752
|
-
});
|
|
1753
2188
|
if (verbose) {
|
|
1754
2189
|
getLogger().info(` ⚡ Materialized: ${fullName}`);
|
|
1755
2190
|
}
|
|
@@ -1778,14 +2213,6 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1778
2213
|
const metadata = loadActionMetadata(metadataFilePath);
|
|
1779
2214
|
if (!metadata)
|
|
1780
2215
|
continue;
|
|
1781
|
-
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1782
|
-
if (!pluginsIndexMap.has(plugin.name)) {
|
|
1783
|
-
pluginsIndexMap.set(plugin.name, {
|
|
1784
|
-
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1785
|
-
contracts: [],
|
|
1786
|
-
actions: []
|
|
1787
|
-
});
|
|
1788
|
-
}
|
|
1789
2216
|
const actionRelPath = path.relative(projectRoot, metadataFilePath);
|
|
1790
2217
|
pluginsIndexMap.get(plugin.name).actions.push({
|
|
1791
2218
|
name: metadata.name,
|
|
@@ -1798,17 +2225,8 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1798
2225
|
}
|
|
1799
2226
|
}
|
|
1800
2227
|
}
|
|
1801
|
-
const index = {
|
|
1802
|
-
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1803
|
-
jay_stack_version: getJayStackVersion(),
|
|
1804
|
-
contracts
|
|
1805
|
-
};
|
|
1806
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
1807
|
-
const indexPath = path.join(outputDir, "contracts-index.yaml");
|
|
1808
|
-
fs.writeFileSync(indexPath, YAML.stringify(index), "utf-8");
|
|
1809
2228
|
const pluginsIndex = {
|
|
1810
|
-
|
|
1811
|
-
jay_stack_version: index.jay_stack_version,
|
|
2229
|
+
jay_stack_version: getJayStackVersion(),
|
|
1812
2230
|
plugins: Array.from(pluginsIndexMap.entries()).map(([name, data]) => ({
|
|
1813
2231
|
name,
|
|
1814
2232
|
path: data.path,
|
|
@@ -1816,15 +2234,16 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1816
2234
|
...data.actions.length > 0 && { actions: data.actions }
|
|
1817
2235
|
}))
|
|
1818
2236
|
};
|
|
1819
|
-
|
|
2237
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
2238
|
+
const agentKitDir = path.dirname(outputDir);
|
|
2239
|
+
const pluginsIndexPath = path.join(agentKitDir, "plugins-index.yaml");
|
|
1820
2240
|
fs.writeFileSync(pluginsIndexPath, YAML.stringify(pluginsIndex), "utf-8");
|
|
1821
2241
|
if (verbose) {
|
|
1822
2242
|
getLogger().info(`
|
|
1823
|
-
✅
|
|
1824
|
-
getLogger().info(`✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
2243
|
+
✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
1825
2244
|
}
|
|
1826
2245
|
return {
|
|
1827
|
-
|
|
2246
|
+
pluginsIndex,
|
|
1828
2247
|
staticCount,
|
|
1829
2248
|
dynamicCount,
|
|
1830
2249
|
outputDir
|
|
@@ -1832,7 +2251,7 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1832
2251
|
}
|
|
1833
2252
|
async function listContracts(options) {
|
|
1834
2253
|
const { projectRoot, dynamicOnly = false, pluginFilter } = options;
|
|
1835
|
-
const
|
|
2254
|
+
const pluginsMap = /* @__PURE__ */ new Map();
|
|
1836
2255
|
const plugins = await scanPlugins({
|
|
1837
2256
|
projectRoot,
|
|
1838
2257
|
includeDevDeps: true
|
|
@@ -1841,6 +2260,13 @@ async function listContracts(options) {
|
|
|
1841
2260
|
if (pluginFilter && plugin.name !== pluginFilter && pluginKey !== pluginFilter)
|
|
1842
2261
|
continue;
|
|
1843
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
|
+
}
|
|
1844
2270
|
if (!dynamicOnly && manifest.contracts) {
|
|
1845
2271
|
for (const contract of manifest.contracts) {
|
|
1846
2272
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1849,8 +2275,7 @@ async function listContracts(options) {
|
|
|
1849
2275
|
projectRoot
|
|
1850
2276
|
);
|
|
1851
2277
|
const relativePath = path.relative(projectRoot, contractPath);
|
|
1852
|
-
contracts.push({
|
|
1853
|
-
plugin: plugin.name,
|
|
2278
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1854
2279
|
name: contract.name,
|
|
1855
2280
|
type: "static",
|
|
1856
2281
|
path: "./" + relativePath
|
|
@@ -1860,8 +2285,7 @@ async function listContracts(options) {
|
|
|
1860
2285
|
if (manifest.dynamic_contracts) {
|
|
1861
2286
|
const dynamicConfigs = Array.isArray(manifest.dynamic_contracts) ? manifest.dynamic_contracts : [manifest.dynamic_contracts];
|
|
1862
2287
|
for (const config of dynamicConfigs) {
|
|
1863
|
-
contracts.push({
|
|
1864
|
-
plugin: plugin.name,
|
|
2288
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1865
2289
|
name: `${config.prefix}/*`,
|
|
1866
2290
|
type: "dynamic",
|
|
1867
2291
|
path: "(run materialization to generate)"
|
|
@@ -1870,9 +2294,12 @@ async function listContracts(options) {
|
|
|
1870
2294
|
}
|
|
1871
2295
|
}
|
|
1872
2296
|
return {
|
|
1873
|
-
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1874
2297
|
jay_stack_version: getJayStackVersion(),
|
|
1875
|
-
|
|
2298
|
+
plugins: Array.from(pluginsMap.entries()).map(([name, data]) => ({
|
|
2299
|
+
name,
|
|
2300
|
+
path: data.path,
|
|
2301
|
+
contracts: data.contracts
|
|
2302
|
+
}))
|
|
1876
2303
|
};
|
|
1877
2304
|
}
|
|
1878
2305
|
async function discoverPluginsWithSetup(options) {
|
|
@@ -2007,9 +2434,12 @@ export {
|
|
|
2007
2434
|
DevSlowlyChangingPhase,
|
|
2008
2435
|
SlowRenderCache,
|
|
2009
2436
|
actionRegistry,
|
|
2437
|
+
buildAutomationWrap,
|
|
2438
|
+
buildScriptFragments,
|
|
2010
2439
|
clearActionRegistry,
|
|
2011
2440
|
clearClientInitData,
|
|
2012
2441
|
clearLifecycleCallbacks,
|
|
2442
|
+
clearServerElementCache,
|
|
2013
2443
|
clearServiceRegistry,
|
|
2014
2444
|
discoverAllPluginActions,
|
|
2015
2445
|
discoverAndRegisterActions,
|
|
@@ -2022,6 +2452,7 @@ export {
|
|
|
2022
2452
|
executePluginServerInits,
|
|
2023
2453
|
executePluginSetup,
|
|
2024
2454
|
generateClientScript,
|
|
2455
|
+
generateSSRPageHtml,
|
|
2025
2456
|
getActionCacheHeaders,
|
|
2026
2457
|
getClientInitData,
|
|
2027
2458
|
getClientInitDataForKey,
|
|
@@ -2031,6 +2462,7 @@ export {
|
|
|
2031
2462
|
getServiceRegistry,
|
|
2032
2463
|
hasAction,
|
|
2033
2464
|
hasService,
|
|
2465
|
+
invalidateServerElementCache,
|
|
2034
2466
|
listContracts,
|
|
2035
2467
|
loadActionMetadata,
|
|
2036
2468
|
loadPageParts,
|