sks-maximo-utils 1.0.7 → 1.1.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/CLI.md CHANGED
@@ -12,6 +12,7 @@
12
12
  | `sks-maximo import-presentation <fileName>` | 导入应用XML配置 |
13
13
  | `sks-maximo import-script <fileName>` | 导入自动化脚本 |
14
14
  | `sks-maximo import-domain <fileName>` | 导入域配置 |
15
+ | `sks-maximo import-maxintobject <fileName>` | 导入对象结构(Integration Object)配置 |
15
16
 
16
17
  ---
17
18
 
@@ -116,7 +117,7 @@ sks-maximo import-script <fileName> [-e env] [-l logname]
116
117
  sks-maximo import-domain <fileName> [-e env] [-l logname]
117
118
  ```
118
119
 
119
- **说明:** 导入 Maximo 域配置
120
+ **说明:** 导入 Maximo 域配置,走 `SKS.AUTOSCRIPT.OBJECTS`(`_type=domains&_action=import`)。文件内容支持域数组 / `{domains:[...]}` / 单域对象三种格式。
120
121
 
121
122
  | 参数 | 说明 | 必填 |
122
123
  |------|------|------|
@@ -126,6 +127,22 @@ sks-maximo import-domain <fileName> [-e env] [-l logname]
126
127
 
127
128
  ---
128
129
 
130
+ ### 3.6 导入对象结构(Integration Object)
131
+
132
+ ```bash
133
+ sks-maximo import-maxintobject <fileName> [-e env] [-l logname]
134
+ ```
135
+
136
+ **说明:** 导入 Maximo 对象结构(发布通道),走 `SKS.AUTOSCRIPT.OBJECTS`(`_type=integrationobjects&_action=import`)。文件内容需为 `{integrationobjects:[...]}` 格式(从对象结构导出的 JSON 可直接回导)。
137
+
138
+ | 参数 | 说明 | 必填 |
139
+ |------|------|------|
140
+ | `<fileName>` | 对象结构 JSON 文件路径 | 是 |
141
+ | `-e` / `--env` | 指定环境(默认 local) | 否 |
142
+ | `-l` / `--logname` | 日志打印名称 | 否 |
143
+
144
+ ---
145
+
129
146
  ## 4. 调用通用脚本接口
130
147
 
131
148
  ```bash
