@dollhousemcp/mcp-server 1.7.3 → 1.7.4

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.
Files changed (51) hide show
  1. package/dist/config/ConfigWizard.d.ts +78 -0
  2. package/dist/config/ConfigWizard.d.ts.map +1 -0
  3. package/dist/config/ConfigWizard.js +370 -0
  4. package/dist/config/ConfigWizardCheck.d.ts +47 -0
  5. package/dist/config/ConfigWizardCheck.d.ts.map +1 -0
  6. package/dist/config/ConfigWizardCheck.js +208 -0
  7. package/dist/config/ConfigWizardDisplay.d.ts +64 -0
  8. package/dist/config/ConfigWizardDisplay.d.ts.map +1 -0
  9. package/dist/config/ConfigWizardDisplay.js +150 -0
  10. package/dist/config/WizardFirstResponse.d.ts +25 -0
  11. package/dist/config/WizardFirstResponse.d.ts.map +1 -0
  12. package/dist/config/WizardFirstResponse.js +118 -0
  13. package/dist/config/portfolioConfig.d.ts +40 -0
  14. package/dist/config/portfolioConfig.d.ts.map +1 -0
  15. package/dist/config/portfolioConfig.js +58 -0
  16. package/dist/config/wizardTemplates.d.ts +84 -0
  17. package/dist/config/wizardTemplates.d.ts.map +1 -0
  18. package/dist/config/wizardTemplates.js +195 -0
  19. package/dist/elements/BaseElement.d.ts +15 -0
  20. package/dist/elements/BaseElement.d.ts.map +1 -1
  21. package/dist/elements/BaseElement.js +38 -5
  22. package/dist/generated/version.d.ts +2 -2
  23. package/dist/generated/version.js +3 -3
  24. package/dist/handlers/PortfolioPullHandler.d.ts +69 -0
  25. package/dist/handlers/PortfolioPullHandler.d.ts.map +1 -0
  26. package/dist/handlers/PortfolioPullHandler.js +340 -0
  27. package/dist/scripts/scripts/run-config-wizard.js +57 -0
  28. package/dist/scripts/src/config/ConfigManager.js +799 -0
  29. package/dist/scripts/src/config/ConfigWizard.js +368 -0
  30. package/dist/scripts/src/errors/SecurityError.js +47 -0
  31. package/dist/scripts/src/security/constants.js +28 -0
  32. package/dist/scripts/src/security/contentValidator.js +415 -0
  33. package/dist/scripts/src/security/errors.js +32 -0
  34. package/dist/scripts/src/security/regexValidator.js +217 -0
  35. package/dist/scripts/src/security/secureYamlParser.js +272 -0
  36. package/dist/scripts/src/security/securityMonitor.js +111 -0
  37. package/dist/scripts/src/security/validators/unicodeValidator.js +315 -0
  38. package/dist/scripts/src/utils/logger.js +288 -0
  39. package/dist/sync/PortfolioDownloader.d.ts +27 -0
  40. package/dist/sync/PortfolioDownloader.d.ts.map +1 -0
  41. package/dist/sync/PortfolioDownloader.js +120 -0
  42. package/dist/sync/PortfolioSyncComparer.d.ts +50 -0
  43. package/dist/sync/PortfolioSyncComparer.d.ts.map +1 -0
  44. package/dist/sync/PortfolioSyncComparer.js +158 -0
  45. package/dist/tools/getWelcomeMessage.d.ts +41 -0
  46. package/dist/tools/getWelcomeMessage.d.ts.map +1 -0
  47. package/dist/tools/getWelcomeMessage.js +109 -0
  48. package/dist/utils/TemplateRenderer.d.ts +63 -0
  49. package/dist/utils/TemplateRenderer.d.ts.map +1 -0
  50. package/dist/utils/TemplateRenderer.js +154 -0
  51. package/package.json +1 -1
