@jay-framework/stack-server-runtime 0.13.0 → 0.15.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 +157 -106
- package/dist/index.js +752 -366
- package/package.json +13 -12
package/dist/index.js
CHANGED
|
@@ -4,20 +4,20 @@ var __publicField = (obj, key, value) => {
|
|
|
4
4
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
|
-
import {
|
|
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";
|
|
7
|
+
import { phaseOutput, isJayAction } from "@jay-framework/fullstack-component";
|
|
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) {
|
|
@@ -83,37 +83,8 @@ function getClientInitDataForKey(key) {
|
|
|
83
83
|
function clearClientInitData() {
|
|
84
84
|
clientInitData = {};
|
|
85
85
|
}
|
|
86
|
-
function isLeftSideParamsSubsetOfRightSideParams(left, right) {
|
|
87
|
-
return Object.keys(left).reduce((prev, curr) => prev && left[curr] === right[curr], true);
|
|
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
86
|
class DevSlowlyChangingPhase {
|
|
97
|
-
|
|
98
|
-
this.dontCacheSlowly = dontCacheSlowly;
|
|
99
|
-
}
|
|
100
|
-
async runSlowlyForPage(pageParams, pageProps, parts) {
|
|
101
|
-
for (const part of parts) {
|
|
102
|
-
const { compDefinition, contractInfo } = part;
|
|
103
|
-
if (compDefinition.loadParams) {
|
|
104
|
-
const services = resolveServices(compDefinition.services);
|
|
105
|
-
const loadParamsArgs = contractInfo ? [
|
|
106
|
-
...services,
|
|
107
|
-
{
|
|
108
|
-
contractName: contractInfo.contractName,
|
|
109
|
-
metadata: contractInfo.metadata
|
|
110
|
-
}
|
|
111
|
-
] : services;
|
|
112
|
-
const compParams = compDefinition.loadParams(loadParamsArgs);
|
|
113
|
-
if (!await findMatchingParams(pageParams, compParams))
|
|
114
|
-
return notFound();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
87
|
+
async runSlowlyForPage(pageParams, pageProps, parts, discoveredInstances, headlessInstanceComponents, jayHtmlPath) {
|
|
117
88
|
let slowlyViewState = {};
|
|
118
89
|
let carryForward = {};
|
|
119
90
|
for (const part of parts) {
|
|
@@ -144,7 +115,57 @@ class DevSlowlyChangingPhase {
|
|
|
144
115
|
return slowlyRenderedPart;
|
|
145
116
|
}
|
|
146
117
|
}
|
|
147
|
-
|
|
118
|
+
if (discoveredInstances && discoveredInstances.length > 0 && headlessInstanceComponents) {
|
|
119
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
120
|
+
for (const comp of headlessInstanceComponents) {
|
|
121
|
+
componentByContractName.set(comp.contractName, comp);
|
|
122
|
+
}
|
|
123
|
+
const instancePhaseData = {
|
|
124
|
+
discovered: [],
|
|
125
|
+
carryForwards: {}
|
|
126
|
+
};
|
|
127
|
+
const instanceSlowViewStates = {};
|
|
128
|
+
const instanceResolvedData = [];
|
|
129
|
+
for (const instance of discoveredInstances) {
|
|
130
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
131
|
+
if (!comp)
|
|
132
|
+
continue;
|
|
133
|
+
const coordKey = instance.coordinate.join("/");
|
|
134
|
+
const contractProps = comp.contract?.props ?? [];
|
|
135
|
+
const normalizedProps = {};
|
|
136
|
+
for (const [key, value] of Object.entries(instance.props)) {
|
|
137
|
+
const match = contractProps.find(
|
|
138
|
+
(p) => p.name.toLowerCase() === key.toLowerCase()
|
|
139
|
+
);
|
|
140
|
+
normalizedProps[match ? match.name : key] = value;
|
|
141
|
+
}
|
|
142
|
+
instancePhaseData.discovered.push({
|
|
143
|
+
contractName: instance.contractName,
|
|
144
|
+
props: normalizedProps,
|
|
145
|
+
coordinate: instance.coordinate
|
|
146
|
+
});
|
|
147
|
+
if (comp.compDefinition.slowlyRender) {
|
|
148
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
149
|
+
const slowResult = await comp.compDefinition.slowlyRender(
|
|
150
|
+
normalizedProps,
|
|
151
|
+
...services
|
|
152
|
+
);
|
|
153
|
+
if (slowResult.kind === "PhaseOutput") {
|
|
154
|
+
instanceSlowViewStates[coordKey] = slowResult.rendered;
|
|
155
|
+
instancePhaseData.carryForwards[coordKey] = slowResult.carryForward;
|
|
156
|
+
instanceResolvedData.push({
|
|
157
|
+
coordinate: instance.coordinate,
|
|
158
|
+
contract: comp.contract,
|
|
159
|
+
slowViewState: slowResult.rendered
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
carryForward.__instances = instancePhaseData;
|
|
165
|
+
carryForward.__instanceSlowViewStates = instanceSlowViewStates;
|
|
166
|
+
carryForward.__instanceResolvedData = instanceResolvedData;
|
|
167
|
+
}
|
|
168
|
+
return phaseOutput(slowlyViewState, carryForward);
|
|
148
169
|
}
|
|
149
170
|
}
|
|
150
171
|
async function runLoadParams(compDefinition, services) {
|
|
@@ -152,7 +173,199 @@ async function runLoadParams(compDefinition, services) {
|
|
|
152
173
|
}
|
|
153
174
|
function runSlowlyChangingRender(compDefinition) {
|
|
154
175
|
}
|
|
155
|
-
|
|
176
|
+
var __defProp2 = Object.defineProperty;
|
|
177
|
+
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
178
|
+
var __publicField2 = (obj, key, value) => {
|
|
179
|
+
__defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
180
|
+
return value;
|
|
181
|
+
};
|
|
182
|
+
class JayAtomicType {
|
|
183
|
+
constructor(name) {
|
|
184
|
+
__publicField2(this, "kind", 0);
|
|
185
|
+
this.name = name;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
new JayAtomicType("string");
|
|
189
|
+
new JayAtomicType("number");
|
|
190
|
+
new JayAtomicType("boolean");
|
|
191
|
+
new JayAtomicType("Date");
|
|
192
|
+
new JayAtomicType("Unknown");
|
|
193
|
+
class JayObjectType {
|
|
194
|
+
constructor(name, props) {
|
|
195
|
+
__publicField2(this, "kind", 8);
|
|
196
|
+
this.name = name;
|
|
197
|
+
this.props = props;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
new JayObjectType("Error", {
|
|
201
|
+
message: new JayAtomicType("string"),
|
|
202
|
+
name: new JayAtomicType("string"),
|
|
203
|
+
stack: new JayAtomicType("string")
|
|
204
|
+
});
|
|
205
|
+
function isOptionalType(aType) {
|
|
206
|
+
return aType.kind === 13;
|
|
207
|
+
}
|
|
208
|
+
function isAtomicType(aType) {
|
|
209
|
+
return aType.kind === 0;
|
|
210
|
+
}
|
|
211
|
+
function isEnumType(aType) {
|
|
212
|
+
return aType.kind === 2;
|
|
213
|
+
}
|
|
214
|
+
function isImportedType(aType) {
|
|
215
|
+
return aType.kind === 4;
|
|
216
|
+
}
|
|
217
|
+
function isObjectType(aType) {
|
|
218
|
+
return aType.kind === 8;
|
|
219
|
+
}
|
|
220
|
+
function isArrayType(aType) {
|
|
221
|
+
return aType.kind === 9;
|
|
222
|
+
}
|
|
223
|
+
function jayTypeToJsonSchema(type) {
|
|
224
|
+
if (isOptionalType(type)) {
|
|
225
|
+
return jayTypeToJsonSchema(type.innerType);
|
|
226
|
+
}
|
|
227
|
+
if (isAtomicType(type)) {
|
|
228
|
+
const name = type.name.toLowerCase();
|
|
229
|
+
if (name === "string" || name === "number" || name === "boolean") {
|
|
230
|
+
return { type: name };
|
|
231
|
+
}
|
|
232
|
+
return { type: "string" };
|
|
233
|
+
}
|
|
234
|
+
if (isEnumType(type)) {
|
|
235
|
+
return { type: "string", enum: type.values };
|
|
236
|
+
}
|
|
237
|
+
if (isImportedType(type)) {
|
|
238
|
+
return { type: "object", description: `Contract: ${type.name}` };
|
|
239
|
+
}
|
|
240
|
+
if (isArrayType(type)) {
|
|
241
|
+
const itemSchema = jayTypeToJsonSchema(type.itemType);
|
|
242
|
+
if (itemSchema) {
|
|
243
|
+
return { type: "array", items: itemSchema };
|
|
244
|
+
}
|
|
245
|
+
return { type: "array" };
|
|
246
|
+
}
|
|
247
|
+
if (isObjectType(type)) {
|
|
248
|
+
const properties = {};
|
|
249
|
+
const required = [];
|
|
250
|
+
for (const [key, propType] of Object.entries(type.props)) {
|
|
251
|
+
const isOpt = isOptionalType(propType);
|
|
252
|
+
const schema = jayTypeToJsonSchema(propType);
|
|
253
|
+
if (schema) {
|
|
254
|
+
properties[key] = schema;
|
|
255
|
+
if (!isOpt) {
|
|
256
|
+
required.push(key);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties,
|
|
263
|
+
...required.length > 0 && { required }
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
var RuntimeMode = /* @__PURE__ */ ((RuntimeMode2) => {
|
|
269
|
+
RuntimeMode2["MainTrusted"] = "mainTrusted";
|
|
270
|
+
RuntimeMode2["MainSandbox"] = "mainSandbox";
|
|
271
|
+
RuntimeMode2["WorkerTrusted"] = "workerTrusted";
|
|
272
|
+
RuntimeMode2["WorkerSandbox"] = "workerSandbox";
|
|
273
|
+
return RuntimeMode2;
|
|
274
|
+
})(RuntimeMode || {});
|
|
275
|
+
const TS_EXTENSION = ".ts";
|
|
276
|
+
const JAY_QUERY_PREFIX = "?jay-";
|
|
277
|
+
const JAY_QUERY_HYDRATE = `${JAY_QUERY_PREFIX}hydrate`;
|
|
278
|
+
[
|
|
279
|
+
// Hydrate target
|
|
280
|
+
{
|
|
281
|
+
pattern: JAY_QUERY_HYDRATE,
|
|
282
|
+
buildEnv: "client",
|
|
283
|
+
isHydrate: true
|
|
284
|
+
},
|
|
285
|
+
// Build environments
|
|
286
|
+
{
|
|
287
|
+
pattern: `${JAY_QUERY_PREFIX}${"client"}`,
|
|
288
|
+
buildEnv: "client"
|
|
289
|
+
/* Client */
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
pattern: `${JAY_QUERY_PREFIX}${"server"}`,
|
|
293
|
+
buildEnv: "server"
|
|
294
|
+
/* Server */
|
|
295
|
+
},
|
|
296
|
+
// Runtime modes (with .ts suffix)
|
|
297
|
+
{
|
|
298
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}${TS_EXTENSION}`,
|
|
299
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}${TS_EXTENSION}`,
|
|
303
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}${TS_EXTENSION}`,
|
|
307
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
308
|
+
},
|
|
309
|
+
// Runtime modes (without .ts suffix)
|
|
310
|
+
{
|
|
311
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}`,
|
|
312
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}`,
|
|
316
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}`,
|
|
320
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
321
|
+
}
|
|
322
|
+
];
|
|
323
|
+
function checkValidationErrors(withValidations) {
|
|
324
|
+
const { validations } = withValidations;
|
|
325
|
+
if (validations.length > 0) {
|
|
326
|
+
throw new Error(validations.join("\n"));
|
|
327
|
+
}
|
|
328
|
+
return withValidations.val;
|
|
329
|
+
}
|
|
330
|
+
createRequire(import.meta.url);
|
|
331
|
+
function normalizeActionEntry(entry) {
|
|
332
|
+
if (typeof entry === "string") {
|
|
333
|
+
return { name: entry };
|
|
334
|
+
}
|
|
335
|
+
return { name: entry.name, action: entry.action };
|
|
336
|
+
}
|
|
337
|
+
function loadPluginManifest(pluginDir) {
|
|
338
|
+
const pluginYamlPath = path$1.join(pluginDir, "plugin.yaml");
|
|
339
|
+
if (!fs$1.existsSync(pluginYamlPath)) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
try {
|
|
343
|
+
const yamlContent = fs$1.readFileSync(pluginYamlPath, "utf-8");
|
|
344
|
+
return YAML.parse(yamlContent);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
function computeForEachInstanceKey(trackByValue, coordinateSuffix) {
|
|
350
|
+
return [trackByValue, coordinateSuffix].toString();
|
|
351
|
+
}
|
|
352
|
+
const s = createRequire(import.meta.url), e = s("typescript");
|
|
353
|
+
new Proxy(e, {
|
|
354
|
+
get(t, r) {
|
|
355
|
+
return t[r];
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
function resolvePathValue(obj, path2) {
|
|
359
|
+
return path2.split(".").reduce((current, segment) => current?.[segment], obj);
|
|
360
|
+
}
|
|
361
|
+
function resolveBinding(binding, item) {
|
|
362
|
+
const match = binding.match(/^\{(.+)\}$/);
|
|
363
|
+
if (match) {
|
|
364
|
+
return String(item[match[1]] ?? "");
|
|
365
|
+
}
|
|
366
|
+
return binding;
|
|
367
|
+
}
|
|
368
|
+
async function renderFastChangingData(pageParams, pageProps, carryForward, parts, instancePhaseData, forEachInstances, headlessInstanceComponents, mergedSlowViewState) {
|
|
156
369
|
let fastViewState = {};
|
|
157
370
|
let fastCarryForward = {};
|
|
158
371
|
for (const part of parts) {
|
|
@@ -185,12 +398,92 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
185
398
|
return fastRenderedPart;
|
|
186
399
|
}
|
|
187
400
|
}
|
|
401
|
+
const instanceViewStates = {};
|
|
402
|
+
const instanceCarryForwards = {};
|
|
403
|
+
if (instancePhaseData && headlessInstanceComponents) {
|
|
404
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
405
|
+
for (const comp of headlessInstanceComponents) {
|
|
406
|
+
componentByContractName.set(comp.contractName, comp);
|
|
407
|
+
}
|
|
408
|
+
for (const instance of instancePhaseData.discovered) {
|
|
409
|
+
const coordKey = instance.coordinate.join("/");
|
|
410
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
411
|
+
if (!comp || !comp.compDefinition.fastRender)
|
|
412
|
+
continue;
|
|
413
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
414
|
+
const cf = instancePhaseData.carryForwards[coordKey];
|
|
415
|
+
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(instance.props, cf, ...services) : await comp.compDefinition.fastRender(instance.props, ...services);
|
|
416
|
+
if (fastResult.kind === "PhaseOutput") {
|
|
417
|
+
const instanceSlowVS = carryForward?.__instanceSlowViewStates?.[coordKey];
|
|
418
|
+
instanceViewStates[coordKey] = instanceSlowVS ? { ...instanceSlowVS, ...fastResult.rendered } : fastResult.rendered;
|
|
419
|
+
if (fastResult.carryForward) {
|
|
420
|
+
instanceCarryForwards[coordKey] = fastResult.carryForward;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (forEachInstances && forEachInstances.length > 0 && headlessInstanceComponents) {
|
|
426
|
+
const componentByContractName = /* @__PURE__ */ new Map();
|
|
427
|
+
for (const comp of headlessInstanceComponents) {
|
|
428
|
+
componentByContractName.set(comp.contractName, comp);
|
|
429
|
+
}
|
|
430
|
+
const mergedForEachVS = { ...mergedSlowViewState || {}, ...fastViewState };
|
|
431
|
+
for (const instance of forEachInstances) {
|
|
432
|
+
const comp = componentByContractName.get(instance.contractName);
|
|
433
|
+
if (!comp)
|
|
434
|
+
continue;
|
|
435
|
+
const items = resolvePathValue(mergedForEachVS, instance.forEachPath);
|
|
436
|
+
if (!Array.isArray(items))
|
|
437
|
+
continue;
|
|
438
|
+
const contractProps = comp.contract?.props ?? [];
|
|
439
|
+
const normalizePropName = (key) => contractProps.find((p) => p.name.toLowerCase() === key.toLowerCase())?.name ?? key;
|
|
440
|
+
for (const item of items) {
|
|
441
|
+
const trackByValue = String(item[instance.trackBy]);
|
|
442
|
+
const props = {};
|
|
443
|
+
for (const [propName, binding] of Object.entries(instance.propBindings)) {
|
|
444
|
+
props[normalizePropName(propName)] = resolveBinding(String(binding), item);
|
|
445
|
+
}
|
|
446
|
+
if (comp.compDefinition.fastRender) {
|
|
447
|
+
const services = resolveServices(comp.compDefinition.services);
|
|
448
|
+
let slowVS = {};
|
|
449
|
+
let cf = {};
|
|
450
|
+
if (comp.compDefinition.slowlyRender) {
|
|
451
|
+
const slowResult = await comp.compDefinition.slowlyRender(
|
|
452
|
+
props,
|
|
453
|
+
...services
|
|
454
|
+
);
|
|
455
|
+
if (slowResult.kind === "PhaseOutput") {
|
|
456
|
+
slowVS = slowResult.rendered;
|
|
457
|
+
cf = slowResult.carryForward;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(props, cf, ...services) : await comp.compDefinition.fastRender(props, ...services);
|
|
461
|
+
if (fastResult.kind === "PhaseOutput") {
|
|
462
|
+
const coord = computeForEachInstanceKey(
|
|
463
|
+
trackByValue,
|
|
464
|
+
instance.coordinateSuffix
|
|
465
|
+
);
|
|
466
|
+
instanceViewStates[coord] = { ...slowVS, ...fastResult.rendered };
|
|
467
|
+
if (fastResult.carryForward) {
|
|
468
|
+
instanceCarryForwards[coord] = fastResult.carryForward;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (Object.keys(instanceViewStates).length > 0) {
|
|
476
|
+
fastViewState.__headlessInstances = instanceViewStates;
|
|
477
|
+
}
|
|
478
|
+
if (Object.keys(instanceCarryForwards).length > 0) {
|
|
479
|
+
fastCarryForward.__headlessInstances = instanceCarryForwards;
|
|
480
|
+
}
|
|
188
481
|
return Promise.resolve(phaseOutput(fastViewState, fastCarryForward));
|
|
189
482
|
}
|
|
190
|
-
function
|
|
483
|
+
function buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options) {
|
|
191
484
|
const { enableAutomation = true, slowViewState } = options;
|
|
192
485
|
const hasSlowViewState = slowViewState && Object.keys(slowViewState).length > 0;
|
|
193
|
-
const
|
|
486
|
+
const partImports = parts.length > 0 ? parts.map((part) => part.clientImport).join("\n") + "\n" : "";
|
|
194
487
|
const compositeParts = parts.length > 0 ? `[
|
|
195
488
|
${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
196
489
|
]` : "[]";
|
|
@@ -214,7 +507,7 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
214
507
|
const clientInitExecution = hasClientInit ? `
|
|
215
508
|
// Plugin client initialization (in dependency order)
|
|
216
509
|
${pluginClientInitCalls}
|
|
217
|
-
|
|
510
|
+
|
|
218
511
|
// Project client initialization
|
|
219
512
|
${projectInitCall}
|
|
220
513
|
` : "";
|
|
@@ -223,7 +516,28 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
223
516
|
import { deepMergeViewStates } from "@jay-framework/view-state-merge";` : `import { wrapWithAutomation, AUTOMATION_CONTEXT } from "@jay-framework/runtime-automation";
|
|
224
517
|
import { registerGlobalContext } from "@jay-framework/runtime";` : "";
|
|
225
518
|
const slowViewStateDecl = enableAutomation && hasSlowViewState ? `const slowViewState = ${JSON.stringify(slowViewState)};` : "";
|
|
226
|
-
|
|
519
|
+
return {
|
|
520
|
+
partImports,
|
|
521
|
+
compositeParts,
|
|
522
|
+
pluginClientInitImports,
|
|
523
|
+
projectInitImport,
|
|
524
|
+
clientInitExecution,
|
|
525
|
+
automationImport,
|
|
526
|
+
slowViewStateDecl
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
function buildAutomationWrap(options, mode) {
|
|
530
|
+
const { enableAutomation = true, slowViewState } = options;
|
|
531
|
+
const hasSlowViewState = slowViewState && Object.keys(slowViewState).length > 0;
|
|
532
|
+
const appendDom = mode === "client";
|
|
533
|
+
if (!enableAutomation) {
|
|
534
|
+
return appendDom ? `
|
|
535
|
+
target.appendChild(instance.element.dom);` : "";
|
|
536
|
+
}
|
|
537
|
+
const appendLine = appendDom ? `
|
|
538
|
+
target.appendChild(wrapped.element.dom);` : "";
|
|
539
|
+
if (hasSlowViewState) {
|
|
540
|
+
return `
|
|
227
541
|
// Wrap with automation for dev tooling
|
|
228
542
|
// Deep merge slow+fast ViewState so automation can see full page state
|
|
229
543
|
const fullViewState = deepMergeViewStates(slowViewState, {...viewState, ...fastCarryForward}, trackByMap);
|
|
@@ -231,14 +545,27 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
231
545
|
registerGlobalContext(AUTOMATION_CONTEXT, wrapped.automation);
|
|
232
546
|
window.__jay = window.__jay || {};
|
|
233
547
|
window.__jay.automation = wrapped.automation;
|
|
234
|
-
|
|
548
|
+
window.dispatchEvent(new Event('jay:automation-ready'));${appendLine}`;
|
|
549
|
+
}
|
|
550
|
+
return `
|
|
235
551
|
// Wrap with automation for dev tooling
|
|
236
552
|
const wrapped = wrapWithAutomation(instance);
|
|
237
553
|
registerGlobalContext(AUTOMATION_CONTEXT, wrapped.automation);
|
|
238
554
|
window.__jay = window.__jay || {};
|
|
239
555
|
window.__jay.automation = wrapped.automation;
|
|
240
|
-
|
|
241
|
-
|
|
556
|
+
window.dispatchEvent(new Event('jay:automation-ready'));${appendLine}`;
|
|
557
|
+
}
|
|
558
|
+
function generateClientScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
|
|
559
|
+
const {
|
|
560
|
+
partImports,
|
|
561
|
+
compositeParts,
|
|
562
|
+
pluginClientInitImports,
|
|
563
|
+
projectInitImport,
|
|
564
|
+
clientInitExecution,
|
|
565
|
+
automationImport,
|
|
566
|
+
slowViewStateDecl
|
|
567
|
+
} = buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options);
|
|
568
|
+
const automationWrap = buildAutomationWrap(options, "client");
|
|
242
569
|
return `<!doctype html>
|
|
243
570
|
<html lang="en">
|
|
244
571
|
<head>
|
|
@@ -254,7 +581,7 @@ ${parts.map((part) => " " + part.clientPart).join(",\n")}
|
|
|
254
581
|
${pluginClientInitImports}
|
|
255
582
|
${projectInitImport}
|
|
256
583
|
import { render } from '${jayHtmlPath}';
|
|
257
|
-
${
|
|
584
|
+
${partImports}${slowViewStateDecl}
|
|
258
585
|
const viewState = ${JSON.stringify(defaultViewState)};
|
|
259
586
|
const fastCarryForward = ${JSON.stringify(fastCarryForward)};
|
|
260
587
|
const trackByMap = ${JSON.stringify(trackByMap)};
|
|
@@ -268,9 +595,171 @@ ${automationWrap}
|
|
|
268
595
|
</body>
|
|
269
596
|
</html>`;
|
|
270
597
|
}
|
|
598
|
+
const serverModuleCache = /* @__PURE__ */ new Map();
|
|
599
|
+
function invalidateServerElementCache(jayHtmlPath) {
|
|
600
|
+
if (serverModuleCache.delete(jayHtmlPath)) {
|
|
601
|
+
getLogger().info(`[SSR] Invalidated server element cache for ${jayHtmlPath}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function clearServerElementCache() {
|
|
605
|
+
serverModuleCache.clear();
|
|
606
|
+
}
|
|
607
|
+
async function generateSSRPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, viewState, jayHtmlImportPath, parts, carryForward, trackByMap = {}, clientInitData2 = {}, buildFolder, projectRoot, routeDir, tsConfigFilePath, projectInit, pluginInits = [], options = {}) {
|
|
608
|
+
const jayHtmlPath = path__default.join(jayHtmlDir, jayHtmlFilename);
|
|
609
|
+
let cached = serverModuleCache.get(jayHtmlPath);
|
|
610
|
+
if (!cached) {
|
|
611
|
+
cached = await compileAndLoadServerElement(
|
|
612
|
+
vite,
|
|
613
|
+
jayHtmlContent,
|
|
614
|
+
jayHtmlFilename,
|
|
615
|
+
jayHtmlDir,
|
|
616
|
+
buildFolder,
|
|
617
|
+
projectRoot,
|
|
618
|
+
routeDir,
|
|
619
|
+
tsConfigFilePath
|
|
620
|
+
);
|
|
621
|
+
serverModuleCache.set(jayHtmlPath, cached);
|
|
622
|
+
}
|
|
623
|
+
const htmlChunks = [];
|
|
624
|
+
const asyncPromises = [];
|
|
625
|
+
const ctx = {
|
|
626
|
+
write: (chunk) => {
|
|
627
|
+
htmlChunks.push(chunk);
|
|
628
|
+
},
|
|
629
|
+
onAsync: (promise, id, templates) => {
|
|
630
|
+
const asyncPromise = promise.then(
|
|
631
|
+
(val) => {
|
|
632
|
+
if (templates.resolved) {
|
|
633
|
+
return templates.resolved(val);
|
|
634
|
+
}
|
|
635
|
+
return "";
|
|
636
|
+
},
|
|
637
|
+
(err) => {
|
|
638
|
+
if (templates.rejected) {
|
|
639
|
+
return templates.rejected(err);
|
|
640
|
+
}
|
|
641
|
+
return "";
|
|
642
|
+
}
|
|
643
|
+
);
|
|
644
|
+
asyncPromises.push(asyncPromise);
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
cached.renderToStream(viewState, ctx);
|
|
648
|
+
const asyncResults = await Promise.all(asyncPromises);
|
|
649
|
+
const ssrHtml = htmlChunks.join("");
|
|
650
|
+
const asyncScripts = asyncResults.filter((r) => r !== "").join("");
|
|
651
|
+
const hydrationScript = generateHydrationScript(
|
|
652
|
+
viewState,
|
|
653
|
+
carryForward,
|
|
654
|
+
parts,
|
|
655
|
+
jayHtmlImportPath,
|
|
656
|
+
trackByMap,
|
|
657
|
+
clientInitData2,
|
|
658
|
+
projectInit,
|
|
659
|
+
pluginInits,
|
|
660
|
+
options
|
|
661
|
+
);
|
|
662
|
+
const headLinksHtml = cached.headLinks.map((link) => {
|
|
663
|
+
const attrs = Object.entries(link.attributes).map(([k, v]) => ` ${k}="${v}"`).join("");
|
|
664
|
+
return ` <link rel="${link.rel}" href="${link.href}"${attrs} />`;
|
|
665
|
+
}).join("\n");
|
|
666
|
+
const inlineCss = cached.css ? ` <style>
|
|
667
|
+
${cached.css}
|
|
668
|
+
</style>` : "";
|
|
669
|
+
const headExtras = [headLinksHtml, inlineCss].filter((_) => _).join("\n");
|
|
670
|
+
return `<!doctype html>
|
|
671
|
+
<html lang="en">
|
|
672
|
+
<head>
|
|
673
|
+
<meta charset="UTF-8" />
|
|
674
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
675
|
+
<title>Vite + TS</title>
|
|
676
|
+
${headExtras ? headExtras + "\n" : ""} </head>
|
|
677
|
+
<body>
|
|
678
|
+
<div id="target">${ssrHtml}</div>${asyncScripts}
|
|
679
|
+
${hydrationScript}
|
|
680
|
+
</body>
|
|
681
|
+
</html>`;
|
|
682
|
+
}
|
|
683
|
+
function rebaseRelativeImports(code, fromDir, toDir) {
|
|
684
|
+
return code.replace(/from "(\.\.\/[^"]+)"/g, (_match, relPath) => {
|
|
685
|
+
const absolutePath = path__default.resolve(fromDir, relPath);
|
|
686
|
+
let newRelPath = path__default.relative(toDir, absolutePath);
|
|
687
|
+
if (!newRelPath.startsWith(".")) {
|
|
688
|
+
newRelPath = "./" + newRelPath;
|
|
689
|
+
}
|
|
690
|
+
return `from "${newRelPath}"`;
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, buildFolder, projectRoot, routeDir, tsConfigFilePath) {
|
|
694
|
+
const jayFile = await parseJayFile(
|
|
695
|
+
jayHtmlContent,
|
|
696
|
+
jayHtmlFilename,
|
|
697
|
+
jayHtmlDir,
|
|
698
|
+
{ relativePath: tsConfigFilePath },
|
|
699
|
+
JAY_IMPORT_RESOLVER,
|
|
700
|
+
projectRoot
|
|
701
|
+
);
|
|
702
|
+
const parsedJayFile = checkValidationErrors(jayFile);
|
|
703
|
+
const pageName = jayHtmlFilename.replace(".jay-html", "");
|
|
704
|
+
const debugCoordinatePreprocessPath = path__default.join(
|
|
705
|
+
buildFolder,
|
|
706
|
+
"debug",
|
|
707
|
+
routeDir,
|
|
708
|
+
`${pageName}.coordinate-preprocess.jay-html`
|
|
709
|
+
);
|
|
710
|
+
const serverElementOptions = {
|
|
711
|
+
debugCoordinatePreprocessPath
|
|
712
|
+
};
|
|
713
|
+
const serverElementCode = checkValidationErrors(
|
|
714
|
+
generateServerElementFile(parsedJayFile, serverElementOptions)
|
|
715
|
+
);
|
|
716
|
+
const serverElementDir = path__default.join(buildFolder, "pre-rendered", routeDir);
|
|
717
|
+
await fs$2.mkdir(serverElementDir, { recursive: true });
|
|
718
|
+
const adjustedCode = rebaseRelativeImports(serverElementCode, jayHtmlDir, serverElementDir);
|
|
719
|
+
const serverElementFilename = jayHtmlFilename.replace(".jay-html", ".server-element.ts");
|
|
720
|
+
const serverElementPath = path__default.join(serverElementDir, serverElementFilename);
|
|
721
|
+
await fs$2.writeFile(serverElementPath, adjustedCode, "utf-8");
|
|
722
|
+
const serverModule = await vite.ssrLoadModule(serverElementPath);
|
|
723
|
+
return {
|
|
724
|
+
renderToStream: serverModule.renderToStream,
|
|
725
|
+
headLinks: parsedJayFile.headLinks,
|
|
726
|
+
css: parsedJayFile.css
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function generateHydrationScript(defaultViewState, fastCarryForward, parts, jayHtmlPath, trackByMap = {}, clientInitData2 = {}, projectInit, pluginInits = [], options = {}) {
|
|
730
|
+
const {
|
|
731
|
+
partImports,
|
|
732
|
+
compositeParts,
|
|
733
|
+
pluginClientInitImports,
|
|
734
|
+
projectInitImport,
|
|
735
|
+
clientInitExecution,
|
|
736
|
+
automationImport,
|
|
737
|
+
slowViewStateDecl
|
|
738
|
+
} = buildScriptFragments(parts, clientInitData2, projectInit, pluginInits, options);
|
|
739
|
+
const automationWrap = buildAutomationWrap(options, "hydrate");
|
|
740
|
+
const hydrateImportPath = `${jayHtmlPath}${JAY_QUERY_HYDRATE}`;
|
|
741
|
+
return `<script type="module">
|
|
742
|
+
import {hydrateCompositeJayComponent} from "@jay-framework/stack-client-runtime";
|
|
743
|
+
${automationImport}
|
|
744
|
+
${pluginClientInitImports}
|
|
745
|
+
${projectInitImport}
|
|
746
|
+
import { hydrate } from '${hydrateImportPath}';
|
|
747
|
+
${partImports}${slowViewStateDecl}
|
|
748
|
+
const viewState = ${JSON.stringify(defaultViewState)};
|
|
749
|
+
const fastCarryForward = ${JSON.stringify(fastCarryForward)};
|
|
750
|
+
const trackByMap = ${JSON.stringify(trackByMap)};
|
|
751
|
+
|
|
752
|
+
const target = document.getElementById('target');
|
|
753
|
+
const rootElement = target.firstElementChild;
|
|
754
|
+
const pageComp = hydrateCompositeJayComponent(hydrate, viewState, fastCarryForward, ${compositeParts}, trackByMap, rootElement);
|
|
755
|
+
${clientInitExecution}
|
|
756
|
+
const instance = pageComp({/* placeholder for page props */});
|
|
757
|
+
${automationWrap}
|
|
758
|
+
<\/script>`;
|
|
759
|
+
}
|
|
271
760
|
const require$3 = createRequire(import.meta.url);
|
|
272
761
|
async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfig, options) {
|
|
273
|
-
const exists = await fs$
|
|
762
|
+
const exists = await fs$2.access(route.compPath, fs$2.constants.F_OK).then(() => true).catch(() => false);
|
|
274
763
|
const parts = [];
|
|
275
764
|
if (exists) {
|
|
276
765
|
const pageComponent = (await vite.ssrLoadModule(route.compPath)).page;
|
|
@@ -281,7 +770,7 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
|
|
|
281
770
|
});
|
|
282
771
|
}
|
|
283
772
|
const jayHtmlFilePath = options?.preRenderedPath ?? route.jayHtmlPath;
|
|
284
|
-
const jayHtmlSource = (await fs$
|
|
773
|
+
const jayHtmlSource = options?.preRenderedContent ?? (await fs$2.readFile(jayHtmlFilePath)).toString();
|
|
285
774
|
const fileName = path__default.basename(route.jayHtmlPath);
|
|
286
775
|
const dirName = path__default.dirname(route.jayHtmlPath);
|
|
287
776
|
const jayHtmlWithValidations = await parseJayFile(
|
|
@@ -338,13 +827,16 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
|
|
|
338
827
|
contract: hi.contract,
|
|
339
828
|
contractPath: hi.contractPath
|
|
340
829
|
}));
|
|
830
|
+
const discoveryResult = headlessInstanceComponents.length > 0 ? discoverHeadlessInstances(jayHtmlSource) : { instances: [], forEachInstances: [], preRenderedJayHtml: jayHtmlSource };
|
|
341
831
|
return {
|
|
342
832
|
parts,
|
|
343
833
|
serverTrackByMap: jayHtml.serverTrackByMap,
|
|
344
834
|
clientTrackByMap: jayHtml.clientTrackByMap,
|
|
345
835
|
usedPackages,
|
|
346
836
|
headlessContracts,
|
|
347
|
-
headlessInstanceComponents
|
|
837
|
+
headlessInstanceComponents,
|
|
838
|
+
discoveredInstances: discoveryResult.instances,
|
|
839
|
+
forEachInstances: discoveryResult.forEachInstances
|
|
348
840
|
};
|
|
349
841
|
});
|
|
350
842
|
}
|
|
@@ -362,8 +854,14 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
362
854
|
if (!comp || !comp.compDefinition.slowlyRender) {
|
|
363
855
|
continue;
|
|
364
856
|
}
|
|
857
|
+
const contractProps = comp.contract?.props ?? [];
|
|
858
|
+
const normalizedProps = {};
|
|
859
|
+
for (const [key, value] of Object.entries(instance.props)) {
|
|
860
|
+
const match = contractProps.find((p) => p.name.toLowerCase() === key.toLowerCase());
|
|
861
|
+
normalizedProps[match ? match.name : key] = value;
|
|
862
|
+
}
|
|
365
863
|
const services = resolveServices(comp.compDefinition.services);
|
|
366
|
-
const slowResult = await comp.compDefinition.slowlyRender(
|
|
864
|
+
const slowResult = await comp.compDefinition.slowlyRender(normalizedProps, ...services);
|
|
367
865
|
if (slowResult.kind === "PhaseOutput") {
|
|
368
866
|
const coordKey = instance.coordinate.join("/");
|
|
369
867
|
resolvedData.push({
|
|
@@ -375,7 +873,7 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
375
873
|
carryForwards[coordKey] = slowResult.carryForward;
|
|
376
874
|
discoveredForFast.push({
|
|
377
875
|
contractName: instance.contractName,
|
|
378
|
-
props:
|
|
876
|
+
props: normalizedProps,
|
|
379
877
|
coordinate: instance.coordinate
|
|
380
878
|
});
|
|
381
879
|
}
|
|
@@ -551,200 +1049,35 @@ class ActionRegistry {
|
|
|
551
1049
|
const parts = [];
|
|
552
1050
|
if (maxAge !== void 0) {
|
|
553
1051
|
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;
|
|
1052
|
+
}
|
|
1053
|
+
if (staleWhileRevalidate !== void 0) {
|
|
1054
|
+
parts.push(`stale-while-revalidate=${staleWhileRevalidate}`);
|
|
1055
|
+
}
|
|
1056
|
+
return parts.length > 0 ? parts.join(", ") : void 0;
|
|
605
1057
|
}
|
|
606
1058
|
}
|
|
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;
|
|
1059
|
+
const actionRegistry = new ActionRegistry();
|
|
1060
|
+
function registerAction(action) {
|
|
1061
|
+
actionRegistry.register(action);
|
|
620
1062
|
}
|
|
621
|
-
function
|
|
622
|
-
return
|
|
1063
|
+
function getRegisteredAction(actionName) {
|
|
1064
|
+
return actionRegistry.get(actionName);
|
|
623
1065
|
}
|
|
624
|
-
function
|
|
625
|
-
return
|
|
1066
|
+
function hasAction(actionName) {
|
|
1067
|
+
return actionRegistry.has(actionName);
|
|
626
1068
|
}
|
|
627
|
-
function
|
|
628
|
-
return
|
|
1069
|
+
function getRegisteredActionNames() {
|
|
1070
|
+
return actionRegistry.getNames();
|
|
629
1071
|
}
|
|
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;
|
|
1072
|
+
function clearActionRegistry() {
|
|
1073
|
+
actionRegistry.clear();
|
|
674
1074
|
}
|
|
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 };
|
|
1075
|
+
async function executeAction(actionName, input) {
|
|
1076
|
+
return actionRegistry.execute(actionName, input);
|
|
729
1077
|
}
|
|
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
|
-
}
|
|
1078
|
+
function getActionCacheHeaders(actionName) {
|
|
1079
|
+
return actionRegistry.getCacheHeaders(actionName);
|
|
741
1080
|
}
|
|
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
1081
|
function parseActionMetadata(yamlContent, fileName) {
|
|
749
1082
|
try {
|
|
750
1083
|
const parsed = parseAction(yamlContent, fileName);
|
|
@@ -1352,16 +1685,8 @@ function preparePluginClientInits(plugins) {
|
|
|
1352
1685
|
};
|
|
1353
1686
|
});
|
|
1354
1687
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
(acc, key) => {
|
|
1358
|
-
acc[key] = params[key];
|
|
1359
|
-
return acc;
|
|
1360
|
-
},
|
|
1361
|
-
{}
|
|
1362
|
-
);
|
|
1363
|
-
return `${jayHtmlPath}:${JSON.stringify(sortedParams)}`;
|
|
1364
|
-
}
|
|
1688
|
+
const CACHE_TAG_START = '<script type="application/jay-cache">';
|
|
1689
|
+
const CACHE_TAG_END = "<\/script>";
|
|
1365
1690
|
function hashParams(params) {
|
|
1366
1691
|
const sortedParams = Object.keys(params).sort().reduce(
|
|
1367
1692
|
(acc, key) => {
|
|
@@ -1375,81 +1700,126 @@ function hashParams(params) {
|
|
|
1375
1700
|
return "";
|
|
1376
1701
|
return "_" + crypto.createHash("md5").update(json).digest("hex").substring(0, 8);
|
|
1377
1702
|
}
|
|
1703
|
+
function embedCacheMetadata(jayHtmlContent, slowViewState, carryForward, sourcePath) {
|
|
1704
|
+
const metadata = JSON.stringify({ slowViewState, carryForward, sourcePath });
|
|
1705
|
+
const cacheTag = `${CACHE_TAG_START}${metadata}${CACHE_TAG_END}`;
|
|
1706
|
+
const headMatch = jayHtmlContent.match(/<head[^>]*>/i);
|
|
1707
|
+
if (headMatch) {
|
|
1708
|
+
const insertPos = headMatch.index + headMatch[0].length;
|
|
1709
|
+
return jayHtmlContent.substring(0, insertPos) + "\n" + cacheTag + jayHtmlContent.substring(insertPos);
|
|
1710
|
+
}
|
|
1711
|
+
return `${cacheTag}
|
|
1712
|
+
${jayHtmlContent}`;
|
|
1713
|
+
}
|
|
1714
|
+
function extractCacheMetadata(fileContent) {
|
|
1715
|
+
const startIdx = fileContent.indexOf(CACHE_TAG_START);
|
|
1716
|
+
if (startIdx === -1)
|
|
1717
|
+
return void 0;
|
|
1718
|
+
const jsonStart = startIdx + CACHE_TAG_START.length;
|
|
1719
|
+
const endIdx = fileContent.indexOf(CACHE_TAG_END, jsonStart);
|
|
1720
|
+
if (endIdx === -1)
|
|
1721
|
+
return void 0;
|
|
1722
|
+
const jsonStr = fileContent.substring(jsonStart, endIdx);
|
|
1723
|
+
const metadata = JSON.parse(jsonStr);
|
|
1724
|
+
const tagEnd = endIdx + CACHE_TAG_END.length;
|
|
1725
|
+
const afterTag = fileContent[tagEnd] === "\n" ? tagEnd + 1 : tagEnd;
|
|
1726
|
+
const content = fileContent.substring(0, startIdx) + fileContent.substring(afterTag);
|
|
1727
|
+
return {
|
|
1728
|
+
content,
|
|
1729
|
+
slowViewState: metadata.slowViewState,
|
|
1730
|
+
carryForward: metadata.carryForward,
|
|
1731
|
+
sourcePath: metadata.sourcePath
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
1378
1734
|
class SlowRenderCache {
|
|
1379
1735
|
/**
|
|
1380
1736
|
* @param cacheDir - Directory where pre-rendered jay-html files are stored
|
|
1381
1737
|
* @param pagesRoot - Root directory of the pages (for relative path calculation)
|
|
1382
1738
|
*/
|
|
1383
1739
|
constructor(cacheDir, pagesRoot) {
|
|
1384
|
-
|
|
1385
|
-
__publicField(this, "
|
|
1740
|
+
/** Maps source jay-html path → set of pre-rendered file paths (for invalidation) */
|
|
1741
|
+
__publicField(this, "pathToFiles", /* @__PURE__ */ new Map());
|
|
1386
1742
|
__publicField(this, "cacheDir");
|
|
1387
1743
|
__publicField(this, "pagesRoot");
|
|
1388
1744
|
this.cacheDir = cacheDir;
|
|
1389
1745
|
this.pagesRoot = pagesRoot;
|
|
1390
1746
|
}
|
|
1391
1747
|
/**
|
|
1392
|
-
* Get a cached pre-rendered jay-html entry
|
|
1748
|
+
* Get a cached pre-rendered jay-html entry by reading from disk.
|
|
1749
|
+
* Returns undefined if the cache file doesn't exist or has no metadata tag.
|
|
1393
1750
|
*/
|
|
1394
|
-
get(jayHtmlPath, params) {
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1751
|
+
async get(jayHtmlPath, params) {
|
|
1752
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1753
|
+
let fileContent;
|
|
1754
|
+
try {
|
|
1755
|
+
fileContent = await fs$2.readFile(preRenderedPath, "utf-8");
|
|
1756
|
+
} catch {
|
|
1757
|
+
return void 0;
|
|
1758
|
+
}
|
|
1759
|
+
const extracted = extractCacheMetadata(fileContent);
|
|
1760
|
+
if (!extracted)
|
|
1761
|
+
return void 0;
|
|
1762
|
+
this.trackFile(jayHtmlPath, preRenderedPath);
|
|
1763
|
+
return {
|
|
1764
|
+
preRenderedPath,
|
|
1765
|
+
preRenderedContent: extracted.content,
|
|
1766
|
+
slowViewState: extracted.slowViewState,
|
|
1767
|
+
carryForward: extracted.carryForward,
|
|
1768
|
+
sourcePath: extracted.sourcePath
|
|
1769
|
+
};
|
|
1397
1770
|
}
|
|
1398
1771
|
/**
|
|
1399
|
-
* Store a pre-rendered jay-html entry
|
|
1400
|
-
*
|
|
1772
|
+
* Store a pre-rendered jay-html entry.
|
|
1773
|
+
* Embeds metadata as a <script> tag and writes to disk.
|
|
1774
|
+
* Returns the full cache entry with stripped content.
|
|
1401
1775
|
*/
|
|
1402
1776
|
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 = {
|
|
1777
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1778
|
+
const fileContent = embedCacheMetadata(
|
|
1779
|
+
preRenderedJayHtml,
|
|
1780
|
+
slowViewState,
|
|
1781
|
+
carryForward,
|
|
1782
|
+
jayHtmlPath
|
|
1783
|
+
);
|
|
1784
|
+
await fs$2.mkdir(path__default.dirname(preRenderedPath), { recursive: true });
|
|
1785
|
+
await fs$2.writeFile(preRenderedPath, fileContent, "utf-8");
|
|
1786
|
+
this.trackFile(jayHtmlPath, preRenderedPath);
|
|
1787
|
+
return {
|
|
1417
1788
|
preRenderedPath,
|
|
1789
|
+
preRenderedContent: preRenderedJayHtml,
|
|
1418
1790
|
slowViewState,
|
|
1419
1791
|
carryForward,
|
|
1420
|
-
createdAt: Date.now(),
|
|
1421
1792
|
sourcePath: jayHtmlPath
|
|
1422
1793
|
};
|
|
1423
|
-
this.cache.set(key, entry);
|
|
1424
|
-
return preRenderedPath;
|
|
1425
1794
|
}
|
|
1426
1795
|
/**
|
|
1427
1796
|
* Check if a pre-rendered entry exists for the given path and params
|
|
1428
1797
|
*/
|
|
1429
|
-
has(jayHtmlPath, params) {
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1798
|
+
async has(jayHtmlPath, params) {
|
|
1799
|
+
const preRenderedPath = this.computeCachePath(jayHtmlPath, params);
|
|
1800
|
+
try {
|
|
1801
|
+
await fs$2.access(preRenderedPath);
|
|
1802
|
+
return true;
|
|
1803
|
+
} catch {
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1432
1806
|
}
|
|
1433
1807
|
/**
|
|
1434
1808
|
* Invalidate all cached entries for a given jay-html source path.
|
|
1435
|
-
*
|
|
1436
|
-
* Also deletes the cached files from disk.
|
|
1809
|
+
* Deletes cached files from disk.
|
|
1437
1810
|
*/
|
|
1438
1811
|
async invalidate(jayHtmlPath) {
|
|
1439
|
-
const
|
|
1440
|
-
if (
|
|
1441
|
-
for (const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
await fs$1.unlink(entry.preRenderedPath);
|
|
1446
|
-
} catch {
|
|
1447
|
-
}
|
|
1812
|
+
const files = this.pathToFiles.get(jayHtmlPath);
|
|
1813
|
+
if (files) {
|
|
1814
|
+
for (const filePath of files) {
|
|
1815
|
+
try {
|
|
1816
|
+
await fs$2.unlink(filePath);
|
|
1817
|
+
} catch {
|
|
1448
1818
|
}
|
|
1449
|
-
this.cache.delete(key);
|
|
1450
1819
|
}
|
|
1451
|
-
this.
|
|
1820
|
+
this.pathToFiles.delete(jayHtmlPath);
|
|
1452
1821
|
}
|
|
1822
|
+
await this.scanAndDeleteCacheFiles(jayHtmlPath);
|
|
1453
1823
|
}
|
|
1454
1824
|
/**
|
|
1455
1825
|
* Invalidate all entries that depend on a changed file.
|
|
@@ -1477,26 +1847,67 @@ class SlowRenderCache {
|
|
|
1477
1847
|
* Clear all cached entries and delete cached files from disk
|
|
1478
1848
|
*/
|
|
1479
1849
|
async clear() {
|
|
1480
|
-
for (const
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1850
|
+
for (const files of this.pathToFiles.values()) {
|
|
1851
|
+
for (const filePath of files) {
|
|
1852
|
+
try {
|
|
1853
|
+
await fs$2.unlink(filePath);
|
|
1854
|
+
} catch {
|
|
1855
|
+
}
|
|
1484
1856
|
}
|
|
1485
1857
|
}
|
|
1486
|
-
this.
|
|
1487
|
-
|
|
1858
|
+
this.pathToFiles.clear();
|
|
1859
|
+
try {
|
|
1860
|
+
await fs$2.rm(this.cacheDir, { recursive: true, force: true });
|
|
1861
|
+
} catch {
|
|
1862
|
+
}
|
|
1488
1863
|
}
|
|
1489
1864
|
/**
|
|
1490
|
-
* Get
|
|
1865
|
+
* Get all cached jay-html paths (for debugging/monitoring)
|
|
1491
1866
|
*/
|
|
1492
|
-
|
|
1493
|
-
return this.
|
|
1867
|
+
getCachedPaths() {
|
|
1868
|
+
return Array.from(this.pathToFiles.keys());
|
|
1494
1869
|
}
|
|
1495
1870
|
/**
|
|
1496
|
-
*
|
|
1871
|
+
* Compute the cache file path for a given jay-html path and params.
|
|
1497
1872
|
*/
|
|
1498
|
-
|
|
1499
|
-
|
|
1873
|
+
computeCachePath(jayHtmlPath, params) {
|
|
1874
|
+
const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
|
|
1875
|
+
const dir = path__default.dirname(relativePath);
|
|
1876
|
+
const basename = path__default.basename(relativePath, ".jay-html");
|
|
1877
|
+
const paramsHash = hashParams(params);
|
|
1878
|
+
const cacheFileName = `${basename}${paramsHash}.jay-html`;
|
|
1879
|
+
return path__default.join(this.cacheDir, dir, cacheFileName);
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Track a pre-rendered file path for invalidation.
|
|
1883
|
+
*/
|
|
1884
|
+
trackFile(jayHtmlPath, preRenderedPath) {
|
|
1885
|
+
if (!this.pathToFiles.has(jayHtmlPath)) {
|
|
1886
|
+
this.pathToFiles.set(jayHtmlPath, /* @__PURE__ */ new Set());
|
|
1887
|
+
}
|
|
1888
|
+
this.pathToFiles.get(jayHtmlPath).add(preRenderedPath);
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Scan the cache directory for files matching a route and delete them.
|
|
1892
|
+
* Handles the startup case where pathToFiles is not populated from a previous session.
|
|
1893
|
+
*/
|
|
1894
|
+
async scanAndDeleteCacheFiles(jayHtmlPath) {
|
|
1895
|
+
const relativePath = path__default.relative(this.pagesRoot, jayHtmlPath);
|
|
1896
|
+
const dir = path__default.dirname(relativePath);
|
|
1897
|
+
const basename = path__default.basename(relativePath, ".jay-html");
|
|
1898
|
+
const cacheSubDir = path__default.join(this.cacheDir, dir);
|
|
1899
|
+
try {
|
|
1900
|
+
const files = await fs$2.readdir(cacheSubDir);
|
|
1901
|
+
for (const file of files) {
|
|
1902
|
+
if (file.startsWith(basename) && file.endsWith(".jay-html")) {
|
|
1903
|
+
try {
|
|
1904
|
+
await fs$2.unlink(path__default.join(cacheSubDir, file));
|
|
1905
|
+
} catch {
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
} catch {
|
|
1910
|
+
}
|
|
1500
1911
|
}
|
|
1501
1912
|
}
|
|
1502
1913
|
const require2 = createRequire(import.meta.url);
|
|
@@ -1640,13 +2051,12 @@ function getJayStackVersion() {
|
|
|
1640
2051
|
async function materializeContracts(options, services = /* @__PURE__ */ new Map()) {
|
|
1641
2052
|
const {
|
|
1642
2053
|
projectRoot,
|
|
1643
|
-
outputDir = path.join(projectRoot, "
|
|
2054
|
+
outputDir = path.join(projectRoot, "agent-kit", "materialized-contracts"),
|
|
1644
2055
|
dynamicOnly = false,
|
|
1645
2056
|
pluginFilter,
|
|
1646
2057
|
verbose = false,
|
|
1647
2058
|
viteServer
|
|
1648
2059
|
} = options;
|
|
1649
|
-
const contracts = [];
|
|
1650
2060
|
const pluginsIndexMap = /* @__PURE__ */ new Map();
|
|
1651
2061
|
let staticCount = 0;
|
|
1652
2062
|
let dynamicCount = 0;
|
|
@@ -1670,6 +2080,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1670
2080
|
📦 Processing plugin: ${plugin.name}`);
|
|
1671
2081
|
}
|
|
1672
2082
|
const { manifest } = plugin;
|
|
2083
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
2084
|
+
if (!pluginsIndexMap.has(plugin.name)) {
|
|
2085
|
+
pluginsIndexMap.set(plugin.name, {
|
|
2086
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
2087
|
+
contracts: [],
|
|
2088
|
+
actions: []
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
1673
2091
|
if (!dynamicOnly && manifest.contracts) {
|
|
1674
2092
|
for (const contract of manifest.contracts) {
|
|
1675
2093
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1678,27 +2096,12 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1678
2096
|
projectRoot
|
|
1679
2097
|
);
|
|
1680
2098
|
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
2099
|
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1698
2100
|
name: contract.name,
|
|
1699
2101
|
type: "static",
|
|
1700
2102
|
path: "./" + relativePath
|
|
1701
2103
|
});
|
|
2104
|
+
staticCount++;
|
|
1702
2105
|
if (verbose) {
|
|
1703
2106
|
getLogger().info(` 📄 Static: ${contract.name}`);
|
|
1704
2107
|
}
|
|
@@ -1728,28 +2131,14 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1728
2131
|
const filePath = path.join(pluginOutputDir, fileName);
|
|
1729
2132
|
fs.writeFileSync(filePath, generated.yaml, "utf-8");
|
|
1730
2133
|
const relativePath = path.relative(projectRoot, filePath);
|
|
1731
|
-
const
|
|
1732
|
-
plugin: plugin.name,
|
|
2134
|
+
const contractEntry = {
|
|
1733
2135
|
name: fullName,
|
|
1734
2136
|
type: "dynamic",
|
|
1735
2137
|
path: "./" + relativePath,
|
|
1736
|
-
metadata: generated.metadata
|
|
2138
|
+
...generated.metadata && { metadata: generated.metadata }
|
|
1737
2139
|
};
|
|
1738
|
-
contracts.push(
|
|
2140
|
+
pluginsIndexMap.get(plugin.name).contracts.push(contractEntry);
|
|
1739
2141
|
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
2142
|
if (verbose) {
|
|
1754
2143
|
getLogger().info(` ⚡ Materialized: ${fullName}`);
|
|
1755
2144
|
}
|
|
@@ -1778,14 +2167,6 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1778
2167
|
const metadata = loadActionMetadata(metadataFilePath);
|
|
1779
2168
|
if (!metadata)
|
|
1780
2169
|
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
2170
|
const actionRelPath = path.relative(projectRoot, metadataFilePath);
|
|
1790
2171
|
pluginsIndexMap.get(plugin.name).actions.push({
|
|
1791
2172
|
name: metadata.name,
|
|
@@ -1798,17 +2179,8 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1798
2179
|
}
|
|
1799
2180
|
}
|
|
1800
2181
|
}
|
|
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
2182
|
const pluginsIndex = {
|
|
1810
|
-
|
|
1811
|
-
jay_stack_version: index.jay_stack_version,
|
|
2183
|
+
jay_stack_version: getJayStackVersion(),
|
|
1812
2184
|
plugins: Array.from(pluginsIndexMap.entries()).map(([name, data]) => ({
|
|
1813
2185
|
name,
|
|
1814
2186
|
path: data.path,
|
|
@@ -1816,15 +2188,16 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1816
2188
|
...data.actions.length > 0 && { actions: data.actions }
|
|
1817
2189
|
}))
|
|
1818
2190
|
};
|
|
1819
|
-
|
|
2191
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
2192
|
+
const agentKitDir = path.dirname(outputDir);
|
|
2193
|
+
const pluginsIndexPath = path.join(agentKitDir, "plugins-index.yaml");
|
|
1820
2194
|
fs.writeFileSync(pluginsIndexPath, YAML.stringify(pluginsIndex), "utf-8");
|
|
1821
2195
|
if (verbose) {
|
|
1822
2196
|
getLogger().info(`
|
|
1823
|
-
✅
|
|
1824
|
-
getLogger().info(`✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
2197
|
+
✅ Plugins index written to: ${pluginsIndexPath}`);
|
|
1825
2198
|
}
|
|
1826
2199
|
return {
|
|
1827
|
-
|
|
2200
|
+
pluginsIndex,
|
|
1828
2201
|
staticCount,
|
|
1829
2202
|
dynamicCount,
|
|
1830
2203
|
outputDir
|
|
@@ -1832,7 +2205,7 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
1832
2205
|
}
|
|
1833
2206
|
async function listContracts(options) {
|
|
1834
2207
|
const { projectRoot, dynamicOnly = false, pluginFilter } = options;
|
|
1835
|
-
const
|
|
2208
|
+
const pluginsMap = /* @__PURE__ */ new Map();
|
|
1836
2209
|
const plugins = await scanPlugins({
|
|
1837
2210
|
projectRoot,
|
|
1838
2211
|
includeDevDeps: true
|
|
@@ -1841,6 +2214,13 @@ async function listContracts(options) {
|
|
|
1841
2214
|
if (pluginFilter && plugin.name !== pluginFilter && pluginKey !== pluginFilter)
|
|
1842
2215
|
continue;
|
|
1843
2216
|
const { manifest } = plugin;
|
|
2217
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
2218
|
+
if (!pluginsMap.has(plugin.name)) {
|
|
2219
|
+
pluginsMap.set(plugin.name, {
|
|
2220
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
2221
|
+
contracts: []
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
1844
2224
|
if (!dynamicOnly && manifest.contracts) {
|
|
1845
2225
|
for (const contract of manifest.contracts) {
|
|
1846
2226
|
const contractPath = resolveStaticContractPath(
|
|
@@ -1849,8 +2229,7 @@ async function listContracts(options) {
|
|
|
1849
2229
|
projectRoot
|
|
1850
2230
|
);
|
|
1851
2231
|
const relativePath = path.relative(projectRoot, contractPath);
|
|
1852
|
-
contracts.push({
|
|
1853
|
-
plugin: plugin.name,
|
|
2232
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1854
2233
|
name: contract.name,
|
|
1855
2234
|
type: "static",
|
|
1856
2235
|
path: "./" + relativePath
|
|
@@ -1860,8 +2239,7 @@ async function listContracts(options) {
|
|
|
1860
2239
|
if (manifest.dynamic_contracts) {
|
|
1861
2240
|
const dynamicConfigs = Array.isArray(manifest.dynamic_contracts) ? manifest.dynamic_contracts : [manifest.dynamic_contracts];
|
|
1862
2241
|
for (const config of dynamicConfigs) {
|
|
1863
|
-
contracts.push({
|
|
1864
|
-
plugin: plugin.name,
|
|
2242
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1865
2243
|
name: `${config.prefix}/*`,
|
|
1866
2244
|
type: "dynamic",
|
|
1867
2245
|
path: "(run materialization to generate)"
|
|
@@ -1870,9 +2248,12 @@ async function listContracts(options) {
|
|
|
1870
2248
|
}
|
|
1871
2249
|
}
|
|
1872
2250
|
return {
|
|
1873
|
-
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1874
2251
|
jay_stack_version: getJayStackVersion(),
|
|
1875
|
-
|
|
2252
|
+
plugins: Array.from(pluginsMap.entries()).map(([name, data]) => ({
|
|
2253
|
+
name,
|
|
2254
|
+
path: data.path,
|
|
2255
|
+
contracts: data.contracts
|
|
2256
|
+
}))
|
|
1876
2257
|
};
|
|
1877
2258
|
}
|
|
1878
2259
|
async function discoverPluginsWithSetup(options) {
|
|
@@ -2007,9 +2388,12 @@ export {
|
|
|
2007
2388
|
DevSlowlyChangingPhase,
|
|
2008
2389
|
SlowRenderCache,
|
|
2009
2390
|
actionRegistry,
|
|
2391
|
+
buildAutomationWrap,
|
|
2392
|
+
buildScriptFragments,
|
|
2010
2393
|
clearActionRegistry,
|
|
2011
2394
|
clearClientInitData,
|
|
2012
2395
|
clearLifecycleCallbacks,
|
|
2396
|
+
clearServerElementCache,
|
|
2013
2397
|
clearServiceRegistry,
|
|
2014
2398
|
discoverAllPluginActions,
|
|
2015
2399
|
discoverAndRegisterActions,
|
|
@@ -2022,6 +2406,7 @@ export {
|
|
|
2022
2406
|
executePluginServerInits,
|
|
2023
2407
|
executePluginSetup,
|
|
2024
2408
|
generateClientScript,
|
|
2409
|
+
generateSSRPageHtml,
|
|
2025
2410
|
getActionCacheHeaders,
|
|
2026
2411
|
getClientInitData,
|
|
2027
2412
|
getClientInitDataForKey,
|
|
@@ -2031,6 +2416,7 @@ export {
|
|
|
2031
2416
|
getServiceRegistry,
|
|
2032
2417
|
hasAction,
|
|
2033
2418
|
hasService,
|
|
2419
|
+
invalidateServerElementCache,
|
|
2034
2420
|
listContracts,
|
|
2035
2421
|
loadActionMetadata,
|
|
2036
2422
|
loadPageParts,
|