@@ -144,7 +161,7 @@ sks-maximo call <scriptName> [--file <fileName>] [--params <params>] [--logname
144
161
  ### 4.1 GET 请求(无请求体)
145
162
 
146
163
  ```bash
147
- sks-maximo call SHARPTREE.AUTOSCRIPT.LIBRARY --params '{"name":"TEST"}'
164
+ sks-maximo call SKS.AUTOSCRIPT.LIBRARY --params '{"name":"TEST"}'
148
165
  ```
149
166
 
150
167
  ### 4.2 POST 请求(带请求体文件)
@@ -154,7 +171,7 @@ sks-maximo call SHARPTREE.AUTOSCRIPT.LIBRARY --params '{"name":"TEST"}'
154
171
  sks-maximo call SKS_DEPLOY_AUTOKEY --file data/autokey.json
155
172
 
156
173
  # XML 请求体
157
- sks-maximo call SHARPTREE.AUTOSCRIPT.SCREENS --file screens/test.xml
174
+ sks-maximo call SKS.AUTOSCRIPT.SCREENS --file screens/test.xml
158
175
 
159
176
  # 同时带参数和请求体
160
177
  sks-maximo call SKS_IMP_MAXAPPINFO --file appinfo.json --params '{"debug":true}' --logname "导入应用信息"
@@ -200,7 +217,7 @@ sks-maximo call SKS_IMP_MAXAPPINFO --file appinfo.json --params '{"debug":true}'
200
217
  ### 示例 1:查询脚本库
201
218
 
202
219
  ```bash
203
- sks-maximo call SHARPTREE.AUTOSCRIPT.LIBRARY --params '{"name":"MY_SCRIPT"}'
220
+ sks-maximo call SKS.AUTOSCRIPT.LIBRARY --params '{"name":"MY_SCRIPT"}'
204
221
  ```
205
222
 
206
223
  ### 示例 2:部署自动编码
package/README.md CHANGED
@@ -40,7 +40,10 @@ import {
40
40
  importMaxAutoKey,
41
41
  importMaxScript,
42
42
  importMaxAppInfo,
43
+ importMaxIntObject,
43
44
  callMaxScript,
45
+ batchImport,
46
+ printBatchStats,
44
47
  fileUtils,
45
48
  loadConfig,
46
49
  logger
@@ -69,12 +72,32 @@ importMaxScript({ fileName: "scripts/TEST.json" });
69
72
  // 导入应用信息配置
70
73
  importMaxAppInfo({ fileName: "MAXAPPINFO/appinfo.json", logname: "应用信息" });
71
74
 
75
+ // 导入对象结构(Integration Object): 走 SKS.AUTOSCRIPT.OBJECTS (_type=integrationobjects&_action=import)
76
+ // body 需为 {integrationobjects:[...]} 格式(导出的 JSON 可直接回导)
77
+ importMaxIntObject({ fileName: "DBMAXINTOBJECT/OSIBM_POISSUE.json", logname: "PO问题对象结构" });
78
+
72
79
  // 通用脚本接口调用(GET)
73
- callMaxScript({ apiScriptName: "SHARPTREE.AUTOSCRIPT.LIBRARY", params: { name: "test" }, logname: "查询脚本库" });
80
+ callMaxScript({ apiScriptName: "SKS.AUTOSCRIPT.LIBRARY", params: { name: "test" }, logname: "查询脚本库" });
74
81
 
75
82
  // 通用脚本接口调用(POST,读取文件内容作为请求体)
76
83
  callMaxScript({ apiScriptName: "SKS_DEPLOY_AUTOKEY", fileName: "data/autokey.json", logname: "部署自动编码" });
77
84
 
85
+ // 通用批量导入(支持对象、脚本、域、应用信息等所有导入功能)
86
+ const stats = await batchImport({
87
+ dirName: "C:/Temp/hd/maxobject_backup", // 目录名(与files二选一)
88
+ extFilter: ".json", // 扩展名过滤
89
+ importFn: importMaxObject, // 导入函数(可换成其他导入方法)
90
+ logname: "批量导入对象",
91
+ concurrency: 1 // 并发数,默认1串行
92
+ });
93
+ printBatchStats(stats); // 打印批量导入统计结果
94
+
95
+ // 直接指定文件列表批量导入
96
+ await batchImport({
97
+ files: ["a.json", "b.json", "c.json"],
98
+ importFn: importMaxDomain
99
+ });
100
+
78
101
  // 文件工具
79
102
  fileUtils.listFiles('scripts', '.json');
80
103
  fileUtils.readFileContent('test.txt');
@@ -133,17 +156,21 @@ fileUtils.readFileContent('test.txt');
133
156
  | importMaxAutoKey | 导入 AutoKey 配置 |
134
157
  | importMaxScript | 导入自动化脚本(自动保存历史记录) |
135
158
  | importMaxAppInfo | 导入应用信息配置 |
159
+ | importMaxIntObject | 导入对象结构(Integration Object)配置 |
136
160
 
137
161
  ### 其他方法
138
162
 
139
163
  | 方法 | 说明 |
140
164
  |------|------|
141
165
  | callMaxScript | 通用脚本接口调用(GET/POST) |
166
+ | batchImport | 通用批量导入(支持对象、脚本、域、应用信息等所有导入功能) |
167
+ | printBatchStats | 打印批量导入统计结果 |
142
168
  | loadConfig(env) | 加载指定环境配置 |
143
169
  | saveScriptHistory(options) | 保存脚本历史记录 |
144
170
  | readFileContent(fileName) | 读取文件内容 |
145
171
  | readJsonFile(fileName) | 读取并解析 JSON 文件 |
146
172
  | fileExists(fileName) | 检查文件是否存在 |
173
+ | fileUtils.resolveFilePath(fileName) | 通用路径转换(相对/绝对路径转规范化绝对路径) |
147
174
  | fileUtils.listFiles(dirName, extFilter, recursive) | 列出目录文件 |
148
175
  | fileUtils.readFileContent(fileName) | 读取文件内容 |
149
176
  | fileUtils.readJsonFile(fileName) | 读取并解析 JSON 文件 |
package/cli.js CHANGED
@@ -3,7 +3,7 @@ import { exec } from 'child_process';
3
3
  import { readFileSync } from 'fs';
4
4
  import { fileURLToPath, URL } from 'url';
5
5
  import { checkAndCreateConfig, getConfigDir, loadConfig } from './nodeutils/config.js';
6
- import { callMaxScript, importMaxObject, importMaxPresentation, importMaxDomain, importMaxAutoKey, importMaxScript, importMaxAppInfo } from './nodeutils/maximoTools.js';
6
+ import { callMaxScript, importMaxObject, importMaxPresentation, importMaxDomain, importMaxAutoKey, importMaxScript, importMaxAppInfo, importMaxIntObject } from './nodeutils/maximoTools.js';
7
7
 
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = new URL('.', import.meta.url).pathname;
@@ -38,6 +38,7 @@ if (!cmd || ['-h', '--help', '-?', '--version', '-v'].includes(cmd)) {
38
38
  console.log(' sks-maximo import-presentation <fileName> # 导入应用XML配置');
39
39
  console.log(' sks-maximo import-script <fileName> # 导入自动化脚本');
40
40
  console.log(' sks-maximo import-domain <fileName> # 导入域配置');
41
+ console.log(' sks-maximo import-maxintobject <fileName> # 导入对象结构(Integration Object)配置');
41
42
  console.log('');
42
43
  console.log('环境:');
43
44
  console.log(' local # 使用本地环境配置');
@@ -51,6 +52,7 @@ if (!cmd || ['-h', '--help', '-?', '--version', '-v'].includes(cmd)) {
51
52
  console.log(' import-presentation # 导入应用XML配置');
52
53
  console.log(' import-script # 导入自动化脚本');
53
54
  console.log(' import-domain # 导入域配置');
55
+ console.log(' import-maxintobject # 导入对象结构(Integration Object)配置');
54
56
  console.log('');
55
57
  console.log('选项:');
56
58
  console.log(' -h, --help # 显示帮助信息');
@@ -271,6 +273,35 @@ if (!cmd || ['-h', '--help', '-?', '--version', '-v'].includes(cmd)) {
271
273
  process.exit(1);
272
274
  }
273
275
  })();
276
+ } else if (cmd === 'import-maxintobject') {
277
+ const fileName = filteredArgs[1];
278
+ if (!fileName) {
279
+ console.error('错误: 请指定对象结构 JSON 文件路径');
280
+ console.log('用法: sks-maximo import-maxintobject <fileName> [-e env] [-l logname]');
281
+ process.exit(1);
282
+ }
283
+ let logname = null;
284
+ for (let i = 2; i < filteredArgs.length; i++) {
285
+ if (filteredArgs[i] === '--logname' || filteredArgs[i] === '-l') {
286
+ logname = filteredArgs[i + 1];
287
+ i++;
288
+ }
289
+ }
290
+ loadConfig(globalEnv);
291
+ (async () => {
292
+ try {
293
+ const result = await importMaxIntObject({ fileName, logname: logname || fileName });
294
+ if (result) {
295
+ console.log('导入成功');
296
+ } else {
297
+ console.error('导入失败');
298
+ process.exit(1);
299
+ }
300
+ } catch (error) {
301
+ console.error('导入出错:', error.message);
302
+ process.exit(1);
303
+ }
304
+ })();
274
305
  } else {
275
306
  console.error(`不支持的命令: ${cmd}`);
276
307
  console.log('使用 sks-maximo --help 查看帮助信息');
package/index.js CHANGED
@@ -3,5 +3,5 @@ export { loadConfig, getConfig, getWorkDir } from './nodeutils/config.js';
3
3
  export { default as logger } from './nodeutils/logger.js';
4
4
  export { default as request } from './nodeutils/requestHttp.js';
5
5
  export * as fileUtils from './nodeutils/fileUtils.js';
6
- export { importMaxObject, importMaxPresentation, importMaxDomain, importMaxAutoKey, importMaxScript, saveScriptHistory, importMaxAppInfo, callMaxScript, batchImport, printBatchStats } from './nodeutils/maximoTools.js';
6
+ export { importMaxObject, importMaxPresentation, importMaxDomain, importMaxAutoKey, importMaxScript, saveScriptHistory, importMaxAppInfo, importMaxIntObject, callMaxScript, batchImport, printBatchStats } from './nodeutils/maximoTools.js';
7
7
  export { sendMockData, sendMockDataBatch, sendPOMockData, sendPOMockDataBatch, sendRlImportMockDataBatch } from './nodeutils/mockdataTools.js';
@@ -34,7 +34,7 @@ export async function importMaxObject({fileName, logname}) {
34
34
  // 发送请求到Maximo API
35
35
  logger.info(`[${logname}]开始发送请求...`);
36
36
  const response = await request({
37
- url: '/api/script/SHARPTREE.AUTOSCRIPT.LIBRARY',
37
+ url: '/api/script/SKS.AUTOSCRIPT.LIBRARY',
38
38
  method: 'post',
39
39
  params: {
40
40
  develop: true,
@@ -101,7 +101,7 @@ export async function importMaxPresentation({fileName, logname}) {
101
101
 
102
102
  logger.info(`[${logname}]开始发送请求...`);
103
103
  const response = await request({
104
- url: '/api/script/SHARPTREE.AUTOSCRIPT.SCREENS',
104
+ url: '/api/script/SKS.AUTOSCRIPT.SCREENS',
105
105
  method: 'post',
106
106
  headers: {
107
107
  'Content-Type': 'application/xml'
@@ -138,10 +138,41 @@ export async function importMaxPresentation({fileName, logname}) {
138
138
  }
139
139
 
140
140
 
141
+ /**
142
+ * 解析 SKS.AUTOSCRIPT.OBJECTS 导入响应,统一处理字符串/对象
143
+ * @param {any} response
144
+ * @returns {Object|null}
145
+ */
146
+ function parseImportResponse(response) {
147
+ if (response === null || response === undefined) return null;
148
+ if (typeof response === 'string') {
149
+ try { return JSON.parse(response); } catch (e) { return null; }
150
+ }
151
+ return response;
152
+ }
153
+
154
+ /**
155
+ * 判断 SKS.AUTOSCRIPT.OBJECTS 批量导入是否真正成功(HTTP 200 但 summary.failed>0 视为失败)
156
+ * @param {any} response
157
+ * @returns {{ok: boolean, summary: Object|null, result: Array}}
158
+ */
159
+ function checkImportResult(response) {
160
+ const data = parseImportResponse(response);
161
+ if (!data || data.status !== 'success' || !data.summary) {
162
+ return { ok: false, summary: data ? data.summary : null, result: data ? (data.result || []) : [] };
163
+ }
164
+ const failed = data.summary.failed || 0;
165
+ if (failed > 0) {
166
+ return { ok: false, summary: data.summary, result: data.result || [] };
167
+ }
168
+ return { ok: true, summary: data.summary, result: data.result || [] };
169
+ }
170
+
141
171
  /**
142
172
  * 导入Maximo域
173
+ * 走 SKS.AUTOSCRIPT.OBJECTS (_type=domains&_action=import), body 支持域数组 / {domains:[...]} / 单域对象
143
174
  * @param {Object} options - 配置选项
144
- * @param {string} options.fileName - 配置文件名(JSON或XML)
175
+ * @param {string} options.fileName - 配置文件名(JSON)
145
176
  * @param {string} options.logname - 日志打印名称
146
177
  * @returns {Promise<boolean>} 是否导入成功
147
178
  */
@@ -150,58 +181,114 @@ export async function importMaxDomain({fileName, logname}) {
150
181
  logname = fileName
151
182
  }
152
183
  try {
153
- // 根据文件扩展名选择读取方式
154
184
  let fileContent = null;
155
185
  fileContent = readFileContent(fileName);
156
-
157
- // 检查文件是否成功读取
186
+
158
187
  if (!fileContent) {
159
188
  logger.error(`[${logname}]文件读取失败: ${fileName}`);
160
189
  return false;
161
190
  }
162
-
191
+
163
192
  logger.info(`[${logname}]成功读取文件: ${fileName}`);
164
193
  logger.info(`[${logname}]文件大小: ${fileContent.length} 字节`);
165
194
  logger.info(`[${logname}]准备导入domain: ${logname || '未指定'}`);
166
-
167
- // 发送请求到Maximo API
195
+
168
196
  logger.info(`[${logname}]开始发送请求...`);
169
197
  const response = await request({
170
- url: '/api/script/SKS_DEPLOY_DOMAIN',
198
+ url: '/api/script/SKS.AUTOSCRIPT.OBJECTS',
171
199
  method: 'post',
172
200
  params: {
173
- develop: true,
201
+ _type: 'domains',
202
+ _action: 'import',
174
203
  _langcode: getConfig().langcode,
175
204
  },
176
- data: fileContent // 将文件内容作为请求体发送
205
+ data: fileContent
177
206
  })
178
-
179
- logger.warn(`[${logname}]收到响应`);
180
- logger.warn(`[${logname}]响应类型:`, typeof response);
181
- logger.warn(`[${logname}]响应内容:`, response);
182
-
183
- // 检查响应 - requestHttp的响应拦截器已返回res.data
184
- if (response !== null && response !== undefined) {
185
- logger.warn(`[${logname}]导入成功`)
207
+
208
+ const { ok, summary, result } = checkImportResult(response);
209
+ if (ok) {
210
+ logger.warn(`[${logname}]导入成功 总计:${summary.total} 成功:${summary.success}`)
186
211
  return true
187
212
  } else {
188
- logger.error(`[${logname}]导入失败,响应为空或null`)
189
- logger.error(`[${logname}]响应值:`, response)
213
+ logger.error(`[${logname}]导入失败, 响应:`, response)
214
+ if (result && result.length > 0) {
215
+ result.filter(r => r.status === 'FAILED').forEach(r => {
216
+ logger.error(`[${logname}] - ${r.domainid || r.id || '未知'}: ${r.message}`)
217
+ })
218
+ }
219
+ return false
220
+ }
221
+ } catch (error) {
222
+ logger.error(`[${logname}]请求出错:`, error.message)
223
+ if (error.response) {
224
+ // 服务器返回了错误状态码
225
+ } else if (error.request) {
226
+ logger.error(`[${logname}]请求已发出但无响应`)
227
+ } else {
228
+ logger.error(`[${logname}]错误详情:`, error)
229
+ }
230
+ return false
231
+ }
232
+ }
233
+
234
+
235
+ /**
236
+ * 导入Maximo对象结构(Integration Object / 发布通道)
237
+ * 走 SKS.AUTOSCRIPT.OBJECTS (_type=integrationobjects&_action=import), body 为 {integrationobjects:[...]}
238
+ * @param {Object} options - 配置选项
239
+ * @param {string} options.fileName - 配置文件名(JSON)
240
+ * @param {string} options.logname - 日志打印名称
241
+ * @returns {Promise<boolean>} 是否导入成功
242
+ */
243
+ export async function importMaxIntObject({fileName, logname}) {
244
+ if(!logname||logname===""||logname===null){
245
+ logname = fileName
246
+ }
247
+ try {
248
+ let fileContent = null;
249
+ fileContent = readFileContent(fileName);
250
+
251
+ if (!fileContent) {
252
+ logger.error(`[${logname}]文件读取失败: ${fileName}`);
253
+ return false;
254
+ }
255
+
256
+ logger.info(`[${logname}]成功读取文件: ${fileName}`);
257
+ logger.info(`[${logname}]文件大小: ${fileContent.length} 字节`);
258
+ logger.info(`[${logname}]准备导入对象结构: ${logname || '未指定'}`);
259
+
260
+ logger.info(`[${logname}]开始发送请求...`);
261
+ const response = await request({
262
+ url: '/api/script/SKS.AUTOSCRIPT.OBJECTS',
263
+ method: 'post',
264
+ params: {
265
+ _type: 'integrationobjects',
266
+ _action: 'import',
267
+ _langcode: getConfig().langcode,
268
+ },
269
+ data: fileContent
270
+ })
271
+
272
+ const { ok, summary, result } = checkImportResult(response);
273
+ if (ok) {
274
+ logger.warn(`[${logname}]导入成功 总计:${summary.total} 成功:${summary.success}`)
275
+ return true
276
+ } else {
277
+ logger.error(`[${logname}]导入失败, 响应:`, response)
278
+ if (result && result.length > 0) {
279
+ result.filter(r => r.status === 'FAILED').forEach(r => {
280
+ logger.error(`[${logname}] - ${r.intobjectname || r.id || '未知'}: ${r.message}`)
281
+ })
282
+ }
190
283
  return false
191
284
  }
192
285
  } catch (error) {
193
286
  logger.error(`[${logname}]请求出错:`, error.message)
194
287
  if (error.response) {
195
288
  // 服务器返回了错误状态码
196
- // logger.error(`[${logname}]错误状态码:`, error.response.status)
197
- // logger.error(`[${logname}]错误响应数据:`, error.response.data)
198
289
  } else if (error.request) {
199
- // 请求已发出但没有收到响应
200
290
  logger.error(`[${logname}]请求已发出但无响应`)
201
- // logger.error(`[${logname}]请求URL:`, error.request.url)
202
- // logger.error(`[${logname}]请求方法:`, error.request.method)
203
291
  } else {
204
- // 其他错误
205
292
  logger.error(`[${logname}]错误详情:`, error)
206
293
  }
207
294
  return false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sks-maximo-utils",
3
- "version": "1.0.7",
3
+ "version": "1.1.0",
4
4
  "description": "Maximo helper tools for updating table structures and data",
5
5
  "type": "module",
6
6
  "main": "index.js",