@jsreport/jsreport-cli 3.0.0-beta.2 → 3.1.1

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.
Files changed (41) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +16 -12
  3. package/cli.js +93 -93
  4. package/example.config.json +43 -43
  5. package/example.server.js +14 -14
  6. package/index.js +20 -22
  7. package/jsreport.config.js +8 -8
  8. package/lib/cliExtension.js +59 -59
  9. package/lib/{createCommandParser.js → commander/createCommandParser.js} +44 -45
  10. package/lib/commander/createCustomCommandBuilder.js +150 -0
  11. package/lib/commander/createLogger.js +51 -0
  12. package/lib/commander/executeCommand.js +37 -0
  13. package/lib/commander/getCommandEventName.js +4 -0
  14. package/lib/commander/index.js +279 -0
  15. package/lib/commander/jsreportInstance.js +98 -0
  16. package/lib/commander/registerCommand.js +91 -0
  17. package/lib/commander/startCommand.js +234 -0
  18. package/lib/commander/startProcessing.js +208 -0
  19. package/lib/commands/_initializeApp.js +206 -208
  20. package/lib/commands/configure.js +393 -395
  21. package/lib/commands/help.js +453 -454
  22. package/lib/commands/init.js +76 -77
  23. package/lib/commands/kill.js +85 -86
  24. package/lib/commands/render.js +490 -488
  25. package/lib/commands/repair.js +55 -56
  26. package/lib/commands/start.js +72 -74
  27. package/lib/commands/win-install.js +124 -126
  28. package/lib/commands/win-uninstall.js +100 -102
  29. package/lib/daemonHandler.js +164 -164
  30. package/lib/daemonInstance.js +225 -225
  31. package/lib/{registerExtensionsCommands.js → detectAndRegisterExtensionsCommands.js} +74 -74
  32. package/lib/instanceHandler.js +316 -316
  33. package/lib/keepAliveProcess.js +205 -205
  34. package/lib/{errorUtils.js → utils/error.js} +149 -127
  35. package/lib/{getTempPaths.js → utils/getTempPaths.js} +39 -39
  36. package/lib/{normalizePathOptionOrArg.js → utils/normalizePathOptionOrArg.js} +41 -41
  37. package/lib/{normalizeSocketPath.js → utils/normalizeSocketPath.js} +9 -9
  38. package/lib/{startSocketServer.js → utils/startSocketServer.js} +53 -53
  39. package/package.json +105 -106
  40. package/test/testUtils.js +197 -198
  41. package/lib/commander.js +0 -1108
