@l4yercak3/cli 1.2.14 → 1.2.15

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.
@@ -19,7 +19,9 @@
19
19
  "Bash(npm run build:*)",
20
20
  "Bash(npm version:*)",
21
21
  "Bash(npm run lint:fix:*)",
22
- "Bash(cat:*)"
22
+ "Bash(cat:*)",
23
+ "Bash(node:*)",
24
+ "Bash(node -c:*)"
23
25
  ]
24
26
  }
25
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@l4yercak3/cli",
3
- "version": "1.2.14",
3
+ "version": "1.2.15",
4
4
  "description": "Icing on the L4yercak3 - The sweet finishing touch for your Layer Cake integration",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -10,6 +10,7 @@ const chalk = require('chalk');
10
10
  const inquirer = require('inquirer');
11
11
  const projectDetector = require('../detectors');
12
12
  const { showLogo } = require('../logo');
13
+ const { showPostLoginMenu, executeMenuAction } = require('../utils/prompt-utils');
13
14
 
14
15
  /**
15
16
  * Generate retro Windows 95 style HTML page
@@ -262,7 +263,9 @@ async function promptSetupWizard() {
262
263
  ]);
263
264
 
264
265
  if (!reconfigure) {
265
- console.log(chalk.gray('\n Run "l4yercak3 spread" anytime to reconfigure.\n'));
266
+ console.log('');
267
+ const action = await showPostLoginMenu({ isInProject: true, hasExistingConfig: true });
268
+ await executeMenuAction(action);
266
269
  return;
267
270
  }
268
271
  } else {
@@ -276,7 +279,9 @@ async function promptSetupWizard() {
276
279
  ]);
277
280
 
278
281
  if (!runWizard) {
279
- console.log(chalk.gray('\n Run "l4yercak3 spread" anytime to set up your project.\n'));
282
+ console.log('');
283
+ const action = await showPostLoginMenu({ isInProject: true, hasExistingConfig: false });
284
+ await executeMenuAction(action);
280
285
  return;
281
286
  }
282
287
  }
@@ -13,6 +13,7 @@ const { generateProjectPathHash } = require('../utils/file-utils');
13
13
  const inquirer = require('inquirer');
14
14
  const chalk = require('chalk');
15
15
  const pkg = require('../../package.json');
16
+ const { showMainMenu, executeMenuAction } = require('../utils/prompt-utils');
16
17
 
17
18
  /**
18
19
  * Helper function to create an organization
@@ -108,7 +109,9 @@ async function handleSpread() {
108
109
 
109
110
  if (!continueAnyway) {
110
111
  console.log(chalk.gray('\n Setup cancelled.\n'));
111
- process.exit(0);
112
+ const action = await showMainMenu({ isLoggedIn: true, isInProject: true });
113
+ await executeMenuAction(action);
114
+ return;
112
115
  }
113
116
  }
114
117
 
@@ -284,7 +287,9 @@ async function handleSpread() {
284
287
  console.log(chalk.cyan('\n To continue, either:'));
285
288
  console.log(chalk.gray(' • Delete an existing key at https://app.l4yercak3.com?openWindow=integrations&panel=api-keys'));
286
289
  console.log(chalk.gray(' • Upgrade your plan at https://app.l4yercak3.com?openWindow=store\n'));
287
- process.exit(0);
290
+ const action = await showMainMenu({ isLoggedIn: true, isInProject: true });
291
+ await executeMenuAction(action);
292
+ return;
288
293
  } else if (existingKeys && existingKeys.keys && existingKeys.keys.length > 0) {
289
294
  // Has existing keys on backend - offer to reuse or generate new
290
295
  const activeKeys = existingKeys.keys.filter(k => k.status === 'active');
@@ -350,7 +355,9 @@ async function handleSpread() {
350
355
  console.log(chalk.cyan('\n To continue, either:'));
351
356
  console.log(chalk.gray(' • Delete an existing key at https://app.l4yercak3.com?openWindow=integrations&panel=api-keys'));
352
357
  console.log(chalk.gray(' • Upgrade your plan at https://app.l4yercak3.com?openWindow=store\n'));
353
- process.exit(0);
358
+ const action = await showMainMenu({ isLoggedIn: true, isInProject: true });
359
+ await executeMenuAction(action);
360
+ return;
354
361
  } else if (error.code === 'API_KEY_ALREADY_LINKED') {
355
362
  console.log(chalk.yellow(`\n ⚠️ ${error.message}`));
356
363
  if (error.suggestion) {
@@ -372,7 +379,9 @@ async function handleSpread() {
372
379
  if (generateNew) {
373
380
  apiKey = await generateNewApiKey(organizationId);
374
381
  } else {
375
- process.exit(0);
382
+ const action = await showMainMenu({ isLoggedIn: true, isInProject: true });
383
+ await executeMenuAction(action);
384
+ return;
376
385
  }
377
386
  } else if (error.code === 'SESSION_EXPIRED' || error.code === 'INVALID_SESSION') {
378
387
  console.log(chalk.red(`\n ❌ Session expired. Please run "l4yercak3 login" again.\n`));
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Prompt Utilities
3
+ * Shared prompt helpers for consistent CLI UX
4
+ * Auto-generated by @l4yercak3/cli
5
+ */
6
+
7
+ const inquirer = require('inquirer');
8
+ const chalk = require('chalk');
9
+
10
+ /**
11
+ * Show a menu with options and handle selection
12
+ * Always includes an Exit option at the end
13
+ *
14
+ * @param {Object} options - Menu configuration
15
+ * @param {string} options.message - Menu header message
16
+ * @param {Array<{name: string, value: string}>} options.choices - Menu choices
17
+ * @returns {Promise<string>} The selected action value
18
+ */
19
+ async function showActionMenu(options) {
20
+ const { message = 'What would you like to do?', choices = [] } = options;
21
+
22
+ // Always include exit option at the end
23
+ const menuChoices = [
24
+ ...choices,
25
+ new inquirer.Separator(),
26
+ { name: 'Exit', value: 'exit' },
27
+ ];
28
+
29
+ const { action } = await inquirer.prompt([
30
+ {
31
+ type: 'list',
32
+ name: 'action',
33
+ message,
34
+ choices: menuChoices,
35
+ },
36
+ ]);
37
+
38
+ // Handle exit
39
+ if (action === 'exit') {
40
+ console.log(chalk.gray('\n Goodbye!\n'));
41
+ process.exit(0);
42
+ }
43
+
44
+ return action;
45
+ }
46
+
47
+ /**
48
+ * Get the full list of available CLI commands as menu choices
49
+ * @param {Object} context - Context for filtering options
50
+ * @param {boolean} context.isLoggedIn - Whether user is logged in
51
+ * @param {boolean} context.isInProject - Whether CLI is running in a project directory
52
+ * @param {boolean} context.hasExistingConfig - Whether project already has L4YERCAK3 config
53
+ */
54
+ function getCommandChoices(context = {}) {
55
+ const { isLoggedIn = true, isInProject = false, hasExistingConfig = false } = context;
56
+
57
+ const choices = [];
58
+
59
+ // Project setup commands (when in a project)
60
+ if (isInProject) {
61
+ if (hasExistingConfig) {
62
+ choices.push({
63
+ name: 'Reconfigure project l4yercak3 spread',
64
+ value: 'spread',
65
+ });
66
+ } else {
67
+ choices.push({
68
+ name: 'Set up L4YERCAK3 l4yercak3 spread',
69
+ value: 'spread',
70
+ });
71
+ }
72
+ } else {
73
+ choices.push({
74
+ name: 'Initialize project l4yercak3 spread',
75
+ value: 'spread',
76
+ });
77
+ }
78
+
79
+ // Always available commands (when logged in)
80
+ if (isLoggedIn) {
81
+ choices.push(
82
+ { name: 'View account status l4yercak3 status', value: 'status' },
83
+ { name: 'Manage API keys l4yercak3 api-keys', value: 'api-keys' },
84
+ { name: 'Set up MCP server l4yercak3 mcp-setup', value: 'mcp-setup' },
85
+ { name: 'Check for updates l4yercak3 upgrade', value: 'upgrade' },
86
+ new inquirer.Separator(),
87
+ { name: 'Log out l4yercak3 logout', value: 'logout' },
88
+ );
89
+ } else {
90
+ choices.push(
91
+ { name: 'Log in l4yercak3 login', value: 'login' },
92
+ { name: 'Check for updates l4yercak3 upgrade', value: 'upgrade' },
93
+ );
94
+ }
95
+
96
+ return choices;
97
+ }
98
+
99
+ /**
100
+ * Show main menu with all available commands
101
+ * @param {Object} context - Context for menu options
102
+ * @param {boolean} context.isLoggedIn - Whether user is logged in
103
+ * @param {boolean} context.isInProject - Whether CLI is running in a project directory
104
+ * @param {boolean} context.hasExistingConfig - Whether project already has L4YERCAK3 config
105
+ * @returns {Promise<string>} The selected action value
106
+ */
107
+ async function showMainMenu(context = {}) {
108
+ const choices = getCommandChoices(context);
109
+
110
+ return await showActionMenu({
111
+ message: 'What would you like to do?',
112
+ choices,
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Show post-login menu with common actions
118
+ * @param {Object} context - Context for menu options
119
+ * @param {boolean} context.isInProject - Whether CLI is running in a project directory
120
+ * @param {boolean} context.hasExistingConfig - Whether project already has L4YERCAK3 config
121
+ */
122
+ async function showPostLoginMenu(context = {}) {
123
+ return await showMainMenu({ ...context, isLoggedIn: true });
124
+ }
125
+
126
+ /**
127
+ * Execute a menu action by calling the appropriate command handler
128
+ * @param {string} action - The action to execute
129
+ * @returns {Promise<void>}
130
+ */
131
+ async function executeMenuAction(action) {
132
+ console.log('');
133
+
134
+ switch (action) {
135
+ case 'spread': {
136
+ const { handler } = require('../commands/spread');
137
+ await handler();
138
+ break;
139
+ }
140
+ case 'status': {
141
+ const { handler } = require('../commands/status');
142
+ await handler();
143
+ break;
144
+ }
145
+ case 'api-keys': {
146
+ const { handler } = require('../commands/api-keys');
147
+ await handler();
148
+ break;
149
+ }
150
+ case 'logout': {
151
+ const { handler } = require('../commands/logout');
152
+ await handler();
153
+ break;
154
+ }
155
+ case 'login': {
156
+ const { handler } = require('../commands/login');
157
+ await handler();
158
+ break;
159
+ }
160
+ case 'mcp-setup': {
161
+ const { handler } = require('../commands/mcp-setup');
162
+ await handler();
163
+ break;
164
+ }
165
+ case 'upgrade': {
166
+ const { handler } = require('../commands/upgrade');
167
+ await handler();
168
+ break;
169
+ }
170
+ default:
171
+ // Unknown action, just return
172
+ break;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Show menu and execute selected action
178
+ * Convenience function that combines showMainMenu + executeMenuAction
179
+ * @param {Object} context - Context for menu options
180
+ * @returns {Promise<string>} The selected action value
181
+ */
182
+ async function showMenuAndExecute(context = {}) {
183
+ const action = await showMainMenu(context);
184
+ await executeMenuAction(action);
185
+ return action;
186
+ }
187
+
188
+ module.exports = {
189
+ showActionMenu,
190
+ showMainMenu,
191
+ showPostLoginMenu,
192
+ getCommandChoices,
193
+ executeMenuAction,
194
+ showMenuAndExecute,
195
+ };