@velaro/cli 1.4.78 → 1.4.80
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/lib/commands/article.js +45 -0
- package/lib/commands/entitlement.js +15 -1
- package/lib/commands/support.js +20 -1
- package/package.json +1 -1
package/lib/commands/article.js
CHANGED
|
@@ -106,6 +106,48 @@ const topicsCommand = {
|
|
|
106
106
|
}),
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
const categoriesCommand = {
|
|
110
|
+
command: 'categories',
|
|
111
|
+
describe: 'List KB categories (topics hang under a category)',
|
|
112
|
+
handler: runCommand(async () => {
|
|
113
|
+
const data = await adminRequest('GET', '/api/kb/categories');
|
|
114
|
+
const cats = data?.categories ?? [];
|
|
115
|
+
if (!cats.length) { console.log('No categories found.'); return; }
|
|
116
|
+
for (const c of cats) console.log(` [${c.id}] ${c.name} (priority ${c.displayPriority})`);
|
|
117
|
+
}),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const categoryCreateCommand = {
|
|
121
|
+
command: 'category-create',
|
|
122
|
+
describe: 'Create a KB category (seed the v20 topic tree before pushing articles)',
|
|
123
|
+
builder: (y) =>
|
|
124
|
+
y
|
|
125
|
+
.option('name', { type: 'string', demandOption: true, describe: 'Category name' })
|
|
126
|
+
.option('priority', { type: 'number', default: 0, describe: 'Display priority (lower sorts first)' })
|
|
127
|
+
.option('icon', { type: 'string', describe: 'Optional icon name' }),
|
|
128
|
+
handler: runCommand(async (argv) => {
|
|
129
|
+
const c = await adminRequest('POST', '/api/kb/categories', { name: argv.name, displayPriority: argv.priority, icon: argv.icon });
|
|
130
|
+
console.log(`Category created: [${c.id}] ${c.name}`);
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const topicCreateCommand = {
|
|
135
|
+
command: 'topic-create',
|
|
136
|
+
describe: 'Create a KB topic under a category and print its ID for `article push --topic-id`',
|
|
137
|
+
builder: (y) =>
|
|
138
|
+
y
|
|
139
|
+
.option('name', { type: 'string', demandOption: true, describe: 'Topic name' })
|
|
140
|
+
.option('slug', { type: 'string', demandOption: true, describe: 'URL slug' })
|
|
141
|
+
.option('category-id', { type: 'string', describe: 'Category ID from `kb article categories`' })
|
|
142
|
+
.option('priority', { type: 'number', default: 0, describe: 'Display priority (lower sorts first)' }),
|
|
143
|
+
handler: runCommand(async (argv) => {
|
|
144
|
+
const t = await adminRequest('POST', '/api/kb/topics', {
|
|
145
|
+
name: argv.name, slug: argv.slug, categoryId: argv.categoryId, displayPriority: argv.priority,
|
|
146
|
+
});
|
|
147
|
+
console.log(`Topic created: [${t.id}] ${t.name} (slug ${t.slug})`);
|
|
148
|
+
}),
|
|
149
|
+
};
|
|
150
|
+
|
|
109
151
|
// ── push ──────────────────────────────────────────────────────────────────────
|
|
110
152
|
|
|
111
153
|
const pushCommand = {
|
|
@@ -500,6 +542,9 @@ export const articleCommand = {
|
|
|
500
542
|
.command(listCommand)
|
|
501
543
|
.command(getCommand)
|
|
502
544
|
.command(topicsCommand)
|
|
545
|
+
.command(categoriesCommand)
|
|
546
|
+
.command(categoryCreateCommand)
|
|
547
|
+
.command(topicCreateCommand)
|
|
503
548
|
.command(pushCommand)
|
|
504
549
|
.command(previewCommand)
|
|
505
550
|
.command(deleteCommand)
|
|
@@ -96,6 +96,18 @@ async function backfill() {
|
|
|
96
96
|
console.log(`✅ Backfill: ${result.inserted} inserted, ${result.skipped} already existed, ${result.unknownPlan} skipped (unknown plan).`);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
async function backfillSapTiers(args) {
|
|
100
|
+
const result = await request('POST', `Entitlements/admin/backfill-sap-tiers?dryRun=${args.apply ? 'false' : 'true'}`);
|
|
101
|
+
if (result.error) { console.error(`❌ ${result.error}`); process.exit(1); }
|
|
102
|
+
console.log(`${args.apply ? '✅ APPLIED' : '🔍 DRY RUN'}: ${JSON.stringify(result, null, 2)}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function backfillLegacyWriteTiers(args) {
|
|
106
|
+
const result = await request('POST', `Entitlements/admin/backfill-legacy-write-tiers?dryRun=${args.apply ? 'false' : 'true'}`);
|
|
107
|
+
if (result.error) { console.error(`❌ ${result.error}`); process.exit(1); }
|
|
108
|
+
console.log(`${args.apply ? '✅ APPLIED' : '🔍 DRY RUN'}: ${JSON.stringify(result, null, 2)}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
99
111
|
async function reconcile(args) {
|
|
100
112
|
if (!args.site) {
|
|
101
113
|
console.error('Usage: velaro entitlement reconcile --site 1032');
|
|
@@ -175,6 +187,8 @@ export function entitlementCommand(yargs) {
|
|
|
175
187
|
, a => removeOverride(a))
|
|
176
188
|
.command('seed', 'Seed the EntitlementFeature registry (idempotent, superadmin only)', () => {}, () => seed())
|
|
177
189
|
.command('seed-plans', 'Seed PlanEntitlement rows from live PackageVersions in messaging DB (idempotent, superadmin only)', () => {}, () => seedPlans())
|
|
190
|
+
.command('backfill-sap-tiers', 'Grant the four SAP add-on packages to existing SAP sites (dry run unless --apply; superadmin only)', (y) => y.option('apply', { type: 'boolean', default: false, describe: 'Write the grants (default is a dry run)' }), (a) => backfillSapTiers(a))
|
|
191
|
+
.command('backfill-legacy-write-tiers', 'Grant EnableServiceNowWrite/AccelaWrite/QuickBooksWrite to existing sites after the OR-gate sweep (dry run unless --apply; superadmin only)', (y) => y.option('apply', { type: 'boolean', default: false, describe: 'Write the grants (default is a dry run)' }), (a) => backfillLegacyWriteTiers(a))
|
|
178
192
|
.command('backfill', 'Backfill SiteSubscription rows from active Subscription rows in messaging DB (idempotent, superadmin only)', () => {}, () => backfill())
|
|
179
193
|
.command('reconcile', 'Diff Subscription.cs vs Entitlements API for a site — zero deltas = ready for cutover', y => y
|
|
180
194
|
.option('site', { type: 'number', demandOption: true, desc: 'Site ID' })
|
|
@@ -195,5 +209,5 @@ export function entitlementCommand(yargs) {
|
|
|
195
209
|
.option('key', { type: 'string', demandOption: true, desc: 'Feature key, e.g. EnableIvr' })
|
|
196
210
|
.option('rollback', { type: 'boolean', desc: 'Pass to roll back this flag to Subscription.cs (default: go live)' })
|
|
197
211
|
, a => setCutover(a))
|
|
198
|
-
.demandCommand(1, 'Specify a subcommand: get | list-features | set-override | remove-override | seed | seed-plans | backfill | reconcile | comp | set-lock | list-cutover | set-cutover');
|
|
212
|
+
.demandCommand(1, 'Specify a subcommand: get | list-features | set-override | remove-override | seed | seed-plans | backfill | backfill-sap-tiers | backfill-legacy-write-tiers | reconcile | comp | set-lock | list-cutover | set-cutover');
|
|
199
213
|
}
|
package/lib/commands/support.js
CHANGED
|
@@ -12,6 +12,20 @@ async function toggleFlag(args) {
|
|
|
12
12
|
console.log(`✅ Site ${args.site}: ${result.flag} ${result.oldValue} → ${result.newValue}`);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
async function setLimit(args) {
|
|
16
|
+
const n = Number(args.value);
|
|
17
|
+
if (!args.site || !args.key || !Number.isInteger(n) || n < 0) {
|
|
18
|
+
console.error('Usage: velaro support set-limit --site 1032 --key maxBotTurnsPerMonth --value 10000');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const result = await request('POST', `SupportTools/sites/${args.site}/subscription/bulk-flags`, { flags: { [args.key]: n } });
|
|
22
|
+
console.log(`Site ${args.site}: applied ${(result.applied || []).join(', ') || '(none)'}`);
|
|
23
|
+
if ((result.skipped || []).length) {
|
|
24
|
+
console.error(`Skipped: ${result.skipped.join(', ')}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
15
29
|
async function scraperCreateJob(args) {
|
|
16
30
|
if (!args.site || !args.urls) {
|
|
17
31
|
console.error('Usage: velaro support scraper-create-job --site 1032 --urls "https://example.com" [--maxPages 30] [--crawlDepth 2] [--name "job name"]');
|
|
@@ -197,6 +211,11 @@ export function supportCommand(yargs) {
|
|
|
197
211
|
.option('flag', { type: 'string', demandOption: true, desc: 'Flag name, e.g. EnableScraperBotIndexing (must be on SupportToolsController.AllowedFeatureFlags)' })
|
|
198
212
|
.option('enabled', { type: 'string', demandOption: true, desc: 'true or false' })
|
|
199
213
|
, a => toggleFlag(a))
|
|
214
|
+
.command('set-limit', 'Set a numeric Subscription cap on a site, e.g. maxBotTurnsPerMonth (superadmin only; 0 = plan value, never unlimited)', y => y
|
|
215
|
+
.option('site', { type: 'number', demandOption: true, desc: 'Site ID' })
|
|
216
|
+
.option('key', { type: 'string', demandOption: true, desc: 'Cap name, e.g. maxBotTurnsPerMonth' })
|
|
217
|
+
.option('value', { type: 'number', demandOption: true, desc: 'Whole number >= 0' })
|
|
218
|
+
, a => setLimit(a))
|
|
200
219
|
.command('scraper-create-job', 'Trigger a scraper job on behalf of any site (superadmin only — no need to be logged in as that site\'s own user)', y => y
|
|
201
220
|
.option('site', { type: 'number', demandOption: true, desc: 'Target site ID' })
|
|
202
221
|
.option('urls', { type: 'string', demandOption: true, desc: 'Comma-separated URLs to crawl' })
|
|
@@ -211,5 +230,5 @@ export function supportCommand(yargs) {
|
|
|
211
230
|
.option('channel', { type: 'string', desc: 'Conversation source, e.g. Web, TwilioSms (default Web)' })
|
|
212
231
|
.option('overrideIndexes', { type: 'string', desc: 'Comma-separated index names to override the config\'s own IndexName for this query' })
|
|
213
232
|
, a => chatQuery(a))
|
|
214
|
-
.demandCommand(1, 'Specify a subcommand: deployments | impersonate | agent-lookup | add-site-user | toggle-flag | scraper-create-job | chat-query | send-email | tour-insights | connection-timeline | connection-evidence');
|
|
233
|
+
.demandCommand(1, 'Specify a subcommand: deployments | impersonate | agent-lookup | add-site-user | toggle-flag | set-limit | scraper-create-job | chat-query | send-email | tour-insights | connection-timeline | connection-evidence');
|
|
215
234
|
}
|
package/package.json
CHANGED