@@ -1,454 +1,453 @@
1
- 'use strict'
2
-
3
- const cliui = require('cliui')
4
- const chalk = require('chalk')
5
- const omit = require('lodash.omit')
6
-
7
- const description = 'Prints information about a command or topic'
8
- const command = 'help'
9
-
10
- exports.command = command
11
- exports.description = description
12
-
13
- function getExamples (command) {
14
- return [
15
- [`${command} render`, 'Print information about the render command'],
16
- [`${command} start`, 'Print information about the start command'],
17
- [`${command} config`, 'Print information about jsreport configuration input format']
18
- ]
19
- }
20
-
21
- exports.builder = (yargs) => {
22
- const examples = getExamples(`jsreport ${command}`)
23
-
24
- examples.forEach((examp) => {
25
- yargs.example(examp[0], examp[1])
26
- })
27
-
28
- return (
29
- yargs
30
- .usage([
31
- `${description}\n`,
32
- `Usage:\n\njsreport ${command} <commandOrTopic>\n`,
33
- 'Topics Available:\n',
34
- 'config -> print details about the configuration shape and types that the current jsreport instance in project supports\n'
35
- ].join('\n'))
36
- // we just define positional argument here to describe it for help usage,
37
- // but in order to have the property "argv.commandOrTopic" with sanitized value we will need to put the
38
- // positional argument in the command string too, however in this case we can't do that because
39
- // the help command has some conflicts with the yargs.help()
40
- .positional('commandOrTopic', {
41
- type: 'string',
42
- description: 'Command or Topic to get help usage'
43
- })
44
- // we need to handle the help option directly since there is a conflict
45
- // in yargs when a custom command is called the same that the option used in .help()
46
- // (that option registers an implicit command with the same name that the option passed)
47
- .option('help', {
48
- global: true,
49
- alias: 'h',
50
- description: 'Show Help',
51
- type: 'boolean'
52
- })
53
- .check((argv, hash) => {
54
- if (argv && argv.help) {
55
- return true
56
- }
57
-
58
- if (!argv || !argv._[1]) {
59
- throw new Error('"commandOrTopic" argument is required')
60
- }
61
-
62
- return true
63
- })
64
- )
65
- }
66
-
67
- exports.handler = async (argv) => {
68
- const context = argv.context
69
- const cwd = context.cwd
70
- const logger = context.logger
71
- const getInstance = context.getInstance
72
- const initInstance = context.initInstance
73
- let commandOrTopic = argv._[1]
74
- let helpResult
75
-
76
- const getCommandHelp = context.getCommandHelp
77
-
78
- if (argv.help) {
79
- commandOrTopic = 'help'
80
- }
81
-
82
- if (commandOrTopic === 'config') {
83
- logger.debug(`searching information about "${commandOrTopic}" as topic`)
84
-
85
- let jsreportInstance
86
-
87
- try {
88
- let _instance
89
-
90
- // look up for an instance in CWD
91
- try {
92
- _instance = await getInstance(cwd)
93
- } catch (e) {
94
- const error = new Error('Couldn\'t find a jsreport installation necessary to check the configuration options')
95
-
96
- error.originalError = e
97
-
98
- throw error
99
- }
100
-
101
- logger.debug('disabling express extension..')
102
-
103
- if (typeof _instance === 'function') {
104
- jsreportInstance = _instance()
105
- } else {
106
- jsreportInstance = _instance
107
- }
108
-
109
- jsreportInstance.options = jsreportInstance.options || {}
110
- jsreportInstance.options.extensions = jsreportInstance.options.extensions || {}
111
- jsreportInstance.options.extensions.express = Object.assign(
112
- {},
113
- jsreportInstance.options.extensions.express,
114
- { start: false }
115
- )
116
-
117
- await initInstance(jsreportInstance)
118
- } catch (e) {
119
- return onCriticalError(e)
120
- }
121
-
122
- try {
123
- helpResult = schemaToConfigFormat(jsreportInstance, jsreportInstance.optionsValidator.getRootSchema())
124
- } catch (e) {
125
- return onCriticalError(e)
126
- }
127
- } else {
128
- logger.debug(`searching information about "${commandOrTopic}" as command`)
129
-
130
- try {
131
- helpResult = await getCommandHelp(commandOrTopic, context)
132
- } catch (e) {
133
- if (e.notFound !== true) {
134
- return onCriticalError(e)
135
- }
136
- }
137
-
138
- if (helpResult) {
139
- helpResult = { output: helpResult.output }
140
- }
141
- }
142
-
143
- if (!helpResult) {
144
- return logger.info(`no information found for command or topic "${commandOrTopic}", to get the list of commands supported on your installation run "jsreport -h" and try again with a supported command or topic`)
145
- }
146
-
147
- logger.info(helpResult.output)
148
-
149
- return helpResult
150
- }
151
-
152
- function onCriticalError (err) {
153
- const error = new Error(`A critical error occurred while trying to execute the ${command} command`)
154
- error.originalError = err
155
- throw error
156
- }
157
-
158
- function schemaToConfigFormat (instance, rootSchema) {
159
- const rawUI = cliui()
160
- const outputUI = cliui()
161
-
162
- function convert (ui, addStyles = true) {
163
- try {
164
- ui.div({
165
- text: 'Configuration format description for local jsreport instance:',
166
- padding: [0, 0, 1, 0]
167
- })
168
-
169
- ui.div('{')
170
-
171
- printProperties(ui, rootSchema.properties, {
172
- defaults: instance.defaults,
173
- required: rootSchema.required,
174
- addStyles
175
- })
176
-
177
- ui.div('}')
178
-
179
- return ui.toString()
180
- } catch (e) {
181
- e.message = `A problem happened while trying to convert schema to help description. ${e.message}`
182
- throw e
183
- }
184
- }
185
-
186
- const results = {}
187
- const toConvert = [rawUI, outputUI]
188
-
189
- toConvert.forEach((ui, idx) => {
190
- if (idx === 0) {
191
- results.raw = convert(ui, false)
192
- } else {
193
- results.output = convert(ui)
194
- }
195
- })
196
-
197
- return results
198
- }
199
-
200
- function printProperties (ui, props, {
201
- required = [],
202
- defaults,
203
- level = 1,
204
- printRestProps = false,
205
- addStyles = true
206
- }) {
207
- const baseLeftPadding = level === 1 ? 2 : 3
208
-
209
- const knowProps = [
210
- 'type', 'required', 'properties', 'items', 'not', 'anyOf', 'allOf', 'oneOf',
211
- 'default', 'defaultNotInitialized', 'enum', 'format', 'pattern',
212
- 'description', 'title', '$jsreport-constantOrArray'
213
- ]
214
-
215
- if (props == null) {
216
- return
217
- }
218
-
219
- let bold
220
-
221
- if (addStyles) {
222
- bold = chalk.bold
223
- } else {
224
- bold = (i) => i
225
- }
226
-
227
- const propsKeys = Array.isArray(props) ? props : Object.keys(props)
228
- const totalKeys = propsKeys.length
229
-
230
- propsKeys.forEach((key, index) => {
231
- const isLastKey = index === totalKeys - 1
232
- let propName
233
- let schema
234
- let customCase
235
- let defaultToUse
236
- let shouldStringifyDefault = true
237
- let isRequired = false
238
-
239
- if (Array.isArray(key)) {
240
- propName = key[0]
241
- schema = key[1]
242
- } else {
243
- propName = key
244
- schema = props[propName]
245
- }
246
-
247
- let shouldAddTopPadding = true
248
-
249
- if (index === 0 && level === 1) {
250
- shouldAddTopPadding = false
251
- }
252
-
253
- const getPadding = (l) => {
254
- return [shouldAddTopPadding ? 1 : 0, 0, 0, l * baseLeftPadding]
255
- }
256
-
257
- const content = {
258
- padding: getPadding(level)
259
- }
260
-
261
- if (propName !== '') {
262
- content.text = `"${bold(propName)}":`
263
- } else {
264
- content.text = '-'
265
- }
266
-
267
- if (propName !== '' && required.indexOf(propName) !== -1) {
268
- isRequired = true
269
- }
270
-
271
- if (schema.type) {
272
- let type = schema.type
273
-
274
- if (Array.isArray(type)) {
275
- type = type.join(' | ')
276
- } else if (type === 'array' && schema.items && schema.items.type) {
277
- type = Array.isArray(schema.items.type) ? schema.items.type.join(' | ') : schema.items.type
278
- type = `array<${type}>`
279
- }
280
-
281
- content.text += ` <${bold(type)}>`
282
- } else {
283
- if (schema.not != null && typeof schema.not === 'object') {
284
- content.text += ` <${bold('any type that is not valid against the description below')}>`
285
- customCase = 'not'
286
- } else if (Array.isArray(schema.anyOf)) {
287
- content.text += ` <${bold('any type that is valid against at least with one of the descriptions below')}>`
288
- customCase = 'anyOf'
289
- } else if (Array.isArray(schema.allOf)) {
290
- content.text += ` <${bold('any type that is valid against all the descriptions below')}>`
291
- customCase = 'allOf'
292
- } else if (Array.isArray(schema.oneOf)) {
293
- content.text += ` <${bold('any type that is valid against just one of the descriptions below')}>`
294
- customCase = 'oneOf'
295
- } else if (schema.description != null) {
296
- content.text += ` <${bold('any')}>`
297
- } else {
298
- // only schemas structures that are not implemented gets printed in raw form,
299
- // this means that we should analize the raw schema printed and then support it
300
- content.text += ` <raw schema: ${JSON.stringify(schema)}>`
301
- }
302
- }
303
-
304
- if (isRequired) {
305
- content.text += ` (${bold('required')})`
306
- }
307
-
308
- if (
309
- defaults &&
310
- typeof defaults === 'object' &&
311
- defaults[propName] !== undefined &&
312
- (
313
- typeof defaults[propName] === 'string' ||
314
- typeof defaults[propName] === 'boolean' ||
315
- typeof defaults[propName] === 'number' ||
316
- defaults[propName] === null
317
- )
318
- ) {
319
- defaultToUse = defaults[propName]
320
- } else if (schema.default !== undefined) {
321
- defaultToUse = schema.default
322
- } else if (schema.defaultNotInitialized !== undefined) {
323
- defaultToUse = schema.defaultNotInitialized
324
-
325
- if (typeof defaultToUse === 'string' && /^<.*>$/.test(defaultToUse)) {
326
- shouldStringifyDefault = false
327
- }
328
- }
329
-
330
- if (defaultToUse !== undefined) {
331
- if (shouldStringifyDefault) {
332
- content.text += ` (default: ${bold(JSON.stringify(defaultToUse))})`
333
- } else {
334
- content.text += ` (default: ${bold(defaultToUse)})`
335
- }
336
- }
337
-
338
- let allowed
339
-
340
- if (schema.enum != null) {
341
- allowed = schema.enum
342
- } else if (schema.type === 'string' && schema['$jsreport-constantOrArray'] != null) {
343
- allowed = schema['$jsreport-constantOrArray']
344
- }
345
-
346
- if (Array.isArray(allowed) && allowed.length > 0) {
347
- content.text += ` (allowed values: ${bold(allowed.map((value) => {
348
- return JSON.stringify(value)
349
- }).join(', '))})`
350
- }
351
-
352
- if (
353
- typeof schema.type === 'string' ||
354
- (Array.isArray(schema.type) && schema.type.indexOf('string') !== -1)
355
- ) {
356
- if (schema.format != null) {
357
- content.text += ` (format: ${schema.format})`
358
- }
359
-
360
- if (schema.pattern != null) {
361
- content.text += ` (pattern: ${schema.pattern})`
362
- }
363
- }
364
-
365
- if (printRestProps) {
366
- const restProps = omit(schema, knowProps)
367
-
368
- if (restProps && Object.keys(restProps).length > 0) {
369
- content.text += ` (raw schema: ${JSON.stringify(restProps)})`
370
- }
371
- }
372
-
373
- if (schema.description != null) {
374
- content.text += ` -> ${schema.description}`
375
- }
376
-
377
- if (
378
- schema.type === 'object' &&
379
- schema.properties != null &&
380
- Object.keys(schema.properties).length > 0
381
- ) {
382
- content.text += ' {'
383
- } else if (
384
- schema.type === 'array' &&
385
- (Array.isArray(schema.items) ||
386
- (schema.items &&
387
- schema.items.type &&
388
- schema.items.type === 'object' &&
389
- schema.items.properties != null &&
390
- Object.keys(schema.items.properties).length > 0))
391
- ) {
392
- content.text += ' ['
393
- } else if (!isLastKey && propName !== '') {
394
- content.text += ','
395
- }
396
-
397
- ui.div(content)
398
-
399
- if (customCase != null) {
400
- if (customCase === 'not') {
401
- printProperties(ui, [['', schema.not]], { level: level + 1 })
402
- } else if (
403
- (customCase === 'anyOf' ||
404
- customCase === 'allOf' ||
405
- customCase === 'oneOf') &&
406
- Array.isArray(schema[customCase]) &&
407
- schema[customCase].length > 0
408
- ) {
409
- printProperties(ui, schema[customCase].map((s) => {
410
- return ['', s]
411
- }), { level: level + 1, printRestProps: true })
412
- }
413
- } else if (
414
- schema.type === 'object' &&
415
- schema.properties != null &&
416
- Object.keys(schema.properties).length > 0
417
- ) {
418
- const hasDefault = (
419
- defaults &&
420
- typeof defaults === 'object' &&
421
- typeof defaults[propName] === 'object'
422
- )
423
-
424
- printProperties(ui, schema.properties, {
425
- level: level + 1,
426
- required: schema.required,
427
- defaults: hasDefault ? defaults[propName] : undefined
428
- })
429
-
430
- ui.div({ text: `}${!isLastKey ? ',' : ''}`, padding: content.padding })
431
- } else if (
432
- schema.type === 'array' &&
433
- schema.items &&
434
- schema.items.type === 'object' &&
435
- schema.items.properties != null &&
436
- Object.keys(schema.items.properties).length > 0
437
- ) {
438
- ui.div({ text: '{', padding: getPadding(level + 1) })
439
-
440
- printProperties(ui, schema.items.properties, {
441
- level: level + 2,
442
- required: schema.items.required
443
- })
444
-
445
- ui.div({ text: '{', padding: getPadding(level + 1) })
446
- ui.div({ text: `]${!isLastKey ? ',' : ''}`, padding: content.padding })
447
- } else if (schema.type === 'array' && Array.isArray(schema.items)) {
448
- printProperties(ui, schema.items.map((s, idx) => {
449
- return [`item at ${idx} index should be`, s]
450
- }), { level: level + 1 })
451
- ui.div({ text: `]${!isLastKey ? ',' : ''}`, padding: content.padding })
452
- }
453
- })
454
- }
1
+ const cliui = require('cliui')
2
+ const chalk = require('chalk')
3
+ const omit = require('lodash.omit')
4
+
5
+ const description = 'Prints information about a command or topic'
6
+ const command = 'help'
7
+ const positionalArgs = '[commandOrTopic]'
8
+
9
+ exports.command = `${command} ${positionalArgs}`
10
+ exports.description = description
11
+
12
+ function getExamples (command) {
13
+ return [
14
+ [`${command} render`, 'Print information about the render command'],
15
+ [`${command} start`, 'Print information about the start command'],
16
+ [`${command} config`, 'Print information about jsreport configuration input format']
17
+ ]
18
+ }
19
+
20
+ exports.builder = (yargs) => {
21
+ const examples = getExamples(`jsreport ${command}`)
22
+
23
+ examples.forEach((examp) => {
24
+ yargs.example(examp[0], examp[1])
25
+ })
26
+
27
+ return (
28
+ yargs
29
+ .usage([
30
+ `${description}\n`,
31
+ `Usage:\n\njsreport ${command} <commandOrTopic>\n`,
32
+ 'Topics Available:\n',
33
+ 'config -> print details about the configuration shape and types that the current jsreport instance in project supports\n'
34
+ ].join('\n'))
35
+ // we just define positional argument here to describe it for help usage,
36
+ // but in order to have the property "argv.commandOrTopic" with sanitized value we will need to put the
37
+ // positional argument in the command string too, however in this case we can't do that because
38
+ // the help command has some conflicts with the yargs.help()
39
+ .positional('commandOrTopic', {
40
+ type: 'string',
41
+ description: 'Command or Topic to get help usage'
42
+ })
43
+ // we need to handle the help option directly since there is a conflict
44
+ // in yargs when a custom command is called the same that the option used in .help()
45
+ // (that option registers an implicit command with the same name that the option passed)
46
+ .option('help', {
47
+ global: true,
48
+ alias: 'h',
49
+ description: 'Show Help',
50
+ type: 'boolean'
51
+ })
52
+ .check((argv, hash) => {
53
+ if (argv && argv.help) {
54
+ return true
55
+ }
56
+
57
+ if (!argv || !argv.commandOrTopic) {
58
+ throw new Error('"commandOrTopic" argument is required')
59
+ }
60
+
61
+ return true
62
+ })
63
+ )
64
+ }
65
+
66
+ exports.handler = async (argv) => {
67
+ const context = argv.context
68
+ const cwd = context.cwd
69
+ const logger = context.logger
70
+ const getInstance = context.getInstance
71
+ const initInstance = context.initInstance
72
+ let commandOrTopic = argv.commandOrTopic
73
+ let helpResult
74
+
75
+ const getCommandHelp = context.getCommandHelp
76
+
77
+ if (argv.help) {
78
+ commandOrTopic = 'help'
79
+ }
80
+
81
+ if (commandOrTopic === 'config') {
82
+ logger.debug(`searching information about "${commandOrTopic}" as topic`)
83
+
84
+ let jsreportInstance
85
+
86
+ try {
87
+ let _instance
88
+
89
+ // look up for an instance in CWD
90
+ try {
91
+ _instance = await getInstance(cwd)
92
+ } catch (e) {
93
+ const error = new Error('Couldn\'t find a jsreport installation necessary to check the configuration options')
94
+
95
+ error.originalError = e
96
+
97
+ throw error
98
+ }
99
+
100
+ logger.debug('disabling express extension..')
101
+
102
+ if (typeof _instance === 'function') {
103
+ jsreportInstance = _instance()
104
+ } else {
105
+ jsreportInstance = _instance
106
+ }
107
+
108
+ jsreportInstance.options = jsreportInstance.options || {}
109
+ jsreportInstance.options.extensions = jsreportInstance.options.extensions || {}
110
+ jsreportInstance.options.extensions.express = Object.assign(
111
+ {},
112
+ jsreportInstance.options.extensions.express,
113
+ { start: false }
114
+ )
115
+
116
+ await initInstance(jsreportInstance)
117
+ } catch (e) {
118
+ return onCriticalError(e)
119
+ }
120
+
121
+ try {
122
+ helpResult = schemaToConfigFormat(jsreportInstance, jsreportInstance.optionsValidator.getRootSchema())
123
+ } catch (e) {
124
+ return onCriticalError(e)
125
+ }
126
+ } else {
127
+ logger.debug(`searching information about "${commandOrTopic}" as command`)
128
+
129
+ try {
130
+ helpResult = await getCommandHelp(commandOrTopic, context)
131
+ } catch (e) {
132
+ if (e.notFound !== true) {
133
+ return onCriticalError(e)
134
+ }
135
+ }
136
+
137
+ if (helpResult != null && typeof helpResult === 'string') {
138
+ helpResult = { output: helpResult }
139
+ }
140
+ }
141
+
142
+ if (!helpResult) {
143
+ return logger.info(`no information found for command or topic "${commandOrTopic}", to get the list of commands supported on your installation run "jsreport -h" and try again with a supported command or topic`)
144
+ }
145
+
146
+ logger.info(helpResult.output)
147
+
148
+ return helpResult
149
+ }
150
+
151
+ function onCriticalError (err) {
152
+ const error = new Error(`A critical error occurred while trying to execute the ${command} command`)
153
+ error.originalError = err
154
+ throw error
155
+ }
156
+
157
+ function schemaToConfigFormat (instance, rootSchema) {
158
+ const rawUI = cliui()
159
+ const outputUI = cliui()
160
+
161
+ function convert (ui, addStyles = true) {
162
+ try {
163
+ ui.div({
164
+ text: 'Configuration format description for local jsreport instance:',
165
+ padding: [0, 0, 1, 0]
166
+ })
167
+
168
+ ui.div('{')
169
+
170
+ printProperties(ui, rootSchema.properties, {
171
+ defaults: instance.defaults,
172
+ required: rootSchema.required,
173
+ addStyles
174
+ })
175
+
176
+ ui.div('}')
177
+
178
+ return ui.toString()
179
+ } catch (e) {
180
+ e.message = `A problem happened while trying to convert schema to help description. ${e.message}`
181
+ throw e
182
+ }
183
+ }
184
+
185
+ const results = {}
186
+ const toConvert = [rawUI, outputUI]
187
+
188
+ toConvert.forEach((ui, idx) => {
189
+ if (idx === 0) {
190
+ results.raw = convert(ui, false)
191
+ } else {
192
+ results.output = convert(ui)
193
+ }
194
+ })
195
+
196
+ return results
197
+ }
198
+
199
+ function printProperties (ui, props, {
200
+ required = [],
201
+ defaults,
202
+ level = 1,
203
+ printRestProps = false,
204
+ addStyles = true
205
+ }) {
206
+ const baseLeftPadding = level === 1 ? 2 : 3
207
+
208
+ const knowProps = [
209
+ 'type', 'required', 'properties', 'items', 'not', 'anyOf', 'allOf', 'oneOf',
210
+ 'default', 'defaultNotInitialized', 'enum', 'format', 'pattern',
211
+ 'description', 'title', '$jsreport-constantOrArray'
212
+ ]
213
+
214
+ if (props == null) {
215
+ return
216
+ }
217
+
218
+ let bold
219
+
220
+ if (addStyles) {
221
+ bold = chalk.bold
222
+ } else {
223
+ bold = (i) => i
224
+ }
225
+
226
+ const propsKeys = Array.isArray(props) ? props : Object.keys(props)
227
+ const totalKeys = propsKeys.length
228
+
229
+ propsKeys.forEach((key, index) => {
230
+ const isLastKey = index === totalKeys - 1
231
+ let propName
232
+ let schema
233
+ let customCase
234
+ let defaultToUse
235
+ let shouldStringifyDefault = true
236
+ let isRequired = false
237
+
238
+ if (Array.isArray(key)) {
239
+ propName = key[0]
240
+ schema = key[1]
241
+ } else {
242
+ propName = key
243
+ schema = props[propName]
244
+ }
245
+
246
+ let shouldAddTopPadding = true
247
+
248
+ if (index === 0 && level === 1) {
249
+ shouldAddTopPadding = false
250
+ }
251
+
252
+ const getPadding = (l) => {
253
+ return [shouldAddTopPadding ? 1 : 0, 0, 0, l * baseLeftPadding]
254
+ }
255
+
256
+ const content = {
257
+ padding: getPadding(level)
258
+ }
259
+
260
+ if (propName !== '') {
261
+ content.text = `"${bold(propName)}":`
262
+ } else {
263
+ content.text = '-'
264
+ }
265
+
266
+ if (propName !== '' && required.indexOf(propName) !== -1) {
267
+ isRequired = true
268
+ }
269
+
270
+ if (schema.type) {
271
+ let type = schema.type
272
+
273
+ if (Array.isArray(type)) {
274
+ type = type.join(' | ')
275
+ } else if (type === 'array' && schema.items && schema.items.type) {
276
+ type = Array.isArray(schema.items.type) ? schema.items.type.join(' | ') : schema.items.type
277
+ type = `array<${type}>`
278
+ }
279
+
280
+ content.text += ` <${bold(type)}>`
281
+ } else {
282
+ if (schema.not != null && typeof schema.not === 'object') {
283
+ content.text += ` <${bold('any type that is not valid against the description below')}>`
284
+ customCase = 'not'
285
+ } else if (Array.isArray(schema.anyOf)) {
286
+ content.text += ` <${bold('any type that is valid against at least with one of the descriptions below')}>`
287
+ customCase = 'anyOf'
288
+ } else if (Array.isArray(schema.allOf)) {
289
+ content.text += ` <${bold('any type that is valid against all the descriptions below')}>`
290
+ customCase = 'allOf'
291
+ } else if (Array.isArray(schema.oneOf)) {
292
+ content.text += ` <${bold('any type that is valid against just one of the descriptions below')}>`
293
+ customCase = 'oneOf'
294
+ } else if (schema.description != null) {
295
+ content.text += ` <${bold('any')}>`
296
+ } else {
297
+ // only schemas structures that are not implemented gets printed in raw form,
298
+ // this means that we should analize the raw schema printed and then support it
299
+ content.text += ` <raw schema: ${JSON.stringify(schema)}>`
300
+ }
301
+ }
302
+
303
+ if (isRequired) {
304
+ content.text += ` (${bold('required')})`
305
+ }
306
+
307
+ if (
308
+ defaults &&
309
+ typeof defaults === 'object' &&
310
+ defaults[propName] !== undefined &&
311
+ (
312
+ typeof defaults[propName] === 'string' ||
313
+ typeof defaults[propName] === 'boolean' ||
314
+ typeof defaults[propName] === 'number' ||
315
+ defaults[propName] === null
316
+ )
317
+ ) {
318
+ defaultToUse = defaults[propName]
319
+ } else if (schema.default !== undefined) {
320
+ defaultToUse = schema.default
321
+ } else if (schema.defaultNotInitialized !== undefined) {
322
+ defaultToUse = schema.defaultNotInitialized
323
+
324
+ if (typeof defaultToUse === 'string' && /^<.*>$/.test(defaultToUse)) {
325
+ shouldStringifyDefault = false
326
+ }
327
+ }
328
+
329
+ if (defaultToUse !== undefined) {
330
+ if (shouldStringifyDefault) {
331
+ content.text += ` (default: ${bold(JSON.stringify(defaultToUse))})`
332
+ } else {
333
+ content.text += ` (default: ${bold(defaultToUse)})`
334
+ }
335
+ }
336
+
337
+ let allowed
338
+
339
+ if (schema.enum != null) {
340
+ allowed = schema.enum
341
+ } else if (schema.type === 'string' && schema['$jsreport-constantOrArray'] != null) {
342
+ allowed = schema['$jsreport-constantOrArray']
343
+ }
344
+
345
+ if (Array.isArray(allowed) && allowed.length > 0) {
346
+ content.text += ` (allowed values: ${bold(allowed.map((value) => {
347
+ return JSON.stringify(value)
348
+ }).join(', '))})`
349
+ }
350
+
351
+ if (
352
+ typeof schema.type === 'string' ||
353
+ (Array.isArray(schema.type) && schema.type.indexOf('string') !== -1)
354
+ ) {
355
+ if (schema.format != null) {
356
+ content.text += ` (format: ${schema.format})`
357
+ }
358
+
359
+ if (schema.pattern != null) {
360
+ content.text += ` (pattern: ${schema.pattern})`
361
+ }
362
+ }
363
+
364
+ if (printRestProps) {
365
+ const restProps = omit(schema, knowProps)
366
+
367
+ if (restProps && Object.keys(restProps).length > 0) {
368
+ content.text += ` (raw schema: ${JSON.stringify(restProps)})`
369
+ }
370
+ }
371
+
372
+ if (schema.description != null) {
373
+ content.text += ` -> ${schema.description}`
374
+ }
375
+
376
+ if (
377
+ schema.type === 'object' &&
378
+ schema.properties != null &&
379
+ Object.keys(schema.properties).length > 0
380
+ ) {
381
+ content.text += ' {'
382
+ } else if (
383
+ schema.type === 'array' &&
384
+ (Array.isArray(schema.items) ||
385
+ (schema.items &&
386
+ schema.items.type &&
387
+ schema.items.type === 'object' &&
388
+ schema.items.properties != null &&
389
+ Object.keys(schema.items.properties).length > 0))
390
+ ) {
391
+ content.text += ' ['
392
+ } else if (!isLastKey && propName !== '') {
393
+ content.text += ','
394
+ }
395
+
396
+ ui.div(content)
397
+
398
+ if (customCase != null) {
399
+ if (customCase === 'not') {
400
+ printProperties(ui, [['', schema.not]], { level: level + 1 })
401
+ } else if (
402
+ (customCase === 'anyOf' ||
403
+ customCase === 'allOf' ||
404
+ customCase === 'oneOf') &&
405
+ Array.isArray(schema[customCase]) &&
406
+ schema[customCase].length > 0
407
+ ) {
408
+ printProperties(ui, schema[customCase].map((s) => {
409
+ return ['', s]
410
+ }), { level: level + 1, printRestProps: true })
411
+ }
412
+ } else if (
413
+ schema.type === 'object' &&
414
+ schema.properties != null &&
415
+ Object.keys(schema.properties).length > 0
416
+ ) {
417
+ const hasDefault = (
418
+ defaults &&
419
+ typeof defaults === 'object' &&
420
+ typeof defaults[propName] === 'object'
421
+ )
422
+
423
+ printProperties(ui, schema.properties, {
424
+ level: level + 1,
425
+ required: schema.required,
426
+ defaults: hasDefault ? defaults[propName] : undefined
427
+ })
428
+
429
+ ui.div({ text: `}${!isLastKey ? ',' : ''}`, padding: content.padding })
430
+ } else if (
431
+ schema.type === 'array' &&
432
+ schema.items &&
433
+ schema.items.type === 'object' &&
434
+ schema.items.properties != null &&
435
+ Object.keys(schema.items.properties).length > 0
436
+ ) {
437
+ ui.div({ text: '{', padding: getPadding(level + 1) })
438
+
439
+ printProperties(ui, schema.items.properties, {
440
+ level: level + 2,
441
+ required: schema.items.required
442
+ })
443
+
444
+ ui.div({ text: '}', padding: getPadding(level + 1) })
445
+ ui.div({ text: `]${!isLastKey ? ',' : ''}`, padding: content.padding })
446
+ } else if (schema.type === 'array' && Array.isArray(schema.items)) {
447
+ printProperties(ui, schema.items.map((s, idx) => {
448
+ return [`item at ${idx} index should be`, s]
449
+ }), { level: level + 1 })
450
+ ui.div({ text: `]${!isLastKey ? ',' : ''}`, padding: content.padding })
451
+ }
452
+ })
453
+ }