@l4yercak3/cli 1.2.14 → 1.2.16
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/.claude/settings.local.json +3 -1
- package/package.json +1 -1
- package/src/commands/login.js +7 -2
- package/src/commands/spread.js +13 -4
- package/src/mcp/registry/domains/applications.js +4 -4
- package/src/mcp/registry/domains/crm.js +11 -11
- package/src/mcp/registry/domains/events.js +12 -12
- package/src/mcp/registry/domains/forms.js +12 -12
- package/src/utils/prompt-utils.js +195 -0
package/package.json
CHANGED
package/src/commands/login.js
CHANGED
|
@@ -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(
|
|
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(
|
|
282
|
+
console.log('');
|
|
283
|
+
const action = await showPostLoginMenu({ isInProject: true, hasExistingConfig: false });
|
|
284
|
+
await executeMenuAction(action);
|
|
280
285
|
return;
|
|
281
286
|
}
|
|
282
287
|
}
|
package/src/commands/spread.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`));
|
|
@@ -73,7 +73,7 @@ Returns an API key for the application to use.`,
|
|
|
73
73
|
required: ['name', 'features'],
|
|
74
74
|
},
|
|
75
75
|
requiresAuth: true,
|
|
76
|
-
requiredPermissions: ['
|
|
76
|
+
requiredPermissions: ['applications:write'],
|
|
77
77
|
handler: async (params, authContext) => {
|
|
78
78
|
// Generate project path hash for tracking
|
|
79
79
|
const projectPathHash = params.projectPath
|
|
@@ -293,7 +293,7 @@ Returns an API key for the application to use.`,
|
|
|
293
293
|
required: ['applicationId'],
|
|
294
294
|
},
|
|
295
295
|
requiresAuth: true,
|
|
296
|
-
requiredPermissions: ['
|
|
296
|
+
requiredPermissions: ['applications:write'],
|
|
297
297
|
handler: async (params, authContext) => {
|
|
298
298
|
const { applicationId, ...updates } = params;
|
|
299
299
|
|
|
@@ -339,7 +339,7 @@ Triggers a sync based on configured model mappings.`,
|
|
|
339
339
|
required: ['applicationId'],
|
|
340
340
|
},
|
|
341
341
|
requiresAuth: true,
|
|
342
|
-
requiredPermissions: ['
|
|
342
|
+
requiredPermissions: ['applications:write'],
|
|
343
343
|
handler: async (params, authContext) => {
|
|
344
344
|
const response = await backendClient.syncApplication(params.applicationId, {
|
|
345
345
|
direction: params.direction || 'bidirectional',
|
|
@@ -403,7 +403,7 @@ Model mappings define how local models sync with L4YERCAK3 types.`,
|
|
|
403
403
|
required: ['applicationId', 'localModel', 'layerCakeType'],
|
|
404
404
|
},
|
|
405
405
|
requiresAuth: true,
|
|
406
|
-
requiredPermissions: ['
|
|
406
|
+
requiredPermissions: ['applications:write'],
|
|
407
407
|
handler: async (params, authContext) => {
|
|
408
408
|
// Get current application
|
|
409
409
|
const appResponse = await backendClient.getApplication(params.applicationId);
|
|
@@ -49,7 +49,7 @@ Returns contacts with their details including name, email, phone, and custom fie
|
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
requiresAuth: true,
|
|
52
|
-
requiredPermissions: ['
|
|
52
|
+
requiredPermissions: ['contacts:read'],
|
|
53
53
|
handler: async (params, authContext) => {
|
|
54
54
|
// Build query params
|
|
55
55
|
const queryParams = new URLSearchParams();
|
|
@@ -130,7 +130,7 @@ Use this to add a customer, lead, or prospect to the user's CRM.`,
|
|
|
130
130
|
required: ['firstName', 'lastName', 'email'],
|
|
131
131
|
},
|
|
132
132
|
requiresAuth: true,
|
|
133
|
-
requiredPermissions: ['
|
|
133
|
+
requiredPermissions: ['contacts:write'],
|
|
134
134
|
handler: async (params, authContext) => {
|
|
135
135
|
const response = await backendClient.request('POST', '/api/v1/crm/contacts', {
|
|
136
136
|
organizationId: authContext.organizationId,
|
|
@@ -177,7 +177,7 @@ Use this to retrieve full details including activities and notes.`,
|
|
|
177
177
|
required: ['contactId'],
|
|
178
178
|
},
|
|
179
179
|
requiresAuth: true,
|
|
180
|
-
requiredPermissions: ['
|
|
180
|
+
requiredPermissions: ['contacts:read'],
|
|
181
181
|
handler: async (params, authContext) => {
|
|
182
182
|
const queryParams = new URLSearchParams();
|
|
183
183
|
if (params.includeActivities) queryParams.set('includeActivities', 'true');
|
|
@@ -242,7 +242,7 @@ Use this to modify contact information.`,
|
|
|
242
242
|
required: ['contactId'],
|
|
243
243
|
},
|
|
244
244
|
requiresAuth: true,
|
|
245
|
-
requiredPermissions: ['
|
|
245
|
+
requiredPermissions: ['contacts:write'],
|
|
246
246
|
handler: async (params, authContext) => {
|
|
247
247
|
const { contactId, ...updates } = params;
|
|
248
248
|
|
|
@@ -273,7 +273,7 @@ This performs a soft delete - the contact can be restored.`,
|
|
|
273
273
|
required: ['contactId'],
|
|
274
274
|
},
|
|
275
275
|
requiresAuth: true,
|
|
276
|
-
requiredPermissions: ['
|
|
276
|
+
requiredPermissions: ['contacts:write'],
|
|
277
277
|
handler: async (params, authContext) => {
|
|
278
278
|
await backendClient.request('DELETE', `/api/v1/crm/contacts/${params.contactId}`);
|
|
279
279
|
|
|
@@ -311,7 +311,7 @@ These are customer companies, not L4YERCAK3 platform organizations.`,
|
|
|
311
311
|
},
|
|
312
312
|
},
|
|
313
313
|
requiresAuth: true,
|
|
314
|
-
requiredPermissions: ['
|
|
314
|
+
requiredPermissions: ['contacts:read'],
|
|
315
315
|
handler: async (params, authContext) => {
|
|
316
316
|
const queryParams = new URLSearchParams();
|
|
317
317
|
queryParams.set('organizationId', authContext.organizationId);
|
|
@@ -386,7 +386,7 @@ Use this to track a customer company in the CRM.`,
|
|
|
386
386
|
required: ['name'],
|
|
387
387
|
},
|
|
388
388
|
requiresAuth: true,
|
|
389
|
-
requiredPermissions: ['
|
|
389
|
+
requiredPermissions: ['contacts:write'],
|
|
390
390
|
handler: async (params, authContext) => {
|
|
391
391
|
const response = await backendClient.request('POST', '/api/v1/crm/organizations', {
|
|
392
392
|
organizationId: authContext.organizationId,
|
|
@@ -426,7 +426,7 @@ Use this to track a customer company in the CRM.`,
|
|
|
426
426
|
required: ['crmOrganizationId'],
|
|
427
427
|
},
|
|
428
428
|
requiresAuth: true,
|
|
429
|
-
requiredPermissions: ['
|
|
429
|
+
requiredPermissions: ['contacts:read'],
|
|
430
430
|
handler: async (params, authContext) => {
|
|
431
431
|
const queryParams = new URLSearchParams();
|
|
432
432
|
if (params.includeContacts) queryParams.set('includeContacts', 'true');
|
|
@@ -488,7 +488,7 @@ Use this to associate a contact with a company they work for.`,
|
|
|
488
488
|
required: ['contactId', 'crmOrganizationId'],
|
|
489
489
|
},
|
|
490
490
|
requiresAuth: true,
|
|
491
|
-
requiredPermissions: ['
|
|
491
|
+
requiredPermissions: ['contacts:write'],
|
|
492
492
|
handler: async (params, authContext) => {
|
|
493
493
|
await backendClient.request('POST', '/api/v1/crm/contact-organization-links', {
|
|
494
494
|
contactId: params.contactId,
|
|
@@ -527,7 +527,7 @@ Use this to record information or interactions with a contact.`,
|
|
|
527
527
|
required: ['contactId', 'content'],
|
|
528
528
|
},
|
|
529
529
|
requiresAuth: true,
|
|
530
|
-
requiredPermissions: ['
|
|
530
|
+
requiredPermissions: ['contacts:write'],
|
|
531
531
|
handler: async (params, authContext) => {
|
|
532
532
|
await backendClient.request('POST', `/api/v1/crm/contacts/${params.contactId}/notes`, {
|
|
533
533
|
content: params.content,
|
|
@@ -572,7 +572,7 @@ Use this to track interactions with contacts.`,
|
|
|
572
572
|
required: ['contactId', 'type', 'summary'],
|
|
573
573
|
},
|
|
574
574
|
requiresAuth: true,
|
|
575
|
-
requiredPermissions: ['
|
|
575
|
+
requiredPermissions: ['contacts:write'],
|
|
576
576
|
handler: async (params, authContext) => {
|
|
577
577
|
await backendClient.request('POST', `/api/v1/crm/contacts/${params.contactId}/activities`, {
|
|
578
578
|
type: params.type,
|
|
@@ -51,7 +51,7 @@ Returns events with their basic details, status, and dates.`,
|
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
53
|
requiresAuth: true,
|
|
54
|
-
requiredPermissions: ['
|
|
54
|
+
requiredPermissions: ['events:read'],
|
|
55
55
|
handler: async (params, authContext) => {
|
|
56
56
|
const queryParams = new URLSearchParams();
|
|
57
57
|
queryParams.set('organizationId', authContext.organizationId);
|
|
@@ -128,7 +128,7 @@ Events start in 'draft' status and can be published when ready.`,
|
|
|
128
128
|
required: ['name', 'startDate', 'endDate', 'location'],
|
|
129
129
|
},
|
|
130
130
|
requiresAuth: true,
|
|
131
|
-
requiredPermissions: ['
|
|
131
|
+
requiredPermissions: ['events:write'],
|
|
132
132
|
handler: async (params, authContext) => {
|
|
133
133
|
// Convert ISO dates to timestamps
|
|
134
134
|
const startDate = new Date(params.startDate).getTime();
|
|
@@ -184,7 +184,7 @@ Includes agenda, products, and optionally sponsors.`,
|
|
|
184
184
|
required: ['eventId'],
|
|
185
185
|
},
|
|
186
186
|
requiresAuth: true,
|
|
187
|
-
requiredPermissions: ['
|
|
187
|
+
requiredPermissions: ['events:read'],
|
|
188
188
|
handler: async (params, authContext) => {
|
|
189
189
|
const queryParams = new URLSearchParams();
|
|
190
190
|
if (params.includeProducts !== false) queryParams.set('includeProducts', 'true');
|
|
@@ -245,7 +245,7 @@ Can update name, dates, location, and other properties.`,
|
|
|
245
245
|
required: ['eventId'],
|
|
246
246
|
},
|
|
247
247
|
requiresAuth: true,
|
|
248
|
-
requiredPermissions: ['
|
|
248
|
+
requiredPermissions: ['events:write'],
|
|
249
249
|
handler: async (params, authContext) => {
|
|
250
250
|
const { eventId, startDate, endDate, ...updates } = params;
|
|
251
251
|
|
|
@@ -278,7 +278,7 @@ Changes status from 'draft' to 'published'.`,
|
|
|
278
278
|
required: ['eventId'],
|
|
279
279
|
},
|
|
280
280
|
requiresAuth: true,
|
|
281
|
-
requiredPermissions: ['
|
|
281
|
+
requiredPermissions: ['events:write'],
|
|
282
282
|
handler: async (params, authContext) => {
|
|
283
283
|
await backendClient.request('POST', `/api/v1/events/${params.eventId}/publish`);
|
|
284
284
|
|
|
@@ -306,7 +306,7 @@ Sets status to 'cancelled'. This is a soft delete.`,
|
|
|
306
306
|
required: ['eventId'],
|
|
307
307
|
},
|
|
308
308
|
requiresAuth: true,
|
|
309
|
-
requiredPermissions: ['
|
|
309
|
+
requiredPermissions: ['events:write'],
|
|
310
310
|
handler: async (params, authContext) => {
|
|
311
311
|
await backendClient.request('POST', `/api/v1/events/${params.eventId}/cancel`);
|
|
312
312
|
|
|
@@ -371,7 +371,7 @@ Replace the entire agenda with a new list of agenda items.`,
|
|
|
371
371
|
required: ['eventId', 'agenda'],
|
|
372
372
|
},
|
|
373
373
|
requiresAuth: true,
|
|
374
|
-
requiredPermissions: ['
|
|
374
|
+
requiredPermissions: ['events:write'],
|
|
375
375
|
handler: async (params, authContext) => {
|
|
376
376
|
await backendClient.request('PATCH', `/api/v1/events/${params.eventId}/agenda`, {
|
|
377
377
|
agenda: params.agenda,
|
|
@@ -403,7 +403,7 @@ Replace the entire agenda with a new list of agenda items.`,
|
|
|
403
403
|
required: ['eventId'],
|
|
404
404
|
},
|
|
405
405
|
requiresAuth: true,
|
|
406
|
-
requiredPermissions: ['
|
|
406
|
+
requiredPermissions: ['events:read'],
|
|
407
407
|
handler: async (params, authContext) => {
|
|
408
408
|
const response = await backendClient.request(
|
|
409
409
|
'GET',
|
|
@@ -470,7 +470,7 @@ Products can be tickets, merchandise, or add-ons.`,
|
|
|
470
470
|
required: ['eventId', 'name', 'priceInCents'],
|
|
471
471
|
},
|
|
472
472
|
requiresAuth: true,
|
|
473
|
-
requiredPermissions: ['
|
|
473
|
+
requiredPermissions: ['events:write'],
|
|
474
474
|
handler: async (params, authContext) => {
|
|
475
475
|
const response = await backendClient.request('POST', '/api/v1/products', {
|
|
476
476
|
organizationId: authContext.organizationId,
|
|
@@ -519,7 +519,7 @@ Returns people who have purchased tickets.`,
|
|
|
519
519
|
required: ['eventId'],
|
|
520
520
|
},
|
|
521
521
|
requiresAuth: true,
|
|
522
|
-
requiredPermissions: ['
|
|
522
|
+
requiredPermissions: ['events:read'],
|
|
523
523
|
handler: async (params, authContext) => {
|
|
524
524
|
const queryParams = new URLSearchParams();
|
|
525
525
|
if (params.status) queryParams.set('status', params.status);
|
|
@@ -571,7 +571,7 @@ Sponsors are CRM organizations linked to the event.`,
|
|
|
571
571
|
required: ['eventId'],
|
|
572
572
|
},
|
|
573
573
|
requiresAuth: true,
|
|
574
|
-
requiredPermissions: ['
|
|
574
|
+
requiredPermissions: ['events:read'],
|
|
575
575
|
handler: async (params, authContext) => {
|
|
576
576
|
const queryParams = new URLSearchParams();
|
|
577
577
|
if (params.sponsorLevel) queryParams.set('sponsorLevel', params.sponsorLevel);
|
|
@@ -629,7 +629,7 @@ Sponsors are CRM organizations linked to the event.`,
|
|
|
629
629
|
required: ['eventId', 'crmOrganizationId'],
|
|
630
630
|
},
|
|
631
631
|
requiresAuth: true,
|
|
632
|
-
requiredPermissions: ['
|
|
632
|
+
requiredPermissions: ['events:write'],
|
|
633
633
|
handler: async (params, authContext) => {
|
|
634
634
|
await backendClient.request('POST', `/api/v1/events/${params.eventId}/sponsors`, {
|
|
635
635
|
crmOrganizationId: params.crmOrganizationId,
|
|
@@ -43,7 +43,7 @@ Returns forms with their type, status, and submission counts.`,
|
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
requiresAuth: true,
|
|
46
|
-
requiredPermissions: ['
|
|
46
|
+
requiredPermissions: ['forms:read'],
|
|
47
47
|
handler: async (params, authContext) => {
|
|
48
48
|
const queryParams = new URLSearchParams();
|
|
49
49
|
queryParams.set('organizationId', authContext.organizationId);
|
|
@@ -197,7 +197,7 @@ Start with basic info, then add fields.`,
|
|
|
197
197
|
required: ['name'],
|
|
198
198
|
},
|
|
199
199
|
requiresAuth: true,
|
|
200
|
-
requiredPermissions: ['
|
|
200
|
+
requiredPermissions: ['forms:write'],
|
|
201
201
|
handler: async (params, authContext) => {
|
|
202
202
|
// Build form schema
|
|
203
203
|
const formSchema = {
|
|
@@ -259,7 +259,7 @@ Start with basic info, then add fields.`,
|
|
|
259
259
|
required: ['formId'],
|
|
260
260
|
},
|
|
261
261
|
requiresAuth: true,
|
|
262
|
-
requiredPermissions: ['
|
|
262
|
+
requiredPermissions: ['forms:read'],
|
|
263
263
|
handler: async (params, authContext) => {
|
|
264
264
|
const response = await backendClient.request('GET', `/api/v1/forms/${params.formId}`);
|
|
265
265
|
|
|
@@ -312,7 +312,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
312
312
|
required: ['formId'],
|
|
313
313
|
},
|
|
314
314
|
requiresAuth: true,
|
|
315
|
-
requiredPermissions: ['
|
|
315
|
+
requiredPermissions: ['forms:write'],
|
|
316
316
|
handler: async (params, authContext) => {
|
|
317
317
|
const { formId, ...updates } = params;
|
|
318
318
|
|
|
@@ -395,7 +395,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
395
395
|
required: ['formId', 'field'],
|
|
396
396
|
},
|
|
397
397
|
requiresAuth: true,
|
|
398
|
-
requiredPermissions: ['
|
|
398
|
+
requiredPermissions: ['forms:write'],
|
|
399
399
|
handler: async (params, authContext) => {
|
|
400
400
|
// Get current form to add field
|
|
401
401
|
const formResponse = await backendClient.request('GET', `/api/v1/forms/${params.formId}`);
|
|
@@ -439,7 +439,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
439
439
|
required: ['formId'],
|
|
440
440
|
},
|
|
441
441
|
requiresAuth: true,
|
|
442
|
-
requiredPermissions: ['
|
|
442
|
+
requiredPermissions: ['forms:write'],
|
|
443
443
|
handler: async (params, authContext) => {
|
|
444
444
|
await backendClient.request('POST', `/api/v1/forms/${params.formId}/publish`);
|
|
445
445
|
|
|
@@ -466,7 +466,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
466
466
|
required: ['formId'],
|
|
467
467
|
},
|
|
468
468
|
requiresAuth: true,
|
|
469
|
-
requiredPermissions: ['
|
|
469
|
+
requiredPermissions: ['forms:write'],
|
|
470
470
|
handler: async (params, authContext) => {
|
|
471
471
|
await backendClient.request('POST', `/api/v1/forms/${params.formId}/unpublish`);
|
|
472
472
|
|
|
@@ -493,7 +493,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
493
493
|
required: ['formId'],
|
|
494
494
|
},
|
|
495
495
|
requiresAuth: true,
|
|
496
|
-
requiredPermissions: ['
|
|
496
|
+
requiredPermissions: ['forms:write'],
|
|
497
497
|
handler: async (params, authContext) => {
|
|
498
498
|
await backendClient.request('DELETE', `/api/v1/forms/${params.formId}`);
|
|
499
499
|
|
|
@@ -518,7 +518,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
518
518
|
required: ['formId'],
|
|
519
519
|
},
|
|
520
520
|
requiresAuth: true,
|
|
521
|
-
requiredPermissions: ['
|
|
521
|
+
requiredPermissions: ['forms:write'],
|
|
522
522
|
handler: async (params, authContext) => {
|
|
523
523
|
const response = await backendClient.request(
|
|
524
524
|
'POST',
|
|
@@ -563,7 +563,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
563
563
|
required: ['formId'],
|
|
564
564
|
},
|
|
565
565
|
requiresAuth: true,
|
|
566
|
-
requiredPermissions: ['
|
|
566
|
+
requiredPermissions: ['forms:read'],
|
|
567
567
|
handler: async (params, authContext) => {
|
|
568
568
|
const queryParams = new URLSearchParams();
|
|
569
569
|
if (params.status) queryParams.set('status', params.status);
|
|
@@ -602,7 +602,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
602
602
|
required: ['responseId'],
|
|
603
603
|
},
|
|
604
604
|
requiresAuth: true,
|
|
605
|
-
requiredPermissions: ['
|
|
605
|
+
requiredPermissions: ['forms:read'],
|
|
606
606
|
handler: async (params, authContext) => {
|
|
607
607
|
const response = await backendClient.request(
|
|
608
608
|
'GET',
|
|
@@ -646,7 +646,7 @@ To update fields, use l4yercak3_forms_add_field or l4yercak3_forms_update_fields
|
|
|
646
646
|
required: ['formId'],
|
|
647
647
|
},
|
|
648
648
|
requiresAuth: true,
|
|
649
|
-
requiredPermissions: ['
|
|
649
|
+
requiredPermissions: ['forms:read'],
|
|
650
650
|
handler: async (params, authContext) => {
|
|
651
651
|
const format = params.format || 'json';
|
|
652
652
|
|
|
@@ -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
|
+
};
|