fix: add input validation and safe JSON parsing across 13 CLIs
Add missing parameter validation to prevent /path/undefined API calls: - dub: require --url for links create - google-search-console: require --sitemap-url for sitemaps submit - kit: validate IDs and emails for subscribers, forms, sequences, tags, broadcasts - mailchimp: validate IDs for lists get, campaigns get/create/send, members add, reports get - resend: validate --from/--to/--subject for send, audience/contact IDs for contacts - rewardful: validate IDs for affiliates get/update, commissions get, links create - semrush: require --domain/--phrase for all domain and keyword commands - sendgrid: validate --from/--to/--subject for send, campaign IDs, email for validate Wrap bare JSON.parse() calls in try/catch for user-provided JSON: - dub (--links), ga4 (--params), kit (--fields x4), mixpanel (--properties x2), onesignal (--filters), paddle (--scheduled-change, --items x2), resend (--emails, --variables x2), segment (--properties, --traits, --events), sendgrid (--template-data) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
51bdf2f6b3
commit
8eaff5e29f
13 changed files with 103 additions and 20 deletions
|
|
@ -58,6 +58,7 @@ async function main() {
|
|||
case 'links':
|
||||
switch (sub) {
|
||||
case 'create': {
|
||||
if (!args.url) { result = { error: '--url required' }; break }
|
||||
const body = {}
|
||||
if (args.url) body.url = args.url
|
||||
if (args.domain) body.domain = args.domain
|
||||
|
|
@ -95,7 +96,12 @@ async function main() {
|
|||
result = await api('DELETE', `/links/${args.id}`)
|
||||
break
|
||||
case 'bulk-create': {
|
||||
const links = JSON.parse(args.links || '[]')
|
||||
let links
|
||||
try {
|
||||
links = JSON.parse(args.links || '[]')
|
||||
} catch {
|
||||
result = { error: 'Invalid JSON in --links' }; break
|
||||
}
|
||||
result = await api('POST', '/links/bulk', links)
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,14 @@ async function main() {
|
|||
if (!args['api-secret']) { result = { error: '--api-secret required' }; break }
|
||||
if (!args['client-id']) { result = { error: '--client-id required' }; break }
|
||||
if (!args['event-name']) { result = { error: '--event-name required' }; break }
|
||||
const eventParams = args.params ? JSON.parse(args.params) : {}
|
||||
let eventParams = {}
|
||||
if (args.params) {
|
||||
try {
|
||||
eventParams = JSON.parse(args.params)
|
||||
} catch {
|
||||
result = { error: 'Invalid JSON in --params' }; break
|
||||
}
|
||||
}
|
||||
const body = {
|
||||
client_id: args['client-id'],
|
||||
events: [{
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ async function main() {
|
|||
result = await api('GET', `/webmasters/v3/sites/${encodedSiteUrl}/sitemaps`)
|
||||
break
|
||||
case 'submit': {
|
||||
if (!args['sitemap-url']) { result = { error: '--sitemap-url required' }; break }
|
||||
const sitemapUrl = encodeURIComponent(args['sitemap-url'])
|
||||
result = await api('PUT', `/webmasters/v3/sites/${encodedSiteUrl}/sitemaps/${sitemapUrl}`)
|
||||
if (!result.body && !result.error) {
|
||||
|
|
|
|||
|
|
@ -91,12 +91,16 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Subscriber ID required' }; break }
|
||||
result = await api('GET', `/subscribers/${rest[0]}`)
|
||||
break
|
||||
case 'update': {
|
||||
if (!rest[0]) { result = { error: 'Subscriber ID required' }; break }
|
||||
const body = {}
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args.fields) body.fields = JSON.parse(args.fields)
|
||||
if (args.fields) {
|
||||
try { body.fields = JSON.parse(args.fields) } catch { result = { error: 'Invalid JSON in --fields' }; break }
|
||||
}
|
||||
result = await api('PUT', `/subscribers/${rest[0]}`, body)
|
||||
break
|
||||
}
|
||||
|
|
@ -116,10 +120,14 @@ async function main() {
|
|||
result = await api('GET', '/forms', null, false)
|
||||
break
|
||||
case 'subscribe': {
|
||||
if (!rest[0]) { result = { error: 'Form ID required' }; break }
|
||||
if (!args.email) { result = { error: '--email required' }; break }
|
||||
const formId = rest[0]
|
||||
const body = { email: args.email }
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args.fields) body.fields = JSON.parse(args.fields)
|
||||
if (args.fields) {
|
||||
try { body.fields = JSON.parse(args.fields) } catch { result = { error: 'Invalid JSON in --fields' }; break }
|
||||
}
|
||||
result = await api('POST', `/forms/${formId}/subscribe`, body, false)
|
||||
break
|
||||
}
|
||||
|
|
@ -134,10 +142,14 @@ async function main() {
|
|||
result = await api('GET', '/sequences', null, false)
|
||||
break
|
||||
case 'subscribe': {
|
||||
if (!rest[0]) { result = { error: 'Sequence ID required' }; break }
|
||||
if (!args.email) { result = { error: '--email required' }; break }
|
||||
const sequenceId = rest[0]
|
||||
const body = { email: args.email }
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args.fields) body.fields = JSON.parse(args.fields)
|
||||
if (args.fields) {
|
||||
try { body.fields = JSON.parse(args.fields) } catch { result = { error: 'Invalid JSON in --fields' }; break }
|
||||
}
|
||||
result = await api('POST', `/sequences/${sequenceId}/subscribe`, body, false)
|
||||
break
|
||||
}
|
||||
|
|
@ -152,16 +164,22 @@ async function main() {
|
|||
result = await api('GET', '/tags', null, false)
|
||||
break
|
||||
case 'subscribe': {
|
||||
if (!rest[0]) { result = { error: 'Tag ID required' }; break }
|
||||
if (!args.email) { result = { error: '--email required' }; break }
|
||||
const tagId = rest[0]
|
||||
const body = { email: args.email }
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args.fields) body.fields = JSON.parse(args.fields)
|
||||
if (args.fields) {
|
||||
try { body.fields = JSON.parse(args.fields) } catch { result = { error: 'Invalid JSON in --fields' }; break }
|
||||
}
|
||||
result = await api('POST', `/tags/${tagId}/subscribe`, body, false)
|
||||
break
|
||||
}
|
||||
case 'remove': {
|
||||
if (!rest[0]) { result = { error: 'Tag ID required' }; break }
|
||||
const tagId = rest[0]
|
||||
const subscriberId = rest[1] || args['subscriber-id']
|
||||
if (!subscriberId) { result = { error: 'Subscriber ID required' }; break }
|
||||
result = await api('DELETE', `/subscribers/${subscriberId}/tags/${tagId}`)
|
||||
break
|
||||
}
|
||||
|
|
@ -178,6 +196,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'create': {
|
||||
if (!args.subject || !args.content) { result = { error: '--subject and --content required' }; break }
|
||||
const body = {
|
||||
subject: args.subject,
|
||||
content: args.content,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'List ID required' }; break }
|
||||
result = await api('GET', `/lists/${rest[0]}`)
|
||||
break
|
||||
default:
|
||||
|
|
@ -91,6 +92,8 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'add': {
|
||||
if (!rest[0]) { result = { error: 'List ID required' }; break }
|
||||
if (!args.email) { result = { error: '--email required' }; break }
|
||||
if (!args['list-id']) {
|
||||
result = { error: '--list-id is required for members add' }
|
||||
break
|
||||
|
|
@ -142,9 +145,11 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Campaign ID required' }; break }
|
||||
result = await api('GET', `/campaigns/${rest[0]}`)
|
||||
break
|
||||
case 'create': {
|
||||
if (!args['list-id']) { result = { error: '--list-id required' }; break }
|
||||
const body = {
|
||||
type: args.type || 'regular',
|
||||
recipients: {
|
||||
|
|
@ -160,6 +165,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'send':
|
||||
if (!rest[0]) { result = { error: 'Campaign ID required' }; break }
|
||||
result = await api('POST', `/campaigns/${rest[0]}/actions/send`)
|
||||
break
|
||||
default:
|
||||
|
|
@ -170,6 +176,7 @@ async function main() {
|
|||
case 'reports':
|
||||
switch (sub) {
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Campaign ID required' }; break }
|
||||
result = await api('GET', `/reports/${rest[0]}`)
|
||||
break
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ async function main() {
|
|||
if (!TOKEN) { result = { error: 'MIXPANEL_TOKEN required for tracking' }; break }
|
||||
if (!args['distinct-id']) { result = { error: '--distinct-id required' }; break }
|
||||
if (!args.event) { result = { error: '--event required' }; break }
|
||||
const properties = args.properties ? JSON.parse(args.properties) : {}
|
||||
let properties
|
||||
try { properties = args.properties ? JSON.parse(args.properties) : {} } catch { result = { error: 'Invalid JSON in --properties' }; break }
|
||||
properties.token = TOKEN
|
||||
properties.distinct_id = args['distinct-id']
|
||||
result = await ingestApi('POST', '/track', [{
|
||||
|
|
@ -137,7 +138,8 @@ async function main() {
|
|||
case 'set': {
|
||||
if (!TOKEN) { result = { error: 'MIXPANEL_TOKEN required for profiles' }; break }
|
||||
if (!args['distinct-id']) { result = { error: '--distinct-id required' }; break }
|
||||
const properties = args.properties ? JSON.parse(args.properties) : {}
|
||||
let properties
|
||||
try { properties = args.properties ? JSON.parse(args.properties) : {} } catch { result = { error: 'Invalid JSON in --properties' }; break }
|
||||
result = await ingestApi('POST', '/engage', [{
|
||||
$token: TOKEN,
|
||||
$distinct_id: args['distinct-id'],
|
||||
|
|
|
|||
|
|
@ -130,7 +130,8 @@ async function main() {
|
|||
case 'create': {
|
||||
const name = args.name
|
||||
if (!name) { result = { error: '--name required' }; break }
|
||||
const filters = args.filters ? JSON.parse(args.filters) : [{ field: 'session_count', relation: '>', value: '0' }]
|
||||
let filters
|
||||
try { filters = args.filters ? JSON.parse(args.filters) : [{ field: 'session_count', relation: '>', value: '0' }] } catch { result = { error: 'Invalid JSON in --filters' }; break }
|
||||
result = await api('POST', `/api/v1/apps/${APP_ID}/segments`, { name, filters })
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,7 +203,9 @@ async function main() {
|
|||
if (!id) { result = { error: '--id required' }; break }
|
||||
const body = {}
|
||||
if (args['proration-billing-mode']) body.proration_billing_mode = args['proration-billing-mode']
|
||||
if (args['scheduled-change']) body.scheduled_change = JSON.parse(args['scheduled-change'])
|
||||
if (args['scheduled-change']) {
|
||||
try { body.scheduled_change = JSON.parse(args['scheduled-change']) } catch { result = { error: 'Invalid JSON in --scheduled-change' }; break }
|
||||
}
|
||||
result = await api('PATCH', `/subscriptions/${id}`, body)
|
||||
break
|
||||
}
|
||||
|
|
@ -248,7 +250,9 @@ async function main() {
|
|||
case 'create': {
|
||||
const items = args.items
|
||||
if (!items) { result = { error: '--items required (JSON array of {price_id, quantity})' }; break }
|
||||
const body = { items: JSON.parse(items) }
|
||||
let parsedItems
|
||||
try { parsedItems = JSON.parse(items) } catch { result = { error: 'Invalid JSON in --items' }; break }
|
||||
const body = { items: parsedItems }
|
||||
if (args['customer-id']) body.customer_id = args['customer-id']
|
||||
result = await api('POST', '/transactions', body)
|
||||
break
|
||||
|
|
@ -304,11 +308,13 @@ async function main() {
|
|||
if (!action) { result = { error: '--action required (refund, credit, chargeback)' }; break }
|
||||
if (!reason) { result = { error: '--reason required' }; break }
|
||||
if (!items) { result = { error: '--items required (JSON array of {item_id, type, amount})' }; break }
|
||||
let parsedItems
|
||||
try { parsedItems = JSON.parse(items) } catch { result = { error: 'Invalid JSON in --items' }; break }
|
||||
result = await api('POST', '/adjustments', {
|
||||
transaction_id: transactionId,
|
||||
action,
|
||||
reason,
|
||||
items: JSON.parse(items),
|
||||
items: parsedItems,
|
||||
})
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ async function main() {
|
|||
|
||||
switch (cmd) {
|
||||
case 'send': {
|
||||
if (!args.from || !args.to || !args.subject) { result = { error: '--from, --to, and --subject required' }; break }
|
||||
const body = { from: args.from, to: args.to?.split(','), subject: args.subject }
|
||||
if (args.html) body.html = args.html
|
||||
if (args.text) body.text = args.text
|
||||
|
|
@ -156,6 +157,7 @@ async function main() {
|
|||
|
||||
case 'contacts': {
|
||||
const audienceId = sub
|
||||
if (!audienceId) { result = { error: 'Audience ID required as subcommand arg' }; break }
|
||||
const action = rest[0]
|
||||
const contactId = rest[1]
|
||||
switch (action) {
|
||||
|
|
@ -166,6 +168,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[1]) { result = { error: 'Contact ID required' }; break }
|
||||
result = await api('GET', `/audiences/${audienceId}/contacts/${contactId}`)
|
||||
break
|
||||
case 'create': {
|
||||
|
|
@ -177,6 +180,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'update': {
|
||||
if (!rest[1]) { result = { error: 'Contact ID required' }; break }
|
||||
const body = {}
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args['last-name']) body.last_name = args['last-name']
|
||||
|
|
@ -185,6 +189,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'delete':
|
||||
if (!rest[1]) { result = { error: 'Contact ID required' }; break }
|
||||
result = await api('DELETE', `/audiences/${audienceId}/contacts/${contactId}`)
|
||||
break
|
||||
default:
|
||||
|
|
@ -216,7 +221,12 @@ async function main() {
|
|||
break
|
||||
|
||||
case 'batch': {
|
||||
const emails = JSON.parse(args.emails || '[]')
|
||||
let emails
|
||||
try {
|
||||
emails = JSON.parse(args.emails || '[]')
|
||||
} catch (e) {
|
||||
result = { error: 'Invalid JSON for --emails: ' + e.message }; break
|
||||
}
|
||||
result = await api('POST', '/emails/batch', emails)
|
||||
break
|
||||
}
|
||||
|
|
@ -241,7 +251,9 @@ async function main() {
|
|||
if (args.subject) body.subject = args.subject
|
||||
if (args['reply-to']) body.reply_to = args['reply-to']
|
||||
if (args.text) body.text = args.text
|
||||
if (args.variables) body.variables = JSON.parse(args.variables)
|
||||
if (args.variables) {
|
||||
try { body.variables = JSON.parse(args.variables) } catch (e) { result = { error: 'Invalid JSON for --variables: ' + e.message }; break }
|
||||
}
|
||||
result = await api('POST', '/templates', body)
|
||||
break
|
||||
}
|
||||
|
|
@ -254,7 +266,9 @@ async function main() {
|
|||
if (args.subject) body.subject = args.subject
|
||||
if (args['reply-to']) body.reply_to = args['reply-to']
|
||||
if (args.text) body.text = args.text
|
||||
if (args.variables) body.variables = JSON.parse(args.variables)
|
||||
if (args.variables) {
|
||||
try { body.variables = JSON.parse(args.variables) } catch (e) { result = { error: 'Invalid JSON for --variables: ' + e.message }; break }
|
||||
}
|
||||
result = await api('PATCH', `/templates/${rest[0]}`, body)
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Affiliate ID required' }; break }
|
||||
result = await api('GET', `/affiliates/${rest[0]}`)
|
||||
break
|
||||
case 'search': {
|
||||
|
|
@ -74,6 +75,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'update': {
|
||||
if (!rest[0]) { result = { error: 'Affiliate ID required' }; break }
|
||||
const body = {}
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args['last-name']) body.last_name = args['last-name']
|
||||
|
|
@ -114,6 +116,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Commission ID required' }; break }
|
||||
result = await api('GET', `/commissions/${rest[0]}`)
|
||||
break
|
||||
default:
|
||||
|
|
@ -124,6 +127,7 @@ async function main() {
|
|||
case 'links':
|
||||
switch (sub) {
|
||||
case 'create': {
|
||||
if (!args['affiliate-id']) { result = { error: '--affiliate-id required' }; break }
|
||||
const body = {}
|
||||
if (args.token) body.token = args.token
|
||||
if (args.url) body.url = args.url
|
||||
|
|
|
|||
|
|
@ -93,7 +93,9 @@ async function main() {
|
|||
userId: args['user-id'],
|
||||
event: args.event,
|
||||
}
|
||||
if (args.properties) body.properties = JSON.parse(args.properties)
|
||||
if (args.properties) {
|
||||
try { body.properties = JSON.parse(args.properties) } catch { result = { error: 'Invalid JSON in --properties' }; break }
|
||||
}
|
||||
result = await trackApi('POST', '/track', body)
|
||||
break
|
||||
}
|
||||
|
|
@ -107,7 +109,9 @@ async function main() {
|
|||
case 'user': {
|
||||
if (!args['user-id']) { result = { error: '--user-id required' }; break }
|
||||
const body = { userId: args['user-id'] }
|
||||
if (args.traits) body.traits = JSON.parse(args.traits)
|
||||
if (args.traits) {
|
||||
try { body.traits = JSON.parse(args.traits) } catch { result = { error: 'Invalid JSON in --traits' }; break }
|
||||
}
|
||||
result = await trackApi('POST', '/identify', body)
|
||||
break
|
||||
}
|
||||
|
|
@ -122,7 +126,9 @@ async function main() {
|
|||
if (!args['user-id']) { result = { error: '--user-id required' }; break }
|
||||
const body = { userId: args['user-id'] }
|
||||
if (args.name) body.name = args.name
|
||||
if (args.properties) body.properties = JSON.parse(args.properties)
|
||||
if (args.properties) {
|
||||
try { body.properties = JSON.parse(args.properties) } catch { result = { error: 'Invalid JSON in --properties' }; break }
|
||||
}
|
||||
result = await trackApi('POST', '/page', body)
|
||||
break
|
||||
}
|
||||
|
|
@ -135,7 +141,8 @@ async function main() {
|
|||
switch (sub) {
|
||||
case 'send': {
|
||||
if (!args.events) { result = { error: '--events required (JSON array)' }; break }
|
||||
const batch = JSON.parse(args.events)
|
||||
let batch
|
||||
try { batch = JSON.parse(args.events) } catch { result = { error: 'Invalid JSON in --events' }; break }
|
||||
result = await trackApi('POST', '/batch', { batch })
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ async function main() {
|
|||
case 'domain':
|
||||
switch (sub) {
|
||||
case 'overview': {
|
||||
if (!args.domain) { result = { error: '--domain required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'domain_ranks',
|
||||
export_columns: 'Db,Dn,Rk,Or,Ot,Oc,Ad,At,Ac',
|
||||
|
|
@ -84,6 +85,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'organic': {
|
||||
if (!args.domain) { result = { error: '--domain required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'domain_organic',
|
||||
export_columns: 'Ph,Po,Pp,Pd,Nq,Cp,Ur,Tr,Tc,Co,Nr',
|
||||
|
|
@ -95,6 +97,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'competitors': {
|
||||
if (!args.domain) { result = { error: '--domain required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'domain_organic_organic',
|
||||
export_columns: 'Dn,Cr,Np,Or,Ot,Oc,Ad',
|
||||
|
|
@ -113,6 +116,7 @@ async function main() {
|
|||
case 'keywords':
|
||||
switch (sub) {
|
||||
case 'overview': {
|
||||
if (!args.phrase) { result = { error: '--phrase required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'phrase_all',
|
||||
export_columns: 'Ph,Nq,Cp,Co,Nr',
|
||||
|
|
@ -123,6 +127,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'related': {
|
||||
if (!args.phrase) { result = { error: '--phrase required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'phrase_related',
|
||||
export_columns: 'Ph,Nq,Cp,Co,Nr,Td',
|
||||
|
|
@ -134,6 +139,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'difficulty': {
|
||||
if (!args.phrase) { result = { error: '--phrase required' }; break }
|
||||
const params = new URLSearchParams({
|
||||
type: 'phrase_kdi',
|
||||
export_columns: 'Ph,Kd',
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ async function main() {
|
|||
|
||||
switch (cmd) {
|
||||
case 'send': {
|
||||
if (!args.from || !args.to || !args.subject) { result = { error: '--from, --to, and --subject required' }; break }
|
||||
const body = {
|
||||
personalizations: [{
|
||||
to: args.to.split(',').map(e => ({ email: e.trim() })),
|
||||
|
|
@ -66,7 +67,7 @@ async function main() {
|
|||
if (args['template-id']) {
|
||||
body.template_id = args['template-id']
|
||||
if (args['template-data']) {
|
||||
body.personalizations[0].dynamic_template_data = JSON.parse(args['template-data'])
|
||||
try { body.personalizations[0].dynamic_template_data = JSON.parse(args['template-data']) } catch (e) { result = { error: 'Invalid JSON for --template-data: ' + e.message }; break }
|
||||
}
|
||||
} else {
|
||||
const content = []
|
||||
|
|
@ -117,6 +118,7 @@ async function main() {
|
|||
break
|
||||
}
|
||||
case 'get':
|
||||
if (!rest[0]) { result = { error: 'Campaign ID required' }; break }
|
||||
result = await api('GET', `/marketing/campaigns/${rest[0]}`)
|
||||
break
|
||||
default:
|
||||
|
|
@ -172,6 +174,7 @@ async function main() {
|
|||
case 'validate':
|
||||
switch (sub) {
|
||||
case 'email': {
|
||||
if (!args.email && !rest[0]) { result = { error: '--email required' }; break }
|
||||
const body = { email: args.email || rest[0] }
|
||||
result = await api('POST', '/validations/email', body)
|
||||
break
|
||||
|
|
|
|||
Loading…
Reference in a new issue