massimo-cli 1.0.1 → 1.2.0

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/help/help.txt CHANGED
@@ -75,6 +75,6 @@ Options:
75
75
  * `--types-comment` - Add a comment at the beginning of the auto generated `.d.ts` type definition.
76
76
  * `--with-credentials` - Adds "credentials: 'include'" to all fetch requests (only for frontend clients).
77
77
  * `--props-optional` - If `true`, properties will be defined as optional unless they're part of the `required` array. By default this option is `true`.
78
- * `--skip-config-update` - If `true`, it will not update the `platformatic|watt` config found in your repo. By default this option is `true`.
79
78
  * `--retry-timeout-ms` - If passed, the HTTP request to get an Open API schema will be retried (reference: https://undici.nodejs.org/#/docs/api/RetryHandler.md)
80
79
  * `--type-extension` - Force the use of module-specific type extensions (.d.mts for ESM, .d.cts for CJS) instead of the default logic.
80
+ * `--skip-prefixed-url` - If passed, it will avoid unnecessary extra HTTP call to check if, for instance, the `/documentation/json` Open API URL exists
package/index.js CHANGED
@@ -428,7 +428,8 @@ async function downloadAndProcess (options) {
428
428
  retryTimeoutMs,
429
429
  moduleFormat,
430
430
  typeExtension,
431
- explicitModuleFormat
431
+ explicitModuleFormat,
432
+ skipPrefixedUrl
432
433
  } = options
433
434
 
434
435
  const generateImplementation = options.generateImplementation
@@ -437,31 +438,33 @@ async function downloadAndProcess (options) {
437
438
  const toTry = []
438
439
  if (url.startsWith('http')) {
439
440
  if (type === 'openapi') {
440
- toTry.push(
441
- downloadAndWriteOpenAPI.bind(
442
- null,
443
- logger,
444
- url + '/documentation/json',
445
- folder,
446
- name,
447
- generateImplementation,
448
- typesOnly,
449
- fullRequest,
450
- fullResponse,
451
- optionalHeaders,
452
- validateResponse,
453
- isFrontend,
454
- language,
455
- urlAuthHeaders,
456
- typesComment,
457
- withCredentials,
458
- propsOptional,
459
- retryTimeoutMs,
460
- moduleFormat,
461
- typeExtension,
462
- explicitModuleFormat
441
+ if (!skipPrefixedUrl) {
442
+ toTry.push(
443
+ downloadAndWriteOpenAPI.bind(
444
+ null,
445
+ logger,
446
+ url + '/documentation/json',
447
+ folder,
448
+ name,
449
+ generateImplementation,
450
+ typesOnly,
451
+ fullRequest,
452
+ fullResponse,
453
+ optionalHeaders,
454
+ validateResponse,
455
+ isFrontend,
456
+ language,
457
+ urlAuthHeaders,
458
+ typesComment,
459
+ withCredentials,
460
+ propsOptional,
461
+ retryTimeoutMs,
462
+ moduleFormat,
463
+ typeExtension,
464
+ explicitModuleFormat
465
+ )
463
466
  )
464
- )
467
+ }
465
468
  toTry.push(
466
469
  downloadAndWriteOpenAPI.bind(
467
470
  null,
@@ -488,19 +491,21 @@ async function downloadAndProcess (options) {
488
491
  )
489
492
  )
490
493
  } else if (options.type === 'graphql') {
491
- toTry.push(
492
- downloadAndWriteGraphQL.bind(
493
- null,
494
- logger,
495
- url + '/graphql',
496
- folder,
497
- name,
498
- generateImplementation,
499
- moduleFormat,
500
- typeExtension,
501
- explicitModuleFormat
494
+ if (!skipPrefixedUrl) {
495
+ toTry.push(
496
+ downloadAndWriteGraphQL.bind(
497
+ null,
498
+ logger,
499
+ url + '/graphql',
500
+ folder,
501
+ name,
502
+ generateImplementation,
503
+ moduleFormat,
504
+ typeExtension,
505
+ explicitModuleFormat
506
+ )
502
507
  )
503
- )
508
+ }
504
509
  toTry.push(
505
510
  downloadAndWriteGraphQL.bind(
506
511
  null,
@@ -516,44 +521,46 @@ async function downloadAndProcess (options) {
516
521
  )
517
522
  } else {
518
523
  // add download functions only if it's an URL
519
- toTry.push(
520
- downloadAndWriteOpenAPI.bind(
521
- null,
522
- logger,
523
- url + '/documentation/json',
524
- folder,
525
- name,
526
- generateImplementation,
527
- typesOnly,
528
- fullRequest,
529
- fullResponse,
530
- optionalHeaders,
531
- validateResponse,
532
- isFrontend,
533
- language,
534
- urlAuthHeaders,
535
- typesComment,
536
- withCredentials,
537
- propsOptional,
538
- retryTimeoutMs,
539
- moduleFormat,
540
- typeExtension,
541
- explicitModuleFormat
524
+ if (!skipPrefixedUrl) {
525
+ toTry.push(
526
+ downloadAndWriteOpenAPI.bind(
527
+ null,
528
+ logger,
529
+ url + '/documentation/json',
530
+ folder,
531
+ name,
532
+ generateImplementation,
533
+ typesOnly,
534
+ fullRequest,
535
+ fullResponse,
536
+ optionalHeaders,
537
+ validateResponse,
538
+ isFrontend,
539
+ language,
540
+ urlAuthHeaders,
541
+ typesComment,
542
+ withCredentials,
543
+ propsOptional,
544
+ retryTimeoutMs,
545
+ moduleFormat,
546
+ typeExtension,
547
+ explicitModuleFormat
548
+ )
542
549
  )
543
- )
544
- toTry.push(
545
- downloadAndWriteGraphQL.bind(
546
- null,
547
- logger,
548
- url + '/graphql',
549
- folder,
550
- name,
551
- generateImplementation,
552
- moduleFormat,
553
- typeExtension,
554
- explicitModuleFormat
550
+ toTry.push(
551
+ downloadAndWriteGraphQL.bind(
552
+ null,
553
+ logger,
554
+ url + '/graphql',
555
+ folder,
556
+ name,
557
+ generateImplementation,
558
+ moduleFormat,
559
+ typeExtension,
560
+ explicitModuleFormat
561
+ )
555
562
  )
556
- )
563
+ }
557
564
  toTry.push(
558
565
  downloadAndWriteOpenAPI.bind(
559
566
  null,
@@ -681,13 +688,14 @@ export async function command (argv) {
681
688
  'frontend',
682
689
  'validate-response',
683
690
  'props-optional',
684
- 'skip-config-update',
685
- 'type-extension'
691
+ 'type-extension',
692
+ 'skip-prefixed-url'
686
693
  ],
687
694
  default: {
688
695
  typescript: false,
689
696
  language: 'js',
690
- full: true
697
+ full: true,
698
+ 'props-optional': true
691
699
  },
692
700
  alias: {
693
701
  n: 'name',
@@ -729,7 +737,7 @@ export async function command (argv) {
729
737
 
730
738
  options.fullRequest = options['full-request']
731
739
  options.fullResponse = options['full-response']
732
- options.propsOptional = options['props-optional'] ?? true
740
+ options.propsOptional = options['props-optional']
733
741
 
734
742
  options.optionalHeaders = options['optional-headers']
735
743
  ? options['optional-headers'].split(',').map((h) => h.trim())
@@ -748,9 +756,9 @@ export async function command (argv) {
748
756
  options.urlAuthHeaders = options['url-auth-headers']
749
757
  options.typesComment = options['types-comment']
750
758
  options.withCredentials = options['with-credentials']
751
- options.skipConfigUpdate = options['skip-config-update'] ?? true
752
759
  options.retryTimeoutMs = options['retry-timeout-ms']
753
760
  options.typeExtension = options['type-extension']
761
+ options.skipPrefixedUrl = options['skip-prefixed-url']
754
762
  options.explicitModuleFormat = !!options.module
755
763
  await downloadAndProcess({ url, ...options, logger })
756
764
  logger.info(`Client generated successfully into ${options.folder}`)
package/lib/get-type.js CHANGED
@@ -65,18 +65,22 @@ export function getType (typeDef, methodType, spec) {
65
65
  return `Array<${getType(typeDef.items, methodType, spec)}>${nullable === true ? ' | null' : ''}`
66
66
  }
67
67
  if (typeDef.enum) {
68
+ // Note: null type represented with an enum have no types and single enum element 'null'
69
+ if (typeDef.type === undefined && typeDef.enum.includes('null')) {
70
+ // Ignore `nullable` as it is implied by the enum
71
+ return 'null'
72
+ }
68
73
  const nullable = typeDef.nullable
69
- return (
70
- typeDef.enum
71
- .map(en => {
72
- if (typeDef.type === 'string') {
73
- return `'${en.replace(/'/g, "\\'")}'`
74
- } else {
75
- return en
76
- }
77
- })
78
- .join(' | ') + (nullable === true ? ' | null' : '')
79
- )
74
+ const chainedTypes = typeDef.enum
75
+ .map(en => {
76
+ if (typeDef.type === 'string') {
77
+ return `'${en.replace(/'/g, "\\'")}'`
78
+ } else {
79
+ return en
80
+ }
81
+ })
82
+ .join(' | ')
83
+ return nullable === true ? `${chainedTypes} | null` : chainedTypes
80
84
  }
81
85
  if (typeDef.type === 'object') {
82
86
  const additionalProps = typeDef?.additionalProperties
@@ -137,8 +141,8 @@ function JSONSchemaToTsType ({ type, format, nullable }, methodType) {
137
141
  resultType = 'boolean'
138
142
  break
139
143
  case 'null':
140
- resultType = 'null'
141
- break
144
+ // Remove duplication, no need to make it nullable later, return directly
145
+ return 'null'
142
146
  // TODO what other types should we support here?
143
147
  }
144
148
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "massimo-cli",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "A client for HTTP services.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -30,13 +30,13 @@
30
30
  "pino-pretty": "^13.0.0",
31
31
  "undici": "^7.0.0",
32
32
  "yaml": "^2.4.1",
33
- "massimo": "1.0.1"
33
+ "massimo": "1.2.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@platformatic/composer": "3.0.0-alpha.6",
36
+ "@platformatic/composer": "3.17.0",
37
37
  "@platformatic/db": "3.0.0-alpha.6",
38
- "@platformatic/foundation": "3.0.0-alpha.6",
39
- "@platformatic/runtime": "3.0.0-alpha.6",
38
+ "@platformatic/foundation": "3.17.0",
39
+ "@platformatic/runtime": "3.16.0",
40
40
  "@platformatic/service": "3.0.0-alpha.6",
41
41
  "@platformatic/sql-graphql": "3.0.0-alpha.6",
42
42
  "@platformatic/sql-mapper": "3.0.0-alpha.6",
@@ -54,7 +54,7 @@
54
54
  "neostandard": "^0.12.0",
55
55
  "react": "^19.1.0",
56
56
  "react-dom": "^19.1.0",
57
- "scheduler": "^0.26.0",
57
+ "scheduler": "^0.27.0",
58
58
  "split2": "^4.2.0",
59
59
  "tsd": "^0.32.0",
60
60
  "typescript": "^5.5.4",