@manyos/smileconnect-api 1.71.8 → 1.72.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.
- package/conf/clients.json +33 -2
- package/docs/releases.md +3 -0
- package/package.json +1 -1
- package/util/config.js +152 -40
package/conf/clients.json
CHANGED
|
@@ -2693,7 +2693,38 @@
|
|
|
2693
2693
|
},
|
|
2694
2694
|
"scriptEndpoints": {
|
|
2695
2695
|
"personData": {
|
|
2696
|
-
"options": {
|
|
2696
|
+
"options": {
|
|
2697
|
+
"openAPISpec": {
|
|
2698
|
+
"summary": "Bla bla",
|
|
2699
|
+
"decription": "Bla bla bla bla bla",
|
|
2700
|
+
"requestSchema": {
|
|
2701
|
+
"type": "object",
|
|
2702
|
+
"properties": {
|
|
2703
|
+
"loginid": {
|
|
2704
|
+
"type": "string",
|
|
2705
|
+
"maxLength": 15,
|
|
2706
|
+
"description": "Login ID"
|
|
2707
|
+
}
|
|
2708
|
+
},
|
|
2709
|
+
"required": [
|
|
2710
|
+
"loginid"
|
|
2711
|
+
]
|
|
2712
|
+
},
|
|
2713
|
+
"responseSchema": {
|
|
2714
|
+
"type": "object",
|
|
2715
|
+
"properties": {
|
|
2716
|
+
"approver": {
|
|
2717
|
+
"type": "string",
|
|
2718
|
+
"description": "Approver username"
|
|
2719
|
+
}
|
|
2720
|
+
},
|
|
2721
|
+
"required": [
|
|
2722
|
+
"approver"
|
|
2723
|
+
]
|
|
2724
|
+
},
|
|
2725
|
+
"description": "Run scripts associated with this endpoint"
|
|
2726
|
+
}
|
|
2727
|
+
},
|
|
2697
2728
|
"scripts": [
|
|
2698
2729
|
"script1_env",
|
|
2699
2730
|
"script1"
|
|
@@ -2702,4 +2733,4 @@
|
|
|
2702
2733
|
}
|
|
2703
2734
|
}
|
|
2704
2735
|
}
|
|
2705
|
-
]
|
|
2736
|
+
]
|
package/docs/releases.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
3
|
## API
|
|
4
|
+
### 1.72.1 - 13.11.25
|
|
5
|
+
Improve OpenAPI Documentation generation. Add requestBody for POST and put requests. Allow custom definition for scriptendpoints.
|
|
6
|
+
|
|
4
7
|
### 1.71.8 - 22.10.25
|
|
5
8
|
Fix error when include classAttributes was used in CI Search
|
|
6
9
|
|
package/package.json
CHANGED
package/util/config.js
CHANGED
|
@@ -11,6 +11,8 @@ const mappingUtil = require('../util/mappingUtil');
|
|
|
11
11
|
const CacheService = require ('../util/cache.service');
|
|
12
12
|
|
|
13
13
|
const CONSTANTS = require('./constants');
|
|
14
|
+
const {response} = require("express");
|
|
15
|
+
const {get} = require("mongoose");
|
|
14
16
|
|
|
15
17
|
const configFileCustomFormMapping = 'conf/customFormMapping.json';
|
|
16
18
|
|
|
@@ -321,6 +323,35 @@ function checkClientConfig(client) {
|
|
|
321
323
|
updateRequired = true;
|
|
322
324
|
}
|
|
323
325
|
|
|
326
|
+
const scriptEnpointKeys = Object.keys(clientConfig.scriptEndpoints);
|
|
327
|
+
scriptEnpointKeys.forEach(scriptEnpointKey => {
|
|
328
|
+
const scriptEnpointConfig = clientConfig.scriptEndpoints[scriptEnpointKey];
|
|
329
|
+
if (!scriptEnpointConfig.options) {
|
|
330
|
+
scriptEnpointConfig.options = {};
|
|
331
|
+
updateRequired = true;
|
|
332
|
+
}
|
|
333
|
+
if (!scriptEnpointConfig.options.openAPISpec) {
|
|
334
|
+
scriptEnpointConfig.options.openAPISpec = {};
|
|
335
|
+
updateRequired = true;
|
|
336
|
+
}
|
|
337
|
+
if (!scriptEnpointConfig.options.openAPISpec.summary) {
|
|
338
|
+
scriptEnpointConfig.options.openAPISpec.summary = "Run scripts associated with this endpoint";
|
|
339
|
+
updateRequired = true;
|
|
340
|
+
}
|
|
341
|
+
if (!scriptEnpointConfig.options.openAPISpec.description) {
|
|
342
|
+
scriptEnpointConfig.options.openAPISpec.description = "Run scripts associated with this endpoint";
|
|
343
|
+
updateRequired = true;
|
|
344
|
+
}
|
|
345
|
+
if (!scriptEnpointConfig.options.openAPISpec.requestSchema) {
|
|
346
|
+
scriptEnpointConfig.options.openAPISpec.requestSchema = {};
|
|
347
|
+
updateRequired = true;
|
|
348
|
+
}
|
|
349
|
+
if (!scriptEnpointConfig.options.openAPISpec.responseSchema) {
|
|
350
|
+
scriptEnpointConfig.options.openAPISpec.responseSchema = {};
|
|
351
|
+
updateRequired = true;
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
324
355
|
if (clientConfig.options.translateSelectionFields === undefined) {
|
|
325
356
|
clientConfig.options.translateSelectionFields = true;
|
|
326
357
|
updateRequired = true;
|
|
@@ -396,11 +427,13 @@ async function getDesignPackage(clientId) {
|
|
|
396
427
|
if (clientObjectConfig.fields && clientObjectConfig.fields.length > 0){
|
|
397
428
|
const mapping = getDeprecatedMappingAsCustom(config.requestType)
|
|
398
429
|
schemas[config.requestType] = await getObjectSchema(clientObjectConfig.fields, mapping, config.forms.regular)
|
|
430
|
+
schemas[config.requestType+'_create_update'] = await getObjectSchema(clientObjectConfig.fields, mapping, config.forms.regular, true)
|
|
399
431
|
paths = {...paths, ... await getPathDef(config.assocTicketType, config.baseURI, config.requestType)}
|
|
400
432
|
}
|
|
401
433
|
if (config.requestTypeWorkLog && clientConfig[config.requestTypeWorkLog].fields && clientConfig[config.requestTypeWorkLog].fields.length > 0) {
|
|
402
434
|
const mapping = getDeprecatedMappingAsCustom(config.requestTypeWorkLog)
|
|
403
435
|
schemas[config.requestTypeWorkLog] = await getObjectSchema(clientConfig[config.requestTypeWorkLog].fields, mapping, config.forms.workLog)
|
|
436
|
+
schemas[config.requestTypeWorkLog + '_create_update'] = await getObjectSchema(clientConfig[config.requestTypeWorkLog].fields, mapping, config.forms.workLog, true)
|
|
404
437
|
paths = {...paths, ... await getPathDef(config.assocTicketType, config.baseURI + '/{ticketId}/worklogs', config.requestTypeWorkLog, true, true)}
|
|
405
438
|
}
|
|
406
439
|
if (config.requestTemplate && clientConfig[config.requestTemplate].fields && clientConfig[config.requestTemplate].fields.length > 0) {
|
|
@@ -454,7 +487,8 @@ async function getDesignPackage(clientId) {
|
|
|
454
487
|
const clientObjectConfig = clientConfig[`custom_${formName}`]
|
|
455
488
|
log.debug('key', key, clientObjectConfig)
|
|
456
489
|
if (clientObjectConfig) {
|
|
457
|
-
schemas[key] = await getObjectSchema(clientObjectConfig.fields, customFormMappings[key].mapping, formName)
|
|
490
|
+
schemas[key] = await getObjectSchema(clientObjectConfig.fields, customFormMappings[key].mapping, formName);
|
|
491
|
+
schemas[key+'_create_update'] = await getObjectSchema(clientObjectConfig.fields, customFormMappings[key].mapping, formName, true);
|
|
458
492
|
paths = {...paths, ... await getPathDef(key, '/v1/customForms/' + key, key)}
|
|
459
493
|
}
|
|
460
494
|
}
|
|
@@ -465,18 +499,21 @@ async function getDesignPackage(clientId) {
|
|
|
465
499
|
const scriptKeys = Object.keys(clientConfig.scriptEndpoints)
|
|
466
500
|
for (let x=0; x < scriptKeys.length; x++) {
|
|
467
501
|
const key = scriptKeys[x]
|
|
502
|
+
const endpointConfig = clientConfig.scriptEndpoints[key];
|
|
503
|
+
const openAPISpec = endpointConfig.options.openAPISpec;
|
|
468
504
|
log.debug('key', key)
|
|
469
|
-
//schemas[key] = await getObjectSchema(clientObjectConfig.fields, customFormMappings[key].mapping, formName)
|
|
470
505
|
const pathDef = {}
|
|
471
506
|
pathDef[`/v1/scriptEndpoints/${key}`] = {};
|
|
472
507
|
pathDef[`/v1/scriptEndpoints/${key}`].post = {
|
|
473
508
|
tags: [key],
|
|
474
|
-
summary: `Run scripts associated with this endpoint`,
|
|
475
|
-
description: "Run scripts associated that are associated with this endpoint. The return Schema is defined in the scripts.",
|
|
509
|
+
summary: openAPISpec.summary || `Run scripts associated with this endpoint`,
|
|
510
|
+
description: openAPISpec.decription || "Run scripts associated that are associated with this endpoint. The return Schema is defined in the scripts.",
|
|
476
511
|
parameters: [],
|
|
477
|
-
responses: await getApiResponse("scriptEndpoint_" + key, true)
|
|
512
|
+
responses: await getApiResponse("scriptEndpoint_" + key, true),
|
|
513
|
+
requestBody: await getApiRequestBody("scriptEndpoint_" + key)
|
|
478
514
|
}
|
|
479
|
-
schemas["scriptEndpoint_" + key] = {};
|
|
515
|
+
schemas["scriptEndpoint_" + key] = openAPISpec.responseSchema || {};
|
|
516
|
+
schemas["scriptEndpoint_" + key + '_create_update'] = openAPISpec.requestSchema || {};
|
|
480
517
|
paths = {...paths, ... pathDef}
|
|
481
518
|
}
|
|
482
519
|
}
|
|
@@ -486,6 +523,7 @@ async function getDesignPackage(clientId) {
|
|
|
486
523
|
|
|
487
524
|
if (clientConfig.cmdbobject && clientConfig.cmdbobject.fields) {
|
|
488
525
|
schemas['cmdbobject'] = await getObjectSchema(clientConfig.cmdbobject.fields, cmdbMapping, 'AST:BaseElement')
|
|
526
|
+
schemas['cmdbobject_create_update'] = await getObjectSchema(clientConfig.cmdbobject.fields, cmdbMapping, 'AST:BaseElement', true)
|
|
489
527
|
|
|
490
528
|
|
|
491
529
|
const cmdbdef = Object.keys(clientConfig.cmdbobject)
|
|
@@ -505,6 +543,10 @@ async function getDesignPackage(clientId) {
|
|
|
505
543
|
required: schemas['cmdbobject'].required.concat(classSchema.required),
|
|
506
544
|
properties: {...schemas['cmdbobject'].properties, ...classSchema.properties}
|
|
507
545
|
}
|
|
546
|
+
schemas[`${schemaName}_create_update`] = {
|
|
547
|
+
required: schemas['cmdbobject'].required.concat(classSchema.required),
|
|
548
|
+
properties: {...schemas['cmdbobject'].properties, ...classSchema.properties}
|
|
549
|
+
}
|
|
508
550
|
log.debug('customForm', formName, fields, classMapping, classSchema)
|
|
509
551
|
}
|
|
510
552
|
|
|
@@ -551,7 +593,7 @@ async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpda
|
|
|
551
593
|
tags: tag,
|
|
552
594
|
summary: `Get a single ${objectName} object by id`,
|
|
553
595
|
description: "A single object is returned in the data attribute",
|
|
554
|
-
parameters:
|
|
596
|
+
parameters: getOpenApiParameters('get'),
|
|
555
597
|
responses: await getApiResponse(schema, true)
|
|
556
598
|
}
|
|
557
599
|
}
|
|
@@ -560,8 +602,9 @@ async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpda
|
|
|
560
602
|
tags: tag,
|
|
561
603
|
summary: `Update an object of type ${objectName}`,
|
|
562
604
|
description: "A single object is returned in the data attribute",
|
|
563
|
-
parameters:
|
|
564
|
-
responses: await getApiResponse(schema, true)
|
|
605
|
+
parameters: getOpenApiParameters('put'),
|
|
606
|
+
responses: await getApiResponse(schema, true),
|
|
607
|
+
requestBody: await getApiRequestBody(schema)
|
|
565
608
|
}
|
|
566
609
|
}
|
|
567
610
|
|
|
@@ -570,7 +613,7 @@ async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpda
|
|
|
570
613
|
tags: tag,
|
|
571
614
|
summary: `Get a list of object of type ${objectName}`,
|
|
572
615
|
description: "An array ob objects is returned in the data attribute",
|
|
573
|
-
parameters:
|
|
616
|
+
parameters: getOpenApiParameters('getAll'),
|
|
574
617
|
responses: await getApiResponse(schema, false)
|
|
575
618
|
}
|
|
576
619
|
}
|
|
@@ -579,8 +622,9 @@ async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpda
|
|
|
579
622
|
tags: tag,
|
|
580
623
|
summary: `Create a new object of type ${objectName}`,
|
|
581
624
|
description: "A single object is returned in the data attribute",
|
|
582
|
-
parameters:
|
|
583
|
-
responses: await getApiResponse(schema, false)
|
|
625
|
+
parameters: getOpenApiParameters('post'),
|
|
626
|
+
responses: await getApiResponse(schema, false),
|
|
627
|
+
requestBody: await getApiRequestBody(schema)
|
|
584
628
|
}
|
|
585
629
|
}
|
|
586
630
|
if (isSubTicket) {
|
|
@@ -589,6 +633,43 @@ async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpda
|
|
|
589
633
|
return pathDef
|
|
590
634
|
}
|
|
591
635
|
|
|
636
|
+
function getOpenApiParameters(operation) {
|
|
637
|
+
const parameters = [
|
|
638
|
+
{
|
|
639
|
+
"examples": {
|
|
640
|
+
"sample": {
|
|
641
|
+
"value": "user123"
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
"name": "impersonateUser",
|
|
645
|
+
"description": "If the clientConfig has the option allowDynamicImpersonate set to *true* then the URL Parameter *impersonateUser* can be used to determine the used Remedy User.",
|
|
646
|
+
"schema": {
|
|
647
|
+
"type": "string"
|
|
648
|
+
},
|
|
649
|
+
"in": "query",
|
|
650
|
+
"required": false
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"examples": {
|
|
654
|
+
"include": {
|
|
655
|
+
"value": "ciRelations,ticketRelations"
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
"name": "include",
|
|
659
|
+
"description": "Defines if and which related objects shoudl be included.\nPossible values:\nciRelations,ticketRelations,personRelations,organisationRelations,supportGroupRelations,persons,supportGroups,organisations,cmdbObjects,incidents,workOrders,changes, problems",
|
|
660
|
+
"schema": {
|
|
661
|
+
"type": "array",
|
|
662
|
+
"items": {
|
|
663
|
+
"type": "string"
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
"in": "query",
|
|
667
|
+
"required": false
|
|
668
|
+
}
|
|
669
|
+
]
|
|
670
|
+
return parameters;
|
|
671
|
+
}
|
|
672
|
+
|
|
592
673
|
async function getApiResponse(schema, single) {
|
|
593
674
|
let dataValue = {
|
|
594
675
|
"$ref": `#/components/schemas/${schema}`
|
|
@@ -628,7 +709,35 @@ async function getApiResponse(schema, single) {
|
|
|
628
709
|
return responses
|
|
629
710
|
}
|
|
630
711
|
|
|
631
|
-
async function
|
|
712
|
+
async function getApiRequestBody(schema) {
|
|
713
|
+
let dataValue = {
|
|
714
|
+
"$ref": `#/components/schemas/${schema}_create_update`
|
|
715
|
+
}
|
|
716
|
+
if (Array.isArray(schema)) {
|
|
717
|
+
dataValue = {
|
|
718
|
+
oneOf: schema.map(item => {
|
|
719
|
+
return {
|
|
720
|
+
"$ref": `#/components/schemas/${item}_create_update`
|
|
721
|
+
}
|
|
722
|
+
})
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return requestBody = {
|
|
726
|
+
content: {
|
|
727
|
+
"application/json": {
|
|
728
|
+
schema: {
|
|
729
|
+
type: "object",
|
|
730
|
+
properties: {
|
|
731
|
+
data: dataValue
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
required: true
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
async function getObjectSchema(clientFields, mapping, formName, isCreateUpdate = false) {
|
|
632
741
|
const fields = await getFields(formName)
|
|
633
742
|
const required = []
|
|
634
743
|
const properties = {}
|
|
@@ -638,37 +747,40 @@ async function getObjectSchema(clientFields, mapping, formName) {
|
|
|
638
747
|
const fieldDef = {}
|
|
639
748
|
const fieldDetails = fields.find(item => item.name === field)
|
|
640
749
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
if (fieldDetails
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
fieldDef.maxLength = fieldDetails.fieldLimit.maxLength
|
|
648
|
-
}
|
|
649
|
-
if (fieldDetails.type === 'SelectionField') {
|
|
650
|
-
fieldDef.type = 'string'
|
|
651
|
-
if (fieldDetails.fieldLimit && fieldDetails.fieldLimit.values) {
|
|
652
|
-
const enumVals = fieldDetails.fieldLimit.values.map(item => item.enumItemName)
|
|
653
|
-
fieldDef.enum = enumVals
|
|
654
|
-
} else if (fieldDetails.fieldLimit && fieldDetails.fieldLimit.valueMapping) {
|
|
655
|
-
const enumVals = Object.values(fieldDetails.fieldLimit.valueMapping)
|
|
656
|
-
fieldDef.enum = enumVals
|
|
750
|
+
// remove id field from create/update schema
|
|
751
|
+
if (!isCreateUpdate || mappedName !== 'id') {
|
|
752
|
+
if (fieldDetails) {
|
|
753
|
+
fieldDef.type = fieldDetails.type
|
|
754
|
+
if (fieldDetails.entryMode === 'Required') {
|
|
755
|
+
required.push(mappedName)
|
|
657
756
|
}
|
|
757
|
+
if(fieldDetails.fieldLimit) {
|
|
758
|
+
fieldDef.maxLength = fieldDetails.fieldLimit.maxLength
|
|
759
|
+
}
|
|
760
|
+
if (fieldDetails.type === 'SelectionField') {
|
|
761
|
+
fieldDef.type = 'string'
|
|
762
|
+
if (fieldDetails.fieldLimit && fieldDetails.fieldLimit.values) {
|
|
763
|
+
const enumVals = fieldDetails.fieldLimit.values.map(item => item.enumItemName)
|
|
764
|
+
fieldDef.enum = enumVals
|
|
765
|
+
} else if (fieldDetails.fieldLimit && fieldDetails.fieldLimit.valueMapping) {
|
|
766
|
+
const enumVals = Object.values(fieldDetails.fieldLimit.valueMapping)
|
|
767
|
+
fieldDef.enum = enumVals
|
|
768
|
+
}
|
|
658
769
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
770
|
+
} else if (fieldDetails.type === 'CharacterField') {
|
|
771
|
+
fieldDef.type = 'string'
|
|
772
|
+
} else if (fieldDetails.type === 'DateTimeField') {
|
|
773
|
+
fieldDef.type = 'string'
|
|
774
|
+
fieldDef.format = 'date-time'
|
|
775
|
+
} else if (fieldDetails.type === 'DateField') {
|
|
776
|
+
fieldDef.format = 'date'
|
|
777
|
+
} else if (fieldDetails.type === 'DecimalField') {
|
|
778
|
+
fieldDef.type = 'number'
|
|
779
|
+
}
|
|
780
|
+
//fieldDef.details = fieldDetails
|
|
668
781
|
}
|
|
669
|
-
|
|
782
|
+
properties[mappedName] = fieldDef
|
|
670
783
|
}
|
|
671
|
-
properties[mappedName] = fieldDef
|
|
672
784
|
})
|
|
673
785
|
//mappedFields.push(fields)
|
|
674
786
|
return {required, properties}
|