@quasar/app-webpack
Version:
Quasar Framework App CLI with Webpack
573 lines (481 loc) • 14.5 kB
JavaScript
const parseArgs = require('minimist')
const { green, red, italic, underline } = require('kolorist')
const { fatal, dot } = require('../utils/logger.js')
const { getApi } = require('../utils/get-api.js')
const { getCtx } = require('../utils/get-ctx.js')
const partArgs = {
p: 'props',
s: 'slots',
m: 'methods',
c: 'computedProps',
e: 'events',
v: 'value',
a: 'arg',
M: 'modifiers',
i: 'injection',
q: 'quasar',
d: 'docs'
}
const partArgsKeys = Object.keys(partArgs)
const argv = parseArgs(process.argv.slice(2), {
alias: {
h: 'help',
f: 'filter',
...partArgs
},
boolean: [ 'h', ...partArgsKeys ],
string: [ 'f' ]
})
const item = argv._[ 0 ]
if (!item || argv.help) {
console.log(`
Description
Describes a component API for project's Quasar version being used
Usage
$ quasar describe <component/directive/Quasar plugin>
# list all available API entries:
$ quasar describe list
# list available API entries that contain a String (ex "storage"):
$ quasar describe list storage
# display everything:
$ quasar describe QIcon
# displaying only props:
$ quasar describe QIcon -p
# displaying props and methods only:
$ quasar describe QIcon -p -m
# filtering by "si":
$ quasar describe QIcon -f si
# filtering only props by "co":
$ quasar describe QIcon -p -f co
# Open docs URL:
$ quasar describe QIcon -d
Options
--filter, -f <filter> Filters the API
--props, -p Displays the API props
--slots, -s Displays the API slots
--events, -e Displays the API events
--methods, -m Displays the API methods
--computedProps, -c Displays the API computed props
--value, -v Displays the API value
--arg, -a Displays the API arg
--modifiers, -M Displays the API modifiers
--injection, -i Displays the API injection
--quasar, -q Displays the API quasar conf options
--docs, -d Opens the docs API URL
--help, -h Displays this message
`)
process.exit(0)
}
const ctx = getCtx()
const apiParts = {}
if (partArgsKeys.some(part => argv[ part ])) {
Object.values(partArgs).forEach(part => {
apiParts[ part ] = argv[ part ]
})
}
else {
Object.values(partArgs).forEach(part => {
if (part !== 'docs') {
apiParts[ part ] = true
}
})
}
function getEventParams (event) {
const params = !event.params || event.params.length === 0
? ''
: Object.keys(event.params).join(', ')
return ' -> function(' + params + ')'
}
function getMethodParams (method, noRequired) {
if (!method.params || method.params.length === 0) {
return ' ()'
}
if (noRequired === true) {
return ` (${ Object.keys(method.params).join(', ') })`
}
const params = Object.keys(method.params)
const optionalIndex = params.findIndex(param => method.params[ param ].required !== true)
const str = optionalIndex !== -1
? params.slice(0, optionalIndex).join(', ')
+ (optionalIndex < params.length
? '[' + (optionalIndex > 0 ? ', ' : '') + params.slice(optionalIndex).join(', ') + ']'
: '')
: params.join(', ')
return ' (' + str + ')'
}
function getMethodReturnValue (method) {
return ' => '
+ (!method.returns
? 'void 0'
: method.returns.type
)
}
function getStringType (type) {
return Array.isArray(type)
? type.join(' | ')
: type
}
function printProp (prop, propName, indentLevel) {
let indent = ' '.repeat(indentLevel)
const type = getStringType(prop.type)
if (propName !== void 0) {
console.log(`${ indent }${ green(propName) } ${ type ? `(${ type })` : '' }${ type !== 'Function' && prop.required ? red(' [Required]') : '' }${ prop.reactive ? red(' [Reactive]') : '' }`)
indentLevel += 2
indent += ' '
}
console.log(`${ indent }Description: ${ prop.desc }`)
if (prop.alias) {
console.log(`${ indent }Alias: ${ prop.alias }`)
}
if (type === 'Function') {
console.log(`${ indent }Function form:${ getMethodParams(prop, true) }${ getMethodReturnValue(prop) }`)
}
if (prop.sync) {
console.log(`${ indent }".sync" modifier required!`)
}
if (prop.link) {
console.log(`${ indent }Link: ${ prop.link }`)
}
if (prop.values) {
console.log(`${ indent }Accepted values: ${ prop.values.join(' | ') }`)
}
if (prop.default) {
console.log(`${ indent }Default value: ${ prop.default }`)
}
if (prop.definition) {
console.log(`${ indent }Props:`)
for (const propName in prop.definition) {
printProp(prop.definition[ propName ], propName, indentLevel + 2)
}
}
if (prop.params) {
console.log(`${ indent }Params:`)
for (const propName in prop.params) {
printProp(prop.params[ propName ], propName, indentLevel + 2)
}
}
if (prop.returns) {
console.log(`${ indent }Returns ${ getStringType(prop.returns.type) }:`)
printProp(prop.returns, void 0, indentLevel + 2)
}
if (prop.scope) {
console.log(`${ indent }Scope:`)
for (const propName in prop.scope) {
printProp(prop.scope[ propName ], propName, indentLevel + 2)
}
}
if (prop.examples !== void 0) {
console.log(`${ indent }Example${ prop.examples.length > 1 ? 's' : '' }:`)
prop.examples.forEach(example => {
console.log(`${ indent } ${ example }`)
})
}
}
function printProperties ({ props }) {
const keys = Object.keys(props || {})
console.log('\n ' + underline('Properties'))
if (keys.length === 0) {
console.log('\n ' + italic('*No properties*'))
return
}
if (argv.filter) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete props[ key ]
}
})
if (Object.keys(props).length === 0) {
console.log('\n ' + italic('*No matching properties*'))
return
}
}
for (const propName in props) {
console.log()
printProp(props[ propName ], propName, 3)
}
}
function printSlots ({ slots }) {
const keys = Object.keys(slots || {})
console.log('\n ' + underline('Slots'))
if (keys.length === 0) {
console.log('\n ' + italic('*No slots*'))
return
}
if (argv.filter !== void 0) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete slots[ key ]
}
})
if (Object.keys(slots).length === 0) {
console.log('\n ' + italic('*No matching slots*'))
return
}
}
for (const slot in slots) {
console.log()
printProp(slots[ slot ], slot, 3)
}
}
function printEvents ({ events }) {
const keys = Object.keys(events || {})
console.log('\n ' + underline('Events'))
if (keys.length === 0) {
console.log('\n ' + italic('*No events*'))
return
}
if (argv.filter !== void 0) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete events[ key ]
}
})
if (Object.keys(events).length === 0) {
console.log('\n ' + italic('*No matching events*'))
return
}
}
for (const eventName in events) {
const event = events[ eventName ]
console.log('\n @' + green(eventName) + getEventParams(event))
console.log(' Description: ' + event.desc)
if (!event.params) {
console.log(' Parameters: ' + italic('*None*'))
}
else {
console.log(' Parameters:')
for (const paramName in event.params) {
printProp(event.params[ paramName ], paramName, 7)
}
}
}
}
function printMethods ({ methods }) {
const keys = Object.keys(methods || {})
console.log('\n ' + underline('Methods'))
if (keys.length === 0) {
console.log('\n ' + italic('*No methods*'))
return
}
if (argv.filter !== void 0) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete methods[ key ]
}
})
if (Object.keys(methods).length === 0) {
console.log('\n ' + italic('*No matching methods*'))
return
}
}
for (const methodName in methods) {
const method = methods[ methodName ]
console.log('\n ' + green(methodName) + getMethodParams(method) + getMethodReturnValue(method))
console.log(' ' + method.desc)
if (method.params) {
console.log(' Parameters:')
for (const paramName in method.params) {
printProp(method.params[ paramName ], paramName, 7)
}
}
if (method.returns) {
console.log(` Returns ${ getStringType(method.returns.type) }:`)
printProp(method.returns, void 0, 7)
}
}
}
function printComputedProps ({ computedProps }) {
const keys = Object.keys(computedProps || {})
console.log('\n ' + underline('Computed Properties'))
if (keys.length === 0) {
console.log('\n ' + italic('*No computed properties*'))
return
}
if (argv.filter) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete computedProps[ key ]
}
})
if (Object.keys(computedProps).length === 0) {
console.log('\n ' + italic('*No matching computed properties*'))
return
}
}
for (const propName in computedProps) {
console.log()
printProp(computedProps[ propName ], propName, 3)
}
}
function printValue ({ value }) {
console.log('\n ' + underline('Value'))
if (value === void 0) {
console.log('\n ' + italic('*No value*'))
}
else {
console.log('\n Type:', value.type)
printProp(value, void 0, 3)
}
}
function printArg ({ arg }) {
console.log('\n ' + underline('Arg'))
if (arg === void 0) {
console.log('\n ' + italic('*No arg*'))
}
else {
console.log('\n Type:', arg.type)
printProp(arg, void 0, 3)
}
}
function printModifiers ({ modifiers }) {
const keys = Object.keys(modifiers || {})
console.log('\n ' + underline('Modifiers'))
if (keys.length === 0) {
console.log('\n ' + italic('*No modifiers*'))
return
}
if (argv.filter !== void 0) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete modifiers[ key ]
}
})
if (Object.keys(modifiers).length === 0) {
console.log('\n ' + italic('*No matching modifiers*'))
return
}
}
for (const modifierName in modifiers) {
const modifier = modifiers[ modifierName ]
console.log('\n ' + green(modifierName))
printProp(modifier, modifierName, 5)
}
}
function printInjection ({ injection }) {
console.log('\n ' + underline('Injection'))
if (injection === void 0) {
console.log('\n ' + italic('*No injection*'))
}
else {
console.log('\n ' + green(injection))
}
}
function printQuasarConfOptions ({ quasarConfOptions }) {
const conf = quasarConfOptions !== void 0
? quasarConfOptions.definition || {}
: {}
const keys = Object.keys(conf)
console.log('\n ' + underline('quasar.config file > framework > config'))
if (keys.length === 0) {
console.log('\n ' + italic('*No configuration options*'))
return
}
if (argv.filter !== void 0) {
keys.forEach(key => {
if (key.indexOf(argv.filter) === -1) {
delete conf[ key ]
}
})
if (Object.keys(conf).length === 0) {
console.log('\n ' + italic('*No matching configuration options*'))
return
}
}
console.log('\n Property name: ' + green(quasarConfOptions.propName))
console.log(' Definition:')
for (const propName in conf) {
console.log()
printProp(conf[ propName ], propName, 5)
}
}
function describe (api) {
switch (api.type) {
case 'component':
apiParts.quasar === true && printQuasarConfOptions(api)
apiParts.props === true && printProperties(api)
apiParts.slots === true && printSlots(api)
apiParts.events === true && printEvents(api)
apiParts.methods === true && printMethods(api)
apiParts.computedProps === true && printComputedProps(api)
break
case 'directive':
apiParts.quasar === true && printQuasarConfOptions(api)
apiParts.value === true && printValue(api)
apiParts.arg === true && printArg(api)
apiParts.modifiers === true && printModifiers(api)
break
case 'plugin':
apiParts.injection === true && printInjection(api)
apiParts.quasar === true && printQuasarConfOptions(api)
apiParts.props === true && printProperties(api)
apiParts.methods === true && printMethods(api)
break
}
if (api.meta && api.meta.docsUrl) {
console.log('\n ' + underline('Documentation URL'))
console.log('\n ' + green(api.meta.docsUrl))
}
}
async function run () {
try {
const { api, supplier } = await getApi(item, ctx)
console.log()
if (apiParts.docs) {
if (api.meta && api.meta.docsUrl) {
const { openBrowser } = require('../utils/open-browser.js')
openBrowser({ url: api.meta.docsUrl, wait: false })
}
else {
console.log(' Please report this issue to: https://github.com/quasarframework/quasar/issues/')
console.log(' Write down the command that you tried along with a complete log of "quasar info" command output')
console.log()
}
}
else {
console.log(` Describing ${ green(item) } ${ api.type } API`)
if (supplier === void 0) {
console.log(` ${ italic('Description is based on your project\'s Quasar version') }`)
}
else {
console.log(` ${ italic(`Supplied by "${ supplier }" App Extension`) }`)
}
describe(api)
console.log()
}
}
catch (e) {
fatal(e)
}
}
function listElements () {
const { getPackage } = require('../utils/get-package.js')
let api = getPackage('quasar/dist/transforms/api-list.json', ctx.appPaths.appDir)
if (api === void 0) {
fatal(' Could not retrieve list...')
}
const filter = argv._[ 1 ]
if (filter) {
const needle = filter.toLowerCase()
const filterBanner = green(filter)
api = api.filter(entry => entry.toLowerCase().indexOf(needle) !== -1)
if (api.length === 0) {
console.log(`\n Nothing matches "${ filterBanner }". Please refine the search term.\n`)
process.exit(0)
}
console.log(`\n The list of API elements that match "${ filterBanner }":\n`)
}
else {
console.log('\n The complete list of API elements:\n')
}
const prefix = green(` ${ dot } `)
api.forEach(entry => {
console.log(prefix + entry)
})
console.log()
}
if (item === 'list') {
listElements()
}
else {
run()
}