@manyos/smileconnect-api 1.73.0 → 1.74.2
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/.claude/settings.local.json +7 -1
- package/Dockerfile +1 -1
- package/controller/scriptController.js +1 -1
- package/docs/releases.md +9 -0
- package/package.json +2 -2
- package/routes/appConfigRoutes.js +4 -4
- package/util/config.js +33 -16
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
"allow": [
|
|
4
4
|
"Bash(cat:*)",
|
|
5
5
|
"Bash(find:*)",
|
|
6
|
-
"Bash(xargs ls:*)"
|
|
6
|
+
"Bash(xargs ls:*)",
|
|
7
|
+
"Bash(npm view *)",
|
|
8
|
+
"Bash(npm pack *)",
|
|
9
|
+
"WebFetch(domain:unpkg.com)",
|
|
10
|
+
"WebFetch(domain:www.npmjs.com)",
|
|
11
|
+
"Bash(node *)",
|
|
12
|
+
"Bash(grep -E '^\\(p-queue|proper-lockfile|async-mutex|p-limit\\)$')"
|
|
7
13
|
]
|
|
8
14
|
}
|
|
9
15
|
}
|
package/Dockerfile
CHANGED
package/docs/releases.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
3
|
## API
|
|
4
|
+
### 1.74.2 - 20.05.26
|
|
5
|
+
Improve client config validation to avoid duplicate client configs.
|
|
6
|
+
|
|
7
|
+
### 1.74.1 - 12.05.26
|
|
8
|
+
Fix issue with dynamic openapi spec for worklogs.
|
|
9
|
+
|
|
10
|
+
### 1.74.0 - 29.04.26
|
|
11
|
+
Update node.js to v22 and replace request-native with native fetch in adapter.
|
|
12
|
+
|
|
4
13
|
### 1.73.0 - 28.04.26
|
|
5
14
|
Add detectMime flag to attachments & attachments to dynamic openapi spec.
|
|
6
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manyos/smileconnect-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.74.2",
|
|
4
4
|
"description": "A proxy and abstraction layer for BMCs IT Service Management Suite",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"node": ">=0.10.3"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@manyos/adapter-foundation": "^
|
|
17
|
+
"@manyos/adapter-foundation": "^2.0.0",
|
|
18
18
|
"@manyos/logger": "^1.3.0",
|
|
19
19
|
"bunyan": "^1.8.15",
|
|
20
20
|
"bunyan-express-serializer": "^1.0.0",
|
|
@@ -317,7 +317,7 @@ module.exports = (function() {
|
|
|
317
317
|
|
|
318
318
|
routes.post('/clients', isAuthorizedAdmin,
|
|
319
319
|
checkSchema(clientConfigSchema),
|
|
320
|
-
function (req, res, next) {
|
|
320
|
+
async function (req, res, next) {
|
|
321
321
|
const origData = JSON.parse(JSON.stringify(req.body));
|
|
322
322
|
setEventData(
|
|
323
323
|
req,
|
|
@@ -336,7 +336,7 @@ module.exports = (function() {
|
|
|
336
336
|
try {
|
|
337
337
|
const clientConfig = req.body.data;
|
|
338
338
|
const clientName = clientConfig.name;
|
|
339
|
-
config.setClient(clientName, clientConfig)
|
|
339
|
+
await config.setClient(clientName, clientConfig)
|
|
340
340
|
const savedClientConfig = config.getClient(clientName);
|
|
341
341
|
req.result = {
|
|
342
342
|
"data": savedClientConfig
|
|
@@ -351,7 +351,7 @@ module.exports = (function() {
|
|
|
351
351
|
|
|
352
352
|
routes.put('/clients/:id', isAuthorizedAdmin,
|
|
353
353
|
checkSchema(clientConfigSchema),
|
|
354
|
-
function (req, res, next) {
|
|
354
|
+
async function (req, res, next) {
|
|
355
355
|
const id = req.params.id;
|
|
356
356
|
const origData = JSON.parse(JSON.stringify(req.body));
|
|
357
357
|
setEventData(
|
|
@@ -370,7 +370,7 @@ module.exports = (function() {
|
|
|
370
370
|
try {
|
|
371
371
|
const clientConfig = req.body.data;
|
|
372
372
|
const clientName = clientConfig.name;
|
|
373
|
-
config.setClient(id, clientConfig);
|
|
373
|
+
await config.setClient(id, clientConfig);
|
|
374
374
|
const savedClientConfig = config.getClient(clientName);
|
|
375
375
|
req.result = {
|
|
376
376
|
"data": savedClientConfig
|
package/util/config.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const fsPromises = require('fs').promises;
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const pLimit = require('p-limit');
|
|
3
5
|
require('dotenv').config();
|
|
4
6
|
|
|
5
7
|
const path = require('path');
|
|
6
8
|
const log = require('@manyos/logger').setupLog('SMILEconnect', path.basename(__filename));
|
|
7
9
|
|
|
8
10
|
const clientConfigFile = 'conf/clients.json';
|
|
11
|
+
const clientConfigWriteLimit = pLimit(1);
|
|
9
12
|
const arquery = require('../util/arquery');
|
|
10
13
|
const mappingUtil = require('../util/mappingUtil');
|
|
11
14
|
const CacheService = require ('../util/cache.service');
|
|
@@ -123,17 +126,31 @@ function setMappings(mapping) {
|
|
|
123
126
|
return true
|
|
124
127
|
}
|
|
125
128
|
|
|
126
|
-
function setClient(clientName, clientConfig) {
|
|
129
|
+
async function setClient(clientName, clientConfig) {
|
|
127
130
|
log.debug('start to update config in file', clientConfigFile);
|
|
128
131
|
log.debug('set client data', clientName, clientConfig);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
if (!clientConfig || typeof clientConfig !== 'object' || !clientConfig.name) {
|
|
133
|
+
throw new Error('setClient: clientConfig.name is required');
|
|
134
|
+
}
|
|
135
|
+
return clientConfigWriteLimit(async () => {
|
|
136
|
+
let config;
|
|
137
|
+
try {
|
|
138
|
+
const raw = await fsPromises.readFile(clientConfigFile, 'utf8');
|
|
139
|
+
config = JSON.parse(raw);
|
|
140
|
+
} catch (e) {
|
|
141
|
+
log.warn('setClient: cannot parse existing clients.json, starting empty', e.message);
|
|
142
|
+
config = [];
|
|
143
|
+
}
|
|
144
|
+
if (!Array.isArray(config)) config = [];
|
|
145
|
+
const namesToRemove = new Set([clientName, clientConfig.name].filter(Boolean));
|
|
146
|
+
config = config.filter(obj => obj && !namesToRemove.has(obj.name));
|
|
147
|
+
config.push(clientConfig);
|
|
148
|
+
log.debug('new config size', config.length);
|
|
149
|
+
const tmp = `${clientConfigFile}.tmp.${process.pid}.${crypto.randomBytes(4).toString('hex')}`;
|
|
150
|
+
await fsPromises.writeFile(tmp, JSON.stringify(config, null, 2));
|
|
151
|
+
await fsPromises.rename(tmp, clientConfigFile);
|
|
152
|
+
return true;
|
|
132
153
|
});
|
|
133
|
-
config.push(clientConfig)
|
|
134
|
-
log.debug('new config', config);
|
|
135
|
-
fs.writeFileSync(clientConfigFile, JSON.stringify(config, null, 2));
|
|
136
|
-
return true
|
|
137
154
|
}
|
|
138
155
|
|
|
139
156
|
function deleteClient(clientName) {
|
|
@@ -243,7 +260,7 @@ async function checkCustomFormMapping() {
|
|
|
243
260
|
}
|
|
244
261
|
}
|
|
245
262
|
|
|
246
|
-
function checkClientConfig(client) {
|
|
263
|
+
async function checkClientConfig(client) {
|
|
247
264
|
let updateRequired = false;
|
|
248
265
|
const clientKeys = [
|
|
249
266
|
'cmdbobject',
|
|
@@ -361,25 +378,25 @@ function checkClientConfig(client) {
|
|
|
361
378
|
log.warn(`check config for client ${client.name} done. Update required.`);
|
|
362
379
|
client.config = clientConfig;
|
|
363
380
|
//save
|
|
364
|
-
setClient(client.name, client);
|
|
381
|
+
await setClient(client.name, client);
|
|
365
382
|
log.warn(`check config for client ${client.name} done. Update done.`);
|
|
366
383
|
}
|
|
367
384
|
log.info(`check config for client ${client.name} done. No update required.`);
|
|
368
385
|
}
|
|
369
386
|
|
|
370
|
-
function checkClientConfigs() {
|
|
387
|
+
async function checkClientConfigs() {
|
|
371
388
|
log.info('check client configs');
|
|
372
389
|
const clientConfigs = getClients();
|
|
373
|
-
|
|
374
|
-
checkClientConfig(clientConfig);
|
|
375
|
-
}
|
|
390
|
+
for (const clientConfig of clientConfigs) {
|
|
391
|
+
await checkClientConfig(clientConfig);
|
|
392
|
+
}
|
|
376
393
|
log.info('check client configs done');
|
|
377
394
|
}
|
|
378
395
|
|
|
379
396
|
async function checkConfig() {
|
|
380
397
|
log.info('check config');
|
|
381
398
|
checkMapping();
|
|
382
|
-
checkClientConfigs();
|
|
399
|
+
await checkClientConfigs();
|
|
383
400
|
await checkCustomFormMapping();
|
|
384
401
|
log.info('check config done');
|
|
385
402
|
}
|
|
@@ -434,7 +451,7 @@ async function getDesignPackage(clientId) {
|
|
|
434
451
|
const mapping = getDeprecatedMappingAsCustom(config.requestTypeWorkLog)
|
|
435
452
|
schemas[config.requestTypeWorkLog] = await getObjectSchema(clientConfig[config.requestTypeWorkLog].fields, mapping, config.forms.workLog)
|
|
436
453
|
schemas[config.requestTypeWorkLog + '_create_update'] = await getObjectSchema(clientConfig[config.requestTypeWorkLog].fields, mapping, config.forms.workLog, true)
|
|
437
|
-
paths = {...paths, ... await getPathDef(config.assocTicketType
|
|
454
|
+
paths = {...paths, ... await getPathDef(`${config.assocTicketType} Worklog`, config.baseURI + '/{ticketId}/worklogs', config.requestTypeWorkLog, true, true)}
|
|
438
455
|
paths = {...paths, ... await getAttachmentPathDef(config.assocTicketType, config.baseURI + '/{ticketId}/worklogs')}
|
|
439
456
|
}
|
|
440
457
|
if (config.requestTemplate && clientConfig[config.requestTemplate].fields && clientConfig[config.requestTemplate].fields.length > 0) {
|