@tenonhq/sincronia-core 0.0.21 → 0.0.23
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/dist/allScopesCommands.js +30 -12
- package/dist/commander.js +60 -1
- package/dist/snClient.js +1 -0
- package/dist/updateSetCommands.js +312 -0
- package/dist/wizard.js +4 -4
- package/package.json +1 -1
|
@@ -37,7 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
if (v !== undefined) module.exports = v;
|
|
38
38
|
}
|
|
39
39
|
else if (typeof define === "function" && define.amd) {
|
|
40
|
-
define(["require", "exports", "./Logger", "./config", "./snClient", "./commands", "path", "fs"], factory);
|
|
40
|
+
define(["require", "exports", "./Logger", "./config", "./wizard", "./snClient", "./commands", "path", "fs"], factory);
|
|
41
41
|
}
|
|
42
42
|
})(function (require, exports) {
|
|
43
43
|
"use strict";
|
|
@@ -47,6 +47,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
47
47
|
exports.watchAllScopesCommand = watchAllScopesCommand;
|
|
48
48
|
const Logger_1 = require("./Logger");
|
|
49
49
|
const ConfigManager = __importStar(require("./config"));
|
|
50
|
+
const wizard_1 = require("./wizard");
|
|
50
51
|
const snClient_1 = require("./snClient");
|
|
51
52
|
const commands_1 = require("./commands");
|
|
52
53
|
const path = __importStar(require("path"));
|
|
@@ -70,7 +71,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
70
71
|
const tables = manifest.tables || {};
|
|
71
72
|
const tableNames = Object.keys(tables);
|
|
72
73
|
Logger_1.logger.info(`Processing ${tableNames.length} tables`);
|
|
73
|
-
Logger_1.logger.debug(`Table names: ${tableNames.join(
|
|
74
|
+
Logger_1.logger.debug(`Table names: ${tableNames.join(", ")}`);
|
|
74
75
|
for (const tableName of tableNames) {
|
|
75
76
|
const tableRecords = tables[tableName];
|
|
76
77
|
const tablePath = path.join(sourceDirectory, tableName);
|
|
@@ -96,7 +97,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
96
97
|
// Create the file
|
|
97
98
|
Logger_1.logger.debug(`Writing file: ${filePath}`);
|
|
98
99
|
try {
|
|
99
|
-
await fsp.writeFile(filePath, fileContent,
|
|
100
|
+
await fsp.writeFile(filePath, fileContent, "utf8");
|
|
100
101
|
}
|
|
101
102
|
catch (writeError) {
|
|
102
103
|
Logger_1.logger.error(`Failed to write file ${filePath}: ${writeError}`);
|
|
@@ -150,14 +151,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
150
151
|
// Create the scope-specific manifest structure
|
|
151
152
|
const scopeManifest = {
|
|
152
153
|
tables: (manifest && manifest.tables) || {},
|
|
153
|
-
scope: scopeName
|
|
154
|
+
scope: scopeName,
|
|
154
155
|
};
|
|
155
156
|
Logger_1.logger.success(`✅ Successfully processed scope: ${scopeName}`);
|
|
156
157
|
Logger_1.logger.info(`Files saved to: ${sourceDirectory}`);
|
|
157
158
|
return {
|
|
158
159
|
scope: scopeName,
|
|
159
160
|
success: true,
|
|
160
|
-
manifest: scopeManifest
|
|
161
|
+
manifest: scopeManifest,
|
|
161
162
|
};
|
|
162
163
|
}
|
|
163
164
|
catch (error) {
|
|
@@ -166,7 +167,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
166
167
|
return {
|
|
167
168
|
scope: scopeName,
|
|
168
169
|
success: false,
|
|
169
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
170
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
170
171
|
};
|
|
171
172
|
}
|
|
172
173
|
}
|
|
@@ -174,9 +175,23 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
174
175
|
(0, commands_1.setLogLevel)(args);
|
|
175
176
|
try {
|
|
176
177
|
// First check if we have environment variables set
|
|
177
|
-
if (!process.env.SN_USER ||
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
if (!process.env.SN_USER ||
|
|
179
|
+
!process.env.SN_PASSWORD ||
|
|
180
|
+
!process.env.SN_INSTANCE) {
|
|
181
|
+
try {
|
|
182
|
+
let loginAnswers = await (0, wizard_1.getLoginInfo)();
|
|
183
|
+
await (0, wizard_1.setupDotEnv)(loginAnswers);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
Logger_1.logger.error("Error getting ServiceNow credentials: " + error);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
if (!process.env.SN_USER ||
|
|
190
|
+
!process.env.SN_PASSWORD ||
|
|
191
|
+
!process.env.SN_INSTANCE) {
|
|
192
|
+
Logger_1.logger.error("Missing ServiceNow credentials. Please ensure SN_USER, SN_PASSWORD, and SN_INSTANCE are set in your .env file");
|
|
193
|
+
throw new Error("ServiceNow credentials not configured");
|
|
194
|
+
}
|
|
180
195
|
}
|
|
181
196
|
// Load config
|
|
182
197
|
await ConfigManager.loadConfigs();
|
|
@@ -190,7 +205,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
190
205
|
// Process all scopes in parallel
|
|
191
206
|
Logger_1.logger.info("Starting parallel processing of all scopes...");
|
|
192
207
|
Logger_1.logger.info("This will download manifests and files for each scope from ServiceNow...\n");
|
|
193
|
-
const scopePromises = scopes.map(scopeName => processScope(scopeName, config.scopes[scopeName]));
|
|
208
|
+
const scopePromises = scopes.map((scopeName) => processScope(scopeName, config.scopes[scopeName]));
|
|
194
209
|
const results = await Promise.allSettled(scopePromises);
|
|
195
210
|
// Collect successful manifests
|
|
196
211
|
const manifests = {};
|
|
@@ -220,7 +235,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
220
235
|
}
|
|
221
236
|
Logger_1.logger.info(`Manifest written to: ${manifestPath}`);
|
|
222
237
|
Logger_1.logger.info("\nAll scope files have been downloaded to their respective source directories.");
|
|
223
|
-
Logger_1.logger.success("\nYou can now use 'npx sinc
|
|
238
|
+
Logger_1.logger.success("\nYou can now use 'npx sinc watchAllScopes' to start development mode!");
|
|
224
239
|
}
|
|
225
240
|
catch (e) {
|
|
226
241
|
Logger_1.logger.error("Error initializing scopes: " + e);
|
|
@@ -231,7 +246,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
231
246
|
(0, commands_1.setLogLevel)(args);
|
|
232
247
|
try {
|
|
233
248
|
// First check if we have environment variables set
|
|
234
|
-
if (!process.env.SN_USER ||
|
|
249
|
+
if (!process.env.SN_USER ||
|
|
250
|
+
!process.env.SN_PASSWORD ||
|
|
251
|
+
!process.env.SN_INSTANCE) {
|
|
252
|
+
let loginAnswers = await (0, wizard_1.getLoginInfo)();
|
|
235
253
|
Logger_1.logger.error("Missing ServiceNow credentials. Please ensure SN_USER, SN_PASSWORD, and SN_INSTANCE are set in your .env file");
|
|
236
254
|
throw new Error("ServiceNow credentials not configured");
|
|
237
255
|
}
|
package/dist/commander.js
CHANGED
|
@@ -7,7 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
if (v !== undefined) module.exports = v;
|
|
8
8
|
}
|
|
9
9
|
else if (typeof define === "function" && define.amd) {
|
|
10
|
-
define(["require", "exports", "./commands", "./allScopesCommands", "yargs"], factory);
|
|
10
|
+
define(["require", "exports", "./commands", "./allScopesCommands", "./updateSetCommands", "yargs"], factory);
|
|
11
11
|
}
|
|
12
12
|
})(function (require, exports) {
|
|
13
13
|
"use strict";
|
|
@@ -15,6 +15,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
15
15
|
exports.initCommands = initCommands;
|
|
16
16
|
const commands_1 = require("./commands");
|
|
17
17
|
const allScopesCommands_1 = require("./allScopesCommands");
|
|
18
|
+
const updateSetCommands_1 = require("./updateSetCommands");
|
|
18
19
|
const yargs_1 = __importDefault(require("yargs"));
|
|
19
20
|
async function initCommands() {
|
|
20
21
|
const sharedOptions = {
|
|
@@ -78,6 +79,64 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
78
79
|
})
|
|
79
80
|
.command("deploy", "Deploy local build files to the scoped application", sharedOptions, commands_1.deployCommand)
|
|
80
81
|
.command("status", "Get information about the connected instance", sharedOptions, commands_1.statusCommand)
|
|
82
|
+
.command("createUpdateSet", "Create a new update set and switch to it", (cmdArgs) => {
|
|
83
|
+
cmdArgs.options({
|
|
84
|
+
...sharedOptions,
|
|
85
|
+
name: {
|
|
86
|
+
alias: "n",
|
|
87
|
+
type: "string",
|
|
88
|
+
describe: "Name of the update set to create",
|
|
89
|
+
},
|
|
90
|
+
description: {
|
|
91
|
+
alias: "d",
|
|
92
|
+
type: "string",
|
|
93
|
+
describe: "Description of the update set",
|
|
94
|
+
},
|
|
95
|
+
scope: {
|
|
96
|
+
alias: "s",
|
|
97
|
+
type: "string",
|
|
98
|
+
describe: "Scope for the update set (e.g., x_company_app)",
|
|
99
|
+
},
|
|
100
|
+
skipDescription: {
|
|
101
|
+
type: "boolean",
|
|
102
|
+
default: false,
|
|
103
|
+
describe: "Skip prompting for description",
|
|
104
|
+
},
|
|
105
|
+
skipScope: {
|
|
106
|
+
type: "boolean",
|
|
107
|
+
default: false,
|
|
108
|
+
describe: "Skip prompting for scope",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return cmdArgs;
|
|
112
|
+
}, updateSetCommands_1.createUpdateSetCommand)
|
|
113
|
+
.command("switchUpdateSet", "Switch to an existing update set", (cmdArgs) => {
|
|
114
|
+
cmdArgs.options({
|
|
115
|
+
...sharedOptions,
|
|
116
|
+
name: {
|
|
117
|
+
alias: "n",
|
|
118
|
+
type: "string",
|
|
119
|
+
describe: "Name or partial name of the update set to switch to",
|
|
120
|
+
},
|
|
121
|
+
scope: {
|
|
122
|
+
alias: "s",
|
|
123
|
+
type: "string",
|
|
124
|
+
describe: "Filter update sets by scope",
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
return cmdArgs;
|
|
128
|
+
}, updateSetCommands_1.switchUpdateSetCommand)
|
|
129
|
+
.command("listUpdateSets", "List all in-progress update sets", (cmdArgs) => {
|
|
130
|
+
cmdArgs.options({
|
|
131
|
+
...sharedOptions,
|
|
132
|
+
scope: {
|
|
133
|
+
alias: "s",
|
|
134
|
+
type: "string",
|
|
135
|
+
describe: "Filter update sets by scope",
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
return cmdArgs;
|
|
139
|
+
}, updateSetCommands_1.listUpdateSetsCommand)
|
|
81
140
|
.help().argv;
|
|
82
141
|
}
|
|
83
142
|
});
|
package/dist/snClient.js
CHANGED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
2
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3
|
+
};
|
|
4
|
+
(function (factory) {
|
|
5
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
6
|
+
var v = factory(require, exports);
|
|
7
|
+
if (v !== undefined) module.exports = v;
|
|
8
|
+
}
|
|
9
|
+
else if (typeof define === "function" && define.amd) {
|
|
10
|
+
define(["require", "exports", "inquirer", "./snClient", "./Logger", "./commands", "chalk"], factory);
|
|
11
|
+
}
|
|
12
|
+
})(function (require, exports) {
|
|
13
|
+
"use strict";
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.createUpdateSetCommand = createUpdateSetCommand;
|
|
16
|
+
exports.switchUpdateSetCommand = switchUpdateSetCommand;
|
|
17
|
+
exports.listUpdateSetsCommand = listUpdateSetsCommand;
|
|
18
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
19
|
+
const snClient_1 = require("./snClient");
|
|
20
|
+
const Logger_1 = require("./Logger");
|
|
21
|
+
const commands_1 = require("./commands");
|
|
22
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new update set with the given name and switches to it
|
|
25
|
+
*/
|
|
26
|
+
async function createUpdateSetCommand(args) {
|
|
27
|
+
(0, commands_1.setLogLevel)(args);
|
|
28
|
+
try {
|
|
29
|
+
const client = (0, snClient_1.defaultClient)();
|
|
30
|
+
// Get update set details from user
|
|
31
|
+
const { name, description, scope } = await promptForUpdateSetDetails(args);
|
|
32
|
+
// Create the update set
|
|
33
|
+
Logger_1.logger.info(`Creating update set: ${name}`);
|
|
34
|
+
const updateSetData = {
|
|
35
|
+
name,
|
|
36
|
+
state: "in progress"
|
|
37
|
+
};
|
|
38
|
+
if (description) {
|
|
39
|
+
updateSetData.description = description;
|
|
40
|
+
}
|
|
41
|
+
if (scope) {
|
|
42
|
+
// Get scope sys_id if scope name provided
|
|
43
|
+
const scopeResult = await (0, snClient_1.unwrapSNResponse)(client.getScopeId(scope));
|
|
44
|
+
if (scopeResult.length === 0) {
|
|
45
|
+
Logger_1.logger.error(`Scope "${scope}" not found`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
updateSetData.application = scopeResult[0].sys_id;
|
|
49
|
+
}
|
|
50
|
+
// Create the update set
|
|
51
|
+
const createResponse = client.createUpdateSet(name);
|
|
52
|
+
const createResult = await (0, snClient_1.unwrapSNResponse)(createResponse);
|
|
53
|
+
const updateSetSysId = createResult.sys_id;
|
|
54
|
+
// Update the description if provided (ServiceNow API might not accept it during creation)
|
|
55
|
+
if (description) {
|
|
56
|
+
await client.updateRecord("sys_update_set", updateSetSysId, { description });
|
|
57
|
+
}
|
|
58
|
+
// Switch to the new update set
|
|
59
|
+
await switchToUpdateSet(updateSetSysId, name);
|
|
60
|
+
Logger_1.logger.info(chalk_1.default.green(`✓ Update set "${name}" created and activated`));
|
|
61
|
+
Logger_1.logger.info(`Update Set ID: ${updateSetSysId}`);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
Logger_1.logger.error("Failed to create update set");
|
|
65
|
+
if (e instanceof Error)
|
|
66
|
+
Logger_1.logger.error(e.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Switches to an existing update set
|
|
72
|
+
*/
|
|
73
|
+
async function switchUpdateSetCommand(args) {
|
|
74
|
+
var _a;
|
|
75
|
+
(0, commands_1.setLogLevel)(args);
|
|
76
|
+
try {
|
|
77
|
+
const client = (0, snClient_1.defaultClient)();
|
|
78
|
+
// Get update set to switch to
|
|
79
|
+
const targetUpdateSet = await selectUpdateSet(args.name, args.scope);
|
|
80
|
+
if (!targetUpdateSet) {
|
|
81
|
+
Logger_1.logger.error("No update set selected");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
// Switch to the selected update set
|
|
85
|
+
await switchToUpdateSet(targetUpdateSet.sys_id, targetUpdateSet.name);
|
|
86
|
+
Logger_1.logger.info(chalk_1.default.green(`✓ Switched to update set: ${targetUpdateSet.name}`));
|
|
87
|
+
Logger_1.logger.info(`Update Set ID: ${targetUpdateSet.sys_id}`);
|
|
88
|
+
if ((_a = targetUpdateSet.application) === null || _a === void 0 ? void 0 : _a.display_value) {
|
|
89
|
+
Logger_1.logger.info(`Scope: ${targetUpdateSet.application.display_value}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
Logger_1.logger.error("Failed to switch update set");
|
|
94
|
+
if (e instanceof Error)
|
|
95
|
+
Logger_1.logger.error(e.message);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Lists all open/in-progress update sets
|
|
101
|
+
*/
|
|
102
|
+
async function listUpdateSetsCommand(args) {
|
|
103
|
+
(0, commands_1.setLogLevel)(args);
|
|
104
|
+
try {
|
|
105
|
+
const client = (0, snClient_1.defaultClient)();
|
|
106
|
+
// Build query for update sets
|
|
107
|
+
let query = "state=in progress";
|
|
108
|
+
if (args.scope) {
|
|
109
|
+
// Get scope sys_id if scope name provided
|
|
110
|
+
const scopeResult = await (0, snClient_1.unwrapSNResponse)(client.getScopeId(args.scope));
|
|
111
|
+
if (scopeResult.length === 0) {
|
|
112
|
+
Logger_1.logger.error(`Scope "${args.scope}" not found`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
query += `^application=${scopeResult[0].sys_id}`;
|
|
116
|
+
}
|
|
117
|
+
// Get list of update sets
|
|
118
|
+
const updateSets = await getUpdateSets(query);
|
|
119
|
+
if (updateSets.length === 0) {
|
|
120
|
+
Logger_1.logger.info("No in-progress update sets found");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Get current update set
|
|
124
|
+
const currentUpdateSetId = await getCurrentUpdateSetId();
|
|
125
|
+
// Display update sets
|
|
126
|
+
Logger_1.logger.info(chalk_1.default.bold("\nIn-Progress Update Sets:"));
|
|
127
|
+
Logger_1.logger.info("─".repeat(80));
|
|
128
|
+
updateSets.forEach((updateSet) => {
|
|
129
|
+
var _a;
|
|
130
|
+
const isCurrent = updateSet.sys_id === currentUpdateSetId;
|
|
131
|
+
const marker = isCurrent ? chalk_1.default.green("► ") : " ";
|
|
132
|
+
const name = isCurrent ? chalk_1.default.green(updateSet.name) : updateSet.name;
|
|
133
|
+
console.log(`${marker}${name}`);
|
|
134
|
+
if (updateSet.description) {
|
|
135
|
+
console.log(` Description: ${updateSet.description}`);
|
|
136
|
+
}
|
|
137
|
+
if ((_a = updateSet.application) === null || _a === void 0 ? void 0 : _a.display_value) {
|
|
138
|
+
console.log(` Scope: ${updateSet.application.display_value}`);
|
|
139
|
+
}
|
|
140
|
+
console.log(` Created: ${formatDate(updateSet.sys_created_on)} by ${updateSet.sys_created_by}`);
|
|
141
|
+
console.log(` ID: ${updateSet.sys_id}`);
|
|
142
|
+
console.log("");
|
|
143
|
+
});
|
|
144
|
+
if (currentUpdateSetId) {
|
|
145
|
+
Logger_1.logger.info(chalk_1.default.dim("► indicates current active update set"));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
Logger_1.logger.error("Failed to list update sets");
|
|
150
|
+
if (e instanceof Error)
|
|
151
|
+
Logger_1.logger.error(e.message);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Helper function to prompt for update set details
|
|
157
|
+
*/
|
|
158
|
+
async function promptForUpdateSetDetails(args) {
|
|
159
|
+
const questions = [];
|
|
160
|
+
if (!args.name) {
|
|
161
|
+
questions.push({
|
|
162
|
+
type: "input",
|
|
163
|
+
name: "name",
|
|
164
|
+
message: "Update set name:",
|
|
165
|
+
validate: (input) => {
|
|
166
|
+
if (!input || input.trim() === "") {
|
|
167
|
+
return "Update set name is required";
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (!args.description && !args.skipDescription) {
|
|
174
|
+
questions.push({
|
|
175
|
+
type: "input",
|
|
176
|
+
name: "description",
|
|
177
|
+
message: "Description (optional):"
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (!args.scope && !args.skipScope) {
|
|
181
|
+
questions.push({
|
|
182
|
+
type: "input",
|
|
183
|
+
name: "scope",
|
|
184
|
+
message: "Scope (optional, e.g., x_company_app):"
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const answers = questions.length > 0 ? await inquirer_1.default.prompt(questions) : {};
|
|
188
|
+
return {
|
|
189
|
+
name: args.name || answers.name,
|
|
190
|
+
description: args.description || answers.description,
|
|
191
|
+
scope: args.scope || answers.scope
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Helper function to switch to an update set
|
|
196
|
+
*/
|
|
197
|
+
async function switchToUpdateSet(updateSetSysId, name) {
|
|
198
|
+
const client = (0, snClient_1.defaultClient)();
|
|
199
|
+
// Get current user sys_id
|
|
200
|
+
const userSysId = await (0, snClient_1.unwrapTableAPIFirstItem)(client.getUserSysId(), "sys_id");
|
|
201
|
+
// Get or create user preference for current update set
|
|
202
|
+
try {
|
|
203
|
+
const curUpdateSetUserPrefId = await (0, snClient_1.unwrapTableAPIFirstItem)(client.getCurrentUpdateSetUserPref(userSysId), "sys_id");
|
|
204
|
+
// Update existing preference
|
|
205
|
+
await client.updateCurrentUpdateSetUserPref(updateSetSysId, curUpdateSetUserPrefId);
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
// Create new preference if it doesn't exist
|
|
209
|
+
await client.createCurrentUpdateSetUserPref(updateSetSysId, userSysId);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Helper function to get update sets based on query
|
|
214
|
+
*/
|
|
215
|
+
async function getUpdateSets(query) {
|
|
216
|
+
const client = (0, snClient_1.defaultClient)();
|
|
217
|
+
const endpoint = "api/now/table/sys_update_set";
|
|
218
|
+
const response = client.client.get(endpoint, {
|
|
219
|
+
params: {
|
|
220
|
+
sysparm_query: query,
|
|
221
|
+
sysparm_fields: "sys_id,name,description,state,application,application.name,sys_created_on,sys_created_by",
|
|
222
|
+
sysparm_limit: 100,
|
|
223
|
+
sysparm_display_value: "all"
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return (0, snClient_1.unwrapSNResponse)(response);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Helper function to get current update set ID
|
|
230
|
+
*/
|
|
231
|
+
async function getCurrentUpdateSetId() {
|
|
232
|
+
try {
|
|
233
|
+
const client = (0, snClient_1.defaultClient)();
|
|
234
|
+
const userSysId = await (0, snClient_1.unwrapTableAPIFirstItem)(client.getUserSysId(), "sys_id");
|
|
235
|
+
const endpoint = "api/now/table/sys_user_preference";
|
|
236
|
+
const response = client.client.get(endpoint, {
|
|
237
|
+
params: {
|
|
238
|
+
sysparm_query: `user=${userSysId}^name=sys_update_set`,
|
|
239
|
+
sysparm_fields: "value"
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
const result = await (0, snClient_1.unwrapSNResponse)(response);
|
|
243
|
+
return result.length > 0 ? result[0].value : null;
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Helper function to select an update set from a list
|
|
251
|
+
*/
|
|
252
|
+
async function selectUpdateSet(nameFilter, scopeFilter) {
|
|
253
|
+
let query = "state=in progress";
|
|
254
|
+
if (scopeFilter) {
|
|
255
|
+
const client = (0, snClient_1.defaultClient)();
|
|
256
|
+
const scopeResult = await (0, snClient_1.unwrapSNResponse)(client.getScopeId(scopeFilter));
|
|
257
|
+
if (scopeResult.length === 0) {
|
|
258
|
+
Logger_1.logger.error(`Scope "${scopeFilter}" not found`);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
query += `^application=${scopeResult[0].sys_id}`;
|
|
262
|
+
}
|
|
263
|
+
const updateSets = await getUpdateSets(query);
|
|
264
|
+
if (updateSets.length === 0) {
|
|
265
|
+
Logger_1.logger.info("No in-progress update sets found");
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
// Filter by name if provided
|
|
269
|
+
let filteredSets = updateSets;
|
|
270
|
+
if (nameFilter) {
|
|
271
|
+
filteredSets = updateSets.filter(us => us.name.toLowerCase().includes(nameFilter.toLowerCase()));
|
|
272
|
+
if (filteredSets.length === 0) {
|
|
273
|
+
Logger_1.logger.error(`No update sets found matching "${nameFilter}"`);
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
// If exact match found, use it
|
|
277
|
+
const exactMatch = filteredSets.find(us => us.name.toLowerCase() === nameFilter.toLowerCase());
|
|
278
|
+
if (exactMatch) {
|
|
279
|
+
return exactMatch;
|
|
280
|
+
}
|
|
281
|
+
// If only one match, use it
|
|
282
|
+
if (filteredSets.length === 1) {
|
|
283
|
+
return filteredSets[0];
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Prompt user to select from list
|
|
287
|
+
const choices = filteredSets.map(us => {
|
|
288
|
+
var _a;
|
|
289
|
+
return ({
|
|
290
|
+
name: `${us.name}${((_a = us.application) === null || _a === void 0 ? void 0 : _a.display_value) ? ` (${us.application.display_value})` : ""} - ${us.description || "No description"}`,
|
|
291
|
+
value: us
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
const { selectedUpdateSet } = await inquirer_1.default.prompt([
|
|
295
|
+
{
|
|
296
|
+
type: "list",
|
|
297
|
+
name: "selectedUpdateSet",
|
|
298
|
+
message: "Select an update set:",
|
|
299
|
+
choices,
|
|
300
|
+
pageSize: 15
|
|
301
|
+
}
|
|
302
|
+
]);
|
|
303
|
+
return selectedUpdateSet;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Helper function to format date
|
|
307
|
+
*/
|
|
308
|
+
function formatDate(dateString) {
|
|
309
|
+
const date = new Date(dateString);
|
|
310
|
+
return date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
|
311
|
+
}
|
|
312
|
+
});
|
package/dist/wizard.js
CHANGED
|
@@ -46,6 +46,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
"use strict";
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.startWizard = startWizard;
|
|
49
|
+
exports.getLoginInfo = getLoginInfo;
|
|
50
|
+
exports.setupDotEnv = setupDotEnv;
|
|
49
51
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
50
52
|
const ConfigManager = __importStar(require("./config"));
|
|
51
53
|
const AppUtils = __importStar(require("./appUtils"));
|
|
@@ -58,11 +60,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
58
60
|
let loginAnswers = await getLoginInfo();
|
|
59
61
|
try {
|
|
60
62
|
let { username, password, instance } = loginAnswers;
|
|
61
|
-
let instanceUrl = instance.
|
|
62
|
-
? instance
|
|
63
|
-
: `https://${instance}`;
|
|
63
|
+
let instanceUrl = instance.replace("https://", "").replace("http://", "");
|
|
64
64
|
if (!instanceUrl.endsWith("/")) {
|
|
65
|
-
instanceUrl +=
|
|
65
|
+
instanceUrl += `/`;
|
|
66
66
|
}
|
|
67
67
|
const client = (0, snClient_1.snClient)(instanceUrl, username, password);
|
|
68
68
|
const apps = await (0, snClient_1.unwrapSNResponse)(client.getAppList());
|