@jay-framework/stack-server-runtime 0.17.3 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +56 -11
- package/dist/index.js +207 -26
- package/package.json +13 -13
package/dist/index.d.ts
CHANGED
|
@@ -129,17 +129,8 @@ interface InstanceSlowRenderResult {
|
|
|
129
129
|
* Shared between preRenderJayHtml (pre-render path) and handleDirectRequest (direct path).
|
|
130
130
|
*/
|
|
131
131
|
declare function slowRenderInstances(discovered: DiscoveredHeadlessInstance[], headlessInstanceComponents: HeadlessInstanceComponent[]): Promise<InstanceSlowRenderResult | undefined>;
|
|
132
|
-
/**
|
|
133
|
-
* Validate that forEach headless instances do not have a slow phase.
|
|
134
|
-
*
|
|
135
|
-
* Components with slowlyRender cannot be used inside forEach because
|
|
136
|
-
* forEach items are only known at request time, after slow rendering completes.
|
|
137
|
-
*
|
|
138
|
-
* @returns Array of validation error messages (empty if all valid)
|
|
139
|
-
*/
|
|
140
|
-
declare function validateForEachInstances(forEachInstances: ForEachHeadlessInstance[], headlessInstanceComponents: HeadlessInstanceComponent[]): string[];
|
|
141
132
|
|
|
142
|
-
declare function renderFastChangingData(pageParams: object, pageProps: PageProps, carryForward: object, parts: Array<DevServerPagePart>, instancePhaseData?: InstancePhaseData, forEachInstances?: ForEachHeadlessInstance[], headlessInstanceComponents?: HeadlessInstanceComponent[], mergedSlowViewState?: object, query?: Record<string, string>): Promise<AnyFastRenderResult>;
|
|
133
|
+
declare function renderFastChangingData(pageParams: object, pageProps: PageProps, carryForward: object, parts: Array<DevServerPagePart>, instancePhaseData?: InstancePhaseData, forEachInstances?: ForEachHeadlessInstance[], headlessInstanceComponents?: HeadlessInstanceComponent[], mergedSlowViewState?: object, query?: Record<string, string>, cookies?: Record<string, string>): Promise<AnyFastRenderResult>;
|
|
143
134
|
|
|
144
135
|
/**
|
|
145
136
|
* Action metadata loaded from .jay-action files.
|
|
@@ -992,6 +983,11 @@ interface RouteIndexEntry {
|
|
|
992
983
|
path: string;
|
|
993
984
|
description?: string;
|
|
994
985
|
}
|
|
986
|
+
/** CLI command entry in plugins-index.yaml (DL#142) */
|
|
987
|
+
interface CommandIndexEntry {
|
|
988
|
+
name: string;
|
|
989
|
+
description?: string;
|
|
990
|
+
}
|
|
995
991
|
/** Entry for plugins-index.yaml (Design Log #85) */
|
|
996
992
|
interface PluginsIndexEntry {
|
|
997
993
|
name: string;
|
|
@@ -1005,6 +1001,8 @@ interface PluginsIndexEntry {
|
|
|
1005
1001
|
contexts?: ContextIndexEntry[];
|
|
1006
1002
|
/** Plugin-provided routes (DL#130) */
|
|
1007
1003
|
routes?: RouteIndexEntry[];
|
|
1004
|
+
/** CLI commands (DL#142) */
|
|
1005
|
+
commands?: CommandIndexEntry[];
|
|
1008
1006
|
}
|
|
1009
1007
|
interface PluginsIndex {
|
|
1010
1008
|
plugins: PluginsIndexEntry[];
|
|
@@ -1261,4 +1259,51 @@ declare function mergeHeadTags(sources: HeadTag[][]): HeadTag[];
|
|
|
1261
1259
|
*/
|
|
1262
1260
|
declare function serializeHeadTags(tags: HeadTag[]): string;
|
|
1263
1261
|
|
|
1264
|
-
|
|
1262
|
+
/**
|
|
1263
|
+
* Parse a Cookie header string into a key-value record.
|
|
1264
|
+
* Handles standard cookie format: "name1=value1; name2=value2".
|
|
1265
|
+
*/
|
|
1266
|
+
declare function parseCookies(cookieHeader: string | null | undefined): Record<string, string>;
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* Plugin CLI Commands (Design Log #142)
|
|
1270
|
+
*
|
|
1271
|
+
* Plugins expose CLI commands via `commands` in plugin.yaml.
|
|
1272
|
+
* Each command has a `makeCliCommand` handler and an optional `.jay-command` metadata file.
|
|
1273
|
+
* Run via `jay-stack run <plugin>/<command>`.
|
|
1274
|
+
*/
|
|
1275
|
+
|
|
1276
|
+
interface CommandMetadata {
|
|
1277
|
+
name: string;
|
|
1278
|
+
description?: string;
|
|
1279
|
+
inputSchema?: Record<string, string>;
|
|
1280
|
+
}
|
|
1281
|
+
interface DiscoveredCommand {
|
|
1282
|
+
pluginName: string;
|
|
1283
|
+
pluginPath: string;
|
|
1284
|
+
packageName: string;
|
|
1285
|
+
isLocal: boolean;
|
|
1286
|
+
commandName: string;
|
|
1287
|
+
handlerExport: string;
|
|
1288
|
+
pluginModule?: string;
|
|
1289
|
+
metadata?: CommandMetadata;
|
|
1290
|
+
metadataPath?: string;
|
|
1291
|
+
}
|
|
1292
|
+
interface CommandFlag {
|
|
1293
|
+
flag: string;
|
|
1294
|
+
description: string;
|
|
1295
|
+
required: boolean;
|
|
1296
|
+
type: 'string' | 'boolean' | 'number';
|
|
1297
|
+
}
|
|
1298
|
+
declare function discoverPluginCommands(options: {
|
|
1299
|
+
projectRoot: string;
|
|
1300
|
+
verbose?: boolean;
|
|
1301
|
+
pluginFilter?: string;
|
|
1302
|
+
}): Promise<DiscoveredCommand[]>;
|
|
1303
|
+
declare function commandSchemaToFlags(inputSchema: Record<string, string>): CommandFlag[];
|
|
1304
|
+
declare function parseInputFromFlags(rawOptions: Record<string, any>, schema: Record<string, string>): Record<string, any>;
|
|
1305
|
+
declare function executePluginCommand(command: DiscoveredCommand, input: Record<string, any>, viteServer?: ViteSSRLoader): Promise<{
|
|
1306
|
+
success: boolean;
|
|
1307
|
+
}>;
|
|
1308
|
+
|
|
1309
|
+
export { type ActionDiscoveryOptions, type ActionDiscoveryResult, type ActionErrorResponse, type ActionExecutionResult, type ActionIndexEntry, type ActionMetadata, ActionRegistry, type ActionSchema, type CommandFlag, type CommandIndexEntry, type CommandMetadata, type ContextIndexEntry, type DevServerPagePart, DevSlowlyChangingPhase, type DiscoveredCommand, type GenerateClientScriptOptions, type HeadlessInstanceComponent, type InstancePhaseData, type InstanceSlowRenderResult, type LoadedPageParts, type MaterializeContractsOptions, type MaterializeResult, type PluginActionDiscoveryOptions, type PluginClientInitInfo, type PluginContractEntry, type PluginInitDiscoveryOptions, type PluginReferencesContext, type PluginReferencesHandler, type PluginReferencesResult, type PluginScanOptions, type PluginSetupContext, type PluginSetupHandler, type PluginSetupResult, type PluginWithInit, type PluginWithReferences, type PluginWithSetup, type PluginsIndex, type PluginsIndexEntry, type ProjectClientInitInfo, type RegisteredAction, type RegisteredActionBase, type RegisteredActionEntry, type RegisteredStreamAction, type RouteIndexEntry, type ScannedPlugin, type ScriptFragments, type ServiceIndexEntry, SlowRenderCache, type SlowRenderCacheEntry, type SlowlyChangingPhase, type ViteSSRLoader, actionRegistry, buildAutomationWrap, buildScriptFragments, clearActionRegistry, clearClientInitData, clearLifecycleCallbacks, clearServerElementCache, clearServiceRegistry, commandSchemaToFlags, discoverAllPluginActions, discoverAndRegisterActions, discoverPluginActions, discoverPluginCommands, discoverPluginsWithInit, discoverPluginsWithReferences, discoverPluginsWithSetup, executeAction, executePluginCommand, executePluginReferences, executePluginServerInits, executePluginSetup, generateClientScript, generateFrozenPageHtml, generatePromiseReconstruction, generateSSRPageHtml, getActionCacheHeaders, getClientInitData, getClientInitDataForKey, getRegisteredAction, getRegisteredActionNames, getService, getServiceRegistry, hasAction, hasService, invalidateServerElementCache, listContracts, loadActionMetadata, loadPageParts, materializeContracts, mergeHeadTags, onInit, onShutdown, parseActionMetadata, parseCookies, parseInputFromFlags, preparePluginClientInits, registerAction, registerService, renderFastChangingData, resolveActionMetadataPath, resolveServices, resolveViewStatePromises, runInitCallbacks, runLoadParams, runShutdownCallbacks, scanPlugins, serializeHeadTags, setClientInitData, slowRenderInstances, sortPluginsByDependencies, tagIdentityKey };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => {
|
|
|
4
4
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
|
-
import { phaseOutput, isJayAction, isJayStreamAction } from "@jay-framework/fullstack-component";
|
|
7
|
+
import { phaseOutput, isJayAction, isJayStreamAction, isJayCliCommand } from "@jay-framework/fullstack-component";
|
|
8
8
|
import "prettier";
|
|
9
9
|
import "js-beautify";
|
|
10
10
|
import fs$1 from "fs";
|
|
@@ -395,10 +395,11 @@ function resolveBinding(binding, item) {
|
|
|
395
395
|
}
|
|
396
396
|
return binding;
|
|
397
397
|
}
|
|
398
|
-
async function renderFastChangingData(pageParams, pageProps, carryForward, parts, instancePhaseData, forEachInstances, headlessInstanceComponents, mergedSlowViewState, query = {}) {
|
|
398
|
+
async function renderFastChangingData(pageParams, pageProps, carryForward, parts, instancePhaseData, forEachInstances, headlessInstanceComponents, mergedSlowViewState, query = {}, cookies = {}) {
|
|
399
399
|
let fastViewState = {};
|
|
400
400
|
let fastCarryForward = {};
|
|
401
401
|
const fastHeadTagSources = [];
|
|
402
|
+
const responseHeaderSources = [];
|
|
402
403
|
for (const part of parts) {
|
|
403
404
|
const { compDefinition, key, contractInfo } = part;
|
|
404
405
|
if (compDefinition.fastRender) {
|
|
@@ -408,6 +409,7 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
408
409
|
...pageProps,
|
|
409
410
|
...pageParams,
|
|
410
411
|
query,
|
|
412
|
+
cookies,
|
|
411
413
|
...contractInfo && {
|
|
412
414
|
contractName: contractInfo.contractName,
|
|
413
415
|
metadata: contractInfo.metadata
|
|
@@ -425,6 +427,9 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
425
427
|
if (fastRenderedPart.headTags) {
|
|
426
428
|
fastHeadTagSources.push(fastRenderedPart.headTags);
|
|
427
429
|
}
|
|
430
|
+
if (fastRenderedPart.responseHeaders) {
|
|
431
|
+
responseHeaderSources.push(fastRenderedPart.responseHeaders);
|
|
432
|
+
}
|
|
428
433
|
} else
|
|
429
434
|
return fastRenderedPart;
|
|
430
435
|
}
|
|
@@ -445,7 +450,7 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
445
450
|
if (comp.compDefinition.fastRender) {
|
|
446
451
|
const services = resolveServices(comp.compDefinition.services);
|
|
447
452
|
const cf = instancePhaseData.carryForwards[coordKey];
|
|
448
|
-
const instanceProps = { ...instance.props, query };
|
|
453
|
+
const instanceProps = { ...instance.props, query, cookies };
|
|
449
454
|
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(instanceProps, cf, ...services) : await comp.compDefinition.fastRender(instanceProps, ...services);
|
|
450
455
|
if (fastResult.kind === "PhaseOutput") {
|
|
451
456
|
instanceViewStates[coordKey] = instanceSlowVS ? { ...instanceSlowVS, ...fastResult.rendered } : fastResult.rendered;
|
|
@@ -455,6 +460,9 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
455
460
|
if (fastResult.headTags) {
|
|
456
461
|
fastHeadTagSources.push(fastResult.headTags);
|
|
457
462
|
}
|
|
463
|
+
if (fastResult.responseHeaders) {
|
|
464
|
+
responseHeaderSources.push(fastResult.responseHeaders);
|
|
465
|
+
}
|
|
458
466
|
}
|
|
459
467
|
} else {
|
|
460
468
|
instanceViewStates[coordKey] = instanceSlowVS ?? {};
|
|
@@ -496,7 +504,7 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
496
504
|
cf = slowResult.carryForward;
|
|
497
505
|
}
|
|
498
506
|
}
|
|
499
|
-
const forEachProps = { ...props, query };
|
|
507
|
+
const forEachProps = { ...props, query, cookies };
|
|
500
508
|
const fastResult = comp.compDefinition.slowlyRender ? await comp.compDefinition.fastRender(forEachProps, cf, ...services) : await comp.compDefinition.fastRender(forEachProps, ...services);
|
|
501
509
|
if (fastResult.kind === "PhaseOutput") {
|
|
502
510
|
const coord = computeForEachInstanceKey(
|
|
@@ -522,6 +530,9 @@ async function renderFastChangingData(pageParams, pageProps, carryForward, parts
|
|
|
522
530
|
if (fastHeadTagSources.length > 0) {
|
|
523
531
|
result.headTags = fastHeadTagSources.flat();
|
|
524
532
|
}
|
|
533
|
+
if (responseHeaderSources.length > 0) {
|
|
534
|
+
result.responseHeaders = Object.assign({}, ...responseHeaderSources);
|
|
535
|
+
}
|
|
525
536
|
return Promise.resolve(result);
|
|
526
537
|
}
|
|
527
538
|
function generatePromiseReconstruction(outcomes) {
|
|
@@ -1282,22 +1293,6 @@ async function slowRenderInstances(discovered, headlessInstanceComponents) {
|
|
|
1282
1293
|
instancePhaseData: { discovered: discoveredForFast, carryForwards, slowViewStates }
|
|
1283
1294
|
};
|
|
1284
1295
|
}
|
|
1285
|
-
function validateForEachInstances(forEachInstances, headlessInstanceComponents) {
|
|
1286
|
-
const componentByContractName = /* @__PURE__ */ new Map();
|
|
1287
|
-
for (const comp of headlessInstanceComponents) {
|
|
1288
|
-
componentByContractName.set(comp.contractName, comp);
|
|
1289
|
-
}
|
|
1290
|
-
const validations = [];
|
|
1291
|
-
for (const instance of forEachInstances) {
|
|
1292
|
-
const comp = componentByContractName.get(instance.contractName);
|
|
1293
|
-
if (comp?.compDefinition.slowlyRender) {
|
|
1294
|
-
validations.push(
|
|
1295
|
-
`<jay:${instance.contractName}> inside forEach has a slow rendering phase. Headless components with slow phases cannot be used inside forEach because forEach items are only known at request time, after slow rendering completes. Use slowForEach instead, or remove the slow phase from the component.`
|
|
1296
|
-
);
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
return validations;
|
|
1300
|
-
}
|
|
1301
1296
|
class ActionRegistry {
|
|
1302
1297
|
constructor() {
|
|
1303
1298
|
__publicField(this, "actions", /* @__PURE__ */ new Map());
|
|
@@ -1314,7 +1309,9 @@ class ActionRegistry {
|
|
|
1314
1309
|
cacheOptions: action.cacheOptions,
|
|
1315
1310
|
services: action.services,
|
|
1316
1311
|
handler: action.handler,
|
|
1317
|
-
...action.acceptsFiles && {
|
|
1312
|
+
...action.acceptsFiles && {
|
|
1313
|
+
acceptsFiles: true
|
|
1314
|
+
}
|
|
1318
1315
|
};
|
|
1319
1316
|
this.actions.set(action.actionName, entry);
|
|
1320
1317
|
}
|
|
@@ -1472,7 +1469,9 @@ class ActionRegistry {
|
|
|
1472
1469
|
isStreaming: true,
|
|
1473
1470
|
services: action.services,
|
|
1474
1471
|
handler: action.handler,
|
|
1475
|
-
...action.acceptsFiles && {
|
|
1472
|
+
...action.acceptsFiles && {
|
|
1473
|
+
acceptsFiles: true
|
|
1474
|
+
}
|
|
1476
1475
|
};
|
|
1477
1476
|
this.actions.set(action.actionName, entry);
|
|
1478
1477
|
}
|
|
@@ -2572,6 +2571,24 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
2572
2571
|
...r.description && { description: r.description }
|
|
2573
2572
|
}));
|
|
2574
2573
|
}
|
|
2574
|
+
if (manifest.commands?.length) {
|
|
2575
|
+
entry.commands = manifest.commands.map((c) => {
|
|
2576
|
+
let description;
|
|
2577
|
+
if (c.command) {
|
|
2578
|
+
try {
|
|
2579
|
+
const cmdPath = path.resolve(plugin.pluginPath, c.command);
|
|
2580
|
+
const cmdContent = fs.readFileSync(cmdPath, "utf-8");
|
|
2581
|
+
const parsed = YAML.parse(cmdContent);
|
|
2582
|
+
description = parsed?.description;
|
|
2583
|
+
} catch {
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
return {
|
|
2587
|
+
name: c.name,
|
|
2588
|
+
...description && { description }
|
|
2589
|
+
};
|
|
2590
|
+
});
|
|
2591
|
+
}
|
|
2575
2592
|
pluginsIndexMap.set(plugin.name, entry);
|
|
2576
2593
|
}
|
|
2577
2594
|
if (!dynamicOnly && manifest.contracts) {
|
|
@@ -2707,7 +2724,8 @@ async function materializeContracts(options, services = /* @__PURE__ */ new Map(
|
|
|
2707
2724
|
...data.actions && data.actions.length > 0 && { actions: data.actions },
|
|
2708
2725
|
...data.services?.length && { services: data.services },
|
|
2709
2726
|
...data.contexts?.length && { contexts: data.contexts },
|
|
2710
|
-
...data.routes?.length && { routes: data.routes }
|
|
2727
|
+
...data.routes?.length && { routes: data.routes },
|
|
2728
|
+
...data.commands?.length && { commands: data.commands }
|
|
2711
2729
|
}))
|
|
2712
2730
|
};
|
|
2713
2731
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
@@ -2770,6 +2788,24 @@ async function listContracts(options) {
|
|
|
2770
2788
|
...r.description && { description: r.description }
|
|
2771
2789
|
}));
|
|
2772
2790
|
}
|
|
2791
|
+
if (manifest.commands?.length) {
|
|
2792
|
+
entry.commands = manifest.commands.map((c) => {
|
|
2793
|
+
let description;
|
|
2794
|
+
if (c.command) {
|
|
2795
|
+
try {
|
|
2796
|
+
const cmdPath = path.resolve(plugin.pluginPath, c.command);
|
|
2797
|
+
const cmdContent = fs.readFileSync(cmdPath, "utf-8");
|
|
2798
|
+
const parsed = YAML.parse(cmdContent);
|
|
2799
|
+
description = parsed?.description;
|
|
2800
|
+
} catch {
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
return {
|
|
2804
|
+
name: c.name,
|
|
2805
|
+
...description && { description }
|
|
2806
|
+
};
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2773
2809
|
pluginsMap.set(plugin.name, entry);
|
|
2774
2810
|
}
|
|
2775
2811
|
if (!dynamicOnly && manifest.contracts) {
|
|
@@ -2817,7 +2853,8 @@ async function listContracts(options) {
|
|
|
2817
2853
|
contracts: data.contracts,
|
|
2818
2854
|
...data.services?.length && { services: data.services },
|
|
2819
2855
|
...data.contexts?.length && { contexts: data.contexts },
|
|
2820
|
-
...data.routes?.length && { routes: data.routes }
|
|
2856
|
+
...data.routes?.length && { routes: data.routes },
|
|
2857
|
+
...data.commands?.length && { commands: data.commands }
|
|
2821
2858
|
}))
|
|
2822
2859
|
};
|
|
2823
2860
|
}
|
|
@@ -2948,6 +2985,146 @@ async function loadHandler(plugin, handlerName, viteServer) {
|
|
|
2948
2985
|
return module[handlerName];
|
|
2949
2986
|
}
|
|
2950
2987
|
}
|
|
2988
|
+
function parseCookies(cookieHeader) {
|
|
2989
|
+
const cookies = {};
|
|
2990
|
+
if (!cookieHeader)
|
|
2991
|
+
return cookies;
|
|
2992
|
+
for (const pair of cookieHeader.split(";")) {
|
|
2993
|
+
const [name, ...rest] = pair.trim().split("=");
|
|
2994
|
+
if (name)
|
|
2995
|
+
cookies[name] = decodeURIComponent(rest.join("="));
|
|
2996
|
+
}
|
|
2997
|
+
return cookies;
|
|
2998
|
+
}
|
|
2999
|
+
async function discoverPluginCommands(options) {
|
|
3000
|
+
const { projectRoot, verbose, pluginFilter } = options;
|
|
3001
|
+
const allPlugins = await scanPlugins({
|
|
3002
|
+
projectRoot,
|
|
3003
|
+
verbose,
|
|
3004
|
+
discoverTransitive: true
|
|
3005
|
+
});
|
|
3006
|
+
const commands = [];
|
|
3007
|
+
for (const [packageName, plugin] of allPlugins) {
|
|
3008
|
+
if (!plugin.manifest.commands || plugin.manifest.commands.length === 0)
|
|
3009
|
+
continue;
|
|
3010
|
+
if (pluginFilter && plugin.name !== pluginFilter && packageName !== pluginFilter) {
|
|
3011
|
+
continue;
|
|
3012
|
+
}
|
|
3013
|
+
for (const cmd of plugin.manifest.commands) {
|
|
3014
|
+
let metadata;
|
|
3015
|
+
let metadataPath;
|
|
3016
|
+
if (cmd.command) {
|
|
3017
|
+
metadataPath = path.resolve(plugin.pluginPath, cmd.command);
|
|
3018
|
+
metadata = loadCommandMetadata(metadataPath);
|
|
3019
|
+
}
|
|
3020
|
+
commands.push({
|
|
3021
|
+
pluginName: plugin.name,
|
|
3022
|
+
pluginPath: plugin.pluginPath,
|
|
3023
|
+
packageName: plugin.packageName,
|
|
3024
|
+
isLocal: plugin.isLocal,
|
|
3025
|
+
commandName: cmd.name,
|
|
3026
|
+
handlerExport: cmd.name,
|
|
3027
|
+
pluginModule: plugin.manifest.module,
|
|
3028
|
+
metadata,
|
|
3029
|
+
metadataPath
|
|
3030
|
+
});
|
|
3031
|
+
if (verbose) {
|
|
3032
|
+
getLogger().info(`[Commands] Found ${plugin.name}/${cmd.name}`);
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
return commands;
|
|
3037
|
+
}
|
|
3038
|
+
function loadCommandMetadata(filePath) {
|
|
3039
|
+
try {
|
|
3040
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
3041
|
+
return YAML.parse(content);
|
|
3042
|
+
} catch {
|
|
3043
|
+
return void 0;
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
function commandSchemaToFlags(inputSchema) {
|
|
3047
|
+
const flags = [];
|
|
3048
|
+
for (const [field, type] of Object.entries(inputSchema)) {
|
|
3049
|
+
const isOptional = field.endsWith("?");
|
|
3050
|
+
const cleanName = isOptional ? field.slice(0, -1) : field;
|
|
3051
|
+
const kebabName = camelToKebab(cleanName);
|
|
3052
|
+
const cleanType = type.toLowerCase().trim();
|
|
3053
|
+
const isBoolean = cleanType === "boolean";
|
|
3054
|
+
flags.push({
|
|
3055
|
+
flag: isBoolean ? `--${kebabName}` : `--${kebabName} <value>`,
|
|
3056
|
+
description: "",
|
|
3057
|
+
required: !isOptional,
|
|
3058
|
+
type: cleanType === "number" ? "number" : isBoolean ? "boolean" : "string"
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
return flags;
|
|
3062
|
+
}
|
|
3063
|
+
function camelToKebab(str) {
|
|
3064
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
3065
|
+
}
|
|
3066
|
+
function parseInputFromFlags(rawOptions, schema) {
|
|
3067
|
+
const input = {};
|
|
3068
|
+
for (const [field, type] of Object.entries(schema)) {
|
|
3069
|
+
const isOptional = field.endsWith("?");
|
|
3070
|
+
const cleanName = isOptional ? field.slice(0, -1) : field;
|
|
3071
|
+
const kebabName = camelToKebab(cleanName);
|
|
3072
|
+
const value = rawOptions[kebabName];
|
|
3073
|
+
if (value === void 0) {
|
|
3074
|
+
if (!isOptional) {
|
|
3075
|
+
throw new Error(`Missing required flag: --${kebabName}`);
|
|
3076
|
+
}
|
|
3077
|
+
continue;
|
|
3078
|
+
}
|
|
3079
|
+
const cleanType = type.toLowerCase().trim();
|
|
3080
|
+
if (cleanType === "number") {
|
|
3081
|
+
const parsed = Number(value);
|
|
3082
|
+
if (isNaN(parsed))
|
|
3083
|
+
throw new Error(`Flag --${kebabName} must be a number`);
|
|
3084
|
+
input[cleanName] = parsed;
|
|
3085
|
+
} else if (cleanType === "boolean") {
|
|
3086
|
+
input[cleanName] = value === true || value === "true";
|
|
3087
|
+
} else {
|
|
3088
|
+
input[cleanName] = String(value);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
return input;
|
|
3092
|
+
}
|
|
3093
|
+
async function executePluginCommand(command, input, viteServer) {
|
|
3094
|
+
const cliCommand = await loadCommandHandler(command, viteServer);
|
|
3095
|
+
const services = resolveServices(cliCommand.services);
|
|
3096
|
+
return cliCommand.handler(input, ...services);
|
|
3097
|
+
}
|
|
3098
|
+
async function loadCommandHandler(command, viteServer) {
|
|
3099
|
+
let module;
|
|
3100
|
+
if (command.isLocal) {
|
|
3101
|
+
const moduleFile = command.pluginModule || "index";
|
|
3102
|
+
const modulePath = path.resolve(command.pluginPath, moduleFile);
|
|
3103
|
+
if (viteServer) {
|
|
3104
|
+
module = await viteServer.ssrLoadModule(modulePath);
|
|
3105
|
+
} else {
|
|
3106
|
+
module = await import(modulePath);
|
|
3107
|
+
}
|
|
3108
|
+
} else {
|
|
3109
|
+
if (viteServer) {
|
|
3110
|
+
module = await viteServer.ssrLoadModule(command.packageName);
|
|
3111
|
+
} else {
|
|
3112
|
+
module = await import(command.packageName);
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
for (const [, exported] of Object.entries(module)) {
|
|
3116
|
+
if (isJayCliCommand(exported) && exported.commandName === command.commandName) {
|
|
3117
|
+
return exported;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
const byName = module[command.handlerExport];
|
|
3121
|
+
if (byName && isJayCliCommand(byName)) {
|
|
3122
|
+
return byName;
|
|
3123
|
+
}
|
|
3124
|
+
throw new Error(
|
|
3125
|
+
`CLI command "${command.commandName}" not found as export in "${command.isLocal ? command.pluginPath : command.packageName}". Available exports: ${Object.keys(module).join(", ")}`
|
|
3126
|
+
);
|
|
3127
|
+
}
|
|
2951
3128
|
export {
|
|
2952
3129
|
ActionRegistry,
|
|
2953
3130
|
DevSlowlyChangingPhase,
|
|
@@ -2960,13 +3137,16 @@ export {
|
|
|
2960
3137
|
clearLifecycleCallbacks,
|
|
2961
3138
|
clearServerElementCache,
|
|
2962
3139
|
clearServiceRegistry,
|
|
3140
|
+
commandSchemaToFlags,
|
|
2963
3141
|
discoverAllPluginActions,
|
|
2964
3142
|
discoverAndRegisterActions,
|
|
2965
3143
|
discoverPluginActions,
|
|
3144
|
+
discoverPluginCommands,
|
|
2966
3145
|
discoverPluginsWithInit,
|
|
2967
3146
|
discoverPluginsWithReferences,
|
|
2968
3147
|
discoverPluginsWithSetup,
|
|
2969
3148
|
executeAction,
|
|
3149
|
+
executePluginCommand,
|
|
2970
3150
|
executePluginReferences,
|
|
2971
3151
|
executePluginServerInits,
|
|
2972
3152
|
executePluginSetup,
|
|
@@ -2992,6 +3172,8 @@ export {
|
|
|
2992
3172
|
onInit,
|
|
2993
3173
|
onShutdown,
|
|
2994
3174
|
parseActionMetadata,
|
|
3175
|
+
parseCookies,
|
|
3176
|
+
parseInputFromFlags,
|
|
2995
3177
|
preparePluginClientInits,
|
|
2996
3178
|
registerAction,
|
|
2997
3179
|
registerService,
|
|
@@ -3007,6 +3189,5 @@ export {
|
|
|
3007
3189
|
setClientInitData,
|
|
3008
3190
|
slowRenderInstances,
|
|
3009
3191
|
sortPluginsByDependencies,
|
|
3010
|
-
tagIdentityKey
|
|
3011
|
-
validateForEachInstances
|
|
3192
|
+
tagIdentityKey
|
|
3012
3193
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/stack-server-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -26,21 +26,21 @@
|
|
|
26
26
|
"test:watch": "vitest"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@jay-framework/compiler-jay-html": "^0.
|
|
30
|
-
"@jay-framework/compiler-shared": "^0.
|
|
31
|
-
"@jay-framework/component": "^0.
|
|
32
|
-
"@jay-framework/fullstack-component": "^0.
|
|
33
|
-
"@jay-framework/logger": "^0.
|
|
34
|
-
"@jay-framework/runtime": "^0.
|
|
35
|
-
"@jay-framework/ssr-runtime": "^0.
|
|
36
|
-
"@jay-framework/stack-route-scanner": "^0.
|
|
37
|
-
"@jay-framework/view-state-merge": "^0.
|
|
29
|
+
"@jay-framework/compiler-jay-html": "^0.18.0",
|
|
30
|
+
"@jay-framework/compiler-shared": "^0.18.0",
|
|
31
|
+
"@jay-framework/component": "^0.18.0",
|
|
32
|
+
"@jay-framework/fullstack-component": "^0.18.0",
|
|
33
|
+
"@jay-framework/logger": "^0.18.0",
|
|
34
|
+
"@jay-framework/runtime": "^0.18.0",
|
|
35
|
+
"@jay-framework/ssr-runtime": "^0.18.0",
|
|
36
|
+
"@jay-framework/stack-route-scanner": "^0.18.0",
|
|
37
|
+
"@jay-framework/view-state-merge": "^0.18.0",
|
|
38
38
|
"yaml": "^2.3.4"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@jay-framework/dev-environment": "^0.
|
|
42
|
-
"@jay-framework/jay-cli": "^0.
|
|
43
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
41
|
+
"@jay-framework/dev-environment": "^0.18.0",
|
|
42
|
+
"@jay-framework/jay-cli": "^0.18.0",
|
|
43
|
+
"@jay-framework/stack-client-runtime": "^0.18.0",
|
|
44
44
|
"@types/express": "^5.0.2",
|
|
45
45
|
"@types/node": "^22.15.21",
|
|
46
46
|
"nodemon": "^3.0.3",
|