@jay-framework/jay-stack-cli 0.24.0 ā 0.24.2
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/agent-kit-template/designer/validation-guide.md +32 -1
- package/dist/index-CatrpDqC.js +1594 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1512 -214
- package/package.json +12 -10
package/dist/index.js
CHANGED
|
@@ -3,21 +3,26 @@ import express from "express";
|
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
import { mkDevServer, createViteForCli } from "@jay-framework/dev-server";
|
|
5
5
|
import getPort from "get-port";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import fs, { promises } from "fs";
|
|
6
|
+
import path$1 from "path";
|
|
7
|
+
import fs$1, { promises } from "fs";
|
|
8
8
|
import YAML from "yaml";
|
|
9
9
|
import { getLogger, setDevLogger, createDevLogger } from "@jay-framework/logger";
|
|
10
|
-
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, parseContract, generateElementFile, generateServerElementFile, htmlElementTagNameMap, loadLinkedContract, getLinkedContractDir } from "@jay-framework/compiler-jay-html";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
10
|
+
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, parseAction, parseContract, generateElementFile, generateServerElementFile, htmlElementTagNameMap, loadLinkedContract, getLinkedContractDir } from "@jay-framework/compiler-jay-html";
|
|
11
|
+
import fs$2 from "node:fs/promises";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import path__default from "node:path";
|
|
14
|
+
import { createRequire } from "module";
|
|
15
|
+
import jsBeautify from "js-beautify";
|
|
16
|
+
import { scanPlugins, sortPluginsByDependencies, getServiceRegistry, actionRegistry, resolveServices, ActionRegistry, discoverPluginsWithInit, executePluginServerInits, runInitCallbacks, registerService } from "@jay-framework/stack-server-runtime";
|
|
17
|
+
import "node:crypto";
|
|
18
|
+
import * as fs from "node:fs";
|
|
19
|
+
import fs__default from "node:fs";
|
|
20
|
+
import { createRequire as createRequire$1 } from "node:module";
|
|
21
|
+
import { isJayAction, isJayStreamAction, isJayCliCommand, CONSOLE_CONTEXT } from "@jay-framework/fullstack-component";
|
|
13
22
|
import { Command } from "commander";
|
|
14
23
|
import chalk from "chalk";
|
|
15
|
-
import
|
|
16
|
-
import fs$1 from "node:fs/promises";
|
|
17
|
-
import { loadPluginManifest, JAY_EXTENSION, RuntimeMode, GenerateTarget, JAY_CONTRACT_EXTENSION, findDynamicContract } from "@jay-framework/compiler-shared";
|
|
18
|
-
import { createRequire } from "module";
|
|
24
|
+
import { loadPluginManifest as loadPluginManifest$1, JAY_EXTENSION, RuntimeMode as RuntimeMode$1, GenerateTarget, JAY_CONTRACT_EXTENSION, findDynamicContract } from "@jay-framework/compiler-shared";
|
|
19
25
|
import { glob } from "glob";
|
|
20
|
-
import fsSync from "node:fs";
|
|
21
26
|
import { fileURLToPath } from "node:url";
|
|
22
27
|
import { select, confirm, input } from "@inquirer/prompts";
|
|
23
28
|
const DEFAULT_CONFIG = {
|
|
@@ -29,13 +34,13 @@ const DEFAULT_CONFIG = {
|
|
|
29
34
|
configBase: "./config"
|
|
30
35
|
}
|
|
31
36
|
};
|
|
32
|
-
function loadConfig() {
|
|
33
|
-
const configPath = path.resolve(".jay");
|
|
34
|
-
if (!fs.existsSync(configPath)) {
|
|
37
|
+
function loadConfig(projectRoot) {
|
|
38
|
+
const configPath = projectRoot ? path$1.resolve(projectRoot, ".jay") : path$1.resolve(".jay");
|
|
39
|
+
if (!fs$1.existsSync(configPath)) {
|
|
35
40
|
return DEFAULT_CONFIG;
|
|
36
41
|
}
|
|
37
42
|
try {
|
|
38
|
-
const configContent = fs.readFileSync(configPath, "utf-8");
|
|
43
|
+
const configContent = fs$1.readFileSync(configPath, "utf-8");
|
|
39
44
|
const userConfig = YAML.parse(configContent);
|
|
40
45
|
return {
|
|
41
46
|
devServer: {
|
|
@@ -62,7 +67,7 @@ function getConfigWithDefaults(config) {
|
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
69
|
function updateConfig(updates) {
|
|
65
|
-
const configPath = path.resolve(".jay");
|
|
70
|
+
const configPath = path$1.resolve(".jay");
|
|
66
71
|
try {
|
|
67
72
|
const existingConfig = loadConfig();
|
|
68
73
|
const updatedConfig = {
|
|
@@ -78,7 +83,7 @@ function updateConfig(updates) {
|
|
|
78
83
|
}
|
|
79
84
|
};
|
|
80
85
|
const yamlContent = YAML.stringify(updatedConfig, { indent: 2 });
|
|
81
|
-
fs.writeFileSync(configPath, yamlContent);
|
|
86
|
+
fs$1.writeFileSync(configPath, yamlContent);
|
|
82
87
|
} catch (error) {
|
|
83
88
|
getLogger().warn(`Failed to update .jay config file: ${error}`);
|
|
84
89
|
}
|
|
@@ -86,14 +91,14 @@ function updateConfig(updates) {
|
|
|
86
91
|
async function generatePageDefinitionFiles(routes, tsConfigPath, projectRoot) {
|
|
87
92
|
for (const route of routes) {
|
|
88
93
|
const jayHtmlPath = route.fsRoute.jayHtmlPath;
|
|
89
|
-
if (!fs.existsSync(jayHtmlPath)) {
|
|
94
|
+
if (!fs$1.existsSync(jayHtmlPath)) {
|
|
90
95
|
continue;
|
|
91
96
|
}
|
|
92
97
|
const definitionFilePath = jayHtmlPath + ".d.ts";
|
|
93
98
|
try {
|
|
94
99
|
const [sourceStats, defStats] = await Promise.all([
|
|
95
|
-
fs.promises.stat(jayHtmlPath),
|
|
96
|
-
fs.promises.stat(definitionFilePath).catch(() => null)
|
|
100
|
+
fs$1.promises.stat(jayHtmlPath),
|
|
101
|
+
fs$1.promises.stat(definitionFilePath).catch(() => null)
|
|
97
102
|
]);
|
|
98
103
|
if (defStats && defStats.mtime >= sourceStats.mtime) {
|
|
99
104
|
continue;
|
|
@@ -101,9 +106,9 @@ async function generatePageDefinitionFiles(routes, tsConfigPath, projectRoot) {
|
|
|
101
106
|
} catch (error) {
|
|
102
107
|
}
|
|
103
108
|
try {
|
|
104
|
-
const jayHtml = await fs.promises.readFile(jayHtmlPath, "utf-8");
|
|
105
|
-
const filename = path.basename(jayHtmlPath);
|
|
106
|
-
const dirname = path.dirname(jayHtmlPath);
|
|
109
|
+
const jayHtml = await fs$1.promises.readFile(jayHtmlPath, "utf-8");
|
|
110
|
+
const filename = path$1.basename(jayHtmlPath);
|
|
111
|
+
const dirname = path$1.dirname(jayHtmlPath);
|
|
107
112
|
const parsedJayHtml = await parseJayFile(
|
|
108
113
|
jayHtml,
|
|
109
114
|
filename,
|
|
@@ -119,7 +124,7 @@ async function generatePageDefinitionFiles(routes, tsConfigPath, projectRoot) {
|
|
|
119
124
|
);
|
|
120
125
|
} else {
|
|
121
126
|
const definitionFilePath2 = jayHtmlPath + ".d.ts";
|
|
122
|
-
await fs.promises.writeFile(definitionFilePath2, definitionFile.val, "utf-8");
|
|
127
|
+
await fs$1.promises.writeFile(definitionFilePath2, definitionFile.val, "utf-8");
|
|
123
128
|
getLogger().info(`š¦ Generated definition file: ${definitionFilePath2}`);
|
|
124
129
|
}
|
|
125
130
|
} catch (error) {
|
|
@@ -143,7 +148,7 @@ async function startDevServer(options = {}) {
|
|
|
143
148
|
const devServerPort = await getPort({ port: resolvedConfig.devServer.portRange });
|
|
144
149
|
const log = getLogger();
|
|
145
150
|
const { server, viteServer, routes, service } = await mkDevServer({
|
|
146
|
-
pagesRootFolder: path.resolve(resolvedConfig.devServer.pagesBase),
|
|
151
|
+
pagesRootFolder: path$1.resolve(resolvedConfig.devServer.pagesBase),
|
|
147
152
|
projectRootFolder: process.cwd(),
|
|
148
153
|
publicBaseUrlPath: "/",
|
|
149
154
|
jayRollupConfig: jayOptions,
|
|
@@ -151,15 +156,15 @@ async function startDevServer(options = {}) {
|
|
|
151
156
|
httpServer
|
|
152
157
|
});
|
|
153
158
|
app.use(server);
|
|
154
|
-
const publicPath = path.resolve(resolvedConfig.devServer.publicFolder);
|
|
155
|
-
if (!fs.existsSync(path.join(publicPath, "sitemap.xml"))) {
|
|
159
|
+
const publicPath = path$1.resolve(resolvedConfig.devServer.publicFolder);
|
|
160
|
+
if (!fs$1.existsSync(path$1.join(publicPath, "sitemap.xml"))) {
|
|
156
161
|
app.get("/sitemap.xml", (_req, res) => {
|
|
157
162
|
res.type("application/xml").send(
|
|
158
163
|
'<?xml version="1.0" encoding="UTF-8"?>\n<!-- Sitemap is generated by the production server from the route manifest. -->\n<!-- Run jay-stack build && jay-stack serve to see the full sitemap. -->\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" />\n'
|
|
159
164
|
);
|
|
160
165
|
});
|
|
161
166
|
}
|
|
162
|
-
if (fs.existsSync(publicPath)) {
|
|
167
|
+
if (fs$1.existsSync(publicPath)) {
|
|
163
168
|
app.use(express.static(publicPath));
|
|
164
169
|
} else {
|
|
165
170
|
log.important(`ā ļø Public folder not found: ${resolvedConfig.devServer.publicFolder}`);
|
|
@@ -177,7 +182,7 @@ async function startDevServer(options = {}) {
|
|
|
177
182
|
log.important(`š Jay Stack dev server started successfully!`);
|
|
178
183
|
log.important(`š± Dev Server: http://localhost:${devServerPort}`);
|
|
179
184
|
log.important(`š Pages directory: ${resolvedConfig.devServer.pagesBase}`);
|
|
180
|
-
if (fs.existsSync(publicPath)) {
|
|
185
|
+
if (fs$1.existsSync(publicPath)) {
|
|
181
186
|
log.important(`š Public folder: ${resolvedConfig.devServer.publicFolder}`);
|
|
182
187
|
}
|
|
183
188
|
if (options.testMode) {
|
|
@@ -222,12 +227,1294 @@ async function startDevServer(options = {}) {
|
|
|
222
227
|
process.on("SIGTERM", shutdown);
|
|
223
228
|
process.on("SIGINT", shutdown);
|
|
224
229
|
}
|
|
230
|
+
createRequire(import.meta.url);
|
|
231
|
+
var __defProp2 = Object.defineProperty;
|
|
232
|
+
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
233
|
+
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, key + "", value);
|
|
234
|
+
class JayAtomicType {
|
|
235
|
+
constructor(name) {
|
|
236
|
+
__publicField2(this, "kind", 0);
|
|
237
|
+
this.name = name;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
new JayAtomicType("string");
|
|
241
|
+
new JayAtomicType("string");
|
|
242
|
+
new JayAtomicType("number");
|
|
243
|
+
new JayAtomicType("boolean");
|
|
244
|
+
new JayAtomicType("Date");
|
|
245
|
+
new JayAtomicType("file");
|
|
246
|
+
new JayAtomicType("Unknown");
|
|
247
|
+
class JayObjectType {
|
|
248
|
+
constructor(name, props) {
|
|
249
|
+
__publicField2(this, "kind", 8);
|
|
250
|
+
this.name = name;
|
|
251
|
+
this.props = props;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
new JayObjectType("Error", {
|
|
255
|
+
message: new JayAtomicType("string"),
|
|
256
|
+
name: new JayAtomicType("string"),
|
|
257
|
+
stack: new JayAtomicType("string")
|
|
258
|
+
});
|
|
259
|
+
function isOptionalType(aType) {
|
|
260
|
+
return aType.kind === 14;
|
|
261
|
+
}
|
|
262
|
+
function isAtomicType(aType) {
|
|
263
|
+
return aType.kind === 0;
|
|
264
|
+
}
|
|
265
|
+
function isEnumType(aType) {
|
|
266
|
+
return aType.kind === 2;
|
|
267
|
+
}
|
|
268
|
+
function isImportedType(aType) {
|
|
269
|
+
return aType.kind === 4;
|
|
270
|
+
}
|
|
271
|
+
function isObjectType(aType) {
|
|
272
|
+
return aType.kind === 8;
|
|
273
|
+
}
|
|
274
|
+
function isArrayType(aType) {
|
|
275
|
+
return aType.kind === 9;
|
|
276
|
+
}
|
|
277
|
+
function isRecordType(aType) {
|
|
278
|
+
return aType.kind === 11;
|
|
279
|
+
}
|
|
280
|
+
function jayTypeToJsonSchema(type) {
|
|
281
|
+
if (isOptionalType(type)) {
|
|
282
|
+
return jayTypeToJsonSchema(type.innerType);
|
|
283
|
+
}
|
|
284
|
+
if (isAtomicType(type)) {
|
|
285
|
+
const name = type.name.toLowerCase();
|
|
286
|
+
if (name === "string" || name === "number" || name === "boolean") {
|
|
287
|
+
return { type: name };
|
|
288
|
+
}
|
|
289
|
+
if (name === "file") {
|
|
290
|
+
return { type: "string", description: "Binary file upload (JayFile)" };
|
|
291
|
+
}
|
|
292
|
+
return { type: "string" };
|
|
293
|
+
}
|
|
294
|
+
if (isEnumType(type)) {
|
|
295
|
+
return { type: "string", enum: type.values };
|
|
296
|
+
}
|
|
297
|
+
if (isImportedType(type)) {
|
|
298
|
+
return { type: "object", description: `Contract: ${type.name}` };
|
|
299
|
+
}
|
|
300
|
+
if (isArrayType(type)) {
|
|
301
|
+
const itemSchema = jayTypeToJsonSchema(type.itemType);
|
|
302
|
+
if (itemSchema) {
|
|
303
|
+
return { type: "array", items: itemSchema };
|
|
304
|
+
}
|
|
305
|
+
return { type: "array" };
|
|
306
|
+
}
|
|
307
|
+
if (isRecordType(type)) {
|
|
308
|
+
const valueSchema = jayTypeToJsonSchema(type.itemType);
|
|
309
|
+
if (valueSchema) {
|
|
310
|
+
return { type: "object", additionalProperties: valueSchema };
|
|
311
|
+
}
|
|
312
|
+
return { type: "object" };
|
|
313
|
+
}
|
|
314
|
+
if (isObjectType(type)) {
|
|
315
|
+
const properties = {};
|
|
316
|
+
const required = [];
|
|
317
|
+
for (const [key, propType] of Object.entries(type.props)) {
|
|
318
|
+
const isOpt = isOptionalType(propType);
|
|
319
|
+
const schema = jayTypeToJsonSchema(propType);
|
|
320
|
+
if (schema) {
|
|
321
|
+
properties[key] = schema;
|
|
322
|
+
if (!isOpt) {
|
|
323
|
+
required.push(key);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
type: "object",
|
|
329
|
+
properties,
|
|
330
|
+
...required.length > 0 && { required }
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
var RuntimeMode = /* @__PURE__ */ ((RuntimeMode2) => {
|
|
336
|
+
RuntimeMode2["MainTrusted"] = "mainTrusted";
|
|
337
|
+
RuntimeMode2["MainSandbox"] = "mainSandbox";
|
|
338
|
+
RuntimeMode2["WorkerTrusted"] = "workerTrusted";
|
|
339
|
+
RuntimeMode2["WorkerSandbox"] = "workerSandbox";
|
|
340
|
+
return RuntimeMode2;
|
|
341
|
+
})(RuntimeMode || {});
|
|
342
|
+
const TS_EXTENSION = ".ts";
|
|
343
|
+
const JAY_QUERY_PREFIX = "?jay-";
|
|
344
|
+
const JAY_QUERY_HYDRATE = `${JAY_QUERY_PREFIX}hydrate`;
|
|
345
|
+
[
|
|
346
|
+
// Hydrate target
|
|
347
|
+
{
|
|
348
|
+
pattern: JAY_QUERY_HYDRATE,
|
|
349
|
+
buildEnv: "client",
|
|
350
|
+
isHydrate: true
|
|
351
|
+
},
|
|
352
|
+
// Build environments
|
|
353
|
+
{
|
|
354
|
+
pattern: `${JAY_QUERY_PREFIX}${"client"}`,
|
|
355
|
+
buildEnv: "client"
|
|
356
|
+
/* Client */
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
pattern: `${JAY_QUERY_PREFIX}${"server"}`,
|
|
360
|
+
buildEnv: "server"
|
|
361
|
+
/* Server */
|
|
362
|
+
},
|
|
363
|
+
// Runtime modes (with .ts suffix)
|
|
364
|
+
{
|
|
365
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}${TS_EXTENSION}`,
|
|
366
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}${TS_EXTENSION}`,
|
|
370
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}${TS_EXTENSION}`,
|
|
374
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
375
|
+
},
|
|
376
|
+
// Runtime modes (without .ts suffix)
|
|
377
|
+
{
|
|
378
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.MainSandbox}`,
|
|
379
|
+
runtimeMode: RuntimeMode.MainSandbox
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerTrusted}`,
|
|
383
|
+
runtimeMode: RuntimeMode.WorkerTrusted
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
pattern: `${JAY_QUERY_PREFIX}${RuntimeMode.WorkerSandbox}`,
|
|
387
|
+
runtimeMode: RuntimeMode.WorkerSandbox
|
|
388
|
+
}
|
|
389
|
+
];
|
|
390
|
+
const { html: htmlBeautify } = jsBeautify;
|
|
391
|
+
createRequire(import.meta.url);
|
|
392
|
+
function normalizeActionEntry(entry) {
|
|
393
|
+
if (typeof entry === "string") {
|
|
394
|
+
return { name: entry };
|
|
395
|
+
}
|
|
396
|
+
return { name: entry.name, action: entry.action };
|
|
397
|
+
}
|
|
398
|
+
function loadPluginManifest(pluginDir) {
|
|
399
|
+
const pluginYamlPath = path$1.join(pluginDir, "plugin.yaml");
|
|
400
|
+
if (!fs$1.existsSync(pluginYamlPath)) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
const yamlContent = fs$1.readFileSync(pluginYamlPath, "utf-8");
|
|
405
|
+
return YAML.parse(yamlContent);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const s$1 = createRequire(import.meta.url), e$1 = s$1("typescript");
|
|
411
|
+
new Proxy(e$1, {
|
|
412
|
+
get(t, r) {
|
|
413
|
+
return t[r];
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
function parseActionMetadata(yamlContent, fileName) {
|
|
417
|
+
try {
|
|
418
|
+
const parsed = parseAction(yamlContent, fileName);
|
|
419
|
+
if (parsed.validations.length > 0) {
|
|
420
|
+
getLogger().warn(
|
|
421
|
+
`[ActionMetadata] ${fileName}: validation errors: ${parsed.validations.join(", ")}`
|
|
422
|
+
);
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
if (!parsed.val) {
|
|
426
|
+
getLogger().warn(`[ActionMetadata] ${fileName}: parsing returned no result`);
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
const action = parsed.val;
|
|
430
|
+
const inputJsonSchema = jayTypeToJsonSchema(action.inputType);
|
|
431
|
+
let inputSchema;
|
|
432
|
+
if (inputJsonSchema && inputJsonSchema.type === "object") {
|
|
433
|
+
inputSchema = {
|
|
434
|
+
type: "object",
|
|
435
|
+
properties: inputJsonSchema.properties || {},
|
|
436
|
+
...inputJsonSchema.required && inputJsonSchema.required.length > 0 && { required: inputJsonSchema.required }
|
|
437
|
+
};
|
|
438
|
+
} else {
|
|
439
|
+
inputSchema = { type: "object", properties: {} };
|
|
440
|
+
}
|
|
441
|
+
const metadata = {
|
|
442
|
+
name: action.name,
|
|
443
|
+
description: action.description,
|
|
444
|
+
inputSchema
|
|
445
|
+
};
|
|
446
|
+
if (action.outputType) {
|
|
447
|
+
const outputJsonSchema = jayTypeToJsonSchema(action.outputType);
|
|
448
|
+
if (outputJsonSchema) {
|
|
449
|
+
metadata.outputSchema = outputJsonSchema;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return metadata;
|
|
453
|
+
} catch (error) {
|
|
454
|
+
getLogger().error(
|
|
455
|
+
`[ActionMetadata] Failed to parse ${fileName}: ${error instanceof Error ? error.message : error}`
|
|
456
|
+
);
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function loadActionMetadata(filePath) {
|
|
461
|
+
if (!fs.existsSync(filePath)) {
|
|
462
|
+
getLogger().warn(`[ActionMetadata] File not found: ${filePath}`);
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
const yamlContent = fs.readFileSync(filePath, "utf-8");
|
|
466
|
+
const fileName = path.basename(filePath);
|
|
467
|
+
return parseActionMetadata(yamlContent, fileName);
|
|
468
|
+
}
|
|
469
|
+
function resolveActionMetadataPath(actionPath, pluginDir) {
|
|
470
|
+
return path.resolve(pluginDir, actionPath);
|
|
471
|
+
}
|
|
472
|
+
const require$2 = createRequire$1(import.meta.url);
|
|
473
|
+
async function discoverAndRegisterActions(options) {
|
|
474
|
+
const {
|
|
475
|
+
projectRoot,
|
|
476
|
+
actionsDir = "src/actions",
|
|
477
|
+
registry = actionRegistry,
|
|
478
|
+
verbose = false,
|
|
479
|
+
viteServer
|
|
480
|
+
} = options;
|
|
481
|
+
const result = {
|
|
482
|
+
actionCount: 0,
|
|
483
|
+
actionNames: [],
|
|
484
|
+
scannedFiles: []
|
|
485
|
+
};
|
|
486
|
+
const actionsPath = path.resolve(projectRoot, actionsDir);
|
|
487
|
+
if (!fs.existsSync(actionsPath)) {
|
|
488
|
+
if (verbose) {
|
|
489
|
+
getLogger().info(`[Actions] No actions directory found at ${actionsPath}`);
|
|
490
|
+
}
|
|
491
|
+
return result;
|
|
492
|
+
}
|
|
493
|
+
const actionFiles = await findActionFiles(actionsPath);
|
|
494
|
+
if (verbose) {
|
|
495
|
+
getLogger().info(`[Actions] Found ${actionFiles.length} action file(s)`);
|
|
496
|
+
}
|
|
497
|
+
for (const filePath of actionFiles) {
|
|
498
|
+
result.scannedFiles.push(filePath);
|
|
499
|
+
try {
|
|
500
|
+
let module;
|
|
501
|
+
if (viteServer) {
|
|
502
|
+
module = await viteServer.ssrLoadModule(filePath);
|
|
503
|
+
} else {
|
|
504
|
+
module = await import(filePath);
|
|
505
|
+
}
|
|
506
|
+
for (const [exportName, exportValue] of Object.entries(module)) {
|
|
507
|
+
if (isJayAction(exportValue)) {
|
|
508
|
+
registry.register(exportValue);
|
|
509
|
+
result.actionNames.push(exportValue.actionName);
|
|
510
|
+
result.actionCount++;
|
|
511
|
+
if (verbose) {
|
|
512
|
+
getLogger().info(
|
|
513
|
+
`[Actions] Registered: ${exportValue.actionName}`
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
} else if (isJayStreamAction(exportValue)) {
|
|
517
|
+
registry.registerStream(exportValue);
|
|
518
|
+
result.actionNames.push(exportValue.actionName);
|
|
519
|
+
result.actionCount++;
|
|
520
|
+
if (verbose) {
|
|
521
|
+
getLogger().info(
|
|
522
|
+
`[Actions] Registered stream: ${exportValue.actionName}`
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
getLogger().error(`[Actions] Failed to import ${filePath}: ${error}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
533
|
+
async function findActionFiles(dir) {
|
|
534
|
+
const files = [];
|
|
535
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
536
|
+
for (const entry of entries) {
|
|
537
|
+
const fullPath = path.join(dir, entry.name);
|
|
538
|
+
if (entry.isDirectory()) {
|
|
539
|
+
const subFiles = await findActionFiles(fullPath);
|
|
540
|
+
files.push(...subFiles);
|
|
541
|
+
} else if (entry.isFile() && entry.name.endsWith(".actions.ts")) {
|
|
542
|
+
files.push(fullPath);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return files;
|
|
546
|
+
}
|
|
547
|
+
async function discoverAllPluginActions(options) {
|
|
548
|
+
const { projectRoot, registry = actionRegistry, verbose = false, viteServer } = options;
|
|
549
|
+
const allActions = [];
|
|
550
|
+
const localPluginsPath = path.join(projectRoot, "src/plugins");
|
|
551
|
+
if (fs.existsSync(localPluginsPath)) {
|
|
552
|
+
const pluginDirs = await fs.promises.readdir(localPluginsPath, { withFileTypes: true });
|
|
553
|
+
for (const entry of pluginDirs) {
|
|
554
|
+
if (entry.isDirectory()) {
|
|
555
|
+
const pluginPath = path.join(localPluginsPath, entry.name);
|
|
556
|
+
const actions = await discoverPluginActions(
|
|
557
|
+
pluginPath,
|
|
558
|
+
projectRoot,
|
|
559
|
+
registry,
|
|
560
|
+
verbose,
|
|
561
|
+
viteServer
|
|
562
|
+
);
|
|
563
|
+
allActions.push(...actions);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
const npmActions = await discoverNpmPluginActions(projectRoot, registry, verbose, viteServer);
|
|
568
|
+
allActions.push(...npmActions);
|
|
569
|
+
return allActions;
|
|
570
|
+
}
|
|
571
|
+
async function discoverNpmPluginActions(projectRoot, registry, verbose, viteServer) {
|
|
572
|
+
const allActions = [];
|
|
573
|
+
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
574
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
575
|
+
return allActions;
|
|
576
|
+
}
|
|
577
|
+
try {
|
|
578
|
+
const packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf-8"));
|
|
579
|
+
const dependencies = {
|
|
580
|
+
...packageJson.dependencies,
|
|
581
|
+
...packageJson.devDependencies
|
|
582
|
+
};
|
|
583
|
+
for (const packageName of Object.keys(dependencies)) {
|
|
584
|
+
try {
|
|
585
|
+
const pluginYamlPath = tryResolvePluginYaml(packageName, projectRoot);
|
|
586
|
+
if (!pluginYamlPath) {
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
const pluginDir = path.dirname(pluginYamlPath);
|
|
590
|
+
const pluginConfig = loadPluginManifest(pluginDir);
|
|
591
|
+
if (!pluginConfig || !pluginConfig.actions || !Array.isArray(pluginConfig.actions)) {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
if (verbose) {
|
|
595
|
+
getLogger().info(
|
|
596
|
+
`[Actions] NPM plugin "${packageName}" declares actions: ${JSON.stringify(pluginConfig.actions)}`
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
const actions = await registerNpmPluginActions(
|
|
600
|
+
packageName,
|
|
601
|
+
pluginConfig,
|
|
602
|
+
pluginDir,
|
|
603
|
+
registry,
|
|
604
|
+
verbose,
|
|
605
|
+
viteServer
|
|
606
|
+
);
|
|
607
|
+
allActions.push(...actions);
|
|
608
|
+
} catch {
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
} catch (error) {
|
|
613
|
+
getLogger().error(`[Actions] Failed to read project package.json: ${error}`);
|
|
614
|
+
}
|
|
615
|
+
return allActions;
|
|
616
|
+
}
|
|
617
|
+
function tryResolvePluginYaml(packageName, projectRoot) {
|
|
618
|
+
try {
|
|
619
|
+
return require$2.resolve(`${packageName}/plugin.yaml`, {
|
|
620
|
+
paths: [projectRoot]
|
|
621
|
+
});
|
|
622
|
+
} catch {
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function resolveNpmActionMetadataPath(actionPath, packageName, pluginDir) {
|
|
627
|
+
if (!actionPath.startsWith(".")) {
|
|
628
|
+
try {
|
|
629
|
+
return require$2.resolve(`${packageName}/${actionPath}`, {
|
|
630
|
+
paths: [pluginDir]
|
|
631
|
+
});
|
|
632
|
+
} catch {
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const resolved = resolveActionMetadataPath(actionPath, pluginDir);
|
|
636
|
+
if (fs.existsSync(resolved)) {
|
|
637
|
+
return resolved;
|
|
638
|
+
}
|
|
639
|
+
getLogger().warn(
|
|
640
|
+
`[Actions] Could not resolve .jay-action file "${actionPath}" for package "${packageName}"`
|
|
641
|
+
);
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
async function registerNpmPluginActions(packageName, pluginConfig, pluginDir, registry, verbose, viteServer) {
|
|
645
|
+
const registeredActions = [];
|
|
646
|
+
try {
|
|
647
|
+
let pluginModule;
|
|
648
|
+
if (viteServer) {
|
|
649
|
+
pluginModule = await viteServer.ssrLoadModule(packageName);
|
|
650
|
+
} else {
|
|
651
|
+
pluginModule = await import(packageName);
|
|
652
|
+
}
|
|
653
|
+
for (const entry of pluginConfig.actions) {
|
|
654
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
655
|
+
const actionExport = pluginModule[actionName];
|
|
656
|
+
if (actionExport && isJayAction(actionExport)) {
|
|
657
|
+
registry.register(actionExport);
|
|
658
|
+
const registeredName = actionExport.actionName;
|
|
659
|
+
registeredActions.push(registeredName);
|
|
660
|
+
if (actionPath) {
|
|
661
|
+
const metadataFilePath = resolveNpmActionMetadataPath(
|
|
662
|
+
actionPath,
|
|
663
|
+
packageName,
|
|
664
|
+
pluginDir
|
|
665
|
+
);
|
|
666
|
+
if (metadataFilePath) {
|
|
667
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
668
|
+
if (metadata) {
|
|
669
|
+
registry.setMetadata(registeredName, metadata);
|
|
670
|
+
if (verbose) {
|
|
671
|
+
getLogger().info(
|
|
672
|
+
`[Actions] Loaded metadata for "${registeredName}" from ${actionPath}`
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (verbose) {
|
|
679
|
+
getLogger().info(`[Actions] Registered NPM plugin action: ${registeredName}`);
|
|
680
|
+
}
|
|
681
|
+
} else if (actionExport && isJayStreamAction(actionExport)) {
|
|
682
|
+
registry.registerStream(actionExport);
|
|
683
|
+
const registeredName = actionExport.actionName;
|
|
684
|
+
registeredActions.push(registeredName);
|
|
685
|
+
if (verbose) {
|
|
686
|
+
getLogger().info(`[Actions] Registered NPM plugin stream: ${registeredName}`);
|
|
687
|
+
}
|
|
688
|
+
} else {
|
|
689
|
+
getLogger().warn(
|
|
690
|
+
`[Actions] NPM plugin "${packageName}" declares action "${actionName}" but it's not exported or not a JayAction`
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
} catch (importError) {
|
|
695
|
+
getLogger().error(`[Actions] Failed to import NPM plugin "${packageName}": ${importError}`);
|
|
696
|
+
}
|
|
697
|
+
return registeredActions;
|
|
698
|
+
}
|
|
699
|
+
async function discoverPluginActions(pluginPath, projectRoot, registry = actionRegistry, verbose = false, viteServer) {
|
|
700
|
+
const pluginConfig = loadPluginManifest(pluginPath);
|
|
701
|
+
if (!pluginConfig) {
|
|
702
|
+
return [];
|
|
703
|
+
}
|
|
704
|
+
if (!pluginConfig.actions || !Array.isArray(pluginConfig.actions)) {
|
|
705
|
+
return [];
|
|
706
|
+
}
|
|
707
|
+
const registeredActions = [];
|
|
708
|
+
const pluginName = pluginConfig.name || path.basename(pluginPath);
|
|
709
|
+
if (verbose) {
|
|
710
|
+
getLogger().info(
|
|
711
|
+
`[Actions] Plugin "${pluginName}" declares actions: ${JSON.stringify(pluginConfig.actions)}`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
let modulePath = pluginConfig.module ? path.join(pluginPath, pluginConfig.module) : path.join(pluginPath, "index.ts");
|
|
715
|
+
if (!fs.existsSync(modulePath)) {
|
|
716
|
+
const tsPath = modulePath + ".ts";
|
|
717
|
+
const jsPath = modulePath + ".js";
|
|
718
|
+
if (fs.existsSync(tsPath)) {
|
|
719
|
+
modulePath = tsPath;
|
|
720
|
+
} else if (fs.existsSync(jsPath)) {
|
|
721
|
+
modulePath = jsPath;
|
|
722
|
+
} else {
|
|
723
|
+
getLogger().warn(`[Actions] Plugin "${pluginName}" module not found at ${modulePath}`);
|
|
724
|
+
return [];
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
try {
|
|
728
|
+
let pluginModule;
|
|
729
|
+
if (viteServer) {
|
|
730
|
+
pluginModule = await viteServer.ssrLoadModule(modulePath);
|
|
731
|
+
} else {
|
|
732
|
+
pluginModule = await import(modulePath);
|
|
733
|
+
}
|
|
734
|
+
for (const entry of pluginConfig.actions) {
|
|
735
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
736
|
+
const actionExport = pluginModule[actionName];
|
|
737
|
+
if (actionExport && isJayAction(actionExport)) {
|
|
738
|
+
registry.register(actionExport);
|
|
739
|
+
const registeredName = actionExport.actionName;
|
|
740
|
+
registeredActions.push(registeredName);
|
|
741
|
+
if (actionPath) {
|
|
742
|
+
const metadataFilePath = resolveActionMetadataPath(actionPath, pluginPath);
|
|
743
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
744
|
+
if (metadata) {
|
|
745
|
+
registry.setMetadata(registeredName, metadata);
|
|
746
|
+
if (verbose) {
|
|
747
|
+
getLogger().info(
|
|
748
|
+
`[Actions] Loaded metadata for "${registeredName}" from ${actionPath}`
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
if (verbose) {
|
|
754
|
+
getLogger().info(`[Actions] Registered plugin action: ${registeredName}`);
|
|
755
|
+
}
|
|
756
|
+
} else if (actionExport && isJayStreamAction(actionExport)) {
|
|
757
|
+
registry.registerStream(actionExport);
|
|
758
|
+
const registeredName = actionExport.actionName;
|
|
759
|
+
registeredActions.push(registeredName);
|
|
760
|
+
if (verbose) {
|
|
761
|
+
getLogger().info(`[Actions] Registered plugin stream: ${registeredName}`);
|
|
762
|
+
}
|
|
763
|
+
} else {
|
|
764
|
+
getLogger().warn(
|
|
765
|
+
`[Actions] Plugin "${pluginName}" declares action "${actionName}" but it's not exported or not a JayAction`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
} catch (importError) {
|
|
770
|
+
getLogger().error(
|
|
771
|
+
`[Actions] Failed to import plugin module at ${modulePath}: ${importError}`
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
return registeredActions;
|
|
775
|
+
}
|
|
776
|
+
const require$1 = createRequire(import.meta.url);
|
|
777
|
+
async function executeDynamicGenerator(plugin, config, projectRoot, services, verbose, viteServer) {
|
|
778
|
+
const { pluginPath, name: pluginName, isLocal, packageName } = plugin;
|
|
779
|
+
if (!config.generator) {
|
|
780
|
+
throw new Error(
|
|
781
|
+
`Plugin "${pluginName}" has dynamic_contracts entry but no generator specified`
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
const isFilePath = config.generator.startsWith("./") || config.generator.startsWith("/") || config.generator.includes(".ts") || config.generator.includes(".js");
|
|
785
|
+
let generator;
|
|
786
|
+
if (isFilePath) {
|
|
787
|
+
let generatorPath;
|
|
788
|
+
if (!isLocal) {
|
|
789
|
+
try {
|
|
790
|
+
generatorPath = require$1.resolve(`${packageName}/${config.generator}`, {
|
|
791
|
+
paths: [projectRoot]
|
|
792
|
+
});
|
|
793
|
+
} catch {
|
|
794
|
+
generatorPath = path.join(pluginPath, config.generator);
|
|
795
|
+
}
|
|
796
|
+
} else {
|
|
797
|
+
generatorPath = path.join(pluginPath, config.generator);
|
|
798
|
+
}
|
|
799
|
+
if (!fs.existsSync(generatorPath)) {
|
|
800
|
+
const withTs = generatorPath + ".ts";
|
|
801
|
+
const withJs = generatorPath + ".js";
|
|
802
|
+
if (fs.existsSync(withTs)) {
|
|
803
|
+
generatorPath = withTs;
|
|
804
|
+
} else if (fs.existsSync(withJs)) {
|
|
805
|
+
generatorPath = withJs;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
if (!fs.existsSync(generatorPath)) {
|
|
809
|
+
throw new Error(
|
|
810
|
+
`Generator file not found for plugin "${pluginName}": ${config.generator}`
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
if (verbose) {
|
|
814
|
+
getLogger().info(` Loading generator from file: ${generatorPath}`);
|
|
815
|
+
}
|
|
816
|
+
let generatorModule;
|
|
817
|
+
if (viteServer) {
|
|
818
|
+
generatorModule = await viteServer.ssrLoadModule(generatorPath);
|
|
819
|
+
} else {
|
|
820
|
+
generatorModule = await import(generatorPath);
|
|
821
|
+
}
|
|
822
|
+
generator = generatorModule.generator || generatorModule.default;
|
|
823
|
+
} else {
|
|
824
|
+
if (verbose) {
|
|
825
|
+
getLogger().info(
|
|
826
|
+
` Loading generator export: ${config.generator} from ${packageName}`
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
let pluginModule;
|
|
830
|
+
if (viteServer) {
|
|
831
|
+
pluginModule = await viteServer.ssrLoadModule(packageName);
|
|
832
|
+
} else {
|
|
833
|
+
pluginModule = await import(packageName);
|
|
834
|
+
}
|
|
835
|
+
generator = pluginModule[config.generator];
|
|
836
|
+
if (!generator) {
|
|
837
|
+
throw new Error(
|
|
838
|
+
`Generator "${config.generator}" not exported from plugin "${pluginName}". Ensure it's exported from the package's index.ts`
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (!generator || typeof generator.generate !== "function") {
|
|
843
|
+
throw new Error(
|
|
844
|
+
`Generator "${config.generator}" for plugin "${pluginName}" must have a 'generate' function. Use makeContractGenerator() to create valid generators.`
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
const resolvedServices = [];
|
|
848
|
+
for (const marker of generator.services) {
|
|
849
|
+
const service = services.get(marker);
|
|
850
|
+
if (!service) {
|
|
851
|
+
const markerName = marker.description ?? "unknown";
|
|
852
|
+
throw new Error(
|
|
853
|
+
`Service "${markerName}" required by ${pluginName} generator not found. Ensure it's registered in init.ts`
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
resolvedServices.push(service);
|
|
857
|
+
}
|
|
858
|
+
if (verbose) {
|
|
859
|
+
getLogger().info(` Executing generator...`);
|
|
860
|
+
}
|
|
861
|
+
return await generator.generate(...resolvedServices);
|
|
862
|
+
}
|
|
863
|
+
function resolveStaticContractPath(plugin, contractSpec, projectRoot) {
|
|
864
|
+
const { pluginPath, isLocal, packageName } = plugin;
|
|
865
|
+
if (!isLocal) {
|
|
866
|
+
try {
|
|
867
|
+
return require$1.resolve(`${packageName}/${contractSpec}`, {
|
|
868
|
+
paths: [projectRoot]
|
|
869
|
+
});
|
|
870
|
+
} catch {
|
|
871
|
+
const possiblePaths = [
|
|
872
|
+
path.join(pluginPath, "dist", contractSpec),
|
|
873
|
+
path.join(pluginPath, "lib", contractSpec),
|
|
874
|
+
path.join(pluginPath, contractSpec)
|
|
875
|
+
];
|
|
876
|
+
const found = possiblePaths.find((p) => fs.existsSync(p));
|
|
877
|
+
return found || possiblePaths[0];
|
|
878
|
+
}
|
|
879
|
+
} else {
|
|
880
|
+
return path.join(pluginPath, contractSpec);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
function resolveActionFilePath(actionPath, packageName, pluginPath, isLocal, projectRoot) {
|
|
884
|
+
if (!isLocal && !actionPath.startsWith(".")) {
|
|
885
|
+
try {
|
|
886
|
+
return require$1.resolve(`${packageName}/${actionPath}`, {
|
|
887
|
+
paths: [projectRoot]
|
|
888
|
+
});
|
|
889
|
+
} catch {
|
|
890
|
+
const possiblePaths = [
|
|
891
|
+
path.join(pluginPath, "dist", actionPath),
|
|
892
|
+
path.join(pluginPath, "lib", actionPath),
|
|
893
|
+
path.join(pluginPath, actionPath)
|
|
894
|
+
];
|
|
895
|
+
const found = possiblePaths.find((p) => fs.existsSync(p));
|
|
896
|
+
return found || null;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
const resolved = resolveActionMetadataPath(actionPath, pluginPath);
|
|
900
|
+
return fs.existsSync(resolved) ? resolved : null;
|
|
901
|
+
}
|
|
902
|
+
function toKebabCase(str) {
|
|
903
|
+
return str.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
904
|
+
}
|
|
905
|
+
async function materializeContracts(options, services = /* @__PURE__ */ new Map()) {
|
|
906
|
+
const {
|
|
907
|
+
projectRoot,
|
|
908
|
+
outputDir = path.join(projectRoot, "agent-kit", "materialized-contracts"),
|
|
909
|
+
dynamicOnly = false,
|
|
910
|
+
pluginFilter,
|
|
911
|
+
verbose = false,
|
|
912
|
+
viteServer
|
|
913
|
+
} = options;
|
|
914
|
+
const pluginsIndexMap = /* @__PURE__ */ new Map();
|
|
915
|
+
let staticCount = 0;
|
|
916
|
+
let dynamicCount = 0;
|
|
917
|
+
if (verbose) {
|
|
918
|
+
getLogger().info("Scanning for plugins...");
|
|
919
|
+
}
|
|
920
|
+
const plugins = await scanPlugins({
|
|
921
|
+
projectRoot,
|
|
922
|
+
verbose,
|
|
923
|
+
includeDevDeps: true
|
|
924
|
+
// Include dev deps for contract discovery
|
|
925
|
+
});
|
|
926
|
+
if (verbose) {
|
|
927
|
+
getLogger().info(`Found ${plugins.size} plugin(s)`);
|
|
928
|
+
}
|
|
929
|
+
for (const [pluginKey, plugin] of plugins) {
|
|
930
|
+
if (pluginFilter && plugin.name !== pluginFilter && pluginKey !== pluginFilter) continue;
|
|
931
|
+
if (verbose) {
|
|
932
|
+
getLogger().info(`
|
|
933
|
+
š¦ Processing plugin: ${plugin.name}`);
|
|
934
|
+
}
|
|
935
|
+
const { manifest } = plugin;
|
|
936
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
937
|
+
if (!pluginsIndexMap.has(plugin.name)) {
|
|
938
|
+
const entry = {
|
|
939
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
940
|
+
contracts: [],
|
|
941
|
+
actions: []
|
|
942
|
+
};
|
|
943
|
+
if (manifest.services?.length) {
|
|
944
|
+
entry.services = manifest.services.map((s2) => {
|
|
945
|
+
const docPath = s2.doc ? "./" + path.relative(projectRoot, path.resolve(plugin.pluginPath, s2.doc)) : void 0;
|
|
946
|
+
return {
|
|
947
|
+
name: s2.name,
|
|
948
|
+
marker: s2.marker,
|
|
949
|
+
...s2.description && { description: s2.description },
|
|
950
|
+
...docPath && { doc: docPath }
|
|
951
|
+
};
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
if (manifest.contexts?.length) {
|
|
955
|
+
entry.contexts = manifest.contexts.map((c) => {
|
|
956
|
+
const docPath = c.doc ? "./" + path.relative(projectRoot, path.resolve(plugin.pluginPath, c.doc)) : void 0;
|
|
957
|
+
return {
|
|
958
|
+
name: c.name,
|
|
959
|
+
marker: c.marker,
|
|
960
|
+
...c.description && { description: c.description },
|
|
961
|
+
...docPath && { doc: docPath }
|
|
962
|
+
};
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
if (manifest.routes?.length) {
|
|
966
|
+
entry.routes = manifest.routes.map((r) => ({
|
|
967
|
+
path: r.path,
|
|
968
|
+
...r.description && { description: r.description }
|
|
969
|
+
}));
|
|
970
|
+
}
|
|
971
|
+
if (manifest.commands?.length) {
|
|
972
|
+
entry.commands = manifest.commands.map((c) => {
|
|
973
|
+
let description;
|
|
974
|
+
if (c.command) {
|
|
975
|
+
try {
|
|
976
|
+
const cmdPath = path.resolve(plugin.pluginPath, c.command);
|
|
977
|
+
const cmdContent = fs.readFileSync(cmdPath, "utf-8");
|
|
978
|
+
const parsed = YAML.parse(cmdContent);
|
|
979
|
+
description = parsed?.description;
|
|
980
|
+
} catch {
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return {
|
|
984
|
+
name: c.name,
|
|
985
|
+
...description && { description }
|
|
986
|
+
};
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
pluginsIndexMap.set(plugin.name, entry);
|
|
990
|
+
}
|
|
991
|
+
if (!dynamicOnly && manifest.contracts) {
|
|
992
|
+
for (const contract of manifest.contracts) {
|
|
993
|
+
const contractPath = resolveStaticContractPath(
|
|
994
|
+
plugin,
|
|
995
|
+
contract.contract,
|
|
996
|
+
projectRoot
|
|
997
|
+
);
|
|
998
|
+
const relativePath = path.relative(projectRoot, contractPath);
|
|
999
|
+
let description = contract.description;
|
|
1000
|
+
if (!description) {
|
|
1001
|
+
try {
|
|
1002
|
+
const contractContent = fs.readFileSync(contractPath, "utf-8");
|
|
1003
|
+
const parsed = YAML.parse(contractContent);
|
|
1004
|
+
if (parsed?.description && typeof parsed.description === "string") {
|
|
1005
|
+
description = parsed.description;
|
|
1006
|
+
}
|
|
1007
|
+
} catch {
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
pluginsIndexMap.get(plugin.name).contracts.push({
|
|
1011
|
+
name: contract.name,
|
|
1012
|
+
...description && { description },
|
|
1013
|
+
type: "static",
|
|
1014
|
+
path: "./" + relativePath
|
|
1015
|
+
});
|
|
1016
|
+
staticCount++;
|
|
1017
|
+
if (verbose) {
|
|
1018
|
+
getLogger().info(` š Static: ${contract.name}`);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (manifest.dynamic_contracts) {
|
|
1023
|
+
const dynamicConfigs = Array.isArray(manifest.dynamic_contracts) ? manifest.dynamic_contracts : [manifest.dynamic_contracts];
|
|
1024
|
+
const pluginOutputDir = path.join(outputDir, plugin.name.replace(/[@/]/g, "_"));
|
|
1025
|
+
fs.mkdirSync(pluginOutputDir, { recursive: true });
|
|
1026
|
+
for (const config of dynamicConfigs) {
|
|
1027
|
+
if (verbose) {
|
|
1028
|
+
getLogger().info(` ā” Dynamic contracts (prefix: ${config.prefix})`);
|
|
1029
|
+
}
|
|
1030
|
+
try {
|
|
1031
|
+
const generatedContracts = await executeDynamicGenerator(
|
|
1032
|
+
plugin,
|
|
1033
|
+
config,
|
|
1034
|
+
projectRoot,
|
|
1035
|
+
services,
|
|
1036
|
+
verbose,
|
|
1037
|
+
viteServer
|
|
1038
|
+
);
|
|
1039
|
+
const prefix = config.prefix;
|
|
1040
|
+
if (generatedContracts.length > 1) {
|
|
1041
|
+
const missing = generatedContracts.filter((c) => !c.name);
|
|
1042
|
+
if (missing.length > 0) {
|
|
1043
|
+
getLogger().error(
|
|
1044
|
+
` ā Dynamic contract generator for "${prefix}" returned ${generatedContracts.length} contracts but ${missing.length} are missing a name. Names are required when a generator returns multiple contracts.`
|
|
1045
|
+
);
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
for (const generated of generatedContracts) {
|
|
1050
|
+
const kebabName = generated.name ? toKebabCase(generated.name) : null;
|
|
1051
|
+
const fullName = kebabName ? `${prefix}/${kebabName}` : prefix;
|
|
1052
|
+
const fileName = kebabName ? `${prefix}-${kebabName}.jay-contract` : `${prefix}.jay-contract`;
|
|
1053
|
+
const filePath = path.join(pluginOutputDir, fileName);
|
|
1054
|
+
fs.writeFileSync(filePath, generated.yaml, "utf-8");
|
|
1055
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
1056
|
+
let dynDescription;
|
|
1057
|
+
try {
|
|
1058
|
+
const parsedYaml = YAML.parse(generated.yaml);
|
|
1059
|
+
if (parsedYaml?.description && typeof parsedYaml.description === "string") {
|
|
1060
|
+
dynDescription = parsedYaml.description;
|
|
1061
|
+
}
|
|
1062
|
+
} catch {
|
|
1063
|
+
}
|
|
1064
|
+
const contractEntry = {
|
|
1065
|
+
name: fullName,
|
|
1066
|
+
...dynDescription && { description: dynDescription },
|
|
1067
|
+
type: "dynamic",
|
|
1068
|
+
path: "./" + relativePath,
|
|
1069
|
+
...generated.metadata && { metadata: generated.metadata }
|
|
1070
|
+
};
|
|
1071
|
+
pluginsIndexMap.get(plugin.name).contracts.push(contractEntry);
|
|
1072
|
+
dynamicCount++;
|
|
1073
|
+
if (verbose) {
|
|
1074
|
+
getLogger().info(` ā” Materialized: ${fullName}`);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
getLogger().error(
|
|
1079
|
+
` ā Failed to materialize dynamic contracts for ${plugin.name} (${config.prefix}): ${error}`
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (manifest.actions && Array.isArray(manifest.actions)) {
|
|
1085
|
+
for (const entry of manifest.actions) {
|
|
1086
|
+
const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
|
|
1087
|
+
if (!actionPath) continue;
|
|
1088
|
+
const metadataFilePath = resolveActionFilePath(
|
|
1089
|
+
actionPath,
|
|
1090
|
+
plugin.packageName,
|
|
1091
|
+
plugin.pluginPath,
|
|
1092
|
+
plugin.isLocal,
|
|
1093
|
+
projectRoot
|
|
1094
|
+
);
|
|
1095
|
+
if (!metadataFilePath) continue;
|
|
1096
|
+
const metadata = loadActionMetadata(metadataFilePath);
|
|
1097
|
+
if (!metadata) continue;
|
|
1098
|
+
const actionRelPath = path.relative(projectRoot, metadataFilePath);
|
|
1099
|
+
const pluginEntry = pluginsIndexMap.get(plugin.name);
|
|
1100
|
+
if (!pluginEntry.actions) pluginEntry.actions = [];
|
|
1101
|
+
pluginEntry.actions.push({
|
|
1102
|
+
name: metadata.name,
|
|
1103
|
+
description: metadata.description,
|
|
1104
|
+
path: "./" + actionRelPath.replace(/\\/g, "/")
|
|
1105
|
+
});
|
|
1106
|
+
if (verbose) {
|
|
1107
|
+
getLogger().info(` š§ Action: ${metadata.name} (${actionPath})`);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
const pluginsIndex = {
|
|
1113
|
+
plugins: Array.from(pluginsIndexMap.entries()).map(([name, data]) => ({
|
|
1114
|
+
name,
|
|
1115
|
+
path: data.path,
|
|
1116
|
+
contracts: data.contracts,
|
|
1117
|
+
...data.actions && data.actions.length > 0 && { actions: data.actions },
|
|
1118
|
+
...data.services?.length && { services: data.services },
|
|
1119
|
+
...data.contexts?.length && { contexts: data.contexts },
|
|
1120
|
+
...data.routes?.length && { routes: data.routes },
|
|
1121
|
+
...data.commands?.length && { commands: data.commands }
|
|
1122
|
+
}))
|
|
1123
|
+
};
|
|
1124
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
1125
|
+
const agentKitDir = path.dirname(outputDir);
|
|
1126
|
+
const pluginsIndexPath = path.join(agentKitDir, "plugins-index.yaml");
|
|
1127
|
+
fs.writeFileSync(pluginsIndexPath, YAML.stringify(pluginsIndex), "utf-8");
|
|
1128
|
+
if (verbose) {
|
|
1129
|
+
getLogger().info(`
|
|
1130
|
+
ā
Plugins index written to: ${pluginsIndexPath}`);
|
|
1131
|
+
}
|
|
1132
|
+
return {
|
|
1133
|
+
pluginsIndex,
|
|
1134
|
+
staticCount,
|
|
1135
|
+
dynamicCount,
|
|
1136
|
+
outputDir
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
async function listContracts(options) {
|
|
1140
|
+
const { projectRoot, dynamicOnly = false, pluginFilter } = options;
|
|
1141
|
+
const pluginsMap = /* @__PURE__ */ new Map();
|
|
1142
|
+
const plugins = await scanPlugins({
|
|
1143
|
+
projectRoot,
|
|
1144
|
+
includeDevDeps: true
|
|
1145
|
+
});
|
|
1146
|
+
for (const [pluginKey, plugin] of plugins) {
|
|
1147
|
+
if (pluginFilter && plugin.name !== pluginFilter && pluginKey !== pluginFilter) continue;
|
|
1148
|
+
const { manifest } = plugin;
|
|
1149
|
+
const pluginRelPath = path.relative(projectRoot, plugin.pluginPath);
|
|
1150
|
+
if (!pluginsMap.has(plugin.name)) {
|
|
1151
|
+
const entry = {
|
|
1152
|
+
path: "./" + pluginRelPath.replace(/\\/g, "/"),
|
|
1153
|
+
contracts: []
|
|
1154
|
+
};
|
|
1155
|
+
if (manifest.services?.length) {
|
|
1156
|
+
entry.services = manifest.services.map((s2) => {
|
|
1157
|
+
const docPath = s2.doc ? "./" + path.relative(projectRoot, path.resolve(plugin.pluginPath, s2.doc)) : void 0;
|
|
1158
|
+
return {
|
|
1159
|
+
name: s2.name,
|
|
1160
|
+
marker: s2.marker,
|
|
1161
|
+
...s2.description && { description: s2.description },
|
|
1162
|
+
...docPath && { doc: docPath }
|
|
1163
|
+
};
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
if (manifest.contexts?.length) {
|
|
1167
|
+
entry.contexts = manifest.contexts.map((c) => {
|
|
1168
|
+
const docPath = c.doc ? "./" + path.relative(projectRoot, path.resolve(plugin.pluginPath, c.doc)) : void 0;
|
|
1169
|
+
return {
|
|
1170
|
+
name: c.name,
|
|
1171
|
+
marker: c.marker,
|
|
1172
|
+
...c.description && { description: c.description },
|
|
1173
|
+
...docPath && { doc: docPath }
|
|
1174
|
+
};
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
if (manifest.routes?.length) {
|
|
1178
|
+
entry.routes = manifest.routes.map((r) => ({
|
|
1179
|
+
path: r.path,
|
|
1180
|
+
...r.description && { description: r.description }
|
|
1181
|
+
}));
|
|
1182
|
+
}
|
|
1183
|
+
if (manifest.commands?.length) {
|
|
1184
|
+
entry.commands = manifest.commands.map((c) => {
|
|
1185
|
+
let description;
|
|
1186
|
+
if (c.command) {
|
|
1187
|
+
try {
|
|
1188
|
+
const cmdPath = path.resolve(plugin.pluginPath, c.command);
|
|
1189
|
+
const cmdContent = fs.readFileSync(cmdPath, "utf-8");
|
|
1190
|
+
const parsed = YAML.parse(cmdContent);
|
|
1191
|
+
description = parsed?.description;
|
|
1192
|
+
} catch {
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
return {
|
|
1196
|
+
name: c.name,
|
|
1197
|
+
...description && { description }
|
|
1198
|
+
};
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
pluginsMap.set(plugin.name, entry);
|
|
1202
|
+
}
|
|
1203
|
+
if (!dynamicOnly && manifest.contracts) {
|
|
1204
|
+
for (const contract of manifest.contracts) {
|
|
1205
|
+
const contractPath = resolveStaticContractPath(
|
|
1206
|
+
plugin,
|
|
1207
|
+
contract.contract,
|
|
1208
|
+
projectRoot
|
|
1209
|
+
);
|
|
1210
|
+
const relativePath = path.relative(projectRoot, contractPath);
|
|
1211
|
+
let listDescription = contract.description;
|
|
1212
|
+
if (!listDescription) {
|
|
1213
|
+
try {
|
|
1214
|
+
const contractContent = fs.readFileSync(contractPath, "utf-8");
|
|
1215
|
+
const parsed = YAML.parse(contractContent);
|
|
1216
|
+
if (parsed?.description && typeof parsed.description === "string") {
|
|
1217
|
+
listDescription = parsed.description;
|
|
1218
|
+
}
|
|
1219
|
+
} catch {
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1223
|
+
name: contract.name,
|
|
1224
|
+
...listDescription && { description: listDescription },
|
|
1225
|
+
type: "static",
|
|
1226
|
+
path: "./" + relativePath
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
if (manifest.dynamic_contracts) {
|
|
1231
|
+
const dynamicConfigs = Array.isArray(manifest.dynamic_contracts) ? manifest.dynamic_contracts : [manifest.dynamic_contracts];
|
|
1232
|
+
for (const config of dynamicConfigs) {
|
|
1233
|
+
pluginsMap.get(plugin.name).contracts.push({
|
|
1234
|
+
name: `${config.prefix}/*`,
|
|
1235
|
+
type: "dynamic",
|
|
1236
|
+
path: "(run materialization to generate)"
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return {
|
|
1242
|
+
plugins: Array.from(pluginsMap.entries()).map(([name, data]) => ({
|
|
1243
|
+
name,
|
|
1244
|
+
path: data.path,
|
|
1245
|
+
contracts: data.contracts,
|
|
1246
|
+
...data.services?.length && { services: data.services },
|
|
1247
|
+
...data.contexts?.length && { contexts: data.contexts },
|
|
1248
|
+
...data.routes?.length && { routes: data.routes },
|
|
1249
|
+
...data.commands?.length && { commands: data.commands }
|
|
1250
|
+
}))
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
async function discoverPluginCommands(options) {
|
|
1254
|
+
const { projectRoot, verbose, pluginFilter } = options;
|
|
1255
|
+
const allPlugins = await scanPlugins({
|
|
1256
|
+
projectRoot,
|
|
1257
|
+
verbose,
|
|
1258
|
+
discoverTransitive: true,
|
|
1259
|
+
includeDevDeps: true
|
|
1260
|
+
});
|
|
1261
|
+
const commands = [];
|
|
1262
|
+
for (const [packageName, plugin] of allPlugins) {
|
|
1263
|
+
if (!plugin.manifest.commands || plugin.manifest.commands.length === 0) continue;
|
|
1264
|
+
if (pluginFilter && plugin.name !== pluginFilter && packageName !== pluginFilter) {
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
for (const cmd of plugin.manifest.commands) {
|
|
1268
|
+
let metadata;
|
|
1269
|
+
let metadataPath;
|
|
1270
|
+
if (cmd.command) {
|
|
1271
|
+
metadataPath = path.resolve(plugin.pluginPath, cmd.command);
|
|
1272
|
+
metadata = loadCommandMetadata(metadataPath);
|
|
1273
|
+
}
|
|
1274
|
+
commands.push({
|
|
1275
|
+
pluginName: plugin.name,
|
|
1276
|
+
pluginPath: plugin.pluginPath,
|
|
1277
|
+
packageName: plugin.packageName,
|
|
1278
|
+
isLocal: plugin.isLocal,
|
|
1279
|
+
commandName: cmd.name,
|
|
1280
|
+
handlerExport: cmd.name,
|
|
1281
|
+
pluginModule: plugin.manifest.module,
|
|
1282
|
+
metadata,
|
|
1283
|
+
metadataPath
|
|
1284
|
+
});
|
|
1285
|
+
if (verbose) {
|
|
1286
|
+
getLogger().info(`[Commands] Found ${plugin.name}/${cmd.name}`);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return commands;
|
|
1291
|
+
}
|
|
1292
|
+
function loadCommandMetadata(filePath) {
|
|
1293
|
+
try {
|
|
1294
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
1295
|
+
return YAML.parse(content);
|
|
1296
|
+
} catch {
|
|
1297
|
+
return void 0;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
function commandSchemaToFlags(inputSchema) {
|
|
1301
|
+
const flags = [];
|
|
1302
|
+
for (const [field, type] of Object.entries(inputSchema)) {
|
|
1303
|
+
const isOptional = field.endsWith("?");
|
|
1304
|
+
const cleanName = isOptional ? field.slice(0, -1) : field;
|
|
1305
|
+
const kebabName = camelToKebab(cleanName);
|
|
1306
|
+
const cleanType = type.toLowerCase().trim();
|
|
1307
|
+
const isBoolean = cleanType === "boolean";
|
|
1308
|
+
flags.push({
|
|
1309
|
+
flag: isBoolean ? `--${kebabName}` : `--${kebabName} <value>`,
|
|
1310
|
+
description: "",
|
|
1311
|
+
required: !isOptional,
|
|
1312
|
+
type: cleanType === "number" ? "number" : isBoolean ? "boolean" : "string"
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
return flags;
|
|
1316
|
+
}
|
|
1317
|
+
function camelToKebab(str) {
|
|
1318
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
1319
|
+
}
|
|
1320
|
+
function parseInputFromFlags(rawOptions, schema) {
|
|
1321
|
+
const input2 = {};
|
|
1322
|
+
for (const [field, type] of Object.entries(schema)) {
|
|
1323
|
+
const isOptional = field.endsWith("?");
|
|
1324
|
+
const cleanName = isOptional ? field.slice(0, -1) : field;
|
|
1325
|
+
const kebabName = camelToKebab(cleanName);
|
|
1326
|
+
const value = rawOptions[kebabName];
|
|
1327
|
+
if (value === void 0) {
|
|
1328
|
+
if (!isOptional) {
|
|
1329
|
+
throw new Error(`Missing required flag: --${kebabName}`);
|
|
1330
|
+
}
|
|
1331
|
+
continue;
|
|
1332
|
+
}
|
|
1333
|
+
const cleanType = type.toLowerCase().trim();
|
|
1334
|
+
if (cleanType === "number") {
|
|
1335
|
+
const parsed = Number(value);
|
|
1336
|
+
if (isNaN(parsed)) throw new Error(`Flag --${kebabName} must be a number`);
|
|
1337
|
+
input2[cleanName] = parsed;
|
|
1338
|
+
} else if (cleanType === "boolean") {
|
|
1339
|
+
input2[cleanName] = value === true || value === "true";
|
|
1340
|
+
} else {
|
|
1341
|
+
input2[cleanName] = String(value);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return input2;
|
|
1345
|
+
}
|
|
1346
|
+
async function executePluginCommand(command, input2, viteServer) {
|
|
1347
|
+
const cliCommand = await loadCommandHandler(command, viteServer);
|
|
1348
|
+
const services = resolveServices(cliCommand.services);
|
|
1349
|
+
return cliCommand.handler(input2, ...services);
|
|
1350
|
+
}
|
|
1351
|
+
async function loadCommandHandler(command, viteServer) {
|
|
1352
|
+
let module;
|
|
1353
|
+
if (command.isLocal) {
|
|
1354
|
+
const moduleFile = command.pluginModule || "index";
|
|
1355
|
+
const modulePath = path.resolve(command.pluginPath, moduleFile);
|
|
1356
|
+
if (viteServer) {
|
|
1357
|
+
module = await viteServer.ssrLoadModule(modulePath);
|
|
1358
|
+
} else {
|
|
1359
|
+
module = await import(modulePath);
|
|
1360
|
+
}
|
|
1361
|
+
} else {
|
|
1362
|
+
if (viteServer) {
|
|
1363
|
+
module = await viteServer.ssrLoadModule(command.packageName);
|
|
1364
|
+
} else {
|
|
1365
|
+
module = await import(command.packageName);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
for (const [, exported] of Object.entries(module)) {
|
|
1369
|
+
if (isJayCliCommand(exported) && exported.commandName === command.commandName) {
|
|
1370
|
+
return exported;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
const byName = module[command.handlerExport];
|
|
1374
|
+
if (byName && isJayCliCommand(byName)) {
|
|
1375
|
+
return byName;
|
|
1376
|
+
}
|
|
1377
|
+
throw new Error(
|
|
1378
|
+
`CLI command "${command.commandName}" not found as export in "${command.isLocal ? command.pluginPath : command.packageName}". Available exports: ${Object.keys(module).join(", ")}`
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
class SetupNeedsAnswerError extends Error {
|
|
1382
|
+
constructor(plugin, key, type, promptMessage, choices) {
|
|
1383
|
+
super(`Setup needs answer for "${key}": ${promptMessage}`);
|
|
1384
|
+
this.plugin = plugin;
|
|
1385
|
+
this.key = key;
|
|
1386
|
+
this.type = type;
|
|
1387
|
+
this.promptMessage = promptMessage;
|
|
1388
|
+
this.choices = choices;
|
|
1389
|
+
this.name = "SetupNeedsAnswerError";
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
async function discoverPluginsWithSetup(options) {
|
|
1393
|
+
const { projectRoot, verbose, pluginFilter } = options;
|
|
1394
|
+
const allPlugins = await scanPlugins({
|
|
1395
|
+
projectRoot,
|
|
1396
|
+
verbose,
|
|
1397
|
+
includeDevDeps: true,
|
|
1398
|
+
discoverTransitive: true
|
|
1399
|
+
});
|
|
1400
|
+
const pluginsWithSetup = [];
|
|
1401
|
+
for (const [packageName, plugin] of allPlugins) {
|
|
1402
|
+
if (!plugin.manifest.setup) continue;
|
|
1403
|
+
if (pluginFilter && plugin.name !== pluginFilter && packageName !== pluginFilter) {
|
|
1404
|
+
continue;
|
|
1405
|
+
}
|
|
1406
|
+
pluginsWithSetup.push({
|
|
1407
|
+
name: plugin.name,
|
|
1408
|
+
pluginPath: plugin.pluginPath,
|
|
1409
|
+
packageName: plugin.packageName,
|
|
1410
|
+
isLocal: plugin.isLocal,
|
|
1411
|
+
setupHandler: plugin.manifest.setup,
|
|
1412
|
+
setupDescription: plugin.manifest.description,
|
|
1413
|
+
dependencies: plugin.dependencies
|
|
1414
|
+
});
|
|
1415
|
+
if (verbose) {
|
|
1416
|
+
getLogger().info(`[Setup] Found plugin with setup: ${plugin.name}`);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return sortPluginsByDependencies(pluginsWithSetup);
|
|
1420
|
+
}
|
|
1421
|
+
async function discoverPluginsWithAgentKit(options) {
|
|
1422
|
+
const { projectRoot, verbose, pluginFilter } = options;
|
|
1423
|
+
const allPlugins = await scanPlugins({
|
|
1424
|
+
projectRoot,
|
|
1425
|
+
verbose,
|
|
1426
|
+
includeDevDeps: true,
|
|
1427
|
+
discoverTransitive: true
|
|
1428
|
+
});
|
|
1429
|
+
const pluginsWithAgentKit = [];
|
|
1430
|
+
for (const [packageName, plugin] of allPlugins) {
|
|
1431
|
+
if (!plugin.manifest.agentkit) continue;
|
|
1432
|
+
if (pluginFilter && plugin.name !== pluginFilter && packageName !== pluginFilter) {
|
|
1433
|
+
continue;
|
|
1434
|
+
}
|
|
1435
|
+
pluginsWithAgentKit.push({
|
|
1436
|
+
name: plugin.name,
|
|
1437
|
+
pluginPath: plugin.pluginPath,
|
|
1438
|
+
packageName: plugin.packageName,
|
|
1439
|
+
isLocal: plugin.isLocal,
|
|
1440
|
+
agentKitHandler: plugin.manifest.agentkit,
|
|
1441
|
+
dependencies: plugin.dependencies
|
|
1442
|
+
});
|
|
1443
|
+
if (verbose) {
|
|
1444
|
+
getLogger().info(`[AgentKit] Found plugin with agent-kit handler: ${plugin.name}`);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
return sortPluginsByDependencies(pluginsWithAgentKit);
|
|
1448
|
+
}
|
|
1449
|
+
async function executePluginSetup(plugin, options) {
|
|
1450
|
+
const { projectRoot, configDir, force, interactive, prompt, initError, viteServer } = options;
|
|
1451
|
+
const context = {
|
|
1452
|
+
pluginName: plugin.name,
|
|
1453
|
+
projectRoot,
|
|
1454
|
+
configDir,
|
|
1455
|
+
services: getServiceRegistry(),
|
|
1456
|
+
initError,
|
|
1457
|
+
force,
|
|
1458
|
+
interactive,
|
|
1459
|
+
prompt
|
|
1460
|
+
};
|
|
1461
|
+
const handler = await loadHandler(plugin, plugin.setupHandler, viteServer);
|
|
1462
|
+
return handler(context);
|
|
1463
|
+
}
|
|
1464
|
+
async function executePluginAgentKit(plugin, options) {
|
|
1465
|
+
const { projectRoot, force, initError, viteServer } = options;
|
|
1466
|
+
const referencesDir = path.join(projectRoot, "agent-kit", "references", plugin.name);
|
|
1467
|
+
const context = {
|
|
1468
|
+
pluginName: plugin.name,
|
|
1469
|
+
projectRoot,
|
|
1470
|
+
referencesDir,
|
|
1471
|
+
services: getServiceRegistry(),
|
|
1472
|
+
initError,
|
|
1473
|
+
force
|
|
1474
|
+
};
|
|
1475
|
+
const handler = await loadHandler(
|
|
1476
|
+
plugin,
|
|
1477
|
+
plugin.agentKitHandler,
|
|
1478
|
+
viteServer
|
|
1479
|
+
);
|
|
1480
|
+
return handler(context);
|
|
1481
|
+
}
|
|
1482
|
+
async function loadHandler(plugin, handlerName, viteServer) {
|
|
1483
|
+
let module;
|
|
1484
|
+
if (plugin.isLocal) {
|
|
1485
|
+
const handlerPath = path.resolve(plugin.pluginPath, handlerName);
|
|
1486
|
+
if (viteServer) {
|
|
1487
|
+
module = await viteServer.ssrLoadModule(handlerPath);
|
|
1488
|
+
} else {
|
|
1489
|
+
module = await import(handlerPath);
|
|
1490
|
+
}
|
|
1491
|
+
if (typeof module[handlerName] === "function") return module[handlerName];
|
|
1492
|
+
if (typeof module.agentkit === "function") return module.agentkit;
|
|
1493
|
+
if (typeof module.setup === "function") return module.setup;
|
|
1494
|
+
if (typeof module.default === "function") return module.default;
|
|
1495
|
+
throw new Error(
|
|
1496
|
+
`Handler "${handlerName}" not found in "${plugin.pluginPath}". Available exports: ${Object.keys(module).join(", ")}`
|
|
1497
|
+
);
|
|
1498
|
+
} else {
|
|
1499
|
+
if (viteServer) {
|
|
1500
|
+
module = await viteServer.ssrLoadModule(plugin.packageName);
|
|
1501
|
+
} else {
|
|
1502
|
+
module = await import(plugin.packageName);
|
|
1503
|
+
}
|
|
1504
|
+
if (typeof module[handlerName] !== "function") {
|
|
1505
|
+
throw new Error(
|
|
1506
|
+
`Handler "${handlerName}" not found as export in "${plugin.packageName}". Available exports: ${Object.keys(module).join(", ")}`
|
|
1507
|
+
);
|
|
1508
|
+
}
|
|
1509
|
+
return module[handlerName];
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
225
1512
|
async function initializeServicesForCli(projectRoot, viteServer, quiet = false) {
|
|
226
1513
|
const path2 = await import("node:path");
|
|
227
1514
|
const fs2 = await import("node:fs");
|
|
228
1515
|
const {
|
|
229
1516
|
runInitCallbacks: runInitCallbacks2,
|
|
230
|
-
getServiceRegistry,
|
|
1517
|
+
getServiceRegistry: getServiceRegistry2,
|
|
231
1518
|
discoverPluginsWithInit: discoverPluginsWithInit2,
|
|
232
1519
|
sortPluginsByDependencies: sortPluginsByDependencies2,
|
|
233
1520
|
executePluginServerInits: executePluginServerInits2
|
|
@@ -260,7 +1547,7 @@ async function initializeServicesForCli(projectRoot, viteServer, quiet = false)
|
|
|
260
1547
|
getLogger().warn(chalk.yellow(`ā ļø Service initialization failed: ${error.message}`));
|
|
261
1548
|
getLogger().warn(chalk.gray(" Static contracts will still be listed."));
|
|
262
1549
|
}
|
|
263
|
-
return { services:
|
|
1550
|
+
return { services: getServiceRegistry2(), initErrors };
|
|
264
1551
|
}
|
|
265
1552
|
async function runDev(projectPath, options) {
|
|
266
1553
|
const logLevel = options.quiet ? "silent" : options.verbose ? "verbose" : "info";
|
|
@@ -274,12 +1561,12 @@ async function runDev(projectPath, options) {
|
|
|
274
1561
|
});
|
|
275
1562
|
}
|
|
276
1563
|
async function resolveProductionContext(projectPath, versionOverride) {
|
|
277
|
-
const resolvedPath =
|
|
278
|
-
const jayConfigPath =
|
|
1564
|
+
const resolvedPath = path__default.resolve(projectPath || process.cwd());
|
|
1565
|
+
const jayConfigPath = path__default.join(resolvedPath, ".jay");
|
|
279
1566
|
let pagesBase = "./src/pages";
|
|
280
1567
|
let siteBaseUrl;
|
|
281
1568
|
try {
|
|
282
|
-
const jayConfig = YAML.parse(await fs$
|
|
1569
|
+
const jayConfig = YAML.parse(await fs$2.readFile(jayConfigPath, "utf-8"));
|
|
283
1570
|
pagesBase = jayConfig?.devServer?.pagesBase || pagesBase;
|
|
284
1571
|
siteBaseUrl = jayConfig?.site?.baseUrl;
|
|
285
1572
|
} catch {
|
|
@@ -287,17 +1574,17 @@ async function resolveProductionContext(projectPath, versionOverride) {
|
|
|
287
1574
|
const version = versionOverride || await resolveVersionFromPackageJson(resolvedPath);
|
|
288
1575
|
return {
|
|
289
1576
|
resolvedPath,
|
|
290
|
-
pagesRoot:
|
|
291
|
-
buildRoot:
|
|
1577
|
+
pagesRoot: path__default.resolve(resolvedPath, pagesBase),
|
|
1578
|
+
buildRoot: path__default.join(resolvedPath, "build"),
|
|
292
1579
|
version,
|
|
293
|
-
tsConfigFilePath:
|
|
1580
|
+
tsConfigFilePath: path__default.join(resolvedPath, "tsconfig.json"),
|
|
294
1581
|
siteBaseUrl
|
|
295
1582
|
};
|
|
296
1583
|
}
|
|
297
1584
|
async function resolveVersionFromPackageJson(projectRoot) {
|
|
298
1585
|
try {
|
|
299
1586
|
const pkgJson = JSON.parse(
|
|
300
|
-
await fs$
|
|
1587
|
+
await fs$2.readFile(path__default.join(projectRoot, "package.json"), "utf-8")
|
|
301
1588
|
);
|
|
302
1589
|
if (pkgJson.version) {
|
|
303
1590
|
return pkgJson.version;
|
|
@@ -313,7 +1600,7 @@ function initLogger(verbose) {
|
|
|
313
1600
|
async function runBuild(projectPath, options) {
|
|
314
1601
|
initLogger(options.verbose);
|
|
315
1602
|
const ctx = await resolveProductionContext(projectPath, options.version);
|
|
316
|
-
const { buildVersion } = await import("
|
|
1603
|
+
const { buildVersion } = await import("./index-CatrpDqC.js");
|
|
317
1604
|
await buildVersion({
|
|
318
1605
|
version: ctx.version,
|
|
319
1606
|
projectRoot: ctx.resolvedPath,
|
|
@@ -1158,7 +2445,7 @@ function isRelativeHandlerRef(value) {
|
|
|
1158
2445
|
function resolveModulePath$1(basePath) {
|
|
1159
2446
|
for (const ext of ["", ".ts", ".js", "/index.ts", "/index.js"]) {
|
|
1160
2447
|
const candidate = basePath + ext;
|
|
1161
|
-
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
2448
|
+
if (fs$1.existsSync(candidate) && fs$1.statSync(candidate).isFile()) {
|
|
1162
2449
|
return candidate;
|
|
1163
2450
|
}
|
|
1164
2451
|
}
|
|
@@ -1166,10 +2453,10 @@ function resolveModulePath$1(basePath) {
|
|
|
1166
2453
|
}
|
|
1167
2454
|
function collectTypeScriptFiles(dir, depth = 0) {
|
|
1168
2455
|
if (depth > 4) return [];
|
|
1169
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
2456
|
+
const entries = fs$1.readdirSync(dir, { withFileTypes: true });
|
|
1170
2457
|
const files = [];
|
|
1171
2458
|
for (const entry of entries) {
|
|
1172
|
-
const fullPath = path.join(dir, entry.name);
|
|
2459
|
+
const fullPath = path$1.join(dir, entry.name);
|
|
1173
2460
|
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "test") {
|
|
1174
2461
|
files.push(...collectTypeScriptFiles(fullPath, depth + 1));
|
|
1175
2462
|
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) {
|
|
@@ -1180,13 +2467,13 @@ function collectTypeScriptFiles(dir, depth = 0) {
|
|
|
1180
2467
|
}
|
|
1181
2468
|
function resolveHandlerSourceFile(pluginPath, handlerRef, isNpmPackage) {
|
|
1182
2469
|
if (isRelativeHandlerRef(handlerRef)) {
|
|
1183
|
-
return resolveModulePath$1(path.join(pluginPath, handlerRef)) ?? null;
|
|
2470
|
+
return resolveModulePath$1(path$1.join(pluginPath, handlerRef)) ?? null;
|
|
1184
2471
|
}
|
|
1185
|
-
const searchRoots = isNpmPackage ? [path.join(pluginPath, "lib"), path.join(pluginPath, "dist")] : [pluginPath];
|
|
2472
|
+
const searchRoots = isNpmPackage ? [path$1.join(pluginPath, "lib"), path$1.join(pluginPath, "dist")] : [pluginPath];
|
|
1186
2473
|
for (const root of searchRoots) {
|
|
1187
|
-
if (!fs.existsSync(root)) continue;
|
|
2474
|
+
if (!fs$1.existsSync(root)) continue;
|
|
1188
2475
|
for (const file of collectTypeScriptFiles(root)) {
|
|
1189
|
-
const content = fs.readFileSync(file, "utf-8");
|
|
2476
|
+
const content = fs$1.readFileSync(file, "utf-8");
|
|
1190
2477
|
const definesHandler = new RegExp(
|
|
1191
2478
|
`export\\s+(?:async\\s+)?function\\s+${handlerRef}\\b`
|
|
1192
2479
|
).test(content);
|
|
@@ -1203,7 +2490,7 @@ function resolveHandlerSourceFile(pluginPath, handlerRef, isNpmPackage) {
|
|
|
1203
2490
|
);
|
|
1204
2491
|
if (reExportMatch) {
|
|
1205
2492
|
const importSpec = reExportMatch[1].replace(/\.js$/, "");
|
|
1206
|
-
const resolved = resolveModulePath$1(path.resolve(path.dirname(file), importSpec));
|
|
2493
|
+
const resolved = resolveModulePath$1(path$1.resolve(path$1.dirname(file), importSpec));
|
|
1207
2494
|
if (resolved) return resolved;
|
|
1208
2495
|
}
|
|
1209
2496
|
}
|
|
@@ -1279,7 +2566,7 @@ function handlerBodyWritesAddMenuCatalog(body) {
|
|
|
1279
2566
|
function resolveSetupHandlerFunctionBody(pluginPath, handlerRef, isNpmPackage) {
|
|
1280
2567
|
const sourceFile = resolveHandlerSourceFile(pluginPath, handlerRef, isNpmPackage);
|
|
1281
2568
|
if (!sourceFile) return null;
|
|
1282
|
-
const source = fs.readFileSync(sourceFile, "utf-8");
|
|
2569
|
+
const source = fs$1.readFileSync(sourceFile, "utf-8");
|
|
1283
2570
|
if (isRelativeHandlerRef(handlerRef)) {
|
|
1284
2571
|
return extractDefaultExportFunctionBody(source) ?? extractFunctionBody(source, "setup") ?? extractFunctionBody(source, handlerRef);
|
|
1285
2572
|
}
|
|
@@ -1312,7 +2599,7 @@ function mapLintFinding(finding, catalogPath, severity) {
|
|
|
1312
2599
|
}
|
|
1313
2600
|
function pluginShipsAddMenuCatalog(context) {
|
|
1314
2601
|
return ADD_MENU_CATALOG_REL_PATHS.some(
|
|
1315
|
-
(relPath) => fs.existsSync(path.join(context.pluginPath, relPath))
|
|
2602
|
+
(relPath) => fs$1.existsSync(path$1.join(context.pluginPath, relPath))
|
|
1316
2603
|
);
|
|
1317
2604
|
}
|
|
1318
2605
|
function validateAddMenuAgentKitHandler(context, result) {
|
|
@@ -1346,7 +2633,7 @@ function validateAddMenuAgentKitHandler(context, result) {
|
|
|
1346
2633
|
async function validateAddMenuCatalogFileAtPath(catalogPath, relPath, result) {
|
|
1347
2634
|
let parsed;
|
|
1348
2635
|
try {
|
|
1349
|
-
const content = await fs.promises.readFile(catalogPath, "utf-8");
|
|
2636
|
+
const content = await fs$1.promises.readFile(catalogPath, "utf-8");
|
|
1350
2637
|
parsed = YAML.parse(content);
|
|
1351
2638
|
} catch (error) {
|
|
1352
2639
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1375,8 +2662,8 @@ async function validateAddMenuCatalogFileAtPath(catalogPath, relPath, result) {
|
|
|
1375
2662
|
async function validateAddMenuCatalog(context, result) {
|
|
1376
2663
|
validateAddMenuAgentKitHandler(context, result);
|
|
1377
2664
|
for (const relPath of ADD_MENU_CATALOG_REL_PATHS) {
|
|
1378
|
-
const catalogPath = path.join(context.pluginPath, relPath);
|
|
1379
|
-
if (!fs.existsSync(catalogPath)) continue;
|
|
2665
|
+
const catalogPath = path$1.join(context.pluginPath, relPath);
|
|
2666
|
+
if (!fs$1.existsSync(catalogPath)) continue;
|
|
1380
2667
|
await validateAddMenuCatalogFileAtPath(catalogPath, relPath, result);
|
|
1381
2668
|
}
|
|
1382
2669
|
}
|
|
@@ -1493,7 +2780,7 @@ function mapSchemaError(error, relPath) {
|
|
|
1493
2780
|
function validateSettingsTemplateAtPath(catalogPath, relPath, result, manifest) {
|
|
1494
2781
|
let parsed;
|
|
1495
2782
|
try {
|
|
1496
|
-
parsed = YAML.parse(fs.readFileSync(catalogPath, "utf-8"));
|
|
2783
|
+
parsed = YAML.parse(fs$1.readFileSync(catalogPath, "utf-8"));
|
|
1497
2784
|
} catch (err) {
|
|
1498
2785
|
result.errors.push({
|
|
1499
2786
|
type: "schema",
|
|
@@ -1527,8 +2814,8 @@ function validateSettingsTemplateAtPath(catalogPath, relPath, result, manifest)
|
|
|
1527
2814
|
}
|
|
1528
2815
|
}
|
|
1529
2816
|
async function validateAiditorSettings(context, result) {
|
|
1530
|
-
const templatePath = path.join(context.pluginPath, AIDITOR_SETTINGS_TEMPLATE_REL_PATH);
|
|
1531
|
-
if (!fs.existsSync(templatePath)) {
|
|
2817
|
+
const templatePath = path$1.join(context.pluginPath, AIDITOR_SETTINGS_TEMPLATE_REL_PATH);
|
|
2818
|
+
if (!fs$1.existsSync(templatePath)) {
|
|
1532
2819
|
return;
|
|
1533
2820
|
}
|
|
1534
2821
|
validateSettingsTemplateAtPath(
|
|
@@ -1563,10 +2850,10 @@ async function validatePluginPackage(pluginPath, options) {
|
|
|
1563
2850
|
contractsChecked: 0,
|
|
1564
2851
|
componentsChecked: 0
|
|
1565
2852
|
};
|
|
1566
|
-
const pluginYamlPath = path.join(pluginPath, "plugin.yaml");
|
|
1567
|
-
const pluginManifest = loadPluginManifest(pluginPath);
|
|
2853
|
+
const pluginYamlPath = path$1.join(pluginPath, "plugin.yaml");
|
|
2854
|
+
const pluginManifest = loadPluginManifest$1(pluginPath);
|
|
1568
2855
|
if (!pluginManifest) {
|
|
1569
|
-
if (!fs.existsSync(pluginYamlPath)) {
|
|
2856
|
+
if (!fs$1.existsSync(pluginYamlPath)) {
|
|
1570
2857
|
result.errors.push({
|
|
1571
2858
|
type: "file-missing",
|
|
1572
2859
|
message: "plugin.yaml not found",
|
|
@@ -1587,7 +2874,7 @@ async function validatePluginPackage(pluginPath, options) {
|
|
|
1587
2874
|
const context = {
|
|
1588
2875
|
manifest: pluginManifest,
|
|
1589
2876
|
pluginPath,
|
|
1590
|
-
isNpmPackage: fs.existsSync(path.join(pluginPath, "package.json"))
|
|
2877
|
+
isNpmPackage: fs$1.existsSync(path$1.join(pluginPath, "package.json"))
|
|
1591
2878
|
};
|
|
1592
2879
|
await validateSchema(context, result);
|
|
1593
2880
|
if (pluginManifest.contracts) {
|
|
@@ -1619,8 +2906,8 @@ async function validatePluginPackage(pluginPath, options) {
|
|
|
1619
2906
|
return result;
|
|
1620
2907
|
}
|
|
1621
2908
|
async function validateLocalPlugins(projectPath, options) {
|
|
1622
|
-
const pluginsPath = path.join(projectPath, "src/plugins");
|
|
1623
|
-
if (!fs.existsSync(pluginsPath)) {
|
|
2909
|
+
const pluginsPath = path$1.join(projectPath, "src/plugins");
|
|
2910
|
+
if (!fs$1.existsSync(pluginsPath)) {
|
|
1624
2911
|
return {
|
|
1625
2912
|
valid: false,
|
|
1626
2913
|
errors: [
|
|
@@ -1634,10 +2921,10 @@ async function validateLocalPlugins(projectPath, options) {
|
|
|
1634
2921
|
warnings: []
|
|
1635
2922
|
};
|
|
1636
2923
|
}
|
|
1637
|
-
const pluginDirs = fs.readdirSync(pluginsPath, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
2924
|
+
const pluginDirs = fs$1.readdirSync(pluginsPath, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1638
2925
|
const allResults = [];
|
|
1639
2926
|
for (const pluginDir of pluginDirs) {
|
|
1640
|
-
const pluginPath = path.join(pluginsPath, pluginDir.name);
|
|
2927
|
+
const pluginPath = path$1.join(pluginsPath, pluginDir.name);
|
|
1641
2928
|
const result = await validatePluginPackage(pluginPath, options);
|
|
1642
2929
|
allResults.push(result);
|
|
1643
2930
|
}
|
|
@@ -1651,8 +2938,8 @@ async function validateLocalPlugins(projectPath, options) {
|
|
|
1651
2938
|
};
|
|
1652
2939
|
}
|
|
1653
2940
|
function validateDocFile(docPath, label, context, result) {
|
|
1654
|
-
const resolvedPath = path.join(context.pluginPath, docPath);
|
|
1655
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
2941
|
+
const resolvedPath = path$1.join(context.pluginPath, docPath);
|
|
2942
|
+
if (!fs$1.existsSync(resolvedPath)) {
|
|
1656
2943
|
result.errors.push({
|
|
1657
2944
|
type: "file-missing",
|
|
1658
2945
|
message: `Doc file for ${label} not found: ${docPath}`,
|
|
@@ -1662,9 +2949,9 @@ function validateDocFile(docPath, label, context, result) {
|
|
|
1662
2949
|
return;
|
|
1663
2950
|
}
|
|
1664
2951
|
if (context.isNpmPackage) {
|
|
1665
|
-
const packageJsonPath = path.join(context.pluginPath, "package.json");
|
|
2952
|
+
const packageJsonPath = path$1.join(context.pluginPath, "package.json");
|
|
1666
2953
|
try {
|
|
1667
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
2954
|
+
const packageJson = JSON.parse(fs$1.readFileSync(packageJsonPath, "utf-8"));
|
|
1668
2955
|
if (packageJson.exports) {
|
|
1669
2956
|
const exportKey = "./" + docPath.replace(/^\.\//, "");
|
|
1670
2957
|
if (!packageJson.exports[exportKey]) {
|
|
@@ -1999,25 +3286,25 @@ async function validateSchema(context, result) {
|
|
|
1999
3286
|
}
|
|
2000
3287
|
}
|
|
2001
3288
|
function checkExportExists(exportName, context) {
|
|
2002
|
-
const packageJsonPath = path.join(context.pluginPath, "package.json");
|
|
2003
|
-
if (!fs.existsSync(packageJsonPath)) return true;
|
|
3289
|
+
const packageJsonPath = path$1.join(context.pluginPath, "package.json");
|
|
3290
|
+
if (!fs$1.existsSync(packageJsonPath)) return true;
|
|
2004
3291
|
let mainPath;
|
|
2005
3292
|
try {
|
|
2006
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
3293
|
+
const packageJson = JSON.parse(fs$1.readFileSync(packageJsonPath, "utf-8"));
|
|
2007
3294
|
if (packageJson.exports?.["."]) {
|
|
2008
3295
|
const entry = packageJson.exports["."];
|
|
2009
3296
|
const entryPath = typeof entry === "string" ? entry : entry.default || entry.import;
|
|
2010
|
-
if (entryPath) mainPath = path.join(context.pluginPath, entryPath);
|
|
3297
|
+
if (entryPath) mainPath = path$1.join(context.pluginPath, entryPath);
|
|
2011
3298
|
}
|
|
2012
3299
|
if (!mainPath && packageJson.main) {
|
|
2013
|
-
mainPath = path.join(context.pluginPath, packageJson.main);
|
|
3300
|
+
mainPath = path$1.join(context.pluginPath, packageJson.main);
|
|
2014
3301
|
}
|
|
2015
3302
|
} catch {
|
|
2016
3303
|
return true;
|
|
2017
3304
|
}
|
|
2018
|
-
if (!mainPath || !fs.existsSync(mainPath)) return true;
|
|
3305
|
+
if (!mainPath || !fs$1.existsSync(mainPath)) return true;
|
|
2019
3306
|
try {
|
|
2020
|
-
const content = fs.readFileSync(mainPath, "utf-8");
|
|
3307
|
+
const content = fs$1.readFileSync(mainPath, "utf-8");
|
|
2021
3308
|
const patterns = [
|
|
2022
3309
|
new RegExp(`export\\s*\\{[^}]*\\b${exportName}\\b[^}]*\\}`, "m"),
|
|
2023
3310
|
new RegExp(`export\\s+(?:async\\s+)?function\\s+${exportName}\\b`),
|
|
@@ -2049,9 +3336,9 @@ function validateHandlerRef(value, label, location, context, result) {
|
|
|
2049
3336
|
});
|
|
2050
3337
|
}
|
|
2051
3338
|
} else if (isRelativePath(value)) {
|
|
2052
|
-
const handlerPath = path.join(context.pluginPath, value);
|
|
3339
|
+
const handlerPath = path$1.join(context.pluginPath, value);
|
|
2053
3340
|
const extensions = ["", ".ts", ".js", "/index.ts", "/index.js"];
|
|
2054
|
-
const found = extensions.some((ext) => fs.existsSync(handlerPath + ext));
|
|
3341
|
+
const found = extensions.some((ext) => fs$1.existsSync(handlerPath + ext));
|
|
2055
3342
|
if (!found) {
|
|
2056
3343
|
result.errors.push({
|
|
2057
3344
|
type: "file-missing",
|
|
@@ -2064,18 +3351,18 @@ function validateHandlerRef(value, label, location, context, result) {
|
|
|
2064
3351
|
}
|
|
2065
3352
|
function resolveContractFile(contractSpec, context) {
|
|
2066
3353
|
if (context.isNpmPackage) {
|
|
2067
|
-
const packageJsonPath = path.join(context.pluginPath, "package.json");
|
|
2068
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
3354
|
+
const packageJsonPath = path$1.join(context.pluginPath, "package.json");
|
|
3355
|
+
if (fs$1.existsSync(packageJsonPath)) {
|
|
2069
3356
|
try {
|
|
2070
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
3357
|
+
const packageJson = JSON.parse(fs$1.readFileSync(packageJsonPath, "utf-8"));
|
|
2071
3358
|
if (packageJson.exports) {
|
|
2072
3359
|
const exportKey = "./" + contractSpec;
|
|
2073
3360
|
const exportValue = packageJson.exports[exportKey];
|
|
2074
3361
|
if (exportValue) {
|
|
2075
3362
|
const resolvedPath = typeof exportValue === "string" ? exportValue : exportValue.default || exportValue.import || exportValue.require;
|
|
2076
3363
|
if (resolvedPath) {
|
|
2077
|
-
const fullPath = path.join(context.pluginPath, resolvedPath);
|
|
2078
|
-
if (fs.existsSync(fullPath)) return fullPath;
|
|
3364
|
+
const fullPath = path$1.join(context.pluginPath, resolvedPath);
|
|
3365
|
+
if (fs$1.existsSync(fullPath)) return fullPath;
|
|
2079
3366
|
}
|
|
2080
3367
|
}
|
|
2081
3368
|
}
|
|
@@ -2083,13 +3370,13 @@ function resolveContractFile(contractSpec, context) {
|
|
|
2083
3370
|
}
|
|
2084
3371
|
}
|
|
2085
3372
|
for (const dir of ["dist", "lib", ""]) {
|
|
2086
|
-
const candidate = path.join(context.pluginPath, dir, contractSpec);
|
|
2087
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
3373
|
+
const candidate = path$1.join(context.pluginPath, dir, contractSpec);
|
|
3374
|
+
if (fs$1.existsSync(candidate)) return candidate;
|
|
2088
3375
|
}
|
|
2089
3376
|
return void 0;
|
|
2090
3377
|
} else {
|
|
2091
|
-
const candidate = path.join(context.pluginPath, contractSpec);
|
|
2092
|
-
return fs.existsSync(candidate) ? candidate : void 0;
|
|
3378
|
+
const candidate = path$1.join(context.pluginPath, contractSpec);
|
|
3379
|
+
return fs$1.existsSync(candidate) ? candidate : void 0;
|
|
2093
3380
|
}
|
|
2094
3381
|
}
|
|
2095
3382
|
async function validateContract(contract, index, context, generateTypes, result) {
|
|
@@ -2100,12 +3387,12 @@ async function validateContract(contract, index, context, generateTypes, result)
|
|
|
2100
3387
|
type: "file-missing",
|
|
2101
3388
|
message: `Contract file not found: ${contract.contract}`,
|
|
2102
3389
|
location: `plugin.yaml contracts[${index}]`,
|
|
2103
|
-
suggestion: context.isNpmPackage ? `Ensure the contract is exported in package.json and the file exists` : `Create the contract file at ${path.join(context.pluginPath, contract.contract)}`
|
|
3390
|
+
suggestion: context.isNpmPackage ? `Ensure the contract is exported in package.json and the file exists` : `Create the contract file at ${path$1.join(context.pluginPath, contract.contract)}`
|
|
2104
3391
|
});
|
|
2105
3392
|
return;
|
|
2106
3393
|
}
|
|
2107
3394
|
try {
|
|
2108
|
-
const contractContent = await fs.promises.readFile(contractPath, "utf-8");
|
|
3395
|
+
const contractContent = await fs$1.promises.readFile(contractPath, "utf-8");
|
|
2109
3396
|
const parsedContract = YAML.parse(contractContent);
|
|
2110
3397
|
if (!parsedContract.name) {
|
|
2111
3398
|
result.errors.push({
|
|
@@ -2172,21 +3459,21 @@ function hasExportModifier(node) {
|
|
|
2172
3459
|
function resolveModulePath(basePath) {
|
|
2173
3460
|
for (const ext of ["", ".ts", ".js", "/index.ts", "/index.js"]) {
|
|
2174
3461
|
const candidate = basePath + ext;
|
|
2175
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
3462
|
+
if (fs$1.existsSync(candidate)) return candidate;
|
|
2176
3463
|
}
|
|
2177
3464
|
return void 0;
|
|
2178
3465
|
}
|
|
2179
3466
|
function resolveComponentSourcePath(componentName, context) {
|
|
2180
3467
|
const modulePath = context.manifest.module || "index";
|
|
2181
|
-
const entryBase = path.join(context.pluginPath, modulePath);
|
|
3468
|
+
const entryBase = path$1.join(context.pluginPath, modulePath);
|
|
2182
3469
|
const entryFile = resolveModulePath(entryBase);
|
|
2183
|
-
const libEntryFile = !entryFile ? resolveModulePath(path.join(context.pluginPath, "lib", modulePath)) : void 0;
|
|
3470
|
+
const libEntryFile = !entryFile ? resolveModulePath(path$1.join(context.pluginPath, "lib", modulePath)) : void 0;
|
|
2184
3471
|
const sourceEntry = entryFile || libEntryFile;
|
|
2185
3472
|
if (!sourceEntry) return void 0;
|
|
2186
3473
|
if (!sourceEntry.endsWith(".ts")) return void 0;
|
|
2187
3474
|
let sourceCode;
|
|
2188
3475
|
try {
|
|
2189
|
-
sourceCode = fs.readFileSync(sourceEntry, "utf-8");
|
|
3476
|
+
sourceCode = fs$1.readFileSync(sourceEntry, "utf-8");
|
|
2190
3477
|
} catch {
|
|
2191
3478
|
return void 0;
|
|
2192
3479
|
}
|
|
@@ -2212,7 +3499,7 @@ function resolveComponentSourcePath(componentName, context) {
|
|
|
2212
3499
|
for (const element of exportClause.elements) {
|
|
2213
3500
|
const exportedName = element.name.text;
|
|
2214
3501
|
if (exportedName === componentName) {
|
|
2215
|
-
const resolvedBase = path.resolve(path.dirname(sourceEntry), moduleSpec);
|
|
3502
|
+
const resolvedBase = path$1.resolve(path$1.dirname(sourceEntry), moduleSpec);
|
|
2216
3503
|
return resolveModulePath(resolvedBase);
|
|
2217
3504
|
}
|
|
2218
3505
|
}
|
|
@@ -2220,11 +3507,11 @@ function resolveComponentSourcePath(componentName, context) {
|
|
|
2220
3507
|
}
|
|
2221
3508
|
for (const moduleSpec of starReexportModules) {
|
|
2222
3509
|
if (!moduleSpec.startsWith(".")) continue;
|
|
2223
|
-
const resolvedBase = path.resolve(path.dirname(sourceEntry), moduleSpec);
|
|
3510
|
+
const resolvedBase = path$1.resolve(path$1.dirname(sourceEntry), moduleSpec);
|
|
2224
3511
|
const resolvedPath = resolveModulePath(resolvedBase);
|
|
2225
3512
|
if (!resolvedPath || !resolvedPath.endsWith(".ts")) continue;
|
|
2226
3513
|
try {
|
|
2227
|
-
const modSource = fs.readFileSync(resolvedPath, "utf-8");
|
|
3514
|
+
const modSource = fs$1.readFileSync(resolvedPath, "utf-8");
|
|
2228
3515
|
const modFile = u.createSourceFile(
|
|
2229
3516
|
resolvedPath,
|
|
2230
3517
|
modSource,
|
|
@@ -2263,15 +3550,15 @@ async function checkComponentContractConsistency(contract, context, result) {
|
|
|
2263
3550
|
if (!contractPath) return;
|
|
2264
3551
|
let contractContent;
|
|
2265
3552
|
try {
|
|
2266
|
-
contractContent = await fs.promises.readFile(contractPath, "utf-8");
|
|
3553
|
+
contractContent = await fs$1.promises.readFile(contractPath, "utf-8");
|
|
2267
3554
|
} catch {
|
|
2268
3555
|
return;
|
|
2269
3556
|
}
|
|
2270
|
-
const parsed = parseContract(contractContent, path.basename(contractPath));
|
|
3557
|
+
const parsed = parseContract(contractContent, path$1.basename(contractPath));
|
|
2271
3558
|
if (parsed.validations.length > 0) return;
|
|
2272
3559
|
let sourceCode;
|
|
2273
3560
|
try {
|
|
2274
|
-
sourceCode = await fs.promises.readFile(sourcePath, "utf-8");
|
|
3561
|
+
sourceCode = await fs$1.promises.readFile(sourcePath, "utf-8");
|
|
2275
3562
|
} catch {
|
|
2276
3563
|
return;
|
|
2277
3564
|
}
|
|
@@ -2290,8 +3577,8 @@ async function checkComponentContractConsistency(contract, context, result) {
|
|
|
2290
3577
|
result.warnings.push(...checkResult.warnings);
|
|
2291
3578
|
}
|
|
2292
3579
|
async function validatePackageJson(context, result) {
|
|
2293
|
-
const packageJsonPath = path.join(context.pluginPath, "package.json");
|
|
2294
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
3580
|
+
const packageJsonPath = path$1.join(context.pluginPath, "package.json");
|
|
3581
|
+
if (!fs$1.existsSync(packageJsonPath)) {
|
|
2295
3582
|
result.warnings.push({
|
|
2296
3583
|
type: "file-missing",
|
|
2297
3584
|
message: "package.json not found",
|
|
@@ -2301,7 +3588,7 @@ async function validatePackageJson(context, result) {
|
|
|
2301
3588
|
return;
|
|
2302
3589
|
}
|
|
2303
3590
|
try {
|
|
2304
|
-
const packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf-8"));
|
|
3591
|
+
const packageJson = JSON.parse(await fs$1.promises.readFile(packageJsonPath, "utf-8"));
|
|
2305
3592
|
if (!packageJson.exports) {
|
|
2306
3593
|
result.warnings.push({
|
|
2307
3594
|
type: "export-mismatch",
|
|
@@ -2365,8 +3652,8 @@ async function validatePackageJson(context, result) {
|
|
|
2365
3652
|
suggestion: 'Add "./plugin.yaml": "./plugin.yaml" to exports field'
|
|
2366
3653
|
});
|
|
2367
3654
|
}
|
|
2368
|
-
const agentKitDir = path.join(context.pluginPath, "agent-kit");
|
|
2369
|
-
if (fs.existsSync(agentKitDir) && fs.statSync(agentKitDir).isDirectory()) {
|
|
3655
|
+
const agentKitDir = path$1.join(context.pluginPath, "agent-kit");
|
|
3656
|
+
if (fs$1.existsSync(agentKitDir) && fs$1.statSync(agentKitDir).isDirectory()) {
|
|
2370
3657
|
const filesArray = packageJson.files;
|
|
2371
3658
|
if (!filesArray || !filesArray.includes("agent-kit")) {
|
|
2372
3659
|
result.warnings.push({
|
|
@@ -2390,7 +3677,7 @@ function isBareFunctionExport(exportName, context) {
|
|
|
2390
3677
|
if (!sourcePath) return false;
|
|
2391
3678
|
let sourceCode;
|
|
2392
3679
|
try {
|
|
2393
|
-
sourceCode = fs.readFileSync(sourcePath, "utf-8");
|
|
3680
|
+
sourceCode = fs$1.readFileSync(sourcePath, "utf-8");
|
|
2394
3681
|
} catch {
|
|
2395
3682
|
return false;
|
|
2396
3683
|
}
|
|
@@ -2418,8 +3705,8 @@ function resolveModulePathWithJsToTs(basePath) {
|
|
|
2418
3705
|
}
|
|
2419
3706
|
function resolveExportSourceFile(exportName, context) {
|
|
2420
3707
|
const modulePath = context.manifest.module || "index";
|
|
2421
|
-
const entryBase = path.join(context.pluginPath, modulePath);
|
|
2422
|
-
const libEntryBase = path.join(context.pluginPath, "lib", modulePath);
|
|
3708
|
+
const entryBase = path$1.join(context.pluginPath, modulePath);
|
|
3709
|
+
const libEntryBase = path$1.join(context.pluginPath, "lib", modulePath);
|
|
2423
3710
|
const sourceEntry = resolveModulePath(entryBase) || resolveModulePath(libEntryBase);
|
|
2424
3711
|
if (!sourceEntry || !sourceEntry.endsWith(".ts")) return void 0;
|
|
2425
3712
|
return followExportChain(exportName, sourceEntry);
|
|
@@ -2427,7 +3714,7 @@ function resolveExportSourceFile(exportName, context) {
|
|
|
2427
3714
|
function followExportChain(exportName, filePath) {
|
|
2428
3715
|
let sourceCode;
|
|
2429
3716
|
try {
|
|
2430
|
-
sourceCode = fs.readFileSync(filePath, "utf-8");
|
|
3717
|
+
sourceCode = fs$1.readFileSync(filePath, "utf-8");
|
|
2431
3718
|
} catch {
|
|
2432
3719
|
return void 0;
|
|
2433
3720
|
}
|
|
@@ -2450,7 +3737,7 @@ function followExportChain(exportName, filePath) {
|
|
|
2450
3737
|
if (u.isNamedExports(statement.exportClause)) {
|
|
2451
3738
|
for (const element of statement.exportClause.elements) {
|
|
2452
3739
|
if (element.name.text === exportName) {
|
|
2453
|
-
const resolvedBase = path.resolve(path.dirname(filePath), moduleSpec);
|
|
3740
|
+
const resolvedBase = path$1.resolve(path$1.dirname(filePath), moduleSpec);
|
|
2454
3741
|
return resolveModulePathWithJsToTs(resolvedBase);
|
|
2455
3742
|
}
|
|
2456
3743
|
}
|
|
@@ -2467,7 +3754,7 @@ function followExportChain(exportName, filePath) {
|
|
|
2467
3754
|
}
|
|
2468
3755
|
for (const moduleSpec of starReexportModules) {
|
|
2469
3756
|
if (!moduleSpec.startsWith(".")) continue;
|
|
2470
|
-
const resolvedBase = path.resolve(path.dirname(filePath), moduleSpec);
|
|
3757
|
+
const resolvedBase = path$1.resolve(path$1.dirname(filePath), moduleSpec);
|
|
2471
3758
|
const resolved = resolveModulePathWithJsToTs(resolvedBase);
|
|
2472
3759
|
if (!resolved) continue;
|
|
2473
3760
|
const found = followExportChain(exportName, resolved);
|
|
@@ -2484,11 +3771,11 @@ async function validateDynamicContracts(context, result) {
|
|
|
2484
3771
|
if (config.generator) {
|
|
2485
3772
|
const isFilePath = config.generator.startsWith("./") || config.generator.startsWith("/") || config.generator.includes(".ts") || config.generator.includes(".js");
|
|
2486
3773
|
if (isFilePath) {
|
|
2487
|
-
const generatorPath = path.join(context.pluginPath, config.generator);
|
|
3774
|
+
const generatorPath = path$1.join(context.pluginPath, config.generator);
|
|
2488
3775
|
const possibleExtensions = ["", ".ts", ".js", "/index.ts", "/index.js"];
|
|
2489
3776
|
let found = false;
|
|
2490
3777
|
for (const ext of possibleExtensions) {
|
|
2491
|
-
if (fs.existsSync(generatorPath + ext)) {
|
|
3778
|
+
if (fs$1.existsSync(generatorPath + ext)) {
|
|
2492
3779
|
found = true;
|
|
2493
3780
|
break;
|
|
2494
3781
|
}
|
|
@@ -2513,11 +3800,11 @@ async function validateDynamicContracts(context, result) {
|
|
|
2513
3800
|
if (config.component) {
|
|
2514
3801
|
const isFilePath = config.component.startsWith("./") || config.component.startsWith("/") || config.component.includes(".ts") || config.component.includes(".js");
|
|
2515
3802
|
if (isFilePath) {
|
|
2516
|
-
const componentPath = path.join(context.pluginPath, config.component);
|
|
3803
|
+
const componentPath = path$1.join(context.pluginPath, config.component);
|
|
2517
3804
|
const possibleExtensions = ["", ".ts", ".js", "/index.ts", "/index.js"];
|
|
2518
3805
|
let found = false;
|
|
2519
3806
|
for (const ext of possibleExtensions) {
|
|
2520
|
-
if (fs.existsSync(componentPath + ext)) {
|
|
3807
|
+
if (fs$1.existsSync(componentPath + ext)) {
|
|
2521
3808
|
found = true;
|
|
2522
3809
|
break;
|
|
2523
3810
|
}
|
|
@@ -2838,12 +4125,12 @@ function checkRefElementTypes(jayHtml, file) {
|
|
|
2838
4125
|
return warnings;
|
|
2839
4126
|
}
|
|
2840
4127
|
function checkPageComponentExport(jayHtmlPath) {
|
|
2841
|
-
const dirname = path.dirname(jayHtmlPath);
|
|
2842
|
-
const compPath = path.join(dirname, "page.ts");
|
|
2843
|
-
if (!fs.existsSync(compPath)) return null;
|
|
4128
|
+
const dirname = path$1.dirname(jayHtmlPath);
|
|
4129
|
+
const compPath = path$1.join(dirname, "page.ts");
|
|
4130
|
+
if (!fs$1.existsSync(compPath)) return null;
|
|
2844
4131
|
let content;
|
|
2845
4132
|
try {
|
|
2846
|
-
content = fs.readFileSync(compPath, "utf-8");
|
|
4133
|
+
content = fs$1.readFileSync(compPath, "utf-8");
|
|
2847
4134
|
} catch {
|
|
2848
4135
|
return null;
|
|
2849
4136
|
}
|
|
@@ -2854,7 +4141,7 @@ function checkPageComponentExport(jayHtmlPath) {
|
|
|
2854
4141
|
new RegExp(`export\\s+(?:const|let|var)\\s+${exportName}\\b`)
|
|
2855
4142
|
];
|
|
2856
4143
|
if (patterns.some((p) => p.test(content))) return null;
|
|
2857
|
-
return `${path.relative(dirname, compPath)} exists but does not export "${exportName}". Remove the file or add the export.`;
|
|
4144
|
+
return `${path$1.relative(dirname, compPath)} exists but does not export "${exportName}". Remove the file or add the export.`;
|
|
2858
4145
|
}
|
|
2859
4146
|
const DOCUMENT_ACCESS_PATTERNS = [
|
|
2860
4147
|
/document\.getElementById\b/,
|
|
@@ -2867,15 +4154,15 @@ const DOCUMENT_ACCESS_PATTERNS = [
|
|
|
2867
4154
|
];
|
|
2868
4155
|
const DOM_SUPPRESS_COMMENT = "jay-dom: allow";
|
|
2869
4156
|
function checkDirectDocumentAccess(jayHtmlPath) {
|
|
2870
|
-
const dirname = path.dirname(jayHtmlPath);
|
|
2871
|
-
const basename = path.basename(jayHtmlPath, JAY_EXTENSION);
|
|
2872
|
-
const candidates = [path.join(dirname, `${basename}.ts`), path.join(dirname, "page.ts")];
|
|
2873
|
-
const compPath = candidates.find((p) => fs.existsSync(p));
|
|
4157
|
+
const dirname = path$1.dirname(jayHtmlPath);
|
|
4158
|
+
const basename = path$1.basename(jayHtmlPath, JAY_EXTENSION);
|
|
4159
|
+
const candidates = [path$1.join(dirname, `${basename}.ts`), path$1.join(dirname, "page.ts")];
|
|
4160
|
+
const compPath = candidates.find((p) => fs$1.existsSync(p));
|
|
2874
4161
|
if (!compPath) return [];
|
|
2875
|
-
const compName = path.basename(compPath);
|
|
4162
|
+
const compName = path$1.basename(compPath);
|
|
2876
4163
|
let content;
|
|
2877
4164
|
try {
|
|
2878
|
-
content = fs.readFileSync(compPath, "utf-8");
|
|
4165
|
+
content = fs$1.readFileSync(compPath, "utf-8");
|
|
2879
4166
|
} catch {
|
|
2880
4167
|
return [];
|
|
2881
4168
|
}
|
|
@@ -2898,8 +4185,8 @@ function checkDirectDocumentAccess(jayHtmlPath) {
|
|
|
2898
4185
|
}
|
|
2899
4186
|
const PARSE_PARAM = /^\[(\[)?(\.\.\.)?([^\]]+)\]?\]$/;
|
|
2900
4187
|
function extractRouteParams(filePath, pagesBase) {
|
|
2901
|
-
const relative = path.relative(pagesBase, filePath);
|
|
2902
|
-
const segments = relative.split(path.sep);
|
|
4188
|
+
const relative = path$1.relative(pagesBase, filePath);
|
|
4189
|
+
const segments = relative.split(path$1.sep);
|
|
2903
4190
|
const params = /* @__PURE__ */ new Set();
|
|
2904
4191
|
for (const segment of segments) {
|
|
2905
4192
|
const match = PARSE_PARAM.exec(segment);
|
|
@@ -3109,7 +4396,7 @@ function resolveLinkedTags(tags, contractDir) {
|
|
|
3109
4396
|
}
|
|
3110
4397
|
function resolveContractLinks(contract, contractPath) {
|
|
3111
4398
|
if (!contractPath) return contract;
|
|
3112
|
-
const contractDir = path.dirname(contractPath);
|
|
4399
|
+
const contractDir = path$1.dirname(contractPath);
|
|
3113
4400
|
return { ...contract, tags: resolveLinkedTags(contract.tags, contractDir) };
|
|
3114
4401
|
}
|
|
3115
4402
|
async function runPluginValidators(projectRoot, parsedFiles, errors, warnings) {
|
|
@@ -3123,7 +4410,7 @@ async function runPluginValidators(projectRoot, parsedFiles, errors, warnings) {
|
|
|
3123
4410
|
try {
|
|
3124
4411
|
let handlerModule;
|
|
3125
4412
|
if (plugin.isLocal) {
|
|
3126
|
-
const handlerPath = path.resolve(plugin.pluginPath, validatorDef.handler);
|
|
4413
|
+
const handlerPath = path$1.resolve(plugin.pluginPath, validatorDef.handler);
|
|
3127
4414
|
handlerModule = await import(handlerPath);
|
|
3128
4415
|
} else {
|
|
3129
4416
|
handlerModule = await import(plugin.packageName);
|
|
@@ -3151,8 +4438,8 @@ async function runPluginValidators(projectRoot, parsedFiles, errors, warnings) {
|
|
|
3151
4438
|
}
|
|
3152
4439
|
loadedValidators.push(source);
|
|
3153
4440
|
for (const { relativePath, parsed } of parsedFiles) {
|
|
3154
|
-
const pageContractPath = parsed.contractRef ? path.resolve(
|
|
3155
|
-
path.dirname(path.resolve(projectRoot, relativePath)),
|
|
4441
|
+
const pageContractPath = parsed.contractRef ? path$1.resolve(
|
|
4442
|
+
path$1.dirname(path$1.resolve(projectRoot, relativePath)),
|
|
3156
4443
|
parsed.contractRef
|
|
3157
4444
|
) : void 0;
|
|
3158
4445
|
const resolvedPageContract = parsed.contract ? resolveContractLinks(parsed.contract, pageContractPath) : void 0;
|
|
@@ -3196,7 +4483,8 @@ async function runPluginValidators(projectRoot, parsedFiles, errors, warnings) {
|
|
|
3196
4483
|
providedHeadTags
|
|
3197
4484
|
};
|
|
3198
4485
|
}),
|
|
3199
|
-
projectRoot
|
|
4486
|
+
projectRoot,
|
|
4487
|
+
validationOverrides: parsed.validationOverrides
|
|
3200
4488
|
};
|
|
3201
4489
|
try {
|
|
3202
4490
|
const findings = await validatorFn(ctx);
|
|
@@ -3232,11 +4520,11 @@ async function runPluginValidators(projectRoot, parsedFiles, errors, warnings) {
|
|
|
3232
4520
|
return loadedValidators;
|
|
3233
4521
|
}
|
|
3234
4522
|
async function validateJayFiles(options = {}) {
|
|
3235
|
-
const config = loadConfig();
|
|
3236
|
-
const resolvedConfig = getConfigWithDefaults(config);
|
|
3237
4523
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
3238
|
-
const
|
|
3239
|
-
const
|
|
4524
|
+
const config = loadConfig(projectRoot);
|
|
4525
|
+
const resolvedConfig = getConfigWithDefaults(config);
|
|
4526
|
+
const scanDir = options.path ? path$1.resolve(options.path) : path$1.resolve(resolvedConfig.devServer.pagesBase);
|
|
4527
|
+
const componentsDir = path$1.resolve(resolvedConfig.devServer.componentsBase);
|
|
3240
4528
|
const errors = [];
|
|
3241
4529
|
const warnings = [];
|
|
3242
4530
|
const coverage = [];
|
|
@@ -3255,10 +4543,10 @@ async function validateJayFiles(options = {}) {
|
|
|
3255
4543
|
`));
|
|
3256
4544
|
}
|
|
3257
4545
|
for (const contractFile of contractFiles) {
|
|
3258
|
-
const relativePath = path.relative(projectRoot, contractFile);
|
|
4546
|
+
const relativePath = path$1.relative(projectRoot, contractFile);
|
|
3259
4547
|
try {
|
|
3260
4548
|
const content = await promises.readFile(contractFile, "utf-8");
|
|
3261
|
-
const result = parseContract(content, path.basename(contractFile));
|
|
4549
|
+
const result = parseContract(content, path$1.basename(contractFile));
|
|
3262
4550
|
if (result.validations.length > 0) {
|
|
3263
4551
|
for (const validation of result.validations) {
|
|
3264
4552
|
errors.push({
|
|
@@ -3285,9 +4573,9 @@ async function validateJayFiles(options = {}) {
|
|
|
3285
4573
|
}
|
|
3286
4574
|
}
|
|
3287
4575
|
for (const jayFile of jayHtmlFiles) {
|
|
3288
|
-
const relativePath = path.relative(projectRoot, jayFile);
|
|
3289
|
-
const filename = path.basename(jayFile.replace(JAY_EXTENSION, ""));
|
|
3290
|
-
const dirname = path.dirname(jayFile);
|
|
4576
|
+
const relativePath = path$1.relative(projectRoot, jayFile);
|
|
4577
|
+
const filename = path$1.basename(jayFile.replace(JAY_EXTENSION, ""));
|
|
4578
|
+
const dirname = path$1.dirname(jayFile);
|
|
3291
4579
|
try {
|
|
3292
4580
|
const content = await promises.readFile(jayFile, "utf-8");
|
|
3293
4581
|
const parsedFile = await parseJayFile(
|
|
@@ -3346,17 +4634,34 @@ async function validateJayFiles(options = {}) {
|
|
|
3346
4634
|
for (const msg of refTypeErrors) {
|
|
3347
4635
|
errors.push({ file: relativePath, message: msg, stage: "generate" });
|
|
3348
4636
|
}
|
|
3349
|
-
const
|
|
3350
|
-
for (const msg of
|
|
3351
|
-
|
|
4637
|
+
const headlessPropResults = checkHeadlessInstanceProps(parsedFile.val, relativePath);
|
|
4638
|
+
for (const msg of headlessPropResults) {
|
|
4639
|
+
if (msg.includes("is missing required prop") || msg.includes("source phase must be")) {
|
|
4640
|
+
errors.push({ file: relativePath, message: msg, stage: "generate" });
|
|
4641
|
+
} else {
|
|
4642
|
+
warnings.push({ file: relativePath, message: msg });
|
|
4643
|
+
}
|
|
3352
4644
|
}
|
|
3353
4645
|
const fileCoverage = analyzeTagCoverage(parsedFile.val, relativePath);
|
|
3354
4646
|
if (fileCoverage) {
|
|
3355
4647
|
coverage.push(fileCoverage);
|
|
4648
|
+
const allowedUnused = parsedFile.val.validationOverrides?.["jay-stack"]?.["allow-unused-tags"];
|
|
4649
|
+
const allowedSet = new Set(Array.isArray(allowedUnused) ? allowedUnused : []);
|
|
4650
|
+
for (const contract of fileCoverage.contracts) {
|
|
4651
|
+
for (const tag of contract.requiredUnusedTags) {
|
|
4652
|
+
const qualifiedTag = contract.key ? `${contract.key}.${tag}` : tag;
|
|
4653
|
+
if (allowedSet.has(qualifiedTag) || allowedSet.has(tag)) continue;
|
|
4654
|
+
const label = contract.key ? `${contract.key} (${contract.contractName})` : contract.contractName;
|
|
4655
|
+
warnings.push({
|
|
4656
|
+
file: relativePath,
|
|
4657
|
+
message: `Required tag "${tag}" from contract "${label}" is not used in the template. Suppress with jay-stack: { allow-unused-tags: ["${qualifiedTag}"] } in <script type="application/jay-validations">. See agent-kit/designer/validation-guide.md`
|
|
4658
|
+
});
|
|
4659
|
+
}
|
|
4660
|
+
}
|
|
3356
4661
|
}
|
|
3357
4662
|
const generatedFile = generateElementFile(
|
|
3358
4663
|
parsedFile.val,
|
|
3359
|
-
RuntimeMode.MainTrusted,
|
|
4664
|
+
RuntimeMode$1.MainTrusted,
|
|
3360
4665
|
GenerateTarget.jay
|
|
3361
4666
|
);
|
|
3362
4667
|
if (generatedFile.validations.length > 0) {
|
|
@@ -3394,8 +4699,8 @@ async function validateJayFiles(options = {}) {
|
|
|
3394
4699
|
}
|
|
3395
4700
|
}
|
|
3396
4701
|
}
|
|
3397
|
-
const robotsTxtPath = path.resolve(projectRoot, "public/robots.txt");
|
|
3398
|
-
if (!fs.existsSync(robotsTxtPath)) {
|
|
4702
|
+
const robotsTxtPath = path$1.resolve(projectRoot, "public/robots.txt");
|
|
4703
|
+
if (!fs$1.existsSync(robotsTxtPath)) {
|
|
3399
4704
|
warnings.push({
|
|
3400
4705
|
file: "public/robots.txt",
|
|
3401
4706
|
message: "public/robots.txt not found ā search engines may crawl pages you don't intend to expose.",
|
|
@@ -3406,7 +4711,7 @@ async function validateJayFiles(options = {}) {
|
|
|
3406
4711
|
warnings.push({
|
|
3407
4712
|
file: ".jay",
|
|
3408
4713
|
message: "site.baseUrl not configured ā sitemap.xml will not be generated in production.",
|
|
3409
|
-
suggestion: "Add to .jay config
|
|
4714
|
+
suggestion: "Add to .jay config:\n site:\n baseUrl: https://your-domain.com"
|
|
3410
4715
|
});
|
|
3411
4716
|
}
|
|
3412
4717
|
const pluginValidators = await runPluginValidators(projectRoot, parsedFiles, errors, warnings);
|
|
@@ -3491,7 +4796,7 @@ function printJayValidationResult(result, options) {
|
|
|
3491
4796
|
}
|
|
3492
4797
|
}
|
|
3493
4798
|
}
|
|
3494
|
-
if (result.coverage.length > 0) {
|
|
4799
|
+
if (options.verbose && result.coverage.length > 0) {
|
|
3495
4800
|
logger.important("");
|
|
3496
4801
|
logger.important(chalk.bold("š¦ Tag Coverage"));
|
|
3497
4802
|
for (const fileCov of result.coverage) {
|
|
@@ -3506,23 +4811,26 @@ function printJayValidationResult(result, options) {
|
|
|
3506
4811
|
chalk.gray(` Unused: ${contract.unusedTags.join(", ")}`)
|
|
3507
4812
|
);
|
|
3508
4813
|
}
|
|
3509
|
-
if (contract.requiredUnusedTags.length > 0) {
|
|
3510
|
-
logger.important(
|
|
3511
|
-
chalk.yellow(
|
|
3512
|
-
` ā Required unused: ${contract.requiredUnusedTags.join(", ")}`
|
|
3513
|
-
)
|
|
3514
|
-
);
|
|
3515
|
-
}
|
|
3516
4814
|
}
|
|
3517
4815
|
}
|
|
3518
4816
|
}
|
|
3519
4817
|
logger.important("");
|
|
3520
|
-
if (result.valid) {
|
|
4818
|
+
if (result.valid && result.warnings.length === 0) {
|
|
3521
4819
|
logger.important(chalk.green("Validation passed."));
|
|
4820
|
+
} else if (result.valid) {
|
|
4821
|
+
logger.important(
|
|
4822
|
+
chalk.yellow(
|
|
4823
|
+
`Validation passed with ${result.warnings.length} warning(s). Warnings must be fixed or explicitly suppressed ā do not ignore them.`
|
|
4824
|
+
)
|
|
4825
|
+
);
|
|
3522
4826
|
} else {
|
|
3523
|
-
logger.important(
|
|
4827
|
+
logger.important(
|
|
4828
|
+
chalk.red(
|
|
4829
|
+
`Validation failed ā ${result.errors.length} error(s)` + (result.warnings.length > 0 ? `, ${result.warnings.length} warning(s). Errors must be fixed. Warnings must be fixed or explicitly suppressed.` : ".")
|
|
4830
|
+
)
|
|
4831
|
+
);
|
|
3524
4832
|
}
|
|
3525
|
-
const totalIssues = result.errors.length + result.warnings.length
|
|
4833
|
+
const totalIssues = result.errors.length + result.warnings.length;
|
|
3526
4834
|
if (totalIssues > 0) {
|
|
3527
4835
|
logger.important(
|
|
3528
4836
|
chalk.gray(
|
|
@@ -3626,7 +4934,7 @@ async function runAgentKit(options) {
|
|
|
3626
4934
|
}
|
|
3627
4935
|
}
|
|
3628
4936
|
async function runMaterialize(projectRoot, options, defaultOutputRelative, keepViteAlive = false) {
|
|
3629
|
-
const outputDir = options.output ??
|
|
4937
|
+
const outputDir = options.output ?? path__default.join(projectRoot, defaultOutputRelative);
|
|
3630
4938
|
let viteServer;
|
|
3631
4939
|
let initErrors = /* @__PURE__ */ new Map();
|
|
3632
4940
|
try {
|
|
@@ -3692,81 +5000,81 @@ Materialized ${totalContracts} contracts`));
|
|
|
3692
5000
|
return { initErrors };
|
|
3693
5001
|
}
|
|
3694
5002
|
async function ensureAgentKitDocs(projectRoot, _force, mode) {
|
|
3695
|
-
const agentKitDir =
|
|
3696
|
-
const thisDir =
|
|
3697
|
-
const templateDir =
|
|
5003
|
+
const agentKitDir = path__default.join(projectRoot, "agent-kit");
|
|
5004
|
+
const thisDir = path__default.dirname(fileURLToPath(import.meta.url));
|
|
5005
|
+
const templateDir = path__default.resolve(thisDir, "..", "agent-kit-template");
|
|
3698
5006
|
const roles = mode && ALL_ROLES.includes(mode) ? [mode] : ALL_ROLES;
|
|
3699
5007
|
for (const role of roles) {
|
|
3700
|
-
const roleTemplateDir =
|
|
3701
|
-
const roleOutputDir =
|
|
5008
|
+
const roleTemplateDir = path__default.join(templateDir, role);
|
|
5009
|
+
const roleOutputDir = path__default.join(agentKitDir, role);
|
|
3702
5010
|
let files;
|
|
3703
5011
|
try {
|
|
3704
|
-
files = (await fs$
|
|
5012
|
+
files = (await fs$2.readdir(roleTemplateDir)).filter((f) => f.endsWith(".md"));
|
|
3705
5013
|
} catch {
|
|
3706
5014
|
continue;
|
|
3707
5015
|
}
|
|
3708
|
-
await fs$
|
|
5016
|
+
await fs$2.mkdir(roleOutputDir, { recursive: true });
|
|
3709
5017
|
for (const filename of files) {
|
|
3710
|
-
await fs$
|
|
3711
|
-
|
|
3712
|
-
|
|
5018
|
+
await fs$2.copyFile(
|
|
5019
|
+
path__default.join(roleTemplateDir, filename),
|
|
5020
|
+
path__default.join(roleOutputDir, filename)
|
|
3713
5021
|
);
|
|
3714
5022
|
getLogger().info(chalk.gray(` Created agent-kit/${role}/${filename}`));
|
|
3715
5023
|
}
|
|
3716
5024
|
}
|
|
3717
|
-
const topLevelFiles = (await fs$
|
|
5025
|
+
const topLevelFiles = (await fs$2.readdir(templateDir)).filter((f) => f.endsWith(".md"));
|
|
3718
5026
|
for (const filename of topLevelFiles) {
|
|
3719
|
-
await fs$
|
|
5027
|
+
await fs$2.copyFile(path__default.join(templateDir, filename), path__default.join(agentKitDir, filename));
|
|
3720
5028
|
getLogger().info(chalk.gray(` Created agent-kit/${filename}`));
|
|
3721
5029
|
}
|
|
3722
5030
|
const sharedDirs = ["contracts"];
|
|
3723
5031
|
for (const dir of sharedDirs) {
|
|
3724
|
-
const srcDir =
|
|
3725
|
-
if (!
|
|
3726
|
-
await copyDirRecursive(srcDir,
|
|
5032
|
+
const srcDir = path__default.join(templateDir, dir);
|
|
5033
|
+
if (!fs__default.existsSync(srcDir)) continue;
|
|
5034
|
+
await copyDirRecursive(srcDir, path__default.join(agentKitDir, dir));
|
|
3727
5035
|
getLogger().info(chalk.gray(` Created agent-kit/${dir}/`));
|
|
3728
5036
|
}
|
|
3729
5037
|
}
|
|
3730
5038
|
async function copyDirRecursive(src, dest) {
|
|
3731
|
-
await fs$
|
|
3732
|
-
const entries = await fs$
|
|
5039
|
+
await fs$2.mkdir(dest, { recursive: true });
|
|
5040
|
+
const entries = await fs$2.readdir(src, { withFileTypes: true });
|
|
3733
5041
|
for (const entry of entries) {
|
|
3734
|
-
const srcPath =
|
|
3735
|
-
const destPath =
|
|
5042
|
+
const srcPath = path__default.join(src, entry.name);
|
|
5043
|
+
const destPath = path__default.join(dest, entry.name);
|
|
3736
5044
|
if (entry.isDirectory()) {
|
|
3737
5045
|
await copyDirRecursive(srcPath, destPath);
|
|
3738
5046
|
} else if (entry.name.endsWith(".md")) {
|
|
3739
|
-
await fs$
|
|
5047
|
+
await fs$2.copyFile(srcPath, destPath);
|
|
3740
5048
|
}
|
|
3741
5049
|
}
|
|
3742
5050
|
}
|
|
3743
5051
|
async function mergePluginAgentKitGuides(projectRoot, mode) {
|
|
3744
5052
|
const plugins = await scanPlugins({ projectRoot, includeDevDeps: true });
|
|
3745
|
-
const agentKitDir =
|
|
5053
|
+
const agentKitDir = path__default.join(projectRoot, "agent-kit");
|
|
3746
5054
|
const roles = mode && ALL_ROLES.includes(mode) ? [mode] : ALL_ROLES;
|
|
3747
5055
|
const copiedPerRole = /* @__PURE__ */ new Map();
|
|
3748
5056
|
for (const [, plugin] of plugins) {
|
|
3749
|
-
const pluginAgentKitDir =
|
|
3750
|
-
if (!
|
|
5057
|
+
const pluginAgentKitDir = path__default.join(plugin.pluginPath, "agent-kit");
|
|
5058
|
+
if (!fs__default.existsSync(pluginAgentKitDir)) continue;
|
|
3751
5059
|
for (const role of roles) {
|
|
3752
|
-
const roleSourceDir =
|
|
5060
|
+
const roleSourceDir = path__default.join(pluginAgentKitDir, role);
|
|
3753
5061
|
let files;
|
|
3754
5062
|
try {
|
|
3755
|
-
files = (await fs$
|
|
5063
|
+
files = (await fs$2.readdir(roleSourceDir)).filter(
|
|
3756
5064
|
(f) => f.endsWith(".md") && f !== "INSTRUCTIONS.md"
|
|
3757
5065
|
);
|
|
3758
5066
|
} catch {
|
|
3759
5067
|
continue;
|
|
3760
5068
|
}
|
|
3761
5069
|
if (files.length === 0) continue;
|
|
3762
|
-
const roleOutputDir =
|
|
3763
|
-
await fs$
|
|
5070
|
+
const roleOutputDir = path__default.join(agentKitDir, role);
|
|
5071
|
+
await fs$2.mkdir(roleOutputDir, { recursive: true });
|
|
3764
5072
|
for (const filename of files) {
|
|
3765
|
-
const sourcePath =
|
|
3766
|
-
await fs$
|
|
5073
|
+
const sourcePath = path__default.join(roleSourceDir, filename);
|
|
5074
|
+
await fs$2.copyFile(sourcePath, path__default.join(roleOutputDir, filename));
|
|
3767
5075
|
let description = "";
|
|
3768
5076
|
try {
|
|
3769
|
-
const content = await fs$
|
|
5077
|
+
const content = await fs$2.readFile(sourcePath, "utf-8");
|
|
3770
5078
|
const lines = content.split("\n");
|
|
3771
5079
|
let pastHeading = false;
|
|
3772
5080
|
for (const line of lines) {
|
|
@@ -3792,8 +5100,8 @@ async function mergePluginAgentKitGuides(projectRoot, mode) {
|
|
|
3792
5100
|
}
|
|
3793
5101
|
}
|
|
3794
5102
|
for (const [role, entries] of copiedPerRole) {
|
|
3795
|
-
const instructionsPath =
|
|
3796
|
-
if (!
|
|
5103
|
+
const instructionsPath = path__default.join(agentKitDir, role, "INSTRUCTIONS.md");
|
|
5104
|
+
if (!fs__default.existsSync(instructionsPath)) continue;
|
|
3797
5105
|
const lines = [
|
|
3798
5106
|
"",
|
|
3799
5107
|
"## Plugin-Contributed Guides",
|
|
@@ -3805,11 +5113,10 @@ async function mergePluginAgentKitGuides(projectRoot, mode) {
|
|
|
3805
5113
|
lines.push(`| [${filename}](${filename}) | ${pluginName} | ${description} |`);
|
|
3806
5114
|
}
|
|
3807
5115
|
lines.push("");
|
|
3808
|
-
await fs$
|
|
5116
|
+
await fs$2.appendFile(instructionsPath, lines.join("\n"));
|
|
3809
5117
|
}
|
|
3810
5118
|
}
|
|
3811
5119
|
async function generatePluginAgentKit(projectRoot, options, initErrors, viteServer) {
|
|
3812
|
-
const { discoverPluginsWithAgentKit, executePluginAgentKit } = await import("@jay-framework/stack-server-runtime");
|
|
3813
5120
|
const plugins = await discoverPluginsWithAgentKit({
|
|
3814
5121
|
projectRoot,
|
|
3815
5122
|
verbose: options.verbose,
|
|
@@ -3882,7 +5189,6 @@ async function runAction(actionRef, options, projectRoot, initializeServices) {
|
|
|
3882
5189
|
}
|
|
3883
5190
|
viteServer = await createViteForCli({ projectRoot });
|
|
3884
5191
|
await initializeServices(projectRoot, viteServer);
|
|
3885
|
-
const { discoverAndRegisterActions, discoverAllPluginActions, ActionRegistry } = await import("@jay-framework/stack-server-runtime");
|
|
3886
5192
|
const registry = new ActionRegistry();
|
|
3887
5193
|
await discoverAndRegisterActions({
|
|
3888
5194
|
projectRoot,
|
|
@@ -3994,8 +5300,8 @@ async function runParams(contractRef, options, projectRoot, initializeServices)
|
|
|
3994
5300
|
);
|
|
3995
5301
|
process.exit(1);
|
|
3996
5302
|
}
|
|
3997
|
-
const { resolveServices } = await import("@jay-framework/stack-server-runtime");
|
|
3998
|
-
const resolvedServices =
|
|
5303
|
+
const { resolveServices: resolveServices2 } = await import("@jay-framework/stack-server-runtime");
|
|
5304
|
+
const resolvedServices = resolveServices2(component.services || []);
|
|
3999
5305
|
const paramsGenerator = component.loadParams(resolvedServices);
|
|
4000
5306
|
let total = 0;
|
|
4001
5307
|
for await (const batch of paramsGenerator) {
|
|
@@ -4089,7 +5395,7 @@ async function runSetup(pluginFilter, options, projectRoot) {
|
|
|
4089
5395
|
try {
|
|
4090
5396
|
const logger = getLogger();
|
|
4091
5397
|
const jayConfig = loadConfig();
|
|
4092
|
-
const configDir =
|
|
5398
|
+
const configDir = path__default.resolve(projectRoot, jayConfig.devServer?.configBase || "./config");
|
|
4093
5399
|
logger.important(chalk.bold("\nš§ Setting up plugins...\n"));
|
|
4094
5400
|
if (options.verbose) {
|
|
4095
5401
|
logger.info("Starting Vite for TypeScript support...");
|
|
@@ -4121,7 +5427,7 @@ async function runSetup(pluginFilter, options, projectRoot) {
|
|
|
4121
5427
|
const interactive = options.interactive === true;
|
|
4122
5428
|
let answersMap;
|
|
4123
5429
|
if (options.answers) {
|
|
4124
|
-
answersMap = YAML.parse(
|
|
5430
|
+
answersMap = YAML.parse(fs__default.readFileSync(options.answers, "utf-8")) || {};
|
|
4125
5431
|
}
|
|
4126
5432
|
let configured = 0;
|
|
4127
5433
|
let needsConfig = 0;
|
|
@@ -4248,12 +5554,12 @@ async function initPlugin(pluginName, allPluginsWithInit, viteServer, logger) {
|
|
|
4248
5554
|
}
|
|
4249
5555
|
async function runProjectInit(projectRoot, viteServer) {
|
|
4250
5556
|
try {
|
|
4251
|
-
const initPathTs =
|
|
4252
|
-
const initPathJs =
|
|
5557
|
+
const initPathTs = path__default.join(projectRoot, "src", "init.ts");
|
|
5558
|
+
const initPathJs = path__default.join(projectRoot, "src", "init.js");
|
|
4253
5559
|
let initModule;
|
|
4254
|
-
if (
|
|
5560
|
+
if (fs__default.existsSync(initPathTs) && viteServer) {
|
|
4255
5561
|
initModule = await viteServer.ssrLoadModule(initPathTs);
|
|
4256
|
-
} else if (
|
|
5562
|
+
} else if (fs__default.existsSync(initPathJs)) {
|
|
4257
5563
|
initModule = await import(initPathJs);
|
|
4258
5564
|
}
|
|
4259
5565
|
if (initModule?.init?._serverInit) {
|
|
@@ -4266,12 +5572,6 @@ async function runProjectInit(projectRoot, viteServer) {
|
|
|
4266
5572
|
async function runCommand(commandRef, rawArgs, options, projectRoot, initializeServices) {
|
|
4267
5573
|
let viteServer;
|
|
4268
5574
|
try {
|
|
4269
|
-
const {
|
|
4270
|
-
discoverPluginCommands,
|
|
4271
|
-
commandSchemaToFlags,
|
|
4272
|
-
parseInputFromFlags,
|
|
4273
|
-
executePluginCommand
|
|
4274
|
-
} = await import("@jay-framework/stack-server-runtime");
|
|
4275
5575
|
const commands = await discoverPluginCommands({
|
|
4276
5576
|
projectRoot,
|
|
4277
5577
|
verbose: options.verbose
|
|
@@ -4327,21 +5627,19 @@ async function runCommand(commandRef, rawArgs, options, projectRoot, initializeS
|
|
|
4327
5627
|
}
|
|
4328
5628
|
viteServer = await createViteForCli({ projectRoot });
|
|
4329
5629
|
await initializeServices(projectRoot, viteServer);
|
|
4330
|
-
const { registerService } = await import("@jay-framework/stack-server-runtime");
|
|
4331
|
-
const { CONSOLE_CONTEXT } = await import("@jay-framework/fullstack-component");
|
|
4332
5630
|
const jayConfig = loadConfig();
|
|
4333
|
-
const publicFolder =
|
|
5631
|
+
const publicFolder = path__default.resolve(
|
|
4334
5632
|
projectRoot,
|
|
4335
5633
|
jayConfig.devServer?.publicFolder || "public"
|
|
4336
5634
|
);
|
|
4337
5635
|
const version = await resolveVersionFromPackageJson(projectRoot);
|
|
4338
|
-
const buildRoot =
|
|
5636
|
+
const buildRoot = path__default.resolve(projectRoot, `build/v${version}`);
|
|
4339
5637
|
registerService(CONSOLE_CONTEXT, {
|
|
4340
5638
|
projectRoot,
|
|
4341
5639
|
publicFolder,
|
|
4342
5640
|
build: {
|
|
4343
|
-
frontend:
|
|
4344
|
-
backend:
|
|
5641
|
+
frontend: path__default.join(buildRoot, "frontend"),
|
|
5642
|
+
backend: path__default.join(buildRoot, "backend")
|
|
4345
5643
|
},
|
|
4346
5644
|
verbose: options.verbose ?? false,
|
|
4347
5645
|
log: (msg) => getLogger().important(msg),
|
|
@@ -4515,9 +5813,9 @@ if (!process.argv.slice(2).length) {
|
|
|
4515
5813
|
}
|
|
4516
5814
|
export {
|
|
4517
5815
|
getConfigWithDefaults,
|
|
4518
|
-
|
|
5816
|
+
listContracts,
|
|
4519
5817
|
loadConfig,
|
|
4520
|
-
|
|
5818
|
+
materializeContracts,
|
|
4521
5819
|
startDevServer,
|
|
4522
5820
|
updateConfig
|
|
4523
5821
|
};
|