@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.
@@ -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 AppUtils = __importStar(require("../appUtils"));
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: "app",
88
- label: "Selecting ServiceNow application",
87
+ key: "apps",
88
+ label: "Selecting ServiceNow applications",
89
89
  run: async (context) => {
90
- const baseUrl = instanceBaseUrl(context.env.SN_INSTANCE);
91
- const client = (0, snClient_1.snClient)(baseUrl, context.env.SN_USER, context.env.SN_PASSWORD);
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
- const apps = await (0, snClient_1.unwrapSNResponse)(client.getAppList());
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
- const choices = apps.map((app) => ({
99
- name: app.displayName + " (" + app.scope + ")",
100
- value: app.scope,
101
- short: app.displayName,
102
- }));
103
- const answer = await inquirer_1.default.prompt([{
104
- type: "list",
105
- name: "app",
106
- message: "Which app would you like to work with?",
107
- choices,
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
- context.answers.selectedScope = answer.app;
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
- return answer.app;
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
- const scope = context.answers.selectedScope;
117
- if (!scope) {
118
- Logger_1.logger.warn("No application selected skipping initialization.");
119
- return;
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
- const rootDir = context.rootDir;
122
- const configPath = path_1.default.join(rootDir, "sinc.config.js");
123
- // Write or merge sinc.config.js
124
- let hasExistingConfig = false;
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
- fs_1.default.writeFileSync(configPath, ConfigManager.getDefaultConfigFile(), "utf8");
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 if manifest already exists for this scope
147
- const manifestPath = path_1.default.join(rootDir, "sinc.manifest." + scope + ".json");
148
- let hasManifest = false;
149
- try {
150
- fs_1.default.accessSync(manifestPath, fs_1.default.constants.F_OK);
151
- hasManifest = true;
152
- }
153
- catch (e) {
154
- // No existing manifest
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
- if (hasManifest) {
157
- const redownload = await inquirer_1.default.prompt([{
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: "Manifest for " + scope + " already exists. Re-download?",
244
+ message: scopesWithManifests.length + " scope(s) already have manifests (" + scopesWithManifests.join(", ") + "). Re-download?",
161
245
  default: false,
162
246
  }]);
163
- if (!redownload.confirmed) {
164
- Logger_1.logger.info("Skipping download for " + scope);
165
- return;
247
+ if (redownload.confirmed) {
248
+ scopesToDownload = scopesToDownload.concat(scopesWithManifests);
166
249
  }
167
250
  }
168
- // Download application files — errors propagate to orchestrator
169
- Logger_1.logger.info("Downloading " + scope + "...");
170
- const baseUrl = instanceBaseUrl(context.env.SN_INSTANCE);
171
- const client = (0, snClient_1.snClient)(baseUrl, context.env.SN_USER, context.env.SN_PASSWORD);
172
- const config = ConfigManager.getConfig();
173
- const man = await (0, snClient_1.unwrapSNResponse)(client.getManifest(scope, config, true));
174
- await AppUtils.processManifest(man);
175
- const tableNames = Object.keys(man.tables || {});
176
- const recordCount = tableNames.reduce((sum, t) => {
177
- return sum + Object.keys(man.tables[t].records || {}).length;
178
- }, 0);
179
- Logger_1.logger.success(chalk_1.default.green("✓ ServiceNow configured " + tableNames.length + " tables, " + recordCount + " records"));
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. Would you like to update it or use the current one?",
206
+ message: "Existing sinc.config.js found:",
182
207
  choices: [
183
208
  { name: "Use current config", value: "keep" },
184
- { name: "Update config", value: "update" },
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
- // 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("");
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.74",
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.10",
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",