@tenonhq/sincronia-core 0.0.74 → 0.0.77
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 +1 -0
- package/dist/config.js +159 -0
- package/dist/initSystem/corePlugin.js +166 -55
- package/dist/initSystem/orchestrator.js +31 -14
- package/package.json +2 -2
|
@@ -36,6 +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.processScope = processScope;
|
|
39
40
|
exports.initScopesCommand = initScopesCommand;
|
|
40
41
|
exports.watchAllScopesCommand = watchAllScopesCommand;
|
|
41
42
|
const Logger_1 = require("./Logger");
|
package/dist/config.js
CHANGED
|
@@ -52,6 +52,7 @@ exports.getDiffPath = getDiffPath;
|
|
|
52
52
|
exports.getDiffFile = getDiffFile;
|
|
53
53
|
exports.getRefresh = getRefresh;
|
|
54
54
|
exports.getDefaultConfigFile = getDefaultConfigFile;
|
|
55
|
+
exports.generateConfigFile = generateConfigFile;
|
|
55
56
|
exports.loadScopeManifest = loadScopeManifest;
|
|
56
57
|
exports.updateManifest = updateManifest;
|
|
57
58
|
exports.isMultiScopeManifest = isMultiScopeManifest;
|
|
@@ -201,6 +202,164 @@ function getDefaultConfigFile() {
|
|
|
201
202
|
};
|
|
202
203
|
`.trim();
|
|
203
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* @description Generates a full sinc.config.js with multi-scope support, table whitelist,
|
|
207
|
+
* field type overrides, and plugin rules. Used by sinc init when creating a new config.
|
|
208
|
+
* @param {Object} params - Configuration parameters
|
|
209
|
+
* @param {Array<{scope: string, sourceDirectory: string}>} params.scopes - Selected scopes with source directories
|
|
210
|
+
* @returns {string} Complete sinc.config.js file content
|
|
211
|
+
*/
|
|
212
|
+
function generateConfigFile(params) {
|
|
213
|
+
var scopeEntries = params.scopes.map(function (s) {
|
|
214
|
+
return "\t\t" + s.scope + ": {\n\t\t\tsourceDirectory: \"" + s.sourceDirectory + "\",\n\t\t},";
|
|
215
|
+
}).join("\n");
|
|
216
|
+
return "module.exports = {\n" +
|
|
217
|
+
"\tsourceDirectory: \"src\",\n" +
|
|
218
|
+
"\tbuildDirectory: \"build\",\n" +
|
|
219
|
+
"\n" +
|
|
220
|
+
"\t// Plugin Rules Configuration\n" +
|
|
221
|
+
"\trules: [\n" +
|
|
222
|
+
"\t\t{\n" +
|
|
223
|
+
"\t\t\tmatch: /sys_script_include.*\\.ts$/,\n" +
|
|
224
|
+
"\t\t\tplugins: [\n" +
|
|
225
|
+
"\t\t\t\t{\n" +
|
|
226
|
+
"\t\t\t\t\tname: \"@sincronia/typescript-plugin\",\n" +
|
|
227
|
+
"\t\t\t\t\toptions: {\n" +
|
|
228
|
+
"\t\t\t\t\t\ttranspile: true,\n" +
|
|
229
|
+
"\t\t\t\t\t\ttypeCheck: true,\n" +
|
|
230
|
+
"\t\t\t\t\t\ttsconfig: \"./tsconfig.servicenow.json\",\n" +
|
|
231
|
+
"\t\t\t\t\t},\n" +
|
|
232
|
+
"\t\t\t\t},\n" +
|
|
233
|
+
"\t\t\t\t{\n" +
|
|
234
|
+
"\t\t\t\t\tname: \"@sincronia/eslint-plugin\",\n" +
|
|
235
|
+
"\t\t\t\t\toptions: {\n" +
|
|
236
|
+
"\t\t\t\t\t\tconfigFile: \"./.eslintrc.js\",\n" +
|
|
237
|
+
"\t\t\t\t\t\tfix: false,\n" +
|
|
238
|
+
"\t\t\t\t\t\tcache: true,\n" +
|
|
239
|
+
"\t\t\t\t\t},\n" +
|
|
240
|
+
"\t\t\t\t},\n" +
|
|
241
|
+
"\t\t\t\t{\n" +
|
|
242
|
+
"\t\t\t\t\tname: \"@sincronia/babel-plugin\",\n" +
|
|
243
|
+
"\t\t\t\t\toptions: {\n" +
|
|
244
|
+
"\t\t\t\t\t\tconfigFile: \"./.babelrc\",\n" +
|
|
245
|
+
"\t\t\t\t\t},\n" +
|
|
246
|
+
"\t\t\t\t},\n" +
|
|
247
|
+
"\t\t\t\t{\n" +
|
|
248
|
+
"\t\t\t\t\tname: \"@sincronia/prettier-plugin\",\n" +
|
|
249
|
+
"\t\t\t\t\toptions: {\n" +
|
|
250
|
+
"\t\t\t\t\t\tconfigFile: \"./.prettierrc.js\",\n" +
|
|
251
|
+
"\t\t\t\t\t},\n" +
|
|
252
|
+
"\t\t\t\t},\n" +
|
|
253
|
+
"\t\t\t],\n" +
|
|
254
|
+
"\t\t},\n" +
|
|
255
|
+
"\t],\n" +
|
|
256
|
+
"\n" +
|
|
257
|
+
"\tincludes: {\n" +
|
|
258
|
+
"\t\t_tables: [\n" +
|
|
259
|
+
"\t\t\t\"sys_script_include\",\n" +
|
|
260
|
+
"\t\t\t\"sys_script\",\n" +
|
|
261
|
+
"\t\t\t\"sys_ui_script\",\n" +
|
|
262
|
+
"\t\t\t\"sys_ui_page\",\n" +
|
|
263
|
+
"\t\t\t\"sys_ux_client_script\",\n" +
|
|
264
|
+
"\t\t\t\"sys_processor\",\n" +
|
|
265
|
+
"\t\t\t\"sys_ws_operation\",\n" +
|
|
266
|
+
"\t\t\t\"sys_rest_message_fn\",\n" +
|
|
267
|
+
"\t\t\t\"sys_ui_action\",\n" +
|
|
268
|
+
"\t\t\t\"sys_security_acl\",\n" +
|
|
269
|
+
"\t\t\t\"sysevent_script_action\",\n" +
|
|
270
|
+
"\t\t\t\"sys_ux_macroponent\",\n" +
|
|
271
|
+
"\t\t\t\"sys_ux_event\",\n" +
|
|
272
|
+
"\t\t\t\"sys_ux_client_script_include\",\n" +
|
|
273
|
+
"\t\t\t\"sys_ux_screen\",\n" +
|
|
274
|
+
"\t\t\t\"sys_script_fix\",\n" +
|
|
275
|
+
"\t\t],\n" +
|
|
276
|
+
"\t\tsys_script_include: {\n" +
|
|
277
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
278
|
+
"\t\t},\n" +
|
|
279
|
+
"\t\tsys_script: {\n" +
|
|
280
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
281
|
+
"\t\t},\n" +
|
|
282
|
+
"\t\tsys_ui_script: {\n" +
|
|
283
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
284
|
+
"\t\t},\n" +
|
|
285
|
+
"\t\tsys_ui_page: {\n" +
|
|
286
|
+
"\t\t\tprocessing_script: { type: \"js\" },\n" +
|
|
287
|
+
"\t\t\tclient_script: { type: \"js\" },\n" +
|
|
288
|
+
"\t\t\thtml: { type: \"html\" },\n" +
|
|
289
|
+
"\t\t},\n" +
|
|
290
|
+
"\t\tsys_processor: {\n" +
|
|
291
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
292
|
+
"\t\t},\n" +
|
|
293
|
+
"\t\tsys_ws_operation: {\n" +
|
|
294
|
+
"\t\t\toperation_script: { type: \"js\" },\n" +
|
|
295
|
+
"\t\t},\n" +
|
|
296
|
+
"\t\tsys_rest_message_fn: {\n" +
|
|
297
|
+
"\t\t\tcontent: { type: \"txt\" },\n" +
|
|
298
|
+
"\t\t},\n" +
|
|
299
|
+
"\t\tsys_ui_action: {\n" +
|
|
300
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
301
|
+
"\t\t\tclient_script_v2: { type: \"js\" },\n" +
|
|
302
|
+
"\t\t},\n" +
|
|
303
|
+
"\t\tsys_security_acl: {\n" +
|
|
304
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
305
|
+
"\t\t},\n" +
|
|
306
|
+
"\t\tsysevent_script_action: {\n" +
|
|
307
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
308
|
+
"\t\t},\n" +
|
|
309
|
+
"\t\tsys_script_fix: {\n" +
|
|
310
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
311
|
+
"\t\t},\n" +
|
|
312
|
+
"\t\tsys_ux_macroponent: {\n" +
|
|
313
|
+
"\t\t\tcomposition: { type: \"json\" },\n" +
|
|
314
|
+
"\t\t\tprops: { type: \"json\" },\n" +
|
|
315
|
+
"\t\t\tdata: { type: \"json\" },\n" +
|
|
316
|
+
"\t\t\trequired_translations: { type: \"json\" },\n" +
|
|
317
|
+
"\t\t\troot_component_definition: { type: \"json\" },\n" +
|
|
318
|
+
"\t\t\tstate_properties: { type: \"json\" },\n" +
|
|
319
|
+
"\t\t\troot_component_config: { type: \"json\" },\n" +
|
|
320
|
+
"\t\t\tinternal_event_mappings: { type: \"json\" },\n" +
|
|
321
|
+
"\t\t\tstate_persistence_config: { type: \"json\" },\n" +
|
|
322
|
+
"\t\t},\n" +
|
|
323
|
+
"\t\tsys_ux_event: {\n" +
|
|
324
|
+
"\t\t\tdescription: { type: \"txt\" },\n" +
|
|
325
|
+
"\t\t\tevent_name: { type: \"txt\" },\n" +
|
|
326
|
+
"\t\t\tlabel: { type: \"txt\" },\n" +
|
|
327
|
+
"\t\t\tprops: { type: \"json\" },\n" +
|
|
328
|
+
"\t\t\trequired_translations: { type: \"json\" },\n" +
|
|
329
|
+
"\t\t},\n" +
|
|
330
|
+
"\t\tsys_ux_client_script: {\n" +
|
|
331
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
332
|
+
"\t\t\tname: { type: \"txt\" },\n" +
|
|
333
|
+
"\t\t},\n" +
|
|
334
|
+
"\t\tsys_ux_client_script_include: {\n" +
|
|
335
|
+
"\t\t\tscript: { type: \"js\" },\n" +
|
|
336
|
+
"\t\t\tname: { type: \"txt\" },\n" +
|
|
337
|
+
"\t\t},\n" +
|
|
338
|
+
"\t\tsys_ux_screen: {\n" +
|
|
339
|
+
"\t\t\tmacroponent_config: { type: \"json\" },\n" +
|
|
340
|
+
"\t\t\tevent_mappings: { type: \"json\" },\n" +
|
|
341
|
+
"\t\t},\n" +
|
|
342
|
+
"\t\t_scopes: {},\n" +
|
|
343
|
+
"\t},\n" +
|
|
344
|
+
"\n" +
|
|
345
|
+
"\texcludes: {\n" +
|
|
346
|
+
"\t\t_tables: [],\n" +
|
|
347
|
+
"\t},\n" +
|
|
348
|
+
"\n" +
|
|
349
|
+
"\tmanifestOptions: {\n" +
|
|
350
|
+
"\t\tupdateFields: true,\n" +
|
|
351
|
+
"\t\tupdateDependencies: true,\n" +
|
|
352
|
+
"\t},\n" +
|
|
353
|
+
"\n" +
|
|
354
|
+
"\tserver: {\n" +
|
|
355
|
+
"\t\twatchPath: \"./src\",\n" +
|
|
356
|
+
"\t},\n" +
|
|
357
|
+
"\n" +
|
|
358
|
+
"\tscopes: {\n" +
|
|
359
|
+
scopeEntries + "\n" +
|
|
360
|
+
"\t},\n" +
|
|
361
|
+
"};\n";
|
|
362
|
+
}
|
|
204
363
|
async function loadConfig(skipConfigPath = false) {
|
|
205
364
|
if (skipConfigPath) {
|
|
206
365
|
Logger_1.logger.warn("Couldn't find config file. Loading default...");
|
|
@@ -42,7 +42,7 @@ exports.normalizeInstance = normalizeInstance;
|
|
|
42
42
|
const snClient_1 = require("../snClient");
|
|
43
43
|
const Logger_1 = require("../Logger");
|
|
44
44
|
const ConfigManager = __importStar(require("../config"));
|
|
45
|
-
const
|
|
45
|
+
const allScopesCommands_1 = require("../allScopesCommands");
|
|
46
46
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
47
47
|
const chalk_1 = __importDefault(require("chalk"));
|
|
48
48
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -84,44 +84,109 @@ exports.corePlugin = {
|
|
|
84
84
|
],
|
|
85
85
|
configure: [
|
|
86
86
|
{
|
|
87
|
-
key: "
|
|
88
|
-
label: "Selecting ServiceNow
|
|
87
|
+
key: "apps",
|
|
88
|
+
label: "Selecting ServiceNow applications",
|
|
89
89
|
run: async (context) => {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
var baseUrl = instanceBaseUrl(context.env.SN_INSTANCE);
|
|
91
|
+
var client = (0, snClient_1.snClient)(baseUrl, context.env.SN_USER, context.env.SN_PASSWORD);
|
|
92
92
|
Logger_1.logger.info("Fetching application list...");
|
|
93
|
-
|
|
93
|
+
var apps = await (0, snClient_1.unwrapSNResponse)(client.getAppList());
|
|
94
94
|
if (apps.length === 0) {
|
|
95
95
|
Logger_1.logger.warn("No applications found on this instance.");
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
// Pre-check scopes that exist in the current config
|
|
99
|
+
var existingScopes = new Set();
|
|
100
|
+
if (context.hasConfig) {
|
|
101
|
+
try {
|
|
102
|
+
var existingConfig = require(path_1.default.join(context.rootDir, "sinc.config.js"));
|
|
103
|
+
if (existingConfig.scopes) {
|
|
104
|
+
Object.keys(existingConfig.scopes).forEach(function (s) {
|
|
105
|
+
existingScopes.add(s);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
// ignore — no existing config or malformed
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
var choices = apps.map(function (app) {
|
|
114
|
+
return {
|
|
115
|
+
name: app.displayName + " (" + app.scope + ")",
|
|
116
|
+
value: app.scope,
|
|
117
|
+
short: app.displayName,
|
|
118
|
+
checked: existingScopes.has(app.scope),
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
var answer = await inquirer_1.default.prompt([{
|
|
122
|
+
type: "checkbox",
|
|
123
|
+
name: "apps",
|
|
124
|
+
message: "Which apps would you like to work with? (space to select, enter to confirm)",
|
|
125
|
+
choices: choices,
|
|
126
|
+
validate: function (input) {
|
|
127
|
+
if (input.length === 0)
|
|
128
|
+
return "Select at least one application.";
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
108
131
|
}]);
|
|
109
|
-
|
|
132
|
+
var selectedScopes = answer.apps;
|
|
133
|
+
context.answers.selectedScopes = selectedScopes;
|
|
134
|
+
context.answers.selectedScope = selectedScopes[0]; // backward compat
|
|
110
135
|
context.answers.apps = apps;
|
|
111
|
-
|
|
136
|
+
// Prompt for source directory per selected scope
|
|
137
|
+
var scopeDirectories = {};
|
|
138
|
+
Logger_1.logger.info("");
|
|
139
|
+
Logger_1.logger.info(chalk_1.default.bold(" Source directories:"));
|
|
140
|
+
for (var i = 0; i < selectedScopes.length; i++) {
|
|
141
|
+
var scope = selectedScopes[i];
|
|
142
|
+
var app = apps.find(function (a) { return a.scope === scope; });
|
|
143
|
+
var displayName = app ? app.displayName : scope;
|
|
144
|
+
// Check if existing config already has a sourceDirectory for this scope
|
|
145
|
+
var existingDir = "";
|
|
146
|
+
if (existingScopes.has(scope)) {
|
|
147
|
+
try {
|
|
148
|
+
var cfgScopes = require(path_1.default.join(context.rootDir, "sinc.config.js")).scopes;
|
|
149
|
+
if (cfgScopes && cfgScopes[scope] && cfgScopes[scope].sourceDirectory) {
|
|
150
|
+
existingDir = cfgScopes[scope].sourceDirectory;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
// ignore
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Suggest a friendly name from displayName, or use existing
|
|
158
|
+
var suggestedDir = existingDir || ("src/" + displayName.replace(/\s+/g, ""));
|
|
159
|
+
var dirAnswer = await inquirer_1.default.prompt([{
|
|
160
|
+
type: "input",
|
|
161
|
+
name: "dir",
|
|
162
|
+
message: scope + ":",
|
|
163
|
+
default: suggestedDir,
|
|
164
|
+
}]);
|
|
165
|
+
scopeDirectories[scope] = dirAnswer.dir;
|
|
166
|
+
}
|
|
167
|
+
context.answers.scopeDirectories = scopeDirectories;
|
|
168
|
+
return selectedScopes;
|
|
112
169
|
},
|
|
113
170
|
},
|
|
114
171
|
],
|
|
115
172
|
initialize: async (context) => {
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
173
|
+
var selectedScopes = context.answers.selectedScopes || [];
|
|
174
|
+
if (selectedScopes.length === 0) {
|
|
175
|
+
// Backward compat: single scope from old flow
|
|
176
|
+
if (context.answers.selectedScope) {
|
|
177
|
+
selectedScopes = [context.answers.selectedScope];
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
Logger_1.logger.warn("No applications selected — skipping initialization.");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
120
183
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
184
|
+
var rootDir = context.rootDir;
|
|
185
|
+
var configPath = path_1.default.join(rootDir, "sinc.config.js");
|
|
186
|
+
var scopeDirectories = context.answers.scopeDirectories || {};
|
|
187
|
+
// Write or preserve sinc.config.js
|
|
188
|
+
var configAction = context.answers.configAction || "keep";
|
|
189
|
+
var hasExistingConfig = false;
|
|
125
190
|
try {
|
|
126
191
|
fs_1.default.accessSync(configPath, fs_1.default.constants.F_OK);
|
|
127
192
|
hasExistingConfig = true;
|
|
@@ -129,9 +194,16 @@ exports.corePlugin = {
|
|
|
129
194
|
catch (e) {
|
|
130
195
|
// No existing config
|
|
131
196
|
}
|
|
132
|
-
if (!hasExistingConfig) {
|
|
197
|
+
if (!hasExistingConfig || configAction === "replace") {
|
|
133
198
|
Logger_1.logger.info("Generating sinc.config.js...");
|
|
134
|
-
|
|
199
|
+
var scopeEntries = selectedScopes.map(function (scope) {
|
|
200
|
+
return {
|
|
201
|
+
scope: scope,
|
|
202
|
+
sourceDirectory: scopeDirectories[scope] || ("src/" + scope),
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
fs_1.default.writeFileSync(configPath, ConfigManager.generateConfigFile({ scopes: scopeEntries }), "utf8");
|
|
206
|
+
Logger_1.logger.success(chalk_1.default.green("✓ Generated sinc.config.js with " + selectedScopes.length + " scope(s)"));
|
|
135
207
|
}
|
|
136
208
|
else {
|
|
137
209
|
Logger_1.logger.info("sinc.config.js already exists — preserving configuration.");
|
|
@@ -143,40 +215,79 @@ exports.corePlugin = {
|
|
|
143
215
|
catch (e) {
|
|
144
216
|
Logger_1.logger.warn("Config reload incomplete — this is expected during first-time init.");
|
|
145
217
|
}
|
|
146
|
-
// Check
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
218
|
+
// Check which scopes already have manifests
|
|
219
|
+
var scopesWithManifests = [];
|
|
220
|
+
var scopesToDownload = [];
|
|
221
|
+
for (var i = 0; i < selectedScopes.length; i++) {
|
|
222
|
+
var scope = selectedScopes[i];
|
|
223
|
+
var manifestPath = path_1.default.join(rootDir, "sinc.manifest." + scope + ".json");
|
|
224
|
+
var hasManifest = false;
|
|
225
|
+
try {
|
|
226
|
+
fs_1.default.accessSync(manifestPath, fs_1.default.constants.F_OK);
|
|
227
|
+
hasManifest = true;
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
// No manifest
|
|
231
|
+
}
|
|
232
|
+
if (hasManifest) {
|
|
233
|
+
scopesWithManifests.push(scope);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
scopesToDownload.push(scope);
|
|
237
|
+
}
|
|
155
238
|
}
|
|
156
|
-
|
|
157
|
-
|
|
239
|
+
// Batch prompt for scopes that already have manifests
|
|
240
|
+
if (scopesWithManifests.length > 0) {
|
|
241
|
+
var redownload = await inquirer_1.default.prompt([{
|
|
158
242
|
type: "confirm",
|
|
159
243
|
name: "confirmed",
|
|
160
|
-
message: "
|
|
244
|
+
message: scopesWithManifests.length + " scope(s) already have manifests (" + scopesWithManifests.join(", ") + "). Re-download?",
|
|
161
245
|
default: false,
|
|
162
246
|
}]);
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
return;
|
|
247
|
+
if (redownload.confirmed) {
|
|
248
|
+
scopesToDownload = scopesToDownload.concat(scopesWithManifests);
|
|
166
249
|
}
|
|
167
250
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return
|
|
178
|
-
}
|
|
179
|
-
|
|
251
|
+
if (scopesToDownload.length === 0) {
|
|
252
|
+
Logger_1.logger.info("No scopes to download — all manifests up to date.");
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Download all scopes using the battle-tested processScope pipeline
|
|
256
|
+
Logger_1.logger.info("Downloading " + scopesToDownload.length + " scope(s)...");
|
|
257
|
+
var config = ConfigManager.getConfig();
|
|
258
|
+
var scopePromises = scopesToDownload.map(function (scopeName) {
|
|
259
|
+
var scopeConfig = (config.scopes && config.scopes[scopeName]) || {};
|
|
260
|
+
return (0, allScopesCommands_1.processScope)(scopeName, scopeConfig, 0);
|
|
261
|
+
});
|
|
262
|
+
var results = await Promise.allSettled(scopePromises);
|
|
263
|
+
// Write per-scope manifest files and tally results
|
|
264
|
+
var successCount = 0;
|
|
265
|
+
var failCount = 0;
|
|
266
|
+
for (var r = 0; r < results.length; r++) {
|
|
267
|
+
var result = results[r];
|
|
268
|
+
var scopeName = scopesToDownload[r];
|
|
269
|
+
if (result.status === "fulfilled" && result.value.success) {
|
|
270
|
+
successCount++;
|
|
271
|
+
// Write per-scope manifest
|
|
272
|
+
if (result.value.manifest) {
|
|
273
|
+
var scopeManifestPath = ConfigManager.getScopeManifestPath(scopeName);
|
|
274
|
+
fs_1.default.writeFileSync(scopeManifestPath, JSON.stringify(result.value.manifest, null, 2), "utf8");
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
failCount++;
|
|
279
|
+
var error = result.status === "rejected" ? result.reason : (result.value && result.value.error);
|
|
280
|
+
Logger_1.logger.error("Failed to initialize " + scopeName + ": " + (error && error.message ? error.message : "Unknown error"));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Summary
|
|
284
|
+
Logger_1.logger.info("");
|
|
285
|
+
if (failCount === 0) {
|
|
286
|
+
Logger_1.logger.success(chalk_1.default.green("✓ ServiceNow configured — " + successCount + " scope(s) initialized"));
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
Logger_1.logger.warn(successCount + "/" + scopesToDownload.length + " scopes initialized, " + failCount + " failed");
|
|
290
|
+
}
|
|
180
291
|
},
|
|
181
292
|
};
|
|
182
293
|
/**
|
|
@@ -113,6 +113,31 @@ async function runLoginPhase(plugin, context) {
|
|
|
113
113
|
return;
|
|
114
114
|
// Core plugin: retry loop with specific error messages
|
|
115
115
|
if (plugin.name === "core") {
|
|
116
|
+
// If .env already has all required credentials, offer to skip login
|
|
117
|
+
const hasAllCreds = context.env.SN_INSTANCE && context.env.SN_USER && context.env.SN_PASSWORD;
|
|
118
|
+
if (hasAllCreds) {
|
|
119
|
+
Logger_1.logger.info("Found existing credentials:");
|
|
120
|
+
Logger_1.logger.info(" Instance: " + context.env.SN_INSTANCE);
|
|
121
|
+
Logger_1.logger.info(" User: " + context.env.SN_USER);
|
|
122
|
+
Logger_1.logger.info("");
|
|
123
|
+
const useExisting = await inquirer_1.default.prompt([{
|
|
124
|
+
type: "confirm",
|
|
125
|
+
name: "confirmed",
|
|
126
|
+
message: "Use these credentials?",
|
|
127
|
+
default: true,
|
|
128
|
+
}]);
|
|
129
|
+
if (useExisting.confirmed) {
|
|
130
|
+
Logger_1.logger.info("Validating credentials...");
|
|
131
|
+
const result = await (0, corePlugin_1.validateCoreLogin)(context);
|
|
132
|
+
if (result === true) {
|
|
133
|
+
Logger_1.logger.success(chalk_1.default.green("✓ Connected to " + context.env.SN_INSTANCE));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
Logger_1.logger.error(chalk_1.default.red("✗ " + result));
|
|
137
|
+
Logger_1.logger.info("Please re-enter your credentials.");
|
|
138
|
+
context.env.SN_PASSWORD = "";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
116
141
|
while (true) {
|
|
117
142
|
await collectLoginHooks(hooks, context);
|
|
118
143
|
// Run per-hook validation
|
|
@@ -178,28 +203,20 @@ async function runConfigPhase(context) {
|
|
|
178
203
|
var answer = await inquirer_1.default.prompt([{
|
|
179
204
|
type: "list",
|
|
180
205
|
name: "configAction",
|
|
181
|
-
message: "Existing config found
|
|
206
|
+
message: "Existing sinc.config.js found:",
|
|
182
207
|
choices: [
|
|
183
208
|
{ name: "Use current config", value: "keep" },
|
|
184
|
-
{ name: "
|
|
209
|
+
{ name: "Replace config (regenerate after scope selection)", value: "replace" },
|
|
185
210
|
],
|
|
186
211
|
}]);
|
|
212
|
+
context.answers.configAction = answer.configAction;
|
|
187
213
|
if (answer.configAction === "keep") {
|
|
188
214
|
Logger_1.logger.info(chalk_1.default.green(" ✓ Using existing sinc.config.js"));
|
|
189
|
-
return;
|
|
190
215
|
}
|
|
216
|
+
return;
|
|
191
217
|
}
|
|
192
|
-
//
|
|
193
|
-
|
|
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("");
|
|
218
|
+
// No config — will be generated in initialize phase after scopes are selected
|
|
219
|
+
context.answers.configAction = "generate";
|
|
203
220
|
}
|
|
204
221
|
async function runConfigurePhase(plugin, context) {
|
|
205
222
|
const hooks = plugin.configure;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenonhq/sincronia-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.77",
|
|
4
4
|
"description": "Next-gen file syncer",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"node": ">=20.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@tenonhq/sincronia-types": "^0.0.
|
|
25
|
+
"@tenonhq/sincronia-types": "^0.0.13",
|
|
26
26
|
"@types/dotenv": "^6.1.1",
|
|
27
27
|
"@types/inquirer": "^8.2.10",
|
|
28
28
|
"@types/jest": "^29.5.5",
|