snow-flow 2.0.2 → 2.0.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.
- package/{.claude/mcp-config.json → .mcp.json} +13 -12
- package/.releaserc.json +47 -0
- package/README.md +48 -1
- package/package.json +1 -1
- package/.claude/claude-settings.json +0 -15
- package/.claude/commands/analysis/README.md +0 -9
- package/.claude/commands/automation/README.md +0 -9
- package/.claude/commands/github/README.md +0 -11
- package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
- package/.claude/commands/hooks/README.md +0 -11
- package/.claude/commands/monitoring/README.md +0 -9
- package/.claude/commands/optimization/README.md +0 -9
- package/.claude/commands/training/README.md +0 -9
- package/.claude/commands/workflows/README.md +0 -9
- package/.claude/config.json +0 -36
- package/.claude/helpers/github-setup.sh +0 -28
- package/.claude/helpers/quick-start.sh +0 -19
- package/.claude/helpers/setup-mcp.sh +0 -18
- package/.claude/settings.json +0 -114
- package/.claude/settings.local.json +0 -33
- package/.claude-flow/metrics/agent-metrics.json +0 -1
- package/.claude-flow/metrics/performance.json +0 -9
- package/.claude-flow/metrics/system-metrics.json +0 -15986
- package/.claude-flow/metrics/task-metrics.json +0 -10
- package/.roo/README.md +0 -402
- package/.roo/mcp-list.txt +0 -257
- package/.roo/mcp.json +0 -32
- package/.roo/workflows/basic-tdd.json +0 -32
- package/.roomodes +0 -201
- package/CLAUDE.md +0 -393
- package/bin/snow-flow.js +0 -3
- package/dist/cli.js.bak +0 -2052
- package/dist/config/snow-flow-config.d.ts +0 -1492
- package/dist/config/snow-flow-config.js +0 -938
- package/scripts/create-env.js +0 -91
- package/scripts/postinstall.js +0 -30
- package/scripts/register-mcp-servers.js +0 -210
- package/scripts/reset-mcp-servers.js +0 -246
- package/scripts/setup-mcp.js +0 -106
- package/scripts/update-version.js +0 -31
- package/src/agents/README.md +0 -192
- package/src/agents/base-agent.ts +0 -251
- package/src/agents/coordinator.ts +0 -971
- package/src/agents/index.ts +0 -18
- package/src/agents/queen-403-handler.ts +0 -230
- package/src/agents/queen-agent.ts +0 -1399
- package/src/agents/script-writer-agent.ts +0 -769
- package/src/agents/security-agent.ts +0 -726
- package/src/agents/widget-creator-agent.ts +0 -568
- package/src/api/error-handling.ts +0 -1758
- package/src/api/natural-language-mapper.ts +0 -630
- package/src/api/performance-optimizer.ts +0 -891
- package/src/api/transaction-manager.ts +0 -754
- package/src/cli/deploy-artifact.ts +0 -304
- package/src/cli/snow-flow-cli-integration.ts +0 -434
- package/src/cli.ts +0 -4455
- package/src/cli.ts.bak +0 -5616
- package/src/compliance/advanced-compliance-system.ts +0 -1268
- package/src/compliance/index.ts +0 -19
- package/src/config/snow-flow-config.ts +0 -1019
- package/src/documentation/index.ts +0 -16
- package/src/documentation/self-documenting-system.ts +0 -1421
- package/src/dynamic-version.ts +0 -44
- package/src/healing/index.ts +0 -20
- package/src/healing/self-healing-system.ts +0 -1435
- package/src/health/README.md +0 -161
- package/src/health/system-health.ts +0 -995
- package/src/index.ts +0 -60
- package/src/intelligence/acl-analyzer.ts +0 -377
- package/src/intelligence/auto-resolution-engine.ts +0 -643
- package/src/intelligence/gap-analysis-engine.ts +0 -488
- package/src/intelligence/manual-instructions-generator.ts +0 -744
- package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
- package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
- package/src/intelligence/performance-recommendations-engine.ts +0 -1223
- package/src/intelligence/requirements-analyzer.ts +0 -1148
- package/src/intelligence/task-analyzer.ts +0 -628
- package/src/managers/scope-manager.ts +0 -555
- package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
- package/src/mcp/base-mcp-server.ts +0 -660
- package/src/mcp/http-transport-wrapper.ts +0 -426
- package/src/mcp/service-discovery-client.ts +0 -312
- package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
- package/src/mcp/servicenow-automation-mcp.ts +0 -838
- package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
- package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
- package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
- package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
- package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
- package/src/mcp/servicenow-integration-mcp.ts +0 -819
- package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
- package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
- package/src/mcp/servicenow-mcp-server.ts +0 -728
- package/src/mcp/servicenow-memory-mcp.ts +0 -474
- package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
- package/src/mcp/servicenow-operations-mcp.ts +0 -3384
- package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
- package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
- package/src/mcp/servicenow-progressive-indexer.ts +0 -370
- package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
- package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
- package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
- package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
- package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
- package/src/mcp/servicenow-update-set-mcp.ts +0 -811
- package/src/mcp/shared/agent-context-provider.ts +0 -365
- package/src/mcp/shared/base-mcp-server.ts +0 -2463
- package/src/mcp/shared/mcp-memory-manager.ts +0 -540
- package/src/mcp/shared/mcp-resource-manager.ts +0 -367
- package/src/mcp/snow-flow-mcp.ts +0 -911
- package/src/mcp/start-all-mcp-servers.ts +0 -102
- package/src/mcp/start-servicenow-mcp.ts +0 -67
- package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
- package/src/monitoring/performance-tracker.ts +0 -777
- package/src/optimization/cost-optimization-engine.ts +0 -1125
- package/src/optimization/index.ts +0 -10
- package/src/queen/README.md +0 -403
- package/src/queen/agent-factory.ts +0 -574
- package/src/queen/index.ts +0 -94
- package/src/queen/mcp-execution-bridge.ts +0 -681
- package/src/queen/neural-learning.ts +0 -319
- package/src/queen/parallel-agent-engine.ts +0 -848
- package/src/queen/queen-memory-system.ts +0 -490
- package/src/queen/queen-memory.ts +0 -456
- package/src/queen/servicenow-queen.ts +0 -1029
- package/src/queen/types.ts +0 -87
- package/src/rollback/smart-rollback-system.ts +0 -866
- package/src/schemas/deployment.schema.json +0 -58
- package/src/schemas/flow.schema.json +0 -79
- package/src/schemas/widget.schema.json +0 -72
- package/src/snow-flow-system.ts +0 -541
- package/src/sparc/sparc-help.ts +0 -49
- package/src/sparc/team-sparc.ts +0 -88
- package/src/strategies/global-scope-strategy.ts +0 -736
- package/src/templates/base/application.template.json +0 -45
- package/src/templates/base/business_rule.template.json +0 -33
- package/src/templates/base/script_include.template.json +0 -18
- package/src/templates/base/table.template.json +0 -64
- package/src/templates/base/widget.template.json +0 -25
- package/src/templates/patterns/composite.incident-management.template.json +0 -140
- package/src/templates/patterns/widget.dashboard.template.json +0 -238
- package/src/templates/patterns/widget.datatable.template.json +0 -292
- package/src/testing/integration-test-suite.ts +0 -1276
- package/src/types/index.ts +0 -183
- package/src/types/neo4j-driver.d.ts +0 -23
- package/src/types/servicenow.types.ts +0 -307
- package/src/types/snow-flow.types.ts +0 -186
- package/src/types/todo.types.ts +0 -70
- package/src/utils/action-type-cache.ts +0 -286
- package/src/utils/agent-detector.ts +0 -573
- package/src/utils/artifact-tracker.ts +0 -379
- package/src/utils/dependency-detector.ts +0 -233
- package/src/utils/deployment-metadata-handler.ts +0 -518
- package/src/utils/error-recovery.ts +0 -680
- package/src/utils/logger.ts +0 -60
- package/src/utils/mcp-auth-middleware.ts +0 -262
- package/src/utils/mcp-config-manager.ts +0 -270
- package/src/utils/mcp-server-manager.ts +0 -446
- package/src/utils/mcp-tool-registry.ts +0 -298
- package/src/utils/migrate-snow-flow.ts +0 -98
- package/src/utils/oauth-html-templates.ts +0 -188
- package/src/utils/scope-utils.ts +0 -443
- package/src/utils/servicenow-client.ts +0 -3321
- package/src/utils/servicenow-id-generator.ts +0 -181
- package/src/utils/snow-memory-manager.ts +0 -605
- package/src/utils/snow-oauth.ts +0 -797
- package/src/utils/template-engine.ts +0 -463
- package/src/utils/theme-manager.ts +0 -295
- package/src/utils/unified-auth-store.ts +0 -222
- package/src/utils/update-set-importer.ts +0 -422
- package/src/utils/update-set-xml-packager.ts +0 -371
- package/src/utils/widget-template-generator.ts +0 -1744
- package/src/version.ts +0 -1950
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Update Set Importer
|
|
4
|
-
*
|
|
5
|
-
* Programmatically imports Update Set XML files into ServiceNow
|
|
6
|
-
* via REST API with full error handling and verification
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { ServiceNowClient } from './servicenow-client.js';
|
|
10
|
-
import { ServiceNowOAuth } from './snow-oauth.js';
|
|
11
|
-
import { Logger } from './logger.js';
|
|
12
|
-
import * as fs from 'fs';
|
|
13
|
-
import * as path from 'path';
|
|
14
|
-
|
|
15
|
-
export interface ImportOptions {
|
|
16
|
-
autoPreview?: boolean;
|
|
17
|
-
autoCommit?: boolean;
|
|
18
|
-
skipOnConflict?: boolean;
|
|
19
|
-
backupBeforeCommit?: boolean;
|
|
20
|
-
validateFirst?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ImportResult {
|
|
24
|
-
success: boolean;
|
|
25
|
-
remoteUpdateSetId?: string;
|
|
26
|
-
localUpdateSetId?: string;
|
|
27
|
-
previewStatus?: 'clean' | 'conflicts' | 'errors';
|
|
28
|
-
previewProblems?: any[];
|
|
29
|
-
commitStatus?: 'success' | 'failed' | 'skipped';
|
|
30
|
-
error?: string;
|
|
31
|
-
backupPath?: string;
|
|
32
|
-
flowSysId?: string;
|
|
33
|
-
flowUrl?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class UpdateSetImporter {
|
|
37
|
-
private client: ServiceNowClient;
|
|
38
|
-
private oauth: ServiceNowOAuth;
|
|
39
|
-
private logger: Logger;
|
|
40
|
-
|
|
41
|
-
constructor() {
|
|
42
|
-
this.client = new ServiceNowClient();
|
|
43
|
-
this.oauth = new ServiceNowOAuth();
|
|
44
|
-
this.logger = new Logger('UpdateSetImporter');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Import Update Set XML file to ServiceNow
|
|
49
|
-
*/
|
|
50
|
-
async importUpdateSet(
|
|
51
|
-
xmlFilePath: string,
|
|
52
|
-
options: ImportOptions = {}
|
|
53
|
-
): Promise<ImportResult> {
|
|
54
|
-
try {
|
|
55
|
-
// Check authentication
|
|
56
|
-
const isAuth = await this.oauth.isAuthenticated();
|
|
57
|
-
if (!isAuth) {
|
|
58
|
-
throw new Error('Not authenticated. Run: snow-flow auth login');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Read XML file
|
|
62
|
-
const xmlContent = await fs.promises.readFile(xmlFilePath, 'utf-8');
|
|
63
|
-
|
|
64
|
-
// Validate XML if requested
|
|
65
|
-
if (options.validateFirst) {
|
|
66
|
-
const validation = this.validateXML(xmlContent);
|
|
67
|
-
if (!validation.valid) {
|
|
68
|
-
throw new Error(`XML validation failed: ${validation.errors.join(', ')}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Step 1: Import as remote update set
|
|
73
|
-
this.logger.info('Importing XML as remote update set...');
|
|
74
|
-
const remoteUpdateSetId = await this.importRemoteUpdateSet(xmlContent);
|
|
75
|
-
|
|
76
|
-
// Step 2: Load the remote update set
|
|
77
|
-
this.logger.info('Loading remote update set...');
|
|
78
|
-
const localUpdateSetId = await this.loadRemoteUpdateSet(remoteUpdateSetId);
|
|
79
|
-
|
|
80
|
-
// Step 3: Preview if requested
|
|
81
|
-
let previewStatus: 'clean' | 'conflicts' | 'errors' = 'clean';
|
|
82
|
-
let previewProblems: any[] = [];
|
|
83
|
-
|
|
84
|
-
if (options.autoPreview !== false) {
|
|
85
|
-
this.logger.info('Previewing update set...');
|
|
86
|
-
const preview = await this.previewUpdateSet(localUpdateSetId);
|
|
87
|
-
previewStatus = preview.status;
|
|
88
|
-
previewProblems = preview.problems;
|
|
89
|
-
|
|
90
|
-
if (previewStatus !== 'clean' && options.skipOnConflict) {
|
|
91
|
-
return {
|
|
92
|
-
success: false,
|
|
93
|
-
remoteUpdateSetId,
|
|
94
|
-
localUpdateSetId,
|
|
95
|
-
previewStatus,
|
|
96
|
-
previewProblems,
|
|
97
|
-
commitStatus: 'skipped',
|
|
98
|
-
error: 'Preview found conflicts/errors, skipping commit'
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Step 4: Backup if requested
|
|
104
|
-
let backupPath: string | undefined;
|
|
105
|
-
if (options.backupBeforeCommit && localUpdateSetId) {
|
|
106
|
-
this.logger.info('Creating backup...');
|
|
107
|
-
backupPath = await this.backupUpdateSet(localUpdateSetId);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Step 5: Commit if requested and preview is clean
|
|
111
|
-
let commitStatus: 'success' | 'failed' | 'skipped' = 'skipped';
|
|
112
|
-
let flowSysId: string | undefined;
|
|
113
|
-
let flowUrl: string | undefined;
|
|
114
|
-
|
|
115
|
-
if (options.autoCommit && previewStatus === 'clean') {
|
|
116
|
-
this.logger.info('Committing update set...');
|
|
117
|
-
const commit = await this.commitUpdateSet(localUpdateSetId);
|
|
118
|
-
commitStatus = commit.success ? 'success' : 'failed';
|
|
119
|
-
|
|
120
|
-
if (commit.success) {
|
|
121
|
-
// Try to find the flow that was deployed
|
|
122
|
-
const flowInfo = await this.findDeployedFlow(localUpdateSetId);
|
|
123
|
-
flowSysId = flowInfo?.sys_id;
|
|
124
|
-
flowUrl = flowInfo?.url;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
success: commitStatus === 'success' || (previewStatus === 'clean' && !options.autoCommit),
|
|
130
|
-
remoteUpdateSetId,
|
|
131
|
-
localUpdateSetId,
|
|
132
|
-
previewStatus,
|
|
133
|
-
previewProblems,
|
|
134
|
-
commitStatus,
|
|
135
|
-
backupPath,
|
|
136
|
-
flowSysId,
|
|
137
|
-
flowUrl
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
} catch (error) {
|
|
141
|
-
this.logger.error('Import failed:', error);
|
|
142
|
-
return {
|
|
143
|
-
success: false,
|
|
144
|
-
error: error instanceof Error ? error.message : String(error)
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Import XML as remote update set
|
|
151
|
-
*/
|
|
152
|
-
private async importRemoteUpdateSet(xmlContent: string): Promise<string> {
|
|
153
|
-
const response = await this.client.makeRequest({
|
|
154
|
-
method: 'POST',
|
|
155
|
-
url: '/api/now/v2/table/sys_remote_update_set/import',
|
|
156
|
-
headers: {
|
|
157
|
-
'Content-Type': 'application/xml',
|
|
158
|
-
'Accept': 'application/json'
|
|
159
|
-
},
|
|
160
|
-
data: xmlContent
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
if (!response.success || !response.result) {
|
|
164
|
-
throw new Error('Failed to import remote update set');
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Handle different response formats
|
|
168
|
-
const sysId = response.result.sys_id ||
|
|
169
|
-
response.result.result?.sys_id ||
|
|
170
|
-
response.result[0]?.sys_id;
|
|
171
|
-
|
|
172
|
-
if (!sysId) {
|
|
173
|
-
throw new Error('Failed to get remote update set sys_id from response');
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return sysId;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Load remote update set to create local update set
|
|
181
|
-
*/
|
|
182
|
-
private async loadRemoteUpdateSet(remoteUpdateSetId: string): Promise<string> {
|
|
183
|
-
// First, update state to loaded
|
|
184
|
-
await this.client.makeRequest({
|
|
185
|
-
method: 'PATCH',
|
|
186
|
-
url: `/api/now/table/sys_remote_update_set/${remoteUpdateSetId}`,
|
|
187
|
-
data: {
|
|
188
|
-
state: 'loaded'
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// Wait a moment for processing
|
|
193
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
194
|
-
|
|
195
|
-
// Find the loaded update set
|
|
196
|
-
const response = await this.client.makeRequest({
|
|
197
|
-
method: 'GET',
|
|
198
|
-
url: '/api/now/table/sys_update_set',
|
|
199
|
-
params: {
|
|
200
|
-
sysparm_query: `origin_sys_id=${remoteUpdateSetId}^ORremote_sys_id=${remoteUpdateSetId}`,
|
|
201
|
-
sysparm_limit: 1,
|
|
202
|
-
sysparm_fields: 'sys_id,name,state'
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (!response.success || !response.result || response.result.length === 0) {
|
|
207
|
-
throw new Error('Failed to find loaded update set');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return response.result[0].sys_id;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Preview update set
|
|
215
|
-
*/
|
|
216
|
-
private async previewUpdateSet(updateSetId: string): Promise<{
|
|
217
|
-
status: 'clean' | 'conflicts' | 'errors';
|
|
218
|
-
problems: any[];
|
|
219
|
-
}> {
|
|
220
|
-
// Trigger preview
|
|
221
|
-
await this.client.makeRequest({
|
|
222
|
-
method: 'POST',
|
|
223
|
-
url: `/api/now/table/sys_update_set/${updateSetId}/preview`,
|
|
224
|
-
data: {}
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Wait for preview to complete
|
|
228
|
-
let attempts = 0;
|
|
229
|
-
const maxAttempts = 30;
|
|
230
|
-
|
|
231
|
-
while (attempts < maxAttempts) {
|
|
232
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
233
|
-
|
|
234
|
-
const response = await this.client.makeRequest({
|
|
235
|
-
method: 'GET',
|
|
236
|
-
url: `/api/now/table/sys_update_set/${updateSetId}`,
|
|
237
|
-
params: {
|
|
238
|
-
sysparm_fields: 'state,preview_state'
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
if (response.result?.preview_state === 'complete') {
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
attempts++;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Check for preview problems
|
|
250
|
-
const problemsResponse = await this.client.makeRequest({
|
|
251
|
-
method: 'GET',
|
|
252
|
-
url: '/api/now/table/sys_update_preview_problem',
|
|
253
|
-
params: {
|
|
254
|
-
sysparm_query: `update_set=${updateSetId}`,
|
|
255
|
-
sysparm_limit: 100
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
const problems = problemsResponse.result || [];
|
|
260
|
-
let status: 'clean' | 'conflicts' | 'errors' = 'clean';
|
|
261
|
-
|
|
262
|
-
if (problems.length > 0) {
|
|
263
|
-
const hasErrors = problems.some((p: any) => p.type === 'error');
|
|
264
|
-
status = hasErrors ? 'errors' : 'conflicts';
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return { status, problems };
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Commit update set
|
|
272
|
-
*/
|
|
273
|
-
private async commitUpdateSet(updateSetId: string): Promise<{ success: boolean; error?: string }> {
|
|
274
|
-
try {
|
|
275
|
-
await this.client.makeRequest({
|
|
276
|
-
method: 'POST',
|
|
277
|
-
url: `/api/now/table/sys_update_set/${updateSetId}/commit`,
|
|
278
|
-
data: {}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// Verify commit completed
|
|
282
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
283
|
-
|
|
284
|
-
const response = await this.client.makeRequest({
|
|
285
|
-
method: 'GET',
|
|
286
|
-
url: `/api/now/table/sys_update_set/${updateSetId}`,
|
|
287
|
-
params: {
|
|
288
|
-
sysparm_fields: 'state'
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
const isCommitted = response.result?.state === 'complete' ||
|
|
293
|
-
response.result?.state === 'committed';
|
|
294
|
-
|
|
295
|
-
return { success: isCommitted };
|
|
296
|
-
} catch (error) {
|
|
297
|
-
return {
|
|
298
|
-
success: false,
|
|
299
|
-
error: error instanceof Error ? error.message : String(error)
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Backup update set before commit
|
|
306
|
-
*/
|
|
307
|
-
private async backupUpdateSet(updateSetId: string): Promise<string> {
|
|
308
|
-
const response = await this.client.makeRequest({
|
|
309
|
-
method: 'GET',
|
|
310
|
-
url: `/api/now/v2/table/sys_update_set/${updateSetId}/export`
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
const backupDir = path.join(process.cwd(), 'update-set-backups');
|
|
314
|
-
if (!fs.existsSync(backupDir)) {
|
|
315
|
-
fs.mkdirSync(backupDir, { recursive: true });
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const backupPath = path.join(
|
|
319
|
-
backupDir,
|
|
320
|
-
`backup_${updateSetId}_${Date.now()}.xml`
|
|
321
|
-
);
|
|
322
|
-
|
|
323
|
-
fs.writeFileSync(backupPath, response.result || response);
|
|
324
|
-
return backupPath;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Find deployed flow from update set
|
|
329
|
-
*/
|
|
330
|
-
private async findDeployedFlow(updateSetId: string): Promise<{ sys_id: string; url: string } | null> {
|
|
331
|
-
try {
|
|
332
|
-
// Look for flow in update set
|
|
333
|
-
const response = await this.client.makeRequest({
|
|
334
|
-
method: 'GET',
|
|
335
|
-
url: '/api/now/table/sys_update_xml',
|
|
336
|
-
params: {
|
|
337
|
-
sysparm_query: `update_set=${updateSetId}^name^STARTSWITHsys_hub_flow_`,
|
|
338
|
-
sysparm_limit: 1,
|
|
339
|
-
sysparm_fields: 'name'
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
if (response.result && response.result.length > 0) {
|
|
344
|
-
const flowSysId = response.result[0].name.replace('sys_hub_flow_', '');
|
|
345
|
-
const credentials = await this.oauth.getCredentials();
|
|
346
|
-
const flowUrl = `https://${credentials?.instance}/flow_designer/${flowSysId}`;
|
|
347
|
-
|
|
348
|
-
return { sys_id: flowSysId, url: flowUrl };
|
|
349
|
-
}
|
|
350
|
-
} catch (error) {
|
|
351
|
-
this.logger.warn('Could not find deployed flow:', error);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return null;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Validate XML structure
|
|
359
|
-
*/
|
|
360
|
-
private validateXML(xml: string): { valid: boolean; errors: string[] } {
|
|
361
|
-
const errors: string[] = [];
|
|
362
|
-
|
|
363
|
-
if (!xml.includes('<?xml')) {
|
|
364
|
-
errors.push('Missing XML declaration');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
if (!xml.includes('<sys_remote_update_set')) {
|
|
368
|
-
errors.push('Missing sys_remote_update_set element');
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (!xml.includes('<unload')) {
|
|
372
|
-
errors.push('Missing unload root element');
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return {
|
|
376
|
-
valid: errors.length === 0,
|
|
377
|
-
errors
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Static helper to import with default options
|
|
383
|
-
*/
|
|
384
|
-
static async importFlow(xmlFilePath: string): Promise<ImportResult> {
|
|
385
|
-
const importer = new UpdateSetImporter();
|
|
386
|
-
return importer.importUpdateSet(xmlFilePath, {
|
|
387
|
-
autoPreview: true,
|
|
388
|
-
autoCommit: true,
|
|
389
|
-
skipOnConflict: false,
|
|
390
|
-
backupBeforeCommit: true,
|
|
391
|
-
validateFirst: true
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Export helper functions
|
|
397
|
-
export async function deployFlowXML(
|
|
398
|
-
xmlFilePath: string,
|
|
399
|
-
autoCommit: boolean = true
|
|
400
|
-
): Promise<ImportResult> {
|
|
401
|
-
const importer = new UpdateSetImporter();
|
|
402
|
-
return importer.importUpdateSet(xmlFilePath, {
|
|
403
|
-
autoPreview: true,
|
|
404
|
-
autoCommit,
|
|
405
|
-
skipOnConflict: false,
|
|
406
|
-
backupBeforeCommit: true,
|
|
407
|
-
validateFirst: true
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
export async function previewFlowXML(xmlFilePath: string): Promise<ImportResult> {
|
|
412
|
-
const importer = new UpdateSetImporter();
|
|
413
|
-
return importer.importUpdateSet(xmlFilePath, {
|
|
414
|
-
autoPreview: true,
|
|
415
|
-
autoCommit: false,
|
|
416
|
-
skipOnConflict: false,
|
|
417
|
-
backupBeforeCommit: false,
|
|
418
|
-
validateFirst: true
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
export default UpdateSetImporter;
|