@tenonhq/sincronia-core 0.0.73 → 0.0.74
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/FileUtils.js +30 -5
- package/dist/allScopesCommands.js +3 -0
- package/dist/appUtils.js +44 -93
- package/dist/commander.js +0 -6
- package/dist/commands.js +142 -142
- package/dist/config.js +32 -0
- package/dist/createRecordCommand.js +1 -1
- package/dist/deleteRecordCommand.js +1 -1
- package/dist/initSystem/orchestrator.js +33 -0
- package/dist/logMessages.js +0 -10
- package/package.json +1 -1
package/dist/FileUtils.js
CHANGED
|
@@ -138,12 +138,20 @@ const getFileExtension = (filePath) => {
|
|
|
138
138
|
return "";
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
|
-
const getBuildExt = (table, recordName, field) => {
|
|
142
|
-
|
|
141
|
+
const getBuildExt = (table, recordName, field, scope) => {
|
|
142
|
+
var manifest = ConfigManager.getManifest();
|
|
143
143
|
if (!manifest) {
|
|
144
144
|
throw new Error("Failed to retrieve manifest");
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
var resolvedManifest = manifest;
|
|
147
|
+
if (scope && ConfigManager.isMultiScopeManifest(manifest)) {
|
|
148
|
+
var scopeMan = ConfigManager.resolveManifestForScope(manifest, scope);
|
|
149
|
+
if (!scopeMan) {
|
|
150
|
+
throw new Error("Failed to find scope " + scope + " in manifest");
|
|
151
|
+
}
|
|
152
|
+
resolvedManifest = scopeMan;
|
|
153
|
+
}
|
|
154
|
+
const files = resolvedManifest.tables[table].records[recordName].files;
|
|
147
155
|
const file = files.find((f) => f.name === field);
|
|
148
156
|
if (!file) {
|
|
149
157
|
throw new Error("Unable to find file");
|
|
@@ -163,11 +171,28 @@ const getFileContextFromPath = (filePath) => {
|
|
|
163
171
|
.split(path_1.default.sep)
|
|
164
172
|
.slice(-2);
|
|
165
173
|
const targetField = getTargetFieldFromPath(filePath, tableName, ext);
|
|
166
|
-
|
|
174
|
+
var manifest = ConfigManager.getManifest();
|
|
167
175
|
if (!manifest) {
|
|
168
176
|
throw new Error("No manifest has been loaded!");
|
|
169
177
|
}
|
|
170
|
-
|
|
178
|
+
var scope;
|
|
179
|
+
var tables;
|
|
180
|
+
if (ConfigManager.isMultiScopeManifest(manifest)) {
|
|
181
|
+
var detectedScope = ConfigManager.resolveScopeFromPath(filePath);
|
|
182
|
+
if (!detectedScope) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
var scopeMan = ConfigManager.resolveManifestForScope(manifest, detectedScope);
|
|
186
|
+
if (!scopeMan) {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
scope = scopeMan.scope || detectedScope;
|
|
190
|
+
tables = scopeMan.tables;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
scope = manifest.scope;
|
|
194
|
+
tables = manifest.tables;
|
|
195
|
+
}
|
|
171
196
|
try {
|
|
172
197
|
const { records } = tables[tableName];
|
|
173
198
|
const record = records[recordName];
|
|
@@ -41,6 +41,7 @@ exports.watchAllScopesCommand = watchAllScopesCommand;
|
|
|
41
41
|
const Logger_1 = require("./Logger");
|
|
42
42
|
const FileLogger_1 = require("./FileLogger");
|
|
43
43
|
const ConfigManager = __importStar(require("./config"));
|
|
44
|
+
const AppUtils = __importStar(require("./appUtils"));
|
|
44
45
|
const wizard_1 = require("./wizard");
|
|
45
46
|
const snClient_1 = require("./snClient");
|
|
46
47
|
const commands_1 = require("./commands");
|
|
@@ -193,6 +194,8 @@ async function processScope(scopeName, scopeConfig, apiDelay = 0) {
|
|
|
193
194
|
else {
|
|
194
195
|
Logger_1.logger.warn("No _tables whitelist defined — writing ALL tables for " + scopeName);
|
|
195
196
|
}
|
|
197
|
+
// Normalize record keys from sys_id to display name
|
|
198
|
+
AppUtils.normalizeManifestKeys(manifest);
|
|
196
199
|
// Build the missing files structure from the filtered manifest
|
|
197
200
|
var manifestTables = manifest.tables || {};
|
|
198
201
|
var allMissingFiles = {};
|
package/dist/appUtils.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.createAndAssignUpdateSet = exports.swapScope = exports.buildFiles = exports.summarizeRecord = exports.pushFiles = exports.getAppFileList = exports.groupAppFiles = exports.processMissingFiles = exports.findMissingFiles = exports.syncManifest = exports.processManifest = exports.normalizeManifestKeys = void 0;
|
|
40
40
|
const path_1 = __importDefault(require("path"));
|
|
41
41
|
const fs_1 = __importDefault(require("fs"));
|
|
42
42
|
const progress_1 = __importDefault(require("progress"));
|
|
@@ -113,6 +113,34 @@ const processTablesInManifest = async (tables, forceWrite, sourcePath, onRecordP
|
|
|
113
113
|
return processRecsInManTable(path_1.default.join(basePath, tableName), tables[tableName], forceWrite, onRecordProcessed);
|
|
114
114
|
});
|
|
115
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* Re-keys manifest records from sys_id to record.name (display value).
|
|
118
|
+
* Some ServiceNow tables return records keyed by sys_id instead of display name.
|
|
119
|
+
* This ensures consistent naming for directories and manifest lookups.
|
|
120
|
+
*/
|
|
121
|
+
const normalizeManifestKeys = (manifest) => {
|
|
122
|
+
var tables = manifest.tables || {};
|
|
123
|
+
var tableNames = Object.keys(tables);
|
|
124
|
+
for (var i = 0; i < tableNames.length; i++) {
|
|
125
|
+
var tableName = tableNames[i];
|
|
126
|
+
var records = tables[tableName].records || {};
|
|
127
|
+
var recordKeys = Object.keys(records);
|
|
128
|
+
var normalized = {};
|
|
129
|
+
for (var j = 0; j < recordKeys.length; j++) {
|
|
130
|
+
var key = recordKeys[j];
|
|
131
|
+
var record = records[key];
|
|
132
|
+
var displayKey = record.name || key;
|
|
133
|
+
// Handle duplicate display names by appending sys_id suffix
|
|
134
|
+
if (normalized[displayKey]) {
|
|
135
|
+
displayKey = displayKey + " (" + record.sys_id.substring(0, 8) + ")";
|
|
136
|
+
}
|
|
137
|
+
normalized[displayKey] = record;
|
|
138
|
+
}
|
|
139
|
+
tables[tableName].records = normalized;
|
|
140
|
+
}
|
|
141
|
+
return manifest;
|
|
142
|
+
};
|
|
143
|
+
exports.normalizeManifestKeys = normalizeManifestKeys;
|
|
116
144
|
const processManifest = async (manifest, forceWrite = false, sourcePath) => {
|
|
117
145
|
const tableCount = Object.keys(manifest.tables).length;
|
|
118
146
|
FileLogger_1.fileLogger.debug("Processing manifest: " + (manifest.scope || "legacy") + " (" + tableCount + " tables)");
|
|
@@ -142,20 +170,20 @@ const syncManifest = async (scope) => {
|
|
|
142
170
|
const config = ConfigManager.getConfig();
|
|
143
171
|
// Resolve scope-specific source directory
|
|
144
172
|
var scopeSourcePath = ConfigManager.getSourcePathForScope(scope);
|
|
145
|
-
const newManifest = await (0, snClient_1.unwrapSNResponse)(client.getManifest(scope, config));
|
|
173
|
+
const newManifest = (0, exports.normalizeManifestKeys)(await (0, snClient_1.unwrapSNResponse)(client.getManifest(scope, config)));
|
|
146
174
|
const refreshTableCount = Object.keys(newManifest.tables).length;
|
|
147
175
|
FileLogger_1.fileLogger.debug("Refreshed manifest for " + scope + ": " + refreshTableCount + " tables");
|
|
148
176
|
await fUtils.writeScopeManifest(scope, newManifest);
|
|
149
177
|
await (0, exports.processMissingFiles)(newManifest, scopeSourcePath);
|
|
150
178
|
// Update the in-memory manifest for this scope
|
|
151
|
-
if (
|
|
179
|
+
if (ConfigManager.isMultiScopeManifest(curManifest)) {
|
|
152
180
|
curManifest[scope] = newManifest;
|
|
153
181
|
ConfigManager.updateManifest(curManifest);
|
|
154
182
|
}
|
|
155
183
|
}
|
|
156
184
|
else {
|
|
157
185
|
// Sync all scopes if manifest has multiple scopes
|
|
158
|
-
if (
|
|
186
|
+
if (ConfigManager.isMultiScopeManifest(curManifest)) {
|
|
159
187
|
// Multiple scopes detected
|
|
160
188
|
for (const scopeName of Object.keys(curManifest)) {
|
|
161
189
|
await (0, exports.syncManifest)(scopeName);
|
|
@@ -422,6 +450,18 @@ const writeBuildFile = async (preBuild, buildRes, summary) => {
|
|
|
422
450
|
const sourcePath = ConfigManager.getSourcePath();
|
|
423
451
|
const buildPath = ConfigManager.getBuildPath();
|
|
424
452
|
const fieldNames = Object.keys(fields);
|
|
453
|
+
const writePromises = fieldNames.map(async (field) => {
|
|
454
|
+
const fieldCtx = fields[field];
|
|
455
|
+
const srcFilePath = fieldCtx.filePath;
|
|
456
|
+
const relativePath = path_1.default.relative(sourcePath, srcFilePath);
|
|
457
|
+
const relPathNoExt = relativePath.split(".").slice(0, -1).join();
|
|
458
|
+
const buildExt = fUtils.getBuildExt(fieldCtx.tableName, fieldCtx.name, fieldCtx.targetField, fieldCtx.scope);
|
|
459
|
+
const relPathNewExt = `${relPathNoExt}.${buildExt}`;
|
|
460
|
+
const buildFilePath = path_1.default.join(buildPath, relPathNewExt);
|
|
461
|
+
await fUtils.createDirRecursively(path_1.default.dirname(buildFilePath));
|
|
462
|
+
const writeResult = await fUtils.writeFileForce(buildFilePath, buildRes.builtRec[fieldCtx.targetField]);
|
|
463
|
+
return writeResult;
|
|
464
|
+
});
|
|
425
465
|
try {
|
|
426
466
|
await (0, genericUtils_1.processBatched)(fieldNames, constants_1.CONCURRENCY_FILES, async function (field) {
|
|
427
467
|
const fieldCtx = fields[field];
|
|
@@ -532,92 +572,3 @@ const createAndAssignUpdateSet = async (updateSetName = "", scope) => {
|
|
|
532
572
|
};
|
|
533
573
|
};
|
|
534
574
|
exports.createAndAssignUpdateSet = createAndAssignUpdateSet;
|
|
535
|
-
const checkScope = async (swap) => {
|
|
536
|
-
try {
|
|
537
|
-
const man = ConfigManager.getManifest();
|
|
538
|
-
if (man) {
|
|
539
|
-
// Detect multi-scope manifest (keys are scope names, no top-level .scope)
|
|
540
|
-
var isMultiScope = typeof man === "object" && !man.scope && !man.tables;
|
|
541
|
-
if (isMultiScope) {
|
|
542
|
-
// Multi-scope: session scope just needs to match any configured scope
|
|
543
|
-
var configuredScopes = Object.keys(man);
|
|
544
|
-
var client = (0, snClient_1.defaultClient)();
|
|
545
|
-
var scopeObj;
|
|
546
|
-
try {
|
|
547
|
-
scopeObj = await (0, snClient_1.unwrapSNResponse)(client.getCurrentScope());
|
|
548
|
-
}
|
|
549
|
-
catch (scopeErr) {
|
|
550
|
-
Logger_1.logger.info("Scope check endpoint unavailable, assuming match for multi-scope project");
|
|
551
|
-
return { match: true, sessionScope: configuredScopes[0], manifestScope: configuredScopes[0] };
|
|
552
|
-
}
|
|
553
|
-
var sessionScope = scopeObj.scope;
|
|
554
|
-
var scopeMatch = configuredScopes.indexOf(sessionScope) !== -1;
|
|
555
|
-
Logger_1.logger.info("Current scope: " + sessionScope + ", Configured scopes: " + configuredScopes.join(", "));
|
|
556
|
-
if (scopeMatch) {
|
|
557
|
-
return { match: true, sessionScope: sessionScope, manifestScope: sessionScope };
|
|
558
|
-
}
|
|
559
|
-
else if (swap && configuredScopes.length > 0) {
|
|
560
|
-
Logger_1.logger.info("Current scope (" + sessionScope + ") not in configured scopes. Swapping to " + configuredScopes[0] + "...\n");
|
|
561
|
-
var swappedScopeObj = await (0, exports.swapScope)(configuredScopes[0]);
|
|
562
|
-
return {
|
|
563
|
-
match: configuredScopes.indexOf(swappedScopeObj.scope) !== -1,
|
|
564
|
-
sessionScope: swappedScopeObj.scope,
|
|
565
|
-
manifestScope: configuredScopes[0],
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
return { match: false, sessionScope: sessionScope, manifestScope: configuredScopes.join(", ") };
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
// Single-scope manifest
|
|
573
|
-
var singleClient = (0, snClient_1.defaultClient)();
|
|
574
|
-
var singleScopeObj;
|
|
575
|
-
try {
|
|
576
|
-
singleScopeObj = await (0, snClient_1.unwrapSNResponse)(singleClient.getCurrentScope());
|
|
577
|
-
}
|
|
578
|
-
catch (scopeErr) {
|
|
579
|
-
// getCurrentScope endpoint may not exist on this instance — skip scope check
|
|
580
|
-
Logger_1.logger.info(`Scope check endpoint unavailable, assuming scope match for: ${man.scope}`);
|
|
581
|
-
return {
|
|
582
|
-
match: true,
|
|
583
|
-
sessionScope: man.scope,
|
|
584
|
-
manifestScope: man.scope,
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
Logger_1.logger.info(`Current scope: ${singleScopeObj.scope}, Manifest scope: ${man.scope}`);
|
|
588
|
-
if (singleScopeObj.scope === man.scope) {
|
|
589
|
-
return {
|
|
590
|
-
match: true,
|
|
591
|
-
sessionScope: singleScopeObj.scope,
|
|
592
|
-
manifestScope: man.scope,
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
else if (swap) {
|
|
596
|
-
Logger_1.logger.info(`Current scope (${singleScopeObj.scope}) does not match manifest scope (${man.scope}). Swapping...\n`);
|
|
597
|
-
var singleSwapped = await (0, exports.swapScope)(man.scope);
|
|
598
|
-
return {
|
|
599
|
-
match: singleSwapped.scope === man.scope,
|
|
600
|
-
sessionScope: singleSwapped.scope,
|
|
601
|
-
manifestScope: man.scope,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
else {
|
|
605
|
-
return {
|
|
606
|
-
match: false,
|
|
607
|
-
sessionScope: singleScopeObj.scope,
|
|
608
|
-
manifestScope: man.scope,
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
//first time case
|
|
613
|
-
return {
|
|
614
|
-
match: true,
|
|
615
|
-
sessionScope: "",
|
|
616
|
-
manifestScope: "",
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
catch (e) {
|
|
620
|
-
throw e;
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
exports.checkScope = checkScope;
|
package/dist/commander.js
CHANGED
|
@@ -50,12 +50,6 @@ async function initCommands() {
|
|
|
50
50
|
default: "",
|
|
51
51
|
describe: "Specify branch to do git diff against",
|
|
52
52
|
},
|
|
53
|
-
scopeSwap: {
|
|
54
|
-
alias: "ss",
|
|
55
|
-
type: "boolean",
|
|
56
|
-
default: false,
|
|
57
|
-
describe: "Will auto-swap to the correct scope for the files being pushed",
|
|
58
|
-
},
|
|
59
53
|
updateSet: {
|
|
60
54
|
alias: "us",
|
|
61
55
|
type: "string",
|
package/dist/commands.js
CHANGED
|
@@ -37,7 +37,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.setLogLevel = setLogLevel;
|
|
40
|
-
exports.devCommand = devCommand;
|
|
41
40
|
exports.refreshCommand = refreshCommand;
|
|
42
41
|
exports.pushCommand = pushCommand;
|
|
43
42
|
exports.downloadCommand = downloadCommand;
|
|
@@ -46,7 +45,6 @@ exports.buildCommand = buildCommand;
|
|
|
46
45
|
exports.deployCommand = deployCommand;
|
|
47
46
|
exports.statusCommand = statusCommand;
|
|
48
47
|
const ConfigManager = __importStar(require("./config"));
|
|
49
|
-
const Watcher_1 = require("./Watcher");
|
|
50
48
|
const AppUtils = __importStar(require("./appUtils"));
|
|
51
49
|
const orchestrator_1 = require("./initSystem/orchestrator");
|
|
52
50
|
const Logger_1 = require("./Logger");
|
|
@@ -56,135 +54,108 @@ const snClient_1 = require("./snClient");
|
|
|
56
54
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
57
55
|
const gitUtils_1 = require("./gitUtils");
|
|
58
56
|
const FileUtils_1 = require("./FileUtils");
|
|
59
|
-
|
|
57
|
+
function setLogLevel(args) {
|
|
58
|
+
Logger_1.logger.setLogLevel(args.logLevel);
|
|
59
|
+
}
|
|
60
|
+
async function refreshCommand(args, log = true) {
|
|
61
|
+
setLogLevel(args);
|
|
60
62
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
else {
|
|
68
|
-
await successFunc();
|
|
69
|
-
}
|
|
63
|
+
if (!log)
|
|
64
|
+
setLogLevel({ logLevel: "warn" });
|
|
65
|
+
FileLogger_1.fileLogger.debug("Syncing manifest from instance");
|
|
66
|
+
await AppUtils.syncManifest();
|
|
67
|
+
Logger_1.logger.success("Refresh complete!");
|
|
68
|
+
setLogLevel(args);
|
|
70
69
|
}
|
|
71
70
|
catch (e) {
|
|
72
|
-
|
|
73
|
-
// Throw exception to register this as an error
|
|
74
|
-
process.exit(1);
|
|
71
|
+
throw e;
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
|
-
function
|
|
78
|
-
Logger_1.logger.setLogLevel(args.logLevel);
|
|
79
|
-
}
|
|
80
|
-
async function devCommand(args) {
|
|
74
|
+
async function pushCommand(args) {
|
|
81
75
|
setLogLevel(args);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
76
|
+
try {
|
|
77
|
+
const { updateSet, ci: skipPrompt, target, diff } = args;
|
|
78
|
+
let encodedPaths;
|
|
79
|
+
if (target !== undefined && target !== "")
|
|
80
|
+
encodedPaths = target;
|
|
81
|
+
else
|
|
82
|
+
encodedPaths = await (0, gitUtils_1.gitDiffToEncodedPaths)(diff);
|
|
83
|
+
const fileList = await AppUtils.getAppFileList(encodedPaths);
|
|
84
|
+
const instance = process.env.SN_INSTANCE || "unknown";
|
|
85
|
+
Logger_1.logger.info(fileList.length + " files to push to " + instance);
|
|
86
|
+
if (!skipPrompt) {
|
|
87
|
+
const targetServer = process.env.SN_INSTANCE;
|
|
88
|
+
if (!targetServer) {
|
|
89
|
+
Logger_1.logger.error("No SN_INSTANCE configured. Set it in your .env file.");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const answers = await inquirer_1.default.prompt([
|
|
93
|
+
{
|
|
94
|
+
type: "confirm",
|
|
95
|
+
name: "confirmed",
|
|
96
|
+
message: "Pushing will overwrite code in your instance. Are you sure?",
|
|
97
|
+
default: false,
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
if (!answers["confirmed"])
|
|
101
|
+
return;
|
|
92
102
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// Handle --clickup flag: resolve ClickUp task into an update set name
|
|
104
|
+
let resolvedUpdateSet = updateSet;
|
|
105
|
+
if (!resolvedUpdateSet && args.clickup) {
|
|
106
|
+
try {
|
|
107
|
+
const { resolveClickUpForPush } = await Promise.resolve().then(() => __importStar(require("./clickupPushHelper")));
|
|
108
|
+
resolvedUpdateSet = await resolveClickUpForPush(args.clickup);
|
|
109
|
+
}
|
|
110
|
+
catch (cuErr) {
|
|
111
|
+
if (cuErr instanceof Error)
|
|
112
|
+
Logger_1.logger.error(cuErr.message);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
105
115
|
}
|
|
106
|
-
|
|
107
|
-
|
|
116
|
+
// Extract scope from file list and auto-swap to it
|
|
117
|
+
var pushScope;
|
|
118
|
+
if (fileList.length > 0) {
|
|
119
|
+
var fieldKeys = Object.keys(fileList[0].fields);
|
|
120
|
+
if (fieldKeys.length > 0) {
|
|
121
|
+
pushScope = fileList[0].fields[fieldKeys[0]].scope;
|
|
122
|
+
}
|
|
108
123
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const fileList = await AppUtils.getAppFileList(encodedPaths);
|
|
122
|
-
const instance = process.env.SN_INSTANCE || "unknown";
|
|
123
|
-
Logger_1.logger.info(fileList.length + " files to push to " + instance);
|
|
124
|
+
if (pushScope) {
|
|
125
|
+
try {
|
|
126
|
+
var client = (0, snClient_1.defaultClient)();
|
|
127
|
+
await client.changeScope(pushScope);
|
|
128
|
+
Logger_1.logger.info("Switched to scope: " + pushScope);
|
|
129
|
+
}
|
|
130
|
+
catch (scopeErr) {
|
|
131
|
+
Logger_1.logger.warn("Could not auto-switch scope: " + scopeErr);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Does not create update set if updateSetName is blank
|
|
135
|
+
if (resolvedUpdateSet) {
|
|
124
136
|
if (!skipPrompt) {
|
|
125
|
-
|
|
126
|
-
if (!targetServer) {
|
|
127
|
-
Logger_1.logger.error("No SN_INSTANCE configured. Set it in your .env file.");
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
const answers = await inquirer_1.default.prompt([
|
|
137
|
+
let answers = await inquirer_1.default.prompt([
|
|
131
138
|
{
|
|
132
139
|
type: "confirm",
|
|
133
140
|
name: "confirmed",
|
|
134
|
-
message: "
|
|
141
|
+
message: `A new Update Set "${resolvedUpdateSet}" will be created for these pushed changes. Do you want to proceed?`,
|
|
135
142
|
default: false,
|
|
136
143
|
},
|
|
137
144
|
]);
|
|
138
|
-
if (!answers["confirmed"])
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
// Handle --clickup flag: resolve ClickUp task into an update set name
|
|
142
|
-
let resolvedUpdateSet = updateSet;
|
|
143
|
-
if (!resolvedUpdateSet && args.clickup) {
|
|
144
|
-
try {
|
|
145
|
-
const { resolveClickUpForPush } = await Promise.resolve().then(() => __importStar(require("./clickupPushHelper")));
|
|
146
|
-
resolvedUpdateSet = await resolveClickUpForPush(args.clickup);
|
|
147
|
-
}
|
|
148
|
-
catch (cuErr) {
|
|
149
|
-
if (cuErr instanceof Error)
|
|
150
|
-
Logger_1.logger.error(cuErr.message);
|
|
151
|
-
process.exit(1);
|
|
145
|
+
if (!answers["confirmed"]) {
|
|
146
|
+
process.exit(0);
|
|
152
147
|
}
|
|
153
148
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (fileList.length > 0) {
|
|
157
|
-
var fieldKeys = Object.keys(fileList[0].fields);
|
|
158
|
-
if (fieldKeys.length > 0) {
|
|
159
|
-
pushScope = fileList[0].fields[fieldKeys[0]].scope;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Does not create update set if updateSetName is blank
|
|
163
|
-
if (resolvedUpdateSet) {
|
|
164
|
-
if (!skipPrompt) {
|
|
165
|
-
let answers = await inquirer_1.default.prompt([
|
|
166
|
-
{
|
|
167
|
-
type: "confirm",
|
|
168
|
-
name: "confirmed",
|
|
169
|
-
message: `A new Update Set "${resolvedUpdateSet}" will be created for these pushed changes. Do you want to proceed?`,
|
|
170
|
-
default: false,
|
|
171
|
-
},
|
|
172
|
-
]);
|
|
173
|
-
if (!answers["confirmed"]) {
|
|
174
|
-
process.exit(0);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
const newUpdateSet = await AppUtils.createAndAssignUpdateSet(resolvedUpdateSet, pushScope);
|
|
178
|
-
Logger_1.logger.debug(`New Update Set Created(${newUpdateSet.name}) sys_id:${newUpdateSet.id}`);
|
|
179
|
-
}
|
|
180
|
-
const pushResults = await AppUtils.pushFiles(fileList);
|
|
181
|
-
(0, logMessages_1.logPushResults)(pushResults);
|
|
182
|
-
}
|
|
183
|
-
catch (e) {
|
|
184
|
-
Logger_1.logger.getInternalLogger().error(e);
|
|
185
|
-
process.exit(1);
|
|
149
|
+
const newUpdateSet = await AppUtils.createAndAssignUpdateSet(resolvedUpdateSet, pushScope);
|
|
150
|
+
Logger_1.logger.debug(`New Update Set Created(${newUpdateSet.name}) sys_id:${newUpdateSet.id}`);
|
|
186
151
|
}
|
|
187
|
-
|
|
152
|
+
const pushResults = await AppUtils.pushFiles(fileList);
|
|
153
|
+
(0, logMessages_1.logPushResults)(pushResults);
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
Logger_1.logger.getInternalLogger().error(e);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
188
159
|
}
|
|
189
160
|
async function downloadCommand(args) {
|
|
190
161
|
setLogLevel(args);
|
|
@@ -284,43 +255,72 @@ async function getDeployPaths() {
|
|
|
284
255
|
}
|
|
285
256
|
async function deployCommand(args) {
|
|
286
257
|
setLogLevel(args);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const { confirmed } = await inquirer_1.default.prompt([
|
|
295
|
-
{
|
|
296
|
-
type: "confirm",
|
|
297
|
-
name: "confirmed",
|
|
298
|
-
message: "Deploying will overwrite code in your instance. Are you sure?",
|
|
299
|
-
default: false,
|
|
300
|
-
},
|
|
301
|
-
]);
|
|
302
|
-
if (!confirmed) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
const paths = await getDeployPaths();
|
|
306
|
-
Logger_1.logger.silly(`${paths.length} paths found...`);
|
|
307
|
-
Logger_1.logger.silly(JSON.stringify(paths, null, 2));
|
|
308
|
-
const appFileList = await AppUtils.getAppFileList(paths);
|
|
309
|
-
const pushResults = await AppUtils.pushFiles(appFileList);
|
|
310
|
-
(0, logMessages_1.logPushResults)(pushResults);
|
|
258
|
+
try {
|
|
259
|
+
const targetServer = process.env.SN_INSTANCE || "";
|
|
260
|
+
if (!targetServer) {
|
|
261
|
+
Logger_1.logger.error("No SN_INSTANCE configured. Set it in your .env file.");
|
|
262
|
+
return;
|
|
311
263
|
}
|
|
312
|
-
|
|
313
|
-
|
|
264
|
+
const { confirmed } = await inquirer_1.default.prompt([
|
|
265
|
+
{
|
|
266
|
+
type: "confirm",
|
|
267
|
+
name: "confirmed",
|
|
268
|
+
message: "Deploying will overwrite code in your instance. Are you sure?",
|
|
269
|
+
default: false,
|
|
270
|
+
},
|
|
271
|
+
]);
|
|
272
|
+
if (!confirmed) {
|
|
273
|
+
return;
|
|
314
274
|
}
|
|
315
|
-
|
|
275
|
+
const paths = await getDeployPaths();
|
|
276
|
+
Logger_1.logger.silly(`${paths.length} paths found...`);
|
|
277
|
+
Logger_1.logger.silly(JSON.stringify(paths, null, 2));
|
|
278
|
+
const appFileList = await AppUtils.getAppFileList(paths);
|
|
279
|
+
// Auto-swap to scope detected from files
|
|
280
|
+
if (appFileList.length > 0) {
|
|
281
|
+
var fieldKeys = Object.keys(appFileList[0].fields);
|
|
282
|
+
if (fieldKeys.length > 0) {
|
|
283
|
+
var deployScope = appFileList[0].fields[fieldKeys[0]].scope;
|
|
284
|
+
if (deployScope) {
|
|
285
|
+
try {
|
|
286
|
+
var client = (0, snClient_1.defaultClient)();
|
|
287
|
+
await client.changeScope(deployScope);
|
|
288
|
+
Logger_1.logger.info("Switched to scope: " + deployScope);
|
|
289
|
+
}
|
|
290
|
+
catch (scopeErr) {
|
|
291
|
+
Logger_1.logger.warn("Could not auto-switch scope: " + scopeErr);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const pushResults = await AppUtils.pushFiles(appFileList);
|
|
297
|
+
(0, logMessages_1.logPushResults)(pushResults);
|
|
298
|
+
}
|
|
299
|
+
catch (e) {
|
|
300
|
+
throw e;
|
|
301
|
+
}
|
|
316
302
|
}
|
|
317
303
|
async function statusCommand() {
|
|
318
304
|
try {
|
|
319
305
|
const client = (0, snClient_1.defaultClient)();
|
|
306
|
+
var config = ConfigManager.getConfig();
|
|
320
307
|
let scopeObj = await (0, snClient_1.unwrapSNResponse)(client.getCurrentScope());
|
|
321
|
-
Logger_1.logger.info("Instance:
|
|
322
|
-
Logger_1.logger.info("
|
|
323
|
-
Logger_1.logger.info("
|
|
308
|
+
Logger_1.logger.info("Instance: " + (process.env.SN_INSTANCE || "not set"));
|
|
309
|
+
Logger_1.logger.info("User: " + (process.env.SN_USER || "not set"));
|
|
310
|
+
Logger_1.logger.info("Active scope: " + scopeObj.scope);
|
|
311
|
+
if (config.scopes) {
|
|
312
|
+
var scopeNames = Object.keys(config.scopes);
|
|
313
|
+
Logger_1.logger.info("\nConfigured scopes (" + scopeNames.length + "):");
|
|
314
|
+
for (var i = 0; i < scopeNames.length; i++) {
|
|
315
|
+
var scopeName = scopeNames[i];
|
|
316
|
+
var scopeConf = config.scopes[scopeName];
|
|
317
|
+
var srcDir = (typeof scopeConf === "object" && scopeConf.sourceDirectory)
|
|
318
|
+
? scopeConf.sourceDirectory
|
|
319
|
+
: "src/" + scopeName;
|
|
320
|
+
var marker = scopeName === scopeObj.scope ? " (active)" : "";
|
|
321
|
+
Logger_1.logger.info(" " + scopeName + marker + " — " + srcDir);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
324
|
}
|
|
325
325
|
catch (e) {
|
|
326
326
|
throw e;
|
package/dist/config.js
CHANGED
|
@@ -54,6 +54,9 @@ exports.getRefresh = getRefresh;
|
|
|
54
54
|
exports.getDefaultConfigFile = getDefaultConfigFile;
|
|
55
55
|
exports.loadScopeManifest = loadScopeManifest;
|
|
56
56
|
exports.updateManifest = updateManifest;
|
|
57
|
+
exports.isMultiScopeManifest = isMultiScopeManifest;
|
|
58
|
+
exports.resolveManifestForScope = resolveManifestForScope;
|
|
59
|
+
exports.resolveScopeFromPath = resolveScopeFromPath;
|
|
57
60
|
exports.isDirectiveKey = isDirectiveKey;
|
|
58
61
|
exports.stripDirectiveKeys = stripDirectiveKeys;
|
|
59
62
|
exports.resolveConfigForScope = resolveConfigForScope;
|
|
@@ -290,6 +293,35 @@ async function loadScopeManifest(scope) {
|
|
|
290
293
|
function updateManifest(man) {
|
|
291
294
|
manifest = man;
|
|
292
295
|
}
|
|
296
|
+
function isMultiScopeManifest(man) {
|
|
297
|
+
return typeof man === "object" && man !== null && !man.scope && !man.tables;
|
|
298
|
+
}
|
|
299
|
+
function resolveManifestForScope(man, scope) {
|
|
300
|
+
if (!isMultiScopeManifest(man)) {
|
|
301
|
+
if (!scope || man.scope === scope) {
|
|
302
|
+
return man;
|
|
303
|
+
}
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
var scopeMan = man[scope];
|
|
307
|
+
if (scopeMan && scopeMan.tables) {
|
|
308
|
+
return scopeMan;
|
|
309
|
+
}
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
function resolveScopeFromPath(filePath) {
|
|
313
|
+
var cfg = getConfig();
|
|
314
|
+
if (!cfg.scopes)
|
|
315
|
+
return undefined;
|
|
316
|
+
var scopeNames = Object.keys(cfg.scopes);
|
|
317
|
+
for (var i = 0; i < scopeNames.length; i++) {
|
|
318
|
+
var scopeSourcePath = getSourcePathForScope(scopeNames[i]);
|
|
319
|
+
if (filePath.indexOf(scopeSourcePath) === 0) {
|
|
320
|
+
return scopeNames[i];
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
293
325
|
async function loadConfigPath(pth) {
|
|
294
326
|
if (!pth) {
|
|
295
327
|
pth = process.cwd();
|
|
@@ -102,7 +102,7 @@ async function resolveScope(args) {
|
|
|
102
102
|
// Try to get scope from current manifest
|
|
103
103
|
try {
|
|
104
104
|
var manifest = ConfigManager.getManifest();
|
|
105
|
-
if (manifest && manifest.scope) {
|
|
105
|
+
if (manifest && !ConfigManager.isMultiScopeManifest(manifest) && manifest.scope) {
|
|
106
106
|
return manifest.scope;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -57,7 +57,7 @@ async function resolveScope(args) {
|
|
|
57
57
|
// Try to get scope from current manifest
|
|
58
58
|
try {
|
|
59
59
|
var manifest = ConfigManager.getManifest();
|
|
60
|
-
if (manifest && manifest.scope) {
|
|
60
|
+
if (manifest && !ConfigManager.isMultiScopeManifest(manifest) && manifest.scope) {
|
|
61
61
|
return manifest.scope;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -173,6 +173,34 @@ async function runLoginPhase(plugin, context) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
async function runConfigPhase(context) {
|
|
177
|
+
if (context.hasConfig) {
|
|
178
|
+
var answer = await inquirer_1.default.prompt([{
|
|
179
|
+
type: "list",
|
|
180
|
+
name: "configAction",
|
|
181
|
+
message: "Existing config found. Would you like to update it or use the current one?",
|
|
182
|
+
choices: [
|
|
183
|
+
{ name: "Use current config", value: "keep" },
|
|
184
|
+
{ name: "Update config", value: "update" },
|
|
185
|
+
],
|
|
186
|
+
}]);
|
|
187
|
+
if (answer.configAction === "keep") {
|
|
188
|
+
Logger_1.logger.info(chalk_1.default.green(" ✓ Using existing sinc.config.js"));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// TODO: Future config wizard steps:
|
|
193
|
+
// 1. Scopes — multi-select from available scopes
|
|
194
|
+
// 2. Tables — multi-select with search (inquirer-autocomplete)
|
|
195
|
+
// 3. Fields for selected tables
|
|
196
|
+
// 4. Special scope tables
|
|
197
|
+
// 5. Special scope fields for tables
|
|
198
|
+
Logger_1.logger.info("");
|
|
199
|
+
Logger_1.logger.info(chalk_1.default.magenta(" 🎬 Coming soon to a terminal near you!"));
|
|
200
|
+
Logger_1.logger.info(chalk_1.default.dim(" The config wizard is still in development — stay tuned."));
|
|
201
|
+
Logger_1.logger.info(chalk_1.default.dim(" For now, " + (context.hasConfig ? "we'll keep your current config." : "we'll set you up with the defaults.")));
|
|
202
|
+
Logger_1.logger.info("");
|
|
203
|
+
}
|
|
176
204
|
async function runConfigurePhase(plugin, context) {
|
|
177
205
|
const hooks = plugin.configure;
|
|
178
206
|
if (!hooks || hooks.length === 0)
|
|
@@ -239,6 +267,11 @@ async function runInit(options) {
|
|
|
239
267
|
}
|
|
240
268
|
// 5. Save env vars after login
|
|
241
269
|
saveEnvVars(context, selectedPlugins);
|
|
270
|
+
// 5.5 Config phase
|
|
271
|
+
Logger_1.logger.info("");
|
|
272
|
+
Logger_1.logger.info(chalk_1.default.bold(" ── Config " + "─".repeat(29)));
|
|
273
|
+
Logger_1.logger.info("");
|
|
274
|
+
await runConfigPhase(context);
|
|
242
275
|
// 6. Configure phase
|
|
243
276
|
Logger_1.logger.info("");
|
|
244
277
|
Logger_1.logger.info(chalk_1.default.bold(" ── Configure " + "─".repeat(26)));
|
package/dist/logMessages.js
CHANGED
|
@@ -4,21 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.logBuildResults = exports.logPushResults = exports.log = void 0;
|
|
7
|
-
exports.scopeCheckMessage = scopeCheckMessage;
|
|
8
|
-
exports.devModeLog = devModeLog;
|
|
9
7
|
exports.logFilePush = logFilePush;
|
|
10
8
|
exports.logDeploy = logDeploy;
|
|
11
9
|
const Logger_1 = require("./Logger");
|
|
12
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
13
11
|
exports.log = console.log;
|
|
14
|
-
function scopeCheckMessage(scopeCheck) {
|
|
15
|
-
let sScope = chalk_1.default.blue(scopeCheck.sessionScope);
|
|
16
|
-
let mScope = chalk_1.default.blue(scopeCheck.manifestScope);
|
|
17
|
-
Logger_1.logger.error("Scope mismatch: your session is " + sScope + " but this project targets " + mScope + ". Switch scopes in ServiceNow to continue.");
|
|
18
|
-
}
|
|
19
|
-
function devModeLog() {
|
|
20
|
-
Logger_1.logger.info(`Dev mode started! Watching for changes...[${chalk_1.default.red("Press CTRL-C to Stop")}]\n`);
|
|
21
|
-
}
|
|
22
12
|
function parseError(err) {
|
|
23
13
|
return `${err.name}:
|
|
24
14
|
${err.message}
|