@@ -0,0 +1,340 @@
1
+ /**
2
+ * PortfolioPullHandler - Handles pulling portfolio elements from GitHub
3
+ *
4
+ * This handler implements the pull functionality for sync_portfolio,
5
+ * enabling users to download their portfolio from GitHub to local storage.
6
+ * Supports multiple sync modes (additive, mirror, backup) and dry-run.
7
+ */
8
+ import { PortfolioRepoManager } from '../portfolio/PortfolioRepoManager.js';
9
+ import { GitHubPortfolioIndexer } from '../portfolio/GitHubPortfolioIndexer.js';
10
+ import { PortfolioManager } from '../portfolio/PortfolioManager.js';
11
+ import { PortfolioIndexManager } from '../portfolio/PortfolioIndexManager.js';
12
+ import { ElementType } from '../portfolio/types.js';
13
+ import { logger } from '../utils/logger.js';
14
+ import { PortfolioSyncComparer } from '../sync/PortfolioSyncComparer.js';
15
+ import { PortfolioDownloader } from '../sync/PortfolioDownloader.js';
16
+ import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
17
+ import { SecurityMonitor } from '../security/securityMonitor.js';
18
+ import { getPortfolioRepositoryName } from '../config/portfolioConfig.js';
19
+ import * as fs from 'fs/promises';
20
+ import * as path from 'path';
21
+ export class PortfolioPullHandler {
22
+ portfolioRepoManager;
23
+ githubIndexer;
24
+ portfolioManager;
25
+ indexManager;
26
+ syncComparer;
27
+ downloader;
28
+ constructor() {
29
+ this.portfolioRepoManager = new PortfolioRepoManager(getPortfolioRepositoryName());
30
+ this.githubIndexer = GitHubPortfolioIndexer.getInstance();
31
+ this.portfolioManager = PortfolioManager.getInstance();
32
+ this.indexManager = PortfolioIndexManager.getInstance();
33
+ this.syncComparer = new PortfolioSyncComparer();
34
+ this.downloader = new PortfolioDownloader();
35
+ }
36
+ /**
37
+ * Execute the pull operation from GitHub to local portfolio
38
+ */
39
+ async executePull(options, personaIndicator) {
40
+ try {
41
+ logger.info('Starting portfolio pull operation', { options });
42
+ // Step 1: Validate sync mode
43
+ const syncMode = this.validateSyncMode(options.mode);
44
+ // Step 2: Fetch GitHub portfolio index
45
+ const progressMessages = [];
46
+ progressMessages.push('šŸ” Fetching portfolio from GitHub...');
47
+ const githubIndex = await this.githubIndexer.getIndex(true);
48
+ if (!githubIndex || githubIndex.totalElements === 0) {
49
+ return {
50
+ content: [{
51
+ type: "text",
52
+ text: `${personaIndicator}āš ļø No elements found in GitHub portfolio. Nothing to pull.`
53
+ }]
54
+ };
55
+ }
56
+ progressMessages.push(`šŸ“Š Found ${githubIndex.totalElements} elements on GitHub`);
57
+ // Step 3: Get local portfolio state
58
+ await this.indexManager.rebuildIndex();
59
+ const localElements = await this.getAllLocalElements();
60
+ progressMessages.push(`šŸ“ Found ${this.countElements(localElements)} local elements`);
61
+ // Step 4: Compare and determine sync actions
62
+ const syncActions = this.syncComparer.compareElements(githubIndex.elements, localElements, syncMode);
63
+ // Step 5: Handle dry-run mode
64
+ if (options.dryRun) {
65
+ return this.formatDryRunResults(syncActions, progressMessages, personaIndicator);
66
+ }
67
+ // Step 6: Check for deletions requiring confirmation
68
+ if (syncActions.toDelete.length > 0 &&
69
+ syncMode === 'mirror' &&
70
+ !options.force &&
71
+ options.confirmDeletions !== false) {
72
+ return {
73
+ content: [{
74
+ type: "text",
75
+ text: `${personaIndicator}āš ļø Pull operation would delete ${syncActions.toDelete.length} local elements.\n\n` +
76
+ `Elements to delete:\n${syncActions.toDelete.map(a => ` - ${a.name}`).join('\n')}\n\n` +
77
+ `To proceed, run with \`force: true\` or \`confirmDeletions: false\``
78
+ }]
79
+ };
80
+ }
81
+ // Step 7: Execute sync actions
82
+ const results = await this.executeSyncActions(syncActions, githubIndex.username, githubIndex.repository, progressMessages);
83
+ // Step 8: Return success summary
84
+ return {
85
+ content: [{
86
+ type: "text",
87
+ text: `${personaIndicator}āœ… **Portfolio Pull Complete**\n\n` +
88
+ progressMessages.join('\n') + '\n\n' +
89
+ `**Summary:**\n` +
90
+ ` šŸ“„ Added: ${results.added}\n` +
91
+ ` šŸ”„ Updated: ${results.updated}\n` +
92
+ ` šŸ”— Skipped: ${results.skipped}\n` +
93
+ (results.deleted > 0 ? ` šŸ—‘ļø Deleted: ${results.deleted}\n` : '') +
94
+ `\nYour local portfolio is now synchronized with GitHub!`
95
+ }]
96
+ };
97
+ }
98
+ catch (error) {
99
+ logger.error('Portfolio pull failed', { error });
100
+ return {
101
+ content: [{
102
+ type: "text",
103
+ text: `${personaIndicator}āŒ Failed to pull portfolio: ${error instanceof Error ? error.message : String(error)}`
104
+ }]
105
+ };
106
+ }
107
+ }
108
+ /**
109
+ * Validate and normalize sync mode
110
+ * SECURITY FIX: Added Unicode normalization to prevent homograph attacks
111
+ */
112
+ validateSyncMode(mode) {
113
+ const validModes = ['additive', 'mirror', 'backup'];
114
+ // SECURITY FIX: Normalize Unicode to prevent homograph attacks
115
+ const normalizedMode = mode ?
116
+ UnicodeValidator.normalize(mode).normalizedContent :
117
+ 'additive';
118
+ const syncMode = normalizedMode.toLowerCase();
119
+ if (!validModes.includes(syncMode)) {
120
+ throw new Error(`Invalid sync mode: ${mode}. Valid modes are: ${validModes.join(', ')}`);
121
+ }
122
+ return syncMode;
123
+ }
124
+ /**
125
+ * Get all local elements organized by type
126
+ */
127
+ async getAllLocalElements() {
128
+ const elements = new Map();
129
+ const elementTypes = Object.values(ElementType);
130
+ for (const type of elementTypes) {
131
+ const typeElements = await this.indexManager.getElementsByType(type);
132
+ if (typeElements.length > 0) {
133
+ elements.set(type, typeElements);
134
+ }
135
+ }
136
+ return elements;
137
+ }
138
+ /**
139
+ * Count total elements in a map
140
+ */
141
+ countElements(elements) {
142
+ let count = 0;
143
+ for (const typeElements of elements.values()) {
144
+ count += typeElements.length;
145
+ }
146
+ return count;
147
+ }
148
+ /**
149
+ * Format dry-run results for display
150
+ */
151
+ formatDryRunResults(syncActions, progressMessages, personaIndicator) {
152
+ const lines = [
153
+ `${personaIndicator}šŸ” **Dry Run Results**`,
154
+ '',
155
+ ...progressMessages,
156
+ '',
157
+ '**Planned Actions:**'
158
+ ];
159
+ if (syncActions.toAdd.length > 0) {
160
+ lines.push(`\nšŸ“„ **To Add (${syncActions.toAdd.length}):**`);
161
+ syncActions.toAdd.forEach(action => {
162
+ lines.push(` - ${action.type}/${action.name}`);
163
+ });
164
+ }
165
+ if (syncActions.toUpdate.length > 0) {
166
+ lines.push(`\nšŸ”„ **To Update (${syncActions.toUpdate.length}):**`);
167
+ syncActions.toUpdate.forEach(action => {
168
+ lines.push(` - ${action.type}/${action.name}`);
169
+ });
170
+ }
171
+ if (syncActions.toDelete.length > 0) {
172
+ lines.push(`\nšŸ—‘ļø **To Delete (${syncActions.toDelete.length}):**`);
173
+ syncActions.toDelete.forEach(action => {
174
+ lines.push(` - ${action.type}/${action.name}`);
175
+ });
176
+ }
177
+ if (syncActions.toSkip.length > 0) {
178
+ lines.push(`\nšŸ”— **To Skip (${syncActions.toSkip.length}):**`);
179
+ syncActions.toSkip.forEach(action => {
180
+ lines.push(` - ${action.type}/${action.name} (${action.reason})`);
181
+ });
182
+ }
183
+ lines.push('', 'Run without `dryRun: true` to execute these changes.');
184
+ return {
185
+ content: [{
186
+ type: "text",
187
+ text: lines.join('\n')
188
+ }]
189
+ };
190
+ }
191
+ /**
192
+ * Execute the sync actions
193
+ */
194
+ async executeSyncActions(syncActions, username, repository, progressMessages) {
195
+ const results = {
196
+ added: 0,
197
+ updated: 0,
198
+ deleted: 0,
199
+ skipped: syncActions.toSkip.length
200
+ };
201
+ // PERFORMANCE: Process downloads in parallel batches for improved speed
202
+ const BATCH_SIZE = 5; // Process 5 downloads at a time to avoid rate limiting
203
+ // Helper function to process a batch of actions
204
+ const processBatch = async (actions, operation) => {
205
+ const results = await Promise.allSettled(actions.map(async (action) => {
206
+ progressMessages.push(`${operation}: ${action.type}/${action.name}`);
207
+ await this.downloadAndSaveElement(action, username, repository);
208
+ return action;
209
+ }));
210
+ return results.map((result, index) => ({
211
+ action: actions[index],
212
+ success: result.status === 'fulfilled',
213
+ error: result.status === 'rejected' ? result.reason : null
214
+ }));
215
+ };
216
+ // Process additions in batches
217
+ for (let i = 0; i < syncActions.toAdd.length; i += BATCH_SIZE) {
218
+ const batch = syncActions.toAdd.slice(i, i + BATCH_SIZE);
219
+ const batchResults = await processBatch(batch, 'šŸ“„ Downloading');
220
+ for (const result of batchResults) {
221
+ if (result.success) {
222
+ results.added++;
223
+ }
224
+ else {
225
+ logger.error(`Failed to add ${result.action.type}/${result.action.name}`, { error: result.error });
226
+ progressMessages.push(`āŒ Failed to add: ${result.action.type}/${result.action.name}`);
227
+ }
228
+ }
229
+ }
230
+ // Process updates in batches
231
+ for (let i = 0; i < syncActions.toUpdate.length; i += BATCH_SIZE) {
232
+ const batch = syncActions.toUpdate.slice(i, i + BATCH_SIZE);
233
+ const batchResults = await processBatch(batch, 'šŸ”„ Updating');
234
+ for (const result of batchResults) {
235
+ if (result.success) {
236
+ results.updated++;
237
+ }
238
+ else {
239
+ logger.error(`Failed to update ${result.action.type}/${result.action.name}`, { error: result.error });
240
+ progressMessages.push(`āŒ Failed to update: ${result.action.type}/${result.action.name}`);
241
+ }
242
+ }
243
+ }
244
+ // Process deletions
245
+ for (const action of syncActions.toDelete) {
246
+ try {
247
+ progressMessages.push(`šŸ—‘ļø Deleting: ${action.type}/${action.name}`);
248
+ await this.deleteLocalElement(action);
249
+ results.deleted++;
250
+ }
251
+ catch (error) {
252
+ logger.error(`Failed to delete ${action.type}/${action.name}`, { error });
253
+ progressMessages.push(`āŒ Failed to delete: ${action.type}/${action.name}`);
254
+ }
255
+ }
256
+ // PERFORMANCE: Batch rebuild index after all operations complete
257
+ if (results.added > 0 || results.updated > 0 || results.deleted > 0) {
258
+ progressMessages.push('šŸ”„ Rebuilding index...');
259
+ await this.indexManager.rebuildIndex();
260
+ }
261
+ return results;
262
+ }
263
+ /**
264
+ * Download element from GitHub and save locally
265
+ * SECURITY: Added audit logging for GitHub operations
266
+ */
267
+ async downloadAndSaveElement(action, username, repository) {
268
+ // Set up the repo manager with the correct context
269
+ this.portfolioRepoManager.setToken(await this.getGitHubToken());
270
+ // SECURITY: Log the download operation for audit trail
271
+ SecurityMonitor.logSecurityEvent({
272
+ type: 'PORTFOLIO_FETCH_SUCCESS',
273
+ severity: 'LOW',
274
+ source: 'PortfolioPullHandler.downloadAndSaveElement',
275
+ details: `Downloading element: ${action.type}/${action.name} from ${username}/${repository}`
276
+ });
277
+ // Download the element content
278
+ const elementData = await this.downloader.downloadFromGitHub(this.portfolioRepoManager, action.path, username, repository);
279
+ // Save to local portfolio
280
+ const elementDir = this.portfolioManager.getElementDir(action.type);
281
+ const fileName = path.basename(action.path);
282
+ const filePath = path.join(elementDir, fileName);
283
+ await fs.writeFile(filePath, elementData.content, 'utf-8');
284
+ // SECURITY: Log successful save for audit trail
285
+ SecurityMonitor.logSecurityEvent({
286
+ type: 'ELEMENT_CREATED',
287
+ severity: 'LOW',
288
+ source: 'PortfolioPullHandler.downloadAndSaveElement',
289
+ details: `Saved element to: ${action.type}/${fileName}`
290
+ });
291
+ // PERFORMANCE: Skip individual index rebuild - will batch rebuild after all operations
292
+ }
293
+ /**
294
+ * Delete local element
295
+ * SECURITY: Added audit logging for deletion operations
296
+ */
297
+ async deleteLocalElement(action) {
298
+ const elementDir = this.portfolioManager.getElementDir(action.type);
299
+ // Use the original filename from the path to preserve extension
300
+ const fileName = path.basename(action.path) || `${action.name}.md`;
301
+ const filePath = path.join(elementDir, fileName);
302
+ // SECURITY: Log deletion attempt for audit trail
303
+ SecurityMonitor.logSecurityEvent({
304
+ type: 'ELEMENT_DELETED',
305
+ severity: 'MEDIUM',
306
+ source: 'PortfolioPullHandler.deleteLocalElement',
307
+ details: `Attempting to delete: ${action.type}/${fileName}`
308
+ });
309
+ try {
310
+ await fs.unlink(filePath);
311
+ // PERFORMANCE: Skip individual index rebuild - will batch rebuild after all operations
312
+ // SECURITY: Log successful deletion
313
+ SecurityMonitor.logSecurityEvent({
314
+ type: 'ELEMENT_DELETED',
315
+ severity: 'MEDIUM',
316
+ source: 'PortfolioPullHandler.deleteLocalElement',
317
+ details: `Successfully deleted: ${action.type}/${fileName}`
318
+ });
319
+ }
320
+ catch (error) {
321
+ if (error.code !== 'ENOENT') {
322
+ throw error;
323
+ }
324
+ // File already doesn't exist, that's fine
325
+ }
326
+ }
327
+ /**
328
+ * Get GitHub token from auth manager
329
+ */
330
+ async getGitHubToken() {
331
+ // This should use the same token management as the rest of the system
332
+ const { TokenManager } = await import('../security/tokenManager.js');
333
+ const token = await TokenManager.getGitHubTokenAsync();
334
+ if (!token) {
335
+ throw new Error('GitHub authentication required. Please run setup_github_auth first.');
336
+ }
337
+ return token;
338
+ }
339
+ }
340
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUG9ydGZvbGlvUHVsbEhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGFuZGxlcnMvUG9ydGZvbGlvUHVsbEhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDNUUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDaEYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDcEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDOUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUscUJBQXFCLEVBQXdCLE1BQU0sa0NBQWtDLENBQUM7QUFDL0YsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDckUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDOUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzFFLE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBaUI3QixNQUFNLE9BQU8sb0JBQW9CO0lBQ3ZCLG9CQUFvQixDQUF1QjtJQUMzQyxhQUFhLENBQXlCO0lBQ3RDLGdCQUFnQixDQUFtQjtJQUNuQyxZQUFZLENBQXdCO0lBQ3BDLFlBQVksQ0FBd0I7SUFDcEMsVUFBVSxDQUFzQjtJQUV4QztRQUNFLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLG9CQUFvQixDQUFDLDBC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eUJBQXlCLE1BQU0sQ0FBQyxJQUFJLElBQUksUUFBUSxFQUFFO2FBQzVELENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1lBQ3BCLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxLQUFLLENBQUM7WUFDZCxDQUFDO1lBQ0QsMENBQTBDO1FBQzVDLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMsY0FBYztRQUMxQixzRUFBc0U7UUFDdEUsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLDZCQUE2QixDQUFDLENBQUM7UUFDckUsTUFBTSxLQUFLLEdBQUcsTUFBTSxZQUFZLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUN2RCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLHFFQUFxRSxDQUFDLENBQUM7UUFDekYsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQb3J0Zm9saW9QdWxsSGFuZGxlciAtIEhhbmRsZXMgcHVsbGluZyBwb3J0Zm9saW8gZWxlbWVudHMgZnJvbSBHaXRIdWJcbiAqIFxuICogVGhpcyBoYW5kbGVyIGltcGxlbWVudHMgdGhlIHB1bGwgZnVuY3Rpb25hbGl0eSBmb3Igc3luY19wb3J0Zm9saW8sXG4gKiBlbmFibGluZyB1c2VycyB0byBkb3dubG9hZCB0aGVpciBwb3J0Zm9saW8gZnJvbSBHaXRIdWIgdG8gbG9jYWwgc3RvcmFnZS5cbiAqIFN1cHBvcnRzIG11bHRpcGxlIHN5bmMgbW9kZXMgKGFkZGl0aXZlLCBtaXJyb3IsIGJhY2t1cCkgYW5kIGRyeS1ydW4uXG4gKi9cblxuaW1wb3J0IHsgUG9ydGZvbGlvUmVwb01hbmFnZXIgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvUmVwb01hbmFnZXIuanMnO1xuaW1wb3J0IHsgR2l0SHViUG9ydGZvbGlvSW5kZXhlciB9IGZyb20gJy4uL3BvcnRmb2xpby9HaXRIdWJQb3J0Zm9saW9JbmRleGVyLmpzJztcbmltcG9ydCB7IFBvcnRmb2xpb01hbmFnZXIgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvTWFuYWdlci5qcyc7XG5pbXBvcnQgeyBQb3J0Zm9saW9JbmRleE1hbmFnZXIgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvSW5kZXhNYW5hZ2VyLmpzJztcbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vcG9ydGZvbGlvL3R5cGVzLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBQb3J0Zm9saW9TeW5jQ29tcGFyZXIsIFN5bmNNb2RlLCBTeW5jQWN0aW9uIH0gZnJvbSAnLi4vc3luYy9Qb3J0Zm9saW9TeW5jQ29tcGFyZXIuanMnO1xuaW1wb3J0IHsgUG9ydGZvbGlvRG93bmxvYWRlciB9IGZyb20gJy4uL3N5bmMvUG9ydGZvbGlvRG93bmxvYWRlci5qcyc7XG5pbXBvcnQgeyBVbmljb2RlVmFsaWRhdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvdmFsaWRhdG9ycy91bmljb2RlVmFsaWRhdG9yLmpzJztcbmltcG9ydCB7IFNlY3VyaXR5TW9uaXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3NlY3VyaXR5TW9uaXRvci5qcyc7XG5pbXBvcnQgeyBnZXRQb3J0Zm9saW9SZXBvc2l0b3J5TmFtZSB9IGZyb20gJy4uL2NvbmZpZy9wb3J0Zm9saW9Db25maWcuanMnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuZXhwb3J0IGludGVyZmFjZSBQdWxsT3B0aW9ucyB7XG4gIGRpcmVjdGlvbjogc3RyaW5nO1xuICBtb2RlPzogc3RyaW5nO1xuICBmb3JjZT86IGJvb2xlYW47XG4gIGRyeVJ1bj86IGJvb2xlYW47XG4gIGNvbmZpcm1EZWxldGlvbnM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFB1bGxSZXN1bHQge1xuICBjb250ZW50OiBBcnJheTx7XG4gICAgdHlwZTogc3RyaW5nO1xuICAgIHRleHQ6IHN0cmluZztcbiAgfT47XG59XG5cbmV4cG9ydCBjbGFzcyBQb3J0Zm9saW9QdWxsSGFuZGxlciB7XG4gIHByaXZhdGUgcG9ydGZvbGlvUmVwb01hbmFnZXI6IFBvcnRmb2xpb1JlcG9NYW5hZ2VyO1xuICBwcml2YXRlIGdpdGh1YkluZGV4ZXI6IEdpdEh1YlBvcnRmb2xpb0luZGV4ZXI7XG4gIHByaXZhdGUgcG9ydGZvbGlvTWFuYWdlcjogUG9ydGZvbGlvTWFuYWdlcjtcbiAgcHJpdmF0ZSBpbmRleE1hbmFnZXI6IFBvcnRmb2xpb0luZGV4TWFuYWdlcjtcbiAgcHJpdmF0ZSBzeW5jQ29tcGFyZXI6IFBvcnRmb2xpb1N5bmNDb21wYXJlcjtcbiAgcHJpdmF0ZSBkb3dubG9hZGVyOiBQb3J0Zm9saW9Eb3dubG9hZGVyO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucG9ydGZvbGlvUmVwb01hbmFnZXIgPSBuZXcgUG9ydGZvbGlvUmVwb01hbmFnZXIoZ2V0UG9ydGZvbGlvUmVwb3NpdG9yeU5hbWUoKSk7XG4gICAgdGhpcy5naXRodWJJbmRleGVyID0gR2l0SHViUG9ydGZvbGlvSW5kZXhlci5nZXRJbnN0YW5jZSgpO1xuICAgIHRoaXMucG9ydGZvbGlvTWFuYWdlciA9IFBvcnRmb2xpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB0aGlzLmluZGV4TWFuYWdlciA9IFBvcnRmb2xpb0luZGV4TWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgIHRoaXMuc3luY0NvbXBhcmVyID0gbmV3IFBvcnRmb2xpb1N5bmNDb21wYXJlcigpO1xuICAgIHRoaXMuZG93bmxvYWRlciA9IG5ldyBQb3J0Zm9saW9Eb3dubG9hZGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSB0aGUgcHVsbCBvcGVyYXRpb24gZnJvbSBHaXRIdWIgdG8gbG9jYWwgcG9ydGZvbGlvXG4gICAqL1xuICBhc3luYyBleGVjdXRlUHVsbChvcHRpb25zOiBQdWxsT3B0aW9ucywgcGVyc29uYUluZGljYXRvcjogc3RyaW5nKTogUHJvbWlzZTxQdWxsUmVzdWx0PiB7XG4gICAgdHJ5IHtcbiAgICAgIGxvZ2dlci5pbmZvKCdTdGFydGluZyBwb3J0Zm9saW8gcHVsbCBvcGVyYXRpb24nLCB7IG9wdGlvbnMgfSk7XG4gICAgICBcbiAgICAgIC8vIFN0ZXAgMTogVmFsaWRhdGUgc3luYyBtb2RlXG4gICAgICBjb25zdCBzeW5jTW9kZSA9IHRoaXMudmFsaWRhdGVTeW5jTW9kZShvcHRpb25zLm1vZGUpO1xuICAgICAgXG4gICAgICAvLyBTdGVwIDI6IEZldGNoIEdpdEh1YiBwb3J0Zm9saW8gaW5kZXhcbiAgICAgIGNvbnN0IHByb2dyZXNzTWVzc2FnZXM6IHN0cmluZ1tdID0gW107XG4gICAgICBwcm9ncmVzc01lc3NhZ2VzLnB1c2goJ/CflI0gRmV0Y2hpbmcgcG9ydGZvbGlvIGZyb20gR2l0SHViLi4uJyk7XG4gICAgICBcbiAgICAgIGNvbnN0IGdpdGh1YkluZGV4ID0gYXdhaXQgdGhpcy5naXRodWJJbmRleGVyLmdldEluZGV4KHRydWUpO1xuICAgICAgXG4gICAgICBpZiAoIWdpdGh1YkluZGV4IHx8IGdpdGh1YkluZGV4LnRvdGFsRWxlbWVudHMgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHtwZXJzb25hSW5kaWNhdG9yfeKaoO+4jyBObyBlbGVtZW50cyBmb3VuZCBpbiBHaXRIdWIgcG9ydGZvbGlvLiBOb3RoaW5nIHRvIHB1bGwuYFxuICAgICAgICAgIH1dXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIHByb2dyZXNzTWVzc2FnZXMucHVzaChg8J+TiiBGb3VuZCAke2dpdGh1YkluZGV4LnRvdGFsRWxlbWVudHN9IGVsZW1lbnRzIG9uIEdpdEh1YmApO1xuICAgICAgXG4gICAgICAvLyBTdGVwIDM6IEdldCBsb2NhbCBwb3J0Zm9saW8gc3RhdGVcbiAgICAgIGF3YWl0IHRoaXMuaW5kZXhNYW5hZ2VyLnJlYnVpbGRJbmRleCgpO1xuICAgICAgY29uc3QgbG9jYWxFbGVtZW50cyA9IGF3YWl0IHRoaXMuZ2V0QWxsTG9jYWxFbGVtZW50cygpO1xuICAgICAgcHJvZ3Jlc3NNZXNzYWdlcy5wdXNoKGDwn5OBIEZvdW5kICR7dGhpcy5jb3VudEVsZW1lbnRzKGxvY2FsRWxlbWVudHMpfSBsb2NhbCBlbGVtZW50c2ApO1xuICAgICAgXG4gICAgICAvLyBTdGVwIDQ6IENvbXBhcmUgYW5kIGRldGVybWluZSBzeW5jIGFjdGlvbnNcbiAgICAgIGNvbnN0IHN5bmNBY3Rpb25zID0gdGhpcy5zeW5jQ29tcGFyZXIuY29tcGFyZUVsZW1lbnRzKFxuICAgICAgICBnaXRodWJJbmRleC5lbGVtZW50cyxcbiAgICAgICAgbG9jYWxFbGVtZW50cyxcbiAgICAgICAgc3luY01vZGVcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIFN0ZXAgNTogSGFuZGxlIGRyeS1ydW4gbW9kZVxuICAgICAgaWYgKG9wdGlvbnMuZHJ5UnVuKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdERyeVJ1blJlc3VsdHMoc3luY0FjdGlvbnMsIHByb2dyZXNzTWVzc2FnZXMsIHBlcnNvbmFJbmRpY2F0b3IpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBTdGVwIDY6IENoZWNrIGZvciBkZWxldGlvbnMgcmVxdWlyaW5nIGNvbmZpcm1hdGlvblxuICAgICAgaWYgKHN5bmNBY3Rpb25zLnRvRGVsZXRlLmxlbmd0aCA+IDAgJiYgXG4gICAgICAgICAgc3luY01vZGUgPT09ICdtaXJyb3InICYmIFxuICAgICAgICAgICFvcHRpb25zLmZvcmNlICYmIFxuICAgICAgICAgIG9wdGlvbnMuY29uZmlybURlbGV0aW9ucyAhPT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBgJHtwZXJzb25hSW5kaWNhdG9yfeKaoO+4jyBQdWxsIG9wZXJhdGlvbiB3b3VsZCBkZWxldGUgJHtzeW5jQWN0aW9ucy50b0RlbGV0ZS5sZW5ndGh9IGxvY2FsIGVsZW1lbnRzLlxcblxcbmAgK1xuICAgICAgICAgICAgICAgICAgYEVsZW1lbnRzIHRvIGRlbGV0ZTpcXG4ke3N5bmNBY3Rpb25zLnRvRGVsZXRlLm1hcChhID0+IGAgIC0gJHthLm5hbWV9YCkuam9pbignXFxuJyl9XFxuXFxuYCArXG4gICAgICAgICAgICAgICAgICBgVG8gcHJvY2VlZCwgcnVuIHdpdGggXFxgZm9yY2U6IHRydWVcXGAgb3IgXFxgY29uZmlybURlbGV0aW9uczogZmFsc2VcXGBgXG4gICAgICAgICAgfV1cbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gU3RlcCA3OiBFeGVjdXRlIHN5bmMgYWN0aW9uc1xuICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZVN5bmNBY3Rpb25zKFxuICAgICAgICBzeW5jQWN0aW9ucywgXG4gICAgICAgIGdpdGh1YkluZGV4LnVzZXJuYW1lLCBcbiAgICAgICAgZ2l0aHViSW5kZXgucmVwb3NpdG9yeSxcbiAgICAgICAgcHJvZ3Jlc3NNZXNzYWdlc1xuICAgICAgKTtcbiAgICAgIFxuICAgICAgLy8gU3RlcCA4OiBSZXR1cm4gc3VjY2VzcyBzdW1tYXJ5XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke3BlcnNvbmFJbmRpY2F0b3J94pyFICoqUG9ydGZvbGlvIFB1bGwgQ29tcGxldGUqKlxcblxcbmAgK1xuICAgICAgICAgICAgICAgIHByb2dyZXNzTWVzc2FnZXMuam9pbignXFxuJykgKyAnXFxuXFxuJyArXG4gICAgICAgICAgICAgICAgYCoqU3VtbWFyeToqKlxcbmAgK1xuICAgICAgICAgICAgICAgIGAgIPCfk6UgQWRkZWQ6ICR7cmVzdWx0cy5hZGRlZH1cXG5gICtcbiAgICAgICAgICAgICAgICBgICDwn5SEIFVwZGF0ZWQ6ICR7cmVzdWx0cy51cGRhdGVkfVxcbmAgK1xuICAgICAgICAgICAgICAgIGAgIPCflJcgU2tpcHBlZDogJHtyZXN1bHRzLnNraXBwZWR9XFxuYCArXG4gICAgICAgICAgICAgICAgKHJlc3VsdHMuZGVsZXRlZCA+IDAgPyBgICDwn5eR77iPIERlbGV0ZWQ6ICR7cmVzdWx0cy5kZWxldGVkfVxcbmAgOiAnJykgK1xuICAgICAgICAgICAgICAgIGBcXG5Zb3VyIGxvY2FsIHBvcnRmb2xpbyBpcyBub3cgc3luY2hyb25pemVkIHdpdGggR2l0SHViIWBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdQb3J0Zm9saW8gcHVsbCBmYWlsZWQnLCB7IGVycm9yIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBgJHtwZXJzb25hSW5kaWNhdG9yfeKdjCBGYWlsZWQgdG8gcHVsbCBwb3J0Zm9saW86ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGFuZCBub3JtYWxpemUgc3luYyBtb2RlXG4gICAqIFNFQ1VSSVRZIEZJWDogQWRkZWQgVW5pY29kZSBub3JtYWxpemF0aW9uIHRvIHByZXZlbnQgaG9tb2dyYXBoIGF0dGFja3NcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVTeW5jTW9kZShtb2RlPzogc3RyaW5nKTogU3luY01vZGUge1xuICAgIGNvbnN0IHZhbGlkTW9kZXM6IFN5bmNNb2RlW10gPSBbJ2FkZGl0aXZlJywgJ21pcnJvcicsICdiYWNrdXAnXTtcbiAgICBcbiAgICAvLyBTRUNVUklUWSBGSVg6IE5vcm1hbGl6ZSBVbmljb2RlIHRvIHByZXZlbnQgaG9tb2dyYXBoIGF0dGFja3NcbiAgICBjb25zdCBub3JtYWxpemVkTW9kZSA9IG1vZGUgPyBcbiAgICAgIFVuaWNvZGVWYWxpZGF0b3Iubm9ybWFsaXplKG1vZGUpLm5vcm1hbGl6ZWRDb250ZW50IDogXG4gICAgICAnYWRkaXRpdmUnO1xuICAgIFxuICAgIGNvbnN0IHN5bmNNb2RlID0gbm9ybWFsaXplZE1vZGUudG9Mb3dlckNhc2UoKSBhcyBTeW5jTW9kZTtcbiAgICBcbiAgICBpZiAoIXZhbGlkTW9kZXMuaW5jbHVkZXMoc3luY01vZGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc3luYyBtb2RlOiAke21vZGV9LiBWYWxpZCBtb2RlcyBhcmU6ICR7dmFsaWRNb2Rlcy5qb2luKCcsICcpfWApO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gc3luY01vZGU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBsb2NhbCBlbGVtZW50cyBvcmdhbml6ZWQgYnkgdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRBbGxMb2NhbEVsZW1lbnRzKCk6IFByb21pc2U8TWFwPEVsZW1lbnRUeXBlLCBhbnlbXT4+IHtcbiAgICBjb25zdCBlbGVtZW50cyA9IG5ldyBNYXA8RWxlbWVudFR5cGUsIGFueVtdPigpO1xuICAgIGNvbnN0IGVsZW1lbnRUeXBlcyA9IE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpO1xuICAgIFxuICAgIGZvciAoY29uc3QgdHlwZSBvZiBlbGVtZW50VHlwZXMpIHtcbiAgICAgIGNvbnN0IHR5cGVFbGVtZW50cyA9IGF3YWl0IHRoaXMuaW5kZXhNYW5hZ2VyLmdldEVsZW1lbnRzQnlUeXBlKHR5cGUpO1xuICAgICAgaWYgKHR5cGVFbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGVsZW1lbnRzLnNldCh0eXBlLCB0eXBlRWxlbWVudHMpO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gZWxlbWVudHM7XG4gIH1cblxuICAvKipcbiAgICogQ291bnQgdG90YWwgZWxlbWVudHMgaW4gYSBtYXBcbiAgICovXG4gIHByaXZhdGUgY291bnRFbGVtZW50cyhlbGVtZW50czogTWFwPEVsZW1lbnRUeXBlLCBhbnlbXT4pOiBudW1iZXIge1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgZm9yIChjb25zdCB0eXBlRWxlbWVudHMgb2YgZWxlbWVudHMudmFsdWVzKCkpIHtcbiAgICAgIGNvdW50ICs9IHR5cGVFbGVtZW50cy5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXQgZHJ5LXJ1biByZXN1bHRzIGZvciBkaXNwbGF5XG4gICAqL1xuICBwcml2YXRlIGZvcm1hdERyeVJ1blJlc3VsdHMoXG4gICAgc3luY0FjdGlvbnM6IHsgdG9BZGQ6IFN5bmNBY3Rpb25bXSwgdG9VcGRhdGU6IFN5bmNBY3Rpb25bXSwgdG9EZWxldGU6IFN5bmNBY3Rpb25bXSwgdG9Ta2lwOiBTeW5jQWN0aW9uW10gfSxcbiAgICBwcm9ncmVzc01lc3NhZ2VzOiBzdHJpbmdbXSxcbiAgICBwZXJzb25hSW5kaWNhdG9yOiBzdHJpbmdcbiAgKTogUHVsbFJlc3VsdCB7XG4gICAgY29uc3QgbGluZXMgPSBbXG4gICAgICBgJHtwZXJzb25hSW5kaWNhdG9yffCflI0gKipEcnkgUnVuIFJlc3VsdHMqKmAsXG4gICAgICAnJyxcbiAgICAgIC4uLnByb2dyZXNzTWVzc2FnZXMsXG4gICAgICAnJyxcbiAgICAgICcqKlBsYW5uZWQgQWN0aW9uczoqKidcbiAgICBdO1xuICAgIFxuICAgIGlmIChzeW5jQWN0aW9ucy50b0FkZC5sZW5ndGggPiAwKSB7XG4gICAgICBsaW5lcy5wdXNoKGBcXG7wn5OlICoqVG8gQWRkICgke3N5bmNBY3Rpb25zLnRvQWRkLmxlbmd0aH0pOioqYCk7XG4gICAgICBzeW5jQWN0aW9ucy50b0FkZC5mb3JFYWNoKGFjdGlvbiA9PiB7XG4gICAgICAgIGxpbmVzLnB1c2goYCAgLSAke2FjdGlvbi50eXBlfS8ke2FjdGlvbi5uYW1lfWApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIGlmIChzeW5jQWN0aW9ucy50b1VwZGF0ZS5sZW5ndGggPiAwKSB7XG4gICAgICBsaW5lcy5wdXNoKGBcXG7wn5SEICoqVG8gVXBkYXRlICgke3N5bmNBY3Rpb25zLnRvVXBkYXRlLmxlbmd0aH0pOioqYCk7XG4gICAgICBzeW5jQWN0aW9ucy50b1VwZGF0ZS5mb3JFYWNoKGFjdGlvbiA9PiB7XG4gICAgICAgIGxpbmVzLnB1c2goYCAgLSAke2FjdGlvbi50eXBlfS8ke2FjdGlvbi5uYW1lfWApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIGlmIChzeW5jQWN0aW9ucy50b0RlbGV0ZS5sZW5ndGggPiAwKSB7XG4gICAgICBsaW5lcy5wdXNoKGBcXG7wn5eR77iPICoqVG8gRGVsZXRlICgke3N5bmNBY3Rpb25zLnRvRGVsZXRlLmxlbmd0aH0pOioqYCk7XG4gICAgICBzeW5jQWN0aW9ucy50b0RlbGV0ZS5mb3JFYWNoKGFjdGlvbiA9PiB7XG4gICAgICAgIGxpbmVzLnB1c2goYCAgLSAke2FjdGlvbi50eXBlfS8ke2FjdGlvbi5uYW1lfWApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIGlmIChzeW5jQWN0aW9ucy50b1NraXAubGVuZ3RoID4gMCkge1xuICAgICAgbGluZXMucHVzaChgXFxu8J+UlyAqKlRvIFNraXAgKCR7c3luY0FjdGlvbnMudG9Ta2lwLmxlbmd0aH0pOioqYCk7XG4gICAgICBzeW5jQWN0aW9ucy50b1NraXAuZm9yRWFjaChhY3Rpb24gPT4ge1xuICAgICAgICBsaW5lcy5wdXNoKGAgIC0gJHthY3Rpb24udHlwZX0vJHthY3Rpb24ubmFtZX0gKCR7YWN0aW9uLnJlYXNvbn0pYCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgXG4gICAgbGluZXMucHVzaCgnJywgJ1J1biB3aXRob3V0IGBkcnlSdW46IHRydWVgIHRvIGV4ZWN1dGUgdGhlc2UgY2hhbmdlcy4nKTtcbiAgICBcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHQ6IGxpbmVzLmpvaW4oJ1xcbicpXG4gICAgICB9XVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSB0aGUgc3luYyBhY3Rpb25zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVTeW5jQWN0aW9ucyhcbiAgICBzeW5jQWN0aW9uczogeyB0b0FkZDogU3luY0FjdGlvbltdLCB0b1VwZGF0ZTogU3luY0FjdGlvbltdLCB0b0RlbGV0ZTogU3luY0FjdGlvbltdLCB0b1NraXA6IFN5bmNBY3Rpb25bXSB9LFxuICAgIHVzZXJuYW1lOiBzdHJpbmcsXG4gICAgcmVwb3NpdG9yeTogc3RyaW5nLFxuICAgIHByb2dyZXNzTWVzc2FnZXM6IHN0cmluZ1tdXG4gICk6IFByb21pc2U8eyBhZGRlZDogbnVtYmVyLCB1cGRhdGVkOiBudW1iZXIsIGRlbGV0ZWQ6IG51bWJlciwgc2tpcHBlZDogbnVtYmVyIH0+IHtcbiAgICBjb25zdCByZXN1bHRzID0ge1xuICAgICAgYWRkZWQ6IDAsXG4gICAgICB1cGRhdGVkOiAwLFxuICAgICAgZGVsZXRlZDogMCxcbiAgICAgIHNraXBwZWQ6IHN5bmNBY3Rpb25zLnRvU2tpcC5sZW5ndGhcbiAgICB9O1xuICAgIFxuICAgIC8vIFBFUkZPUk1BTkNFOiBQcm9jZXNzIGRvd25sb2FkcyBpbiBwYXJhbGxlbCBiYXRjaGVzIGZvciBpbXByb3ZlZCBzcGVlZFxuICAgIGNvbnN0IEJBVENIX1NJWkUgPSA1OyAvLyBQcm9jZXNzIDUgZG93bmxvYWRzIGF0IGEgdGltZSB0byBhdm9pZCByYXRlIGxpbWl0aW5nXG4gICAgXG4gICAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIHByb2Nlc3MgYSBiYXRjaCBvZiBhY3Rpb25zXG4gICAgY29uc3QgcHJvY2Vzc0JhdGNoID0gYXN5bmMgKGFjdGlvbnM6IFN5bmNBY3Rpb25bXSwgb3BlcmF0aW9uOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXG4gICAgICAgIGFjdGlvbnMubWFwKGFzeW5jIChhY3Rpb24pID0+IHtcbiAgICAgICAgICBwcm9ncmVzc01lc3NhZ2VzLnB1c2goYCR7b3BlcmF0aW9ufTogJHthY3Rpb24udHlwZX0vJHthY3Rpb24ubmFtZX1gKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmRvd25sb2FkQW5kU2F2ZUVsZW1lbnQoYWN0aW9uLCB1c2VybmFtZSwgcmVwb3NpdG9yeSk7XG4gICAgICAgICAgcmV0dXJuIGFjdGlvbjtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBcbiAgICAgIHJldHVybiByZXN1bHRzLm1hcCgocmVzdWx0LCBpbmRleCkgPT4gKHtcbiAgICAgICAgYWN0aW9uOiBhY3Rpb25zW2luZGV4XSxcbiAgICAgICAgc3VjY2VzczogcmVzdWx0LnN0YXR1cyA9PT0gJ2Z1bGZpbGxlZCcsXG4gICAgICAgIGVycm9yOiByZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnID8gcmVzdWx0LnJlYXNvbiA6IG51bGxcbiAgICAgIH0pKTtcbiAgICB9O1xuICAgIFxuICAgIC8vIFByb2Nlc3MgYWRkaXRpb25zIGluIGJhdGNoZXNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN5bmNBY3Rpb25zLnRvQWRkLmxlbmd0aDsgaSArPSBCQVRDSF9TSVpFKSB7XG4gICAgICBjb25zdCBiYXRjaCA9IHN5bmNBY3Rpb25zLnRvQWRkLnNsaWNlKGksIGkgKyBCQVRDSF9TSVpFKTtcbiAgICAgIGNvbnN0IGJhdGNoUmVzdWx0cyA9IGF3YWl0IHByb2Nlc3NCYXRjaChiYXRjaCwgJ/Cfk6UgRG93bmxvYWRpbmcnKTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgYmF0Y2hSZXN1bHRzKSB7XG4gICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgIHJlc3VsdHMuYWRkZWQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBhZGQgJHtyZXN1bHQuYWN0aW9uLnR5cGV9LyR7cmVzdWx0LmFjdGlvbi5uYW1lfWAsIHsgZXJyb3I6IHJlc3VsdC5lcnJvciB9KTtcbiAgICAgICAgICBwcm9ncmVzc01lc3NhZ2VzLnB1c2goYOKdjCBGYWlsZWQgdG8gYWRkOiAke3Jlc3VsdC5hY3Rpb24udHlwZX0vJHtyZXN1bHQuYWN0aW9uLm5hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gUHJvY2VzcyB1cGRhdGVzIGluIGJhdGNoZXNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN5bmNBY3Rpb25zLnRvVXBkYXRlLmxlbmd0aDsgaSArPSBCQVRDSF9TSVpFKSB7XG4gICAgICBjb25zdCBiYXRjaCA9IHN5bmNBY3Rpb25zLnRvVXBkYXRlLnNsaWNlKGksIGkgKyBCQVRDSF9TSVpFKTtcbiAgICAgIGNvbnN0IGJhdGNoUmVzdWx0cyA9IGF3YWl0IHByb2Nlc3NCYXRjaChiYXRjaCwgJ/CflIQgVXBkYXRpbmcnKTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgYmF0Y2hSZXN1bHRzKSB7XG4gICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgIHJlc3VsdHMudXBkYXRlZCsrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHVwZGF0ZSAke3Jlc3VsdC5hY3Rpb24udHlwZX0vJHtyZXN1bHQuYWN0aW9uLm5hbWV9YCwgeyBlcnJvcjogcmVzdWx0LmVycm9yIH0pO1xuICAgICAgICAgIHByb2dyZXNzTWVzc2FnZXMucHVzaChg4p2MIEZhaWxlZCB0byB1cGRhdGU6ICR7cmVzdWx0LmFjdGlvbi50eXBlfS8ke3Jlc3VsdC5hY3Rpb24ubmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBQcm9jZXNzIGRlbGV0aW9uc1xuICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIHN5bmNBY3Rpb25zLnRvRGVsZXRlKSB7XG4gICAgICB0cnkge1xuICAgICAgICBwcm9ncmVzc01lc3NhZ2VzLnB1c2goYPCfl5HvuI8gRGVsZXRpbmc6ICR7YWN0aW9uLnR5cGV9LyR7YWN0aW9uLm5hbWV9YCk7XG4gICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTG9jYWxFbGVtZW50KGFjdGlvbik7XG4gICAgICAgIHJlc3VsdHMuZGVsZXRlZCsrO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gZGVsZXRlICR7YWN0aW9uLnR5cGV9LyR7YWN0aW9uLm5hbWV9YCwgeyBlcnJvciB9KTtcbiAgICAgICAgcHJvZ3Jlc3NNZXNzYWdlcy5wdXNoKGDinYwgRmFpbGVkIHRvIGRlbGV0ZTogJHthY3Rpb24udHlwZX0vJHthY3Rpb24ubmFtZX1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gUEVSRk9STUFOQ0U6IEJhdGNoIHJlYnVpbGQgaW5kZXggYWZ0ZXIgYWxsIG9wZXJhdGlvbnMgY29tcGxldGVcbiAgICBpZiAocmVzdWx0cy5hZGRlZCA+IDAgfHwgcmVzdWx0cy51cGRhdGVkID4gMCB8fCByZXN1bHRzLmRlbGV0ZWQgPiAwKSB7XG4gICAgICBwcm9ncmVzc01lc3NhZ2VzLnB1c2goJ/CflIQgUmVidWlsZGluZyBpbmRleC4uLicpO1xuICAgICAgYXdhaXQgdGhpcy5pbmRleE1hbmFnZXIucmVidWlsZEluZGV4KCk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIERvd25sb2FkIGVsZW1lbnQgZnJvbSBHaXRIdWIgYW5kIHNhdmUgbG9jYWxseVxuICAgKiBTRUNVUklUWTogQWRkZWQgYXVkaXQgbG9nZ2luZyBmb3IgR2l0SHViIG9wZXJhdGlvbnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZG93bmxvYWRBbmRTYXZlRWxlbWVudChcbiAgICBhY3Rpb246IFN5bmNBY3Rpb24sXG4gICAgdXNlcm5hbWU6IHN0cmluZyxcbiAgICByZXBvc2l0b3J5OiBzdHJpbmdcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gU2V0IHVwIHRoZSByZXBvIG1hbmFnZXIgd2l0aCB0aGUgY29ycmVjdCBjb250ZXh0XG4gICAgdGhpcy5wb3J0Zm9saW9SZXBvTWFuYWdlci5zZXRUb2tlbihhd2FpdCB0aGlzLmdldEdpdEh1YlRva2VuKCkpO1xuICAgIFxuICAgIC8vIFNFQ1VSSVRZOiBMb2cgdGhlIGRvd25sb2FkIG9wZXJhdGlvbiBmb3IgYXVkaXQgdHJhaWxcbiAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICB0eXBlOiAnUE9SVEZPTElPX0ZFVENIX1NVQ0NFU1MnLFxuICAgICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgICAgc291cmNlOiAnUG9ydGZvbGlvUHVsbEhhbmRsZXIuZG93bmxvYWRBbmRTYXZlRWxlbWVudCcsXG4gICAgICBkZXRhaWxzOiBgRG93bmxvYWRpbmcgZWxlbWVudDogJHthY3Rpb24udHlwZX0vJHthY3Rpb24ubmFtZX0gZnJvbSAke3VzZXJuYW1lfS8ke3JlcG9zaXRvcnl9YFxuICAgIH0pO1xuICAgIFxuICAgIC8vIERvd25sb2FkIHRoZSBlbGVtZW50IGNvbnRlbnRcbiAgICBjb25zdCBlbGVtZW50RGF0YSA9IGF3YWl0IHRoaXMuZG93bmxvYWRlci5kb3dubG9hZEZyb21HaXRIdWIoXG4gICAgICB0aGlzLnBvcnRmb2xpb1JlcG9NYW5hZ2VyLFxuICAgICAgYWN0aW9uLnBhdGgsXG4gICAgICB1c2VybmFtZSxcbiAgICAgIHJlcG9zaXRvcnlcbiAgICApO1xuICAgIFxuICAgIC8vIFNhdmUgdG8gbG9jYWwgcG9ydGZvbGlvXG4gICAgY29uc3QgZWxlbWVudERpciA9IHRoaXMucG9ydGZvbGlvTWFuYWdlci5nZXRFbGVtZW50RGlyKGFjdGlvbi50eXBlKTtcbiAgICBjb25zdCBmaWxlTmFtZSA9IHBhdGguYmFzZW5hbWUoYWN0aW9uLnBhdGgpO1xuICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKGVsZW1lbnREaXIsIGZpbGVOYW1lKTtcbiAgICBcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIGVsZW1lbnREYXRhLmNvbnRlbnQsICd1dGYtOCcpO1xuICAgIFxuICAgIC8vIFNFQ1VSSVRZOiBMb2cgc3VjY2Vzc2Z1bCBzYXZlIGZvciBhdWRpdCB0cmFpbFxuICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgIHR5cGU6ICdFTEVNRU5UX0NSRUFURUQnLFxuICAgICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgICAgc291cmNlOiAnUG9ydGZvbGlvUHVsbEhhbmRsZXIuZG93bmxvYWRBbmRTYXZlRWxlbWVudCcsXG4gICAgICBkZXRhaWxzOiBgU2F2ZWQgZWxlbWVudCB0bzogJHthY3Rpb24udHlwZX0vJHtmaWxlTmFtZX1gXG4gICAgfSk7XG4gICAgXG4gICAgLy8gUEVSRk9STUFOQ0U6IFNraXAgaW5kaXZpZHVhbCBpbmRleCByZWJ1aWxkIC0gd2lsbCBiYXRjaCByZWJ1aWxkIGFmdGVyIGFsbCBvcGVyYXRpb25zXG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlIGxvY2FsIGVsZW1lbnRcbiAgICogU0VDVVJJVFk6IEFkZGVkIGF1ZGl0IGxvZ2dpbmcgZm9yIGRlbGV0aW9uIG9wZXJhdGlvbnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGVsZXRlTG9jYWxFbGVtZW50KGFjdGlvbjogU3luY0FjdGlvbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGVsZW1lbnREaXIgPSB0aGlzLnBvcnRmb2xpb01hbmFnZXIuZ2V0RWxlbWVudERpcihhY3Rpb24udHlwZSk7XG4gICAgLy8gVXNlIHRoZSBvcmlnaW5hbCBmaWxlbmFtZSBmcm9tIHRoZSBwYXRoIHRvIHByZXNlcnZlIGV4dGVuc2lvblxuICAgIGNvbnN0IGZpbGVOYW1lID0gcGF0aC5iYXNlbmFtZShhY3Rpb24ucGF0aCkgfHwgYCR7YWN0aW9uLm5hbWV9Lm1kYDtcbiAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbihlbGVtZW50RGlyLCBmaWxlTmFtZSk7XG4gICAgXG4gICAgLy8gU0VDVVJJVFk6IExvZyBkZWxldGlvbiBhdHRlbXB0IGZvciBhdWRpdCB0cmFpbFxuICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgIHR5cGU6ICdFTEVNRU5UX0RFTEVURUQnLFxuICAgICAgc2V2ZXJpdHk6ICdNRURJVU0nLFxuICAgICAgc291cmNlOiAnUG9ydGZvbGlvUHVsbEhhbmRsZXIuZGVsZXRlTG9jYWxFbGVtZW50JyxcbiAgICAgIGRldGFpbHM6IGBBdHRlbXB0aW5nIHRvIGRlbGV0ZTogJHthY3Rpb24udHlwZX0vJHtmaWxlTmFtZX1gXG4gICAgfSk7XG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLnVubGluayhmaWxlUGF0aCk7XG4gICAgICAvLyBQRVJGT1JNQU5DRTogU2tpcCBpbmRpdmlkdWFsIGluZGV4IHJlYnVpbGQgLSB3aWxsIGJhdGNoIHJlYnVpbGQgYWZ0ZXIgYWxsIG9wZXJhdGlvbnNcbiAgICAgIFxuICAgICAgLy8gU0VDVVJJVFk6IExvZyBzdWNjZXNzZnVsIGRlbGV0aW9uXG4gICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgIHR5cGU6ICdFTEVNRU5UX0RFTEVURUQnLFxuICAgICAgICBzZXZlcml0eTogJ01FRElVTScsXG4gICAgICAgIHNvdXJjZTogJ1BvcnRmb2xpb1B1bGxIYW5kbGVyLmRlbGV0ZUxvY2FsRWxlbWVudCcsXG4gICAgICAgIGRldGFpbHM6IGBTdWNjZXNzZnVsbHkgZGVsZXRlZDogJHthY3Rpb24udHlwZX0vJHtmaWxlTmFtZX1gXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBpZiAoZXJyb3IuY29kZSAhPT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgICAvLyBGaWxlIGFscmVhZHkgZG9lc24ndCBleGlzdCwgdGhhdCdzIGZpbmVcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IEdpdEh1YiB0b2tlbiBmcm9tIGF1dGggbWFuYWdlclxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRHaXRIdWJUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIC8vIFRoaXMgc2hvdWxkIHVzZSB0aGUgc2FtZSB0b2tlbiBtYW5hZ2VtZW50IGFzIHRoZSByZXN0IG9mIHRoZSBzeXN0ZW1cbiAgICBjb25zdCB7IFRva2VuTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KCcuLi9zZWN1cml0eS90b2tlbk1hbmFnZXIuanMnKTtcbiAgICBjb25zdCB0b2tlbiA9IGF3YWl0IFRva2VuTWFuYWdlci5nZXRHaXRIdWJUb2tlbkFzeW5jKCk7XG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdHaXRIdWIgYXV0aGVudGljYXRpb24gcmVxdWlyZWQuIFBsZWFzZSBydW4gc2V0dXBfZ2l0aHViX2F1dGggZmlyc3QuJyk7XG4gICAgfVxuICAgIHJldHVybiB0b2tlbjtcbiAgfVxufSJdfQ==
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Standalone script to run the configuration wizard
5
+ * Can be used for testing or manual configuration
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.runConfigWizard = main;
9
+ const ConfigManager_js_1 = require("../src/config/ConfigManager.js");
10
+ const ConfigWizard_js_1 = require("../src/config/ConfigWizard.js");
11
+ const chalk_1 = require("chalk");
12
+ async function main() {
13
+ try {
14
+ // Initialize config manager
15
+ const configManager = ConfigManager_js_1.ConfigManager.getInstance();
16
+ await configManager.initialize();
17
+ // Create and run wizard
18
+ const wizard = new ConfigWizard_js_1.ConfigWizard(configManager);
19
+ // Check if we should force run (for testing)
20
+ const forceRun = process.argv.includes('--force');
21
+ if (forceRun || await wizard.shouldRunWizard()) {
22
+ const choice = await wizard.promptInitial();
23
+ if (choice === 'yes') {
24
+ await wizard.runWizard();
25
+ }
26
+ else if (choice === 'never') {
27
+ await wizard.markDismissed();
28
+ console.log(chalk_1.default.gray('\nWizard dismissed. You can run it manually anytime.\n'));
29
+ }
30
+ else {
31
+ console.log(chalk_1.default.gray('\nSkipped for now. The wizard will ask again next time.\n'));
32
+ }
33
+ }
34
+ else {
35
+ const config = configManager.getConfig();
36
+ if (config.wizard?.completed) {
37
+ console.log(chalk_1.default.green('\nāœ… Configuration wizard already completed.'));
38
+ console.log(chalk_1.default.gray('Use --force to run it again.\n'));
39
+ }
40
+ else if (config.wizard?.dismissed) {
41
+ console.log(chalk_1.default.yellow('\nāš ļø Configuration wizard was previously dismissed.'));
42
+ console.log(chalk_1.default.gray('Use --force to run it anyway.\n'));
43
+ }
44
+ }
45
+ // Clean up
46
+ wizard.close();
47
+ process.exit(0);
48
+ }
49
+ catch (error) {
50
+ console.error(chalk_1.default.red('\nāŒ Error running configuration wizard:'), error);
51
+ process.exit(1);
52
+ }
53
+ }
54
+ // Run if called directly
55
+ if (import.meta.url === `file://${process.argv[1]}`) {
56
+ main();
57
+ }