@jay-framework/jay-stack-cli 0.22.0 → 0.22.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.
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
# CLI Commands Reference
|
|
2
2
|
|
|
3
|
-
## jay-stack setup
|
|
3
|
+
## jay-stack-cli setup
|
|
4
4
|
|
|
5
|
-
Run plugin setup. Plugins
|
|
5
|
+
Run plugin setup. Plugins create configuration files, prompt for credentials, and validate services.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# Run setup for all installed plugins
|
|
9
|
-
jay-stack setup
|
|
8
|
+
# Run setup for all installed plugins (interactive — may prompt for input)
|
|
9
|
+
jay-stack-cli setup
|
|
10
10
|
|
|
11
11
|
# Run setup for a specific plugin
|
|
12
|
-
jay-stack setup wix-stores
|
|
12
|
+
jay-stack-cli setup wix-stores
|
|
13
13
|
|
|
14
14
|
# Re-run setup (e.g., after config change)
|
|
15
|
-
jay-stack setup
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Plugins declare their setup handler in `plugin.yaml`. Setup does two things:
|
|
15
|
+
jay-stack-cli setup --force
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
# Non-interactive mode (creates config templates without prompting)
|
|
18
|
+
jay-stack-cli setup --no-interactive
|
|
19
|
+
```
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
Setup is **interactive by default** — plugins may prompt for API keys and credentials. Use `--no-interactive` in CI/scripts.
|
|
24
22
|
|
|
25
|
-
Run this after installing new plugins, before `jay-stack agent-kit`.
|
|
23
|
+
Run this after installing new plugins, before `jay-stack-cli agent-kit`.
|
|
26
24
|
|
|
27
25
|
## jay-stack agent-kit
|
|
28
26
|
|
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
# CLI Commands Reference
|
|
2
2
|
|
|
3
|
-
## jay-stack setup
|
|
3
|
+
## jay-stack-cli setup
|
|
4
4
|
|
|
5
|
-
Run plugin setup. Plugins can create configuration files,
|
|
5
|
+
Run plugin setup. Plugins can create configuration files, prompt for credentials, and validate their prerequisites.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# Run setup for all installed plugins
|
|
9
|
-
jay-stack setup
|
|
8
|
+
# Run setup for all installed plugins (interactive — may prompt for input)
|
|
9
|
+
jay-stack-cli setup
|
|
10
10
|
|
|
11
11
|
# Run setup for a specific plugin
|
|
12
|
-
jay-stack setup wix-stores
|
|
12
|
+
jay-stack-cli setup wix-stores
|
|
13
13
|
|
|
14
14
|
# Re-run setup (e.g., after config change)
|
|
15
|
-
jay-stack setup wix-data --force
|
|
15
|
+
jay-stack-cli setup wix-data --force
|
|
16
|
+
|
|
17
|
+
# Non-interactive mode (CI/scripts — creates config templates without prompting)
|
|
18
|
+
jay-stack-cli setup --no-interactive
|
|
16
19
|
```
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
Setup is **interactive by default** — plugins can prompt for API keys, credentials, and configuration choices. In non-interactive mode (`--no-interactive`), prompts are skipped and plugins create config templates with placeholders instead.
|
|
22
|
+
|
|
23
|
+
Plugins declare their setup handler in `plugin.yaml`. Setup does three things:
|
|
19
24
|
|
|
20
|
-
1. **Config templates**: Creates `config/<plugin>.yaml` with
|
|
21
|
-
2. **Credential
|
|
25
|
+
1. **Config templates**: Creates `config/<plugin>.yaml` with credentials (interactive) or placeholders (non-interactive)
|
|
26
|
+
2. **Credential prompts**: Asks for API keys and configuration when running interactively
|
|
27
|
+
3. **Service validation**: Attempts to initialize services, reports success or failure
|
|
22
28
|
|
|
23
|
-
Reference data (product catalogs, collection schemas) is generated by `jay-stack agent-kit`, not by setup.
|
|
29
|
+
Reference data (product catalogs, collection schemas) is generated by `jay-stack-cli agent-kit`, not by setup.
|
|
24
30
|
|
|
25
|
-
Run this after installing new plugins, before `jay-stack agent-kit`.
|
|
31
|
+
Run this after installing new plugins, before `jay-stack-cli agent-kit`.
|
|
26
32
|
|
|
27
33
|
## jay-stack agent-kit
|
|
28
34
|
|
|
@@ -14,6 +14,56 @@ The devops role handles the production lifecycle: building artifacts, configurin
|
|
|
14
14
|
4. **Invalidate** — rebuild specific pages when data changes
|
|
15
15
|
5. **Admin** — run plugin CLI commands via `jay-stack run <plugin>/<command>` (media upload, data sync, cache purge)
|
|
16
16
|
|
|
17
|
+
## Plugin Setup
|
|
18
|
+
|
|
19
|
+
Plugins may need credentials or configuration before they can run. The setup command handles this.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Default (non-interactive) — exits with structured output if input is needed
|
|
23
|
+
jay-stack-cli setup
|
|
24
|
+
|
|
25
|
+
# Interactive — prompts for credentials via terminal
|
|
26
|
+
jay-stack-cli setup --interactive
|
|
27
|
+
|
|
28
|
+
# With pre-provided answers (for automation)
|
|
29
|
+
jay-stack-cli setup --answers answers.yaml
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Automated setup (CI / agents)
|
|
33
|
+
|
|
34
|
+
When running `jay-stack-cli setup` without `--interactive`, plugins that need user input will exit with structured YAML output:
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
setup-needs-answer:
|
|
38
|
+
plugin: wix-server-client
|
|
39
|
+
key: api-key
|
|
40
|
+
type: input
|
|
41
|
+
message: 'Enter your API key'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
To provide the answer, create a YAML file and re-run:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# answers.yaml
|
|
48
|
+
api-key: 'IST.abc123...'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
jay-stack-cli setup --answers answers.yaml
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Repeat until all plugins report `configured`. The flow is iterative — each run may reveal the next question.
|
|
56
|
+
|
|
57
|
+
### Setup order
|
|
58
|
+
|
|
59
|
+
Run setup **before** agent-kit and build:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
jay-stack-cli setup # 1. Configure plugins
|
|
63
|
+
jay-stack-cli agent-kit # 2. Generate contracts and discovery data
|
|
64
|
+
jay-stack-cli build # 3. Production build
|
|
65
|
+
```
|
|
66
|
+
|
|
17
67
|
## Guides
|
|
18
68
|
|
|
19
69
|
| File | Topic |
|
|
@@ -30,10 +30,12 @@ description: Validate credentials and install config # optional, top-level
|
|
|
30
30
|
|
|
31
31
|
## Writing a Setup Handler
|
|
32
32
|
|
|
33
|
-
The setup handler creates config files and
|
|
33
|
+
The setup handler creates config files, validates services, and can prompt the user for credentials. It receives a `PluginSetupContext` and returns a `PluginSetupResult`.
|
|
34
34
|
|
|
35
35
|
**Do not** write add-menu catalogs in setup — use the agent-kit handler.
|
|
36
36
|
|
|
37
|
+
### Basic setup (non-interactive)
|
|
38
|
+
|
|
37
39
|
```typescript
|
|
38
40
|
import type { PluginSetupContext, PluginSetupResult } from '@jay-framework/stack-server-runtime';
|
|
39
41
|
import fs from 'node:fs';
|
|
@@ -49,7 +51,7 @@ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetu
|
|
|
49
51
|
|
|
50
52
|
if (!fs.existsSync(configPath) || ctx.force) {
|
|
51
53
|
fs.mkdirSync(ctx.configDir, { recursive: true });
|
|
52
|
-
fs.writeFileSync(configPath, '# My Plugin config\n', 'utf-8');
|
|
54
|
+
fs.writeFileSync(configPath, '# My Plugin config\napiKey: "<your-api-key>"\n', 'utf-8');
|
|
53
55
|
configCreated.push('config/.my-plugin.yaml');
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -64,16 +66,124 @@ export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetu
|
|
|
64
66
|
}
|
|
65
67
|
```
|
|
66
68
|
|
|
69
|
+
### Interactive setup (with prompts)
|
|
70
|
+
|
|
71
|
+
When the setup handler needs user input (API keys, credentials, configuration choices), use `ctx.prompt`:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetupResult> {
|
|
75
|
+
const configPath = path.join(ctx.configDir, '.my-plugin.yaml');
|
|
76
|
+
|
|
77
|
+
// Already configured — skip unless --force
|
|
78
|
+
if (fs.existsSync(configPath) && !ctx.force) {
|
|
79
|
+
return { status: 'configured', message: 'Already configured' };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// In non-interactive mode, create a template and ask the user to fill it in later
|
|
83
|
+
if (!ctx.interactive) {
|
|
84
|
+
fs.mkdirSync(ctx.configDir, { recursive: true });
|
|
85
|
+
fs.writeFileSync(configPath, 'apiKey: "<your-api-key>"\n', 'utf-8');
|
|
86
|
+
return {
|
|
87
|
+
status: 'needs-config',
|
|
88
|
+
configCreated: ['config/.my-plugin.yaml'],
|
|
89
|
+
message: 'Run `jay-stack-cli setup` interactively to enter your API key',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Interactive mode — prompt the user
|
|
94
|
+
const apiKey = await ctx.prompt.input({
|
|
95
|
+
message: 'Enter your API key (create one at https://example.com/api-keys):',
|
|
96
|
+
validate: (v) => (v.trim() ? true : 'API key is required'),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const region = await ctx.prompt.select({
|
|
100
|
+
message: 'Select your region:',
|
|
101
|
+
choices: [
|
|
102
|
+
{ name: 'US East', value: 'us-east' },
|
|
103
|
+
{ name: 'EU West', value: 'eu-west' },
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
fs.mkdirSync(ctx.configDir, { recursive: true });
|
|
108
|
+
fs.writeFileSync(configPath, `apiKey: "${apiKey.trim()}"\nregion: ${region}\n`, 'utf-8');
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
status: 'configured',
|
|
112
|
+
configCreated: ['config/.my-plugin.yaml'],
|
|
113
|
+
message: 'Credentials configured successfully',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Setup modes
|
|
119
|
+
|
|
120
|
+
Setup runs in three modes:
|
|
121
|
+
|
|
122
|
+
| Mode | Command | `ctx.interactive` | `ctx.prompt` behavior |
|
|
123
|
+
| ----------------------------- | ----------------------------------------- | ----------------- | ----------------------------------------------------- |
|
|
124
|
+
| **Default** (agents, CI) | `jay-stack-cli setup` | `false` | Throws `SetupNeedsAnswerError` with structured output |
|
|
125
|
+
| **Interactive** (humans) | `jay-stack-cli setup --interactive` | `true` | Prompts via terminal |
|
|
126
|
+
| **Answers file** (automation) | `jay-stack-cli setup --answers file.yaml` | `false` | Reads from file, throws if missing |
|
|
127
|
+
|
|
128
|
+
In default mode, when a prompt has no answer, the CLI exits with structured YAML telling the caller what's needed. Agents can then provide the answer via `--answers` and re-run.
|
|
129
|
+
|
|
130
|
+
### Idempotency requirement
|
|
131
|
+
|
|
132
|
+
Setup handlers **must be idempotent** — re-running with the same answers must produce the same result without side effects. This is critical because:
|
|
133
|
+
|
|
134
|
+
- Agents re-run setup iteratively as they provide answers one at a time
|
|
135
|
+
- Users re-run setup after fixing credentials
|
|
136
|
+
- CI pipelines may run setup on every deploy
|
|
137
|
+
|
|
138
|
+
**Rules:**
|
|
139
|
+
|
|
140
|
+
1. Check if config already exists before creating it — skip if present (unless `ctx.force`)
|
|
141
|
+
2. Check if credentials are already valid before prompting — skip if configured
|
|
142
|
+
3. Never append to files — write the complete content each time
|
|
143
|
+
4. Use `ctx.force` to allow explicit re-creation when the user asks for it
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
export async function setupMyPlugin(ctx: PluginSetupContext): Promise<PluginSetupResult> {
|
|
147
|
+
const configPath = path.join(ctx.configDir, '.my-plugin.yaml');
|
|
148
|
+
|
|
149
|
+
// Idempotent: skip if already configured (unless --force)
|
|
150
|
+
if (fs.existsSync(configPath) && !ctx.force) {
|
|
151
|
+
// Optionally validate the existing config
|
|
152
|
+
return { status: 'configured', message: 'Already configured' };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Prompt only when needed
|
|
156
|
+
const apiKey = await ctx.prompt.input({
|
|
157
|
+
key: 'api-key',
|
|
158
|
+
message: 'Enter your API key:',
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Write complete config (not append)
|
|
162
|
+
fs.writeFileSync(configPath, `apiKey: "${apiKey}"\n`);
|
|
163
|
+
return { status: 'configured', configCreated: ['config/.my-plugin.yaml'] };
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
67
167
|
### PluginSetupContext
|
|
68
168
|
|
|
69
|
-
| Field | Type
|
|
70
|
-
| ------------- |
|
|
71
|
-
| `pluginName` | `string`
|
|
72
|
-
| `projectRoot` | `string`
|
|
73
|
-
| `configDir` | `string`
|
|
74
|
-
| `services` | `Map`
|
|
75
|
-
| `initError` | `Error?`
|
|
76
|
-
| `force` | `boolean`
|
|
169
|
+
| Field | Type | Description |
|
|
170
|
+
| ------------- | ------------------- | ----------------------------------------------------------------- |
|
|
171
|
+
| `pluginName` | `string` | Plugin name from plugin.yaml |
|
|
172
|
+
| `projectRoot` | `string` | Absolute project root path |
|
|
173
|
+
| `configDir` | `string` | Config directory (from `.jay` configBase, defaults to `./config`) |
|
|
174
|
+
| `services` | `Map` | Registered services (may be empty if init failed) |
|
|
175
|
+
| `initError` | `Error?` | Present if plugin init failed — check this before using services |
|
|
176
|
+
| `force` | `boolean` | Whether `--force` flag was passed |
|
|
177
|
+
| `interactive` | `boolean` | Whether running in interactive mode (can prompt user) |
|
|
178
|
+
| `prompt` | `PluginSetupPrompt` | Prompt functions for user input (see below) |
|
|
179
|
+
|
|
180
|
+
### PluginSetupPrompt
|
|
181
|
+
|
|
182
|
+
| Method | Signature | Description |
|
|
183
|
+
| --------- | -------------------------------------------------- | ---------------------------------------------------------- |
|
|
184
|
+
| `input` | `(opts: { message, validate? }) → Promise<string>` | Text input. Non-interactive: returns `""` |
|
|
185
|
+
| `confirm` | `(opts: { message, default? }) → Promise<boolean>` | Yes/no. Non-interactive: returns `default` or `false` |
|
|
186
|
+
| `select` | `(opts: { message, choices }) → Promise<string>` | Single choice. Non-interactive: returns first choice value |
|
|
77
187
|
|
|
78
188
|
### PluginSetupResult
|
|
79
189
|
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import YAML from "yaml";
|
|
|
10
10
|
import { getLogger, setDevLogger, createDevLogger } from "@jay-framework/logger";
|
|
11
11
|
import { parseJayFile, JAY_IMPORT_RESOLVER, generateElementDefinitionFile, ContractTagType, parseContract, generateElementFile, generateServerElementFile, htmlElementTagNameMap, loadLinkedContract, getLinkedContractDir } from "@jay-framework/compiler-jay-html";
|
|
12
12
|
import { JAY_CONTRACT_EXTENSION, JAY_EXTENSION, resolvePluginManifest, LOCAL_PLUGIN_PATH, JayAtomicType, JayEnumType, loadPluginManifest, RuntimeMode, GenerateTarget, findDynamicContract } from "@jay-framework/compiler-shared";
|
|
13
|
-
import { scanPlugins as scanPlugins$1, listContracts, materializeContracts } from "@jay-framework/stack-server-runtime";
|
|
13
|
+
import { scanPlugins as scanPlugins$1, listContracts, materializeContracts, SetupNeedsAnswerError } from "@jay-framework/stack-server-runtime";
|
|
14
14
|
import { listContracts as listContracts2, materializeContracts as materializeContracts2 } from "@jay-framework/stack-server-runtime";
|
|
15
15
|
import { Command } from "commander";
|
|
16
16
|
import chalk from "chalk";
|
|
@@ -20,6 +20,7 @@ import { createRequire } from "module";
|
|
|
20
20
|
import { glob } from "glob";
|
|
21
21
|
import fsSync from "node:fs";
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { input, confirm, select } from "@inquirer/prompts";
|
|
23
24
|
const DEFAULT_CONFIG = {
|
|
24
25
|
devServer: {
|
|
25
26
|
portRange: [3e3, 3100],
|
|
@@ -5958,7 +5959,7 @@ async function runAction(actionRef, options, projectRoot, initializeServices) {
|
|
|
5958
5959
|
process.exit(1);
|
|
5959
5960
|
}
|
|
5960
5961
|
const actionExport = actionRef.substring(slashIndex + 1);
|
|
5961
|
-
const
|
|
5962
|
+
const input2 = options.input ? JSON.parse(options.input) : {};
|
|
5962
5963
|
if (options.verbose) {
|
|
5963
5964
|
getLogger().info("Starting Vite for TypeScript support...");
|
|
5964
5965
|
}
|
|
@@ -5991,9 +5992,9 @@ async function runAction(actionRef, options, projectRoot, initializeServices) {
|
|
|
5991
5992
|
}
|
|
5992
5993
|
if (options.verbose) {
|
|
5993
5994
|
getLogger().info(`Executing action: ${matchedName}`);
|
|
5994
|
-
getLogger().info(`Input: ${JSON.stringify(
|
|
5995
|
+
getLogger().info(`Input: ${JSON.stringify(input2)}`);
|
|
5995
5996
|
}
|
|
5996
|
-
const result = await registry.execute(matchedName,
|
|
5997
|
+
const result = await registry.execute(matchedName, input2);
|
|
5997
5998
|
if (result.success) {
|
|
5998
5999
|
if (options.yaml) {
|
|
5999
6000
|
getLogger().important(YAML.stringify(result.data));
|
|
@@ -6106,6 +6107,69 @@ async function runParams(contractRef, options, projectRoot, initializeServices)
|
|
|
6106
6107
|
}
|
|
6107
6108
|
}
|
|
6108
6109
|
}
|
|
6110
|
+
function createInteractivePrompt() {
|
|
6111
|
+
return {
|
|
6112
|
+
async input(options) {
|
|
6113
|
+
return input({ message: options.message, validate: options.validate });
|
|
6114
|
+
},
|
|
6115
|
+
async confirm(options) {
|
|
6116
|
+
return confirm({ message: options.message, default: options.default });
|
|
6117
|
+
},
|
|
6118
|
+
async select(options) {
|
|
6119
|
+
return select({
|
|
6120
|
+
message: options.message,
|
|
6121
|
+
choices: options.choices.map((c) => ({ name: c.name, value: c.value }))
|
|
6122
|
+
});
|
|
6123
|
+
}
|
|
6124
|
+
};
|
|
6125
|
+
}
|
|
6126
|
+
function createAnswersFilePrompt(answers, pluginName) {
|
|
6127
|
+
return {
|
|
6128
|
+
async input(options) {
|
|
6129
|
+
const value = answers[options.key];
|
|
6130
|
+
if (value !== void 0)
|
|
6131
|
+
return value;
|
|
6132
|
+
throw new SetupNeedsAnswerError(pluginName, options.key, "input", options.message);
|
|
6133
|
+
},
|
|
6134
|
+
async confirm(options) {
|
|
6135
|
+
const value = answers[options.key];
|
|
6136
|
+
if (value !== void 0)
|
|
6137
|
+
return value === "true" || value === "yes";
|
|
6138
|
+
throw new SetupNeedsAnswerError(pluginName, options.key, "confirm", options.message);
|
|
6139
|
+
},
|
|
6140
|
+
async select(options) {
|
|
6141
|
+
const value = answers[options.key];
|
|
6142
|
+
if (value !== void 0)
|
|
6143
|
+
return value;
|
|
6144
|
+
throw new SetupNeedsAnswerError(
|
|
6145
|
+
pluginName,
|
|
6146
|
+
options.key,
|
|
6147
|
+
"select",
|
|
6148
|
+
options.message,
|
|
6149
|
+
options.choices
|
|
6150
|
+
);
|
|
6151
|
+
}
|
|
6152
|
+
};
|
|
6153
|
+
}
|
|
6154
|
+
function createDefaultPrompt(pluginName) {
|
|
6155
|
+
return {
|
|
6156
|
+
async input(options) {
|
|
6157
|
+
throw new SetupNeedsAnswerError(pluginName, options.key, "input", options.message);
|
|
6158
|
+
},
|
|
6159
|
+
async confirm(options) {
|
|
6160
|
+
throw new SetupNeedsAnswerError(pluginName, options.key, "confirm", options.message);
|
|
6161
|
+
},
|
|
6162
|
+
async select(options) {
|
|
6163
|
+
throw new SetupNeedsAnswerError(
|
|
6164
|
+
pluginName,
|
|
6165
|
+
options.key,
|
|
6166
|
+
"select",
|
|
6167
|
+
options.message,
|
|
6168
|
+
options.choices
|
|
6169
|
+
);
|
|
6170
|
+
}
|
|
6171
|
+
};
|
|
6172
|
+
}
|
|
6109
6173
|
async function runSetup(pluginFilter, options, projectRoot, initializeServices) {
|
|
6110
6174
|
let viteServer;
|
|
6111
6175
|
try {
|
|
@@ -6145,6 +6209,11 @@ async function runSetup(pluginFilter, options, projectRoot, initializeServices)
|
|
|
6145
6209
|
logger.info(chalk.yellow(`⚠️ ${name} init error: ${err.message}`));
|
|
6146
6210
|
}
|
|
6147
6211
|
}
|
|
6212
|
+
const interactive = options.interactive === true;
|
|
6213
|
+
let answersMap;
|
|
6214
|
+
if (options.answers) {
|
|
6215
|
+
answersMap = YAML.parse(fsSync.readFileSync(options.answers, "utf-8")) || {};
|
|
6216
|
+
}
|
|
6148
6217
|
let configured = 0;
|
|
6149
6218
|
let needsConfig = 0;
|
|
6150
6219
|
let errors = 0;
|
|
@@ -6153,11 +6222,14 @@ async function runSetup(pluginFilter, options, projectRoot, initializeServices)
|
|
|
6153
6222
|
if (plugin.setupDescription && options.verbose) {
|
|
6154
6223
|
logger.important(chalk.gray(` ${plugin.setupDescription}`));
|
|
6155
6224
|
}
|
|
6225
|
+
const prompt = interactive ? createInteractivePrompt() : answersMap ? createAnswersFilePrompt(answersMap, plugin.name) : createDefaultPrompt(plugin.name);
|
|
6156
6226
|
try {
|
|
6157
6227
|
const result = await executePluginSetup(plugin, {
|
|
6158
6228
|
projectRoot,
|
|
6159
6229
|
configDir,
|
|
6160
6230
|
force: options.force ?? false,
|
|
6231
|
+
interactive,
|
|
6232
|
+
prompt,
|
|
6161
6233
|
initError: initErrors.get(plugin.name),
|
|
6162
6234
|
viteServer,
|
|
6163
6235
|
verbose: options.verbose
|
|
@@ -6200,10 +6272,34 @@ async function runSetup(pluginFilter, options, projectRoot, initializeServices)
|
|
|
6200
6272
|
break;
|
|
6201
6273
|
}
|
|
6202
6274
|
} catch (error) {
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
logger.
|
|
6275
|
+
if (error instanceof SetupNeedsAnswerError) {
|
|
6276
|
+
needsConfig++;
|
|
6277
|
+
logger.important("");
|
|
6278
|
+
logger.important(chalk.yellow("setup-needs-answer:"));
|
|
6279
|
+
logger.important(chalk.yellow(` plugin: ${error.plugin}`));
|
|
6280
|
+
logger.important(chalk.yellow(` key: ${error.key}`));
|
|
6281
|
+
logger.important(chalk.yellow(` type: ${error.type}`));
|
|
6282
|
+
logger.important(chalk.yellow(` message: "${error.promptMessage}"`));
|
|
6283
|
+
if (error.choices) {
|
|
6284
|
+
logger.important(chalk.yellow(" choices:"));
|
|
6285
|
+
for (const c of error.choices) {
|
|
6286
|
+
logger.important(chalk.yellow(` - ${c.value}: ${c.name}`));
|
|
6287
|
+
}
|
|
6288
|
+
}
|
|
6289
|
+
logger.important("");
|
|
6290
|
+
logger.important(chalk.gray("Provide the answer via file:"));
|
|
6291
|
+
logger.important(chalk.gray(` jay-stack-cli setup --answers answers.yaml`));
|
|
6292
|
+
logger.important(chalk.gray(` answers.yaml format:`));
|
|
6293
|
+
logger.important(chalk.gray(` ${error.key}: "your-answer"`));
|
|
6294
|
+
logger.important("");
|
|
6295
|
+
logger.important(chalk.gray("Or run interactively:"));
|
|
6296
|
+
logger.important(chalk.gray(` jay-stack-cli setup --interactive`));
|
|
6297
|
+
} else {
|
|
6298
|
+
errors++;
|
|
6299
|
+
logger.important(chalk.red(` ❌ Setup failed: ${error.message}`));
|
|
6300
|
+
if (options.verbose) {
|
|
6301
|
+
logger.error(error.stack);
|
|
6302
|
+
}
|
|
6207
6303
|
}
|
|
6208
6304
|
}
|
|
6209
6305
|
logger.important("");
|
|
@@ -6284,11 +6380,11 @@ async function runCommand(commandRef, rawArgs, options, projectRoot, initializeS
|
|
|
6284
6380
|
}
|
|
6285
6381
|
process.exit(1);
|
|
6286
6382
|
}
|
|
6287
|
-
let
|
|
6383
|
+
let input2 = {};
|
|
6288
6384
|
if (command.metadata?.inputSchema) {
|
|
6289
6385
|
const flagDefs = commandSchemaToFlags(command.metadata.inputSchema);
|
|
6290
6386
|
const rawOptions = parseRawFlags(rawArgs, flagDefs);
|
|
6291
|
-
|
|
6387
|
+
input2 = parseInputFromFlags(rawOptions, command.metadata.inputSchema);
|
|
6292
6388
|
}
|
|
6293
6389
|
if (options.verbose) {
|
|
6294
6390
|
getLogger().info("Starting Vite for TypeScript support...");
|
|
@@ -6319,7 +6415,7 @@ async function runCommand(commandRef, rawArgs, options, projectRoot, initializeS
|
|
|
6319
6415
|
if (options.verbose) {
|
|
6320
6416
|
getLogger().info(`Executing ${command.pluginName}/${command.commandName}...`);
|
|
6321
6417
|
}
|
|
6322
|
-
const result = await executePluginCommand(command,
|
|
6418
|
+
const result = await executePluginCommand(command, input2, viteServer);
|
|
6323
6419
|
if (!result.success) {
|
|
6324
6420
|
process.exit(1);
|
|
6325
6421
|
}
|
|
@@ -6459,7 +6555,7 @@ program.command("validate-plugin").description("Validate a Jay Stack plugin pack
|
|
|
6459
6555
|
process.exit(1);
|
|
6460
6556
|
}
|
|
6461
6557
|
});
|
|
6462
|
-
program.command("setup [plugin]").description("Run plugin setup: config templates, credential validation, reference data").option("--force", "Force re-run (overwrite config templates and regenerate references)").option("-v, --verbose", "Show detailed output").action(async (plugin, options) => {
|
|
6558
|
+
program.command("setup [plugin]").description("Run plugin setup: config templates, credential validation, reference data").option("--force", "Force re-run (overwrite config templates and regenerate references)").option("--interactive", "Prompt for input via terminal (for humans)").option("--answers <file>", "Read answers from YAML file (for agents)").option("-v, --verbose", "Show detailed output").action(async (plugin, options) => {
|
|
6463
6559
|
await runSetup(plugin, options, process.cwd(), initializeServicesForCli);
|
|
6464
6560
|
});
|
|
6465
6561
|
program.command("agent-kit").description("Prepare agent kit: materialize contracts, generate references, write docs").option("-o, --output <dir>", "Output directory (default: agent-kit/materialized-contracts)").option("--yaml", "Output contract index as YAML to stdout").option("--list", "List contracts without writing files").option("--plugin <name>", "Filter to specific plugin").option("--dynamic-only", "Only process dynamic contracts").option("--force", "Force re-materialization").option("--no-references", "Skip reference data generation").option(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/jay-stack-cli",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,15 +24,16 @@
|
|
|
24
24
|
"test:watch": "vitest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@jay-framework/compiler-
|
|
29
|
-
"@jay-framework/
|
|
30
|
-
"@jay-framework/
|
|
31
|
-
"@jay-framework/
|
|
32
|
-
"@jay-framework/
|
|
33
|
-
"@jay-framework/
|
|
34
|
-
"@jay-framework/
|
|
35
|
-
"@jay-framework/
|
|
27
|
+
"@inquirer/prompts": "^8.5.2",
|
|
28
|
+
"@jay-framework/compiler-jay-html": "^0.22.2",
|
|
29
|
+
"@jay-framework/compiler-shared": "^0.22.2",
|
|
30
|
+
"@jay-framework/dev-server": "^0.22.2",
|
|
31
|
+
"@jay-framework/editor-server": "^0.22.2",
|
|
32
|
+
"@jay-framework/fullstack-component": "^0.22.2",
|
|
33
|
+
"@jay-framework/logger": "^0.22.2",
|
|
34
|
+
"@jay-framework/plugin-validator": "^0.22.2",
|
|
35
|
+
"@jay-framework/production-server": "^0.22.2",
|
|
36
|
+
"@jay-framework/stack-server-runtime": "^0.22.2",
|
|
36
37
|
"chalk": "^4.1.2",
|
|
37
38
|
"commander": "^14.0.0",
|
|
38
39
|
"express": "^5.0.1",
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
"yaml": "^2.3.4"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
|
-
"@jay-framework/dev-environment": "^0.22.
|
|
47
|
+
"@jay-framework/dev-environment": "^0.22.2",
|
|
47
48
|
"@types/express": "^5.0.2",
|
|
48
49
|
"@types/node": "^22.15.21",
|
|
49
50
|
"nodemon": "^3.0.3",
|