snow-flow 1.1.42 โ 1.1.45
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/README.md +97 -0
- package/dist/mcp/servicenow-deployment-mcp.js +352 -0
- package/dist/mcp/servicenow-deployment-mcp.js.map +1 -1
- package/dist/mcp/servicenow-intelligent-mcp.js +4 -0
- package/dist/mcp/servicenow-intelligent-mcp.js.map +1 -1
- package/dist/mcp/servicenow-operations-mcp.js +1226 -3
- package/dist/mcp/servicenow-operations-mcp.js.map +1 -1
- package/dist/mcp/servicenow-platform-development-mcp.js +187 -0
- package/dist/mcp/servicenow-platform-development-mcp.js.map +1 -1
- package/dist/utils/servicenow-client.d.ts +5 -0
- package/dist/utils/servicenow-client.d.ts.map +1 -1
- package/dist/utils/servicenow-client.js +73 -13
- package/dist/utils/servicenow-client.js.map +1 -1
- package/dist/version.d.ts +16 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +80 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Snow-Flow is a powerful multi-agent AI platform that revolutionizes ServiceNow development through intelligent automation, natural language processing, and autonomous deployment capabilities. Built with 11 specialized MCP (Model Context Protocol) servers, Snow-Flow enables developers to create, manage, and deploy ServiceNow artifacts using simple natural language commands.
|
|
4
4
|
|
|
5
|
+
## ๐ What's New in v1.1.45
|
|
6
|
+
|
|
7
|
+
### ๐ Enhanced Catalog Discovery
|
|
8
|
+
- **Fuzzy Search**: Find "iPhone 6S" even when searching "iPhone"
|
|
9
|
+
- **Smart Variations**: Automatically searches related terms (laptop โ notebook, MacBook)
|
|
10
|
+
- **Category Filtering**: Narrow down results by catalog category
|
|
11
|
+
|
|
12
|
+
### ๐งช Flow Testing Revolution
|
|
13
|
+
- **Mock Data Creation**: Automatically creates test users and catalog items
|
|
14
|
+
- **Approval Simulation**: Auto-approves during testing for complete flow validation
|
|
15
|
+
- **Execution Monitoring**: Real-time tracking with 60-second timeout protection
|
|
16
|
+
- **Cleanup Support**: Optional removal of all test data after execution
|
|
17
|
+
|
|
18
|
+
### ๐ Direct Catalog-Flow Integration
|
|
19
|
+
- **Three Linking Methods**: Modern flow_catalog_process, legacy workflow, or process_engine
|
|
20
|
+
- **Variable Mapping**: Map catalog variables to flow inputs with transformations
|
|
21
|
+
- **Trigger Control**: Configure exactly when flows should execute
|
|
22
|
+
- **Test Integration**: Create test requests to verify the link works
|
|
23
|
+
|
|
24
|
+
### โก Performance Improvements
|
|
25
|
+
- **Bulk Deployment**: Deploy multiple artifacts in a single transaction
|
|
26
|
+
- **Parallel Processing**: Up to 5x faster with concurrent operations
|
|
27
|
+
- **Smart Rollback**: Automatic rollback on any deployment failure
|
|
28
|
+
|
|
5
29
|
## ๐ Key Features
|
|
6
30
|
|
|
7
31
|
### ๐ค 11 Specialized MCP Servers
|
|
@@ -181,6 +205,79 @@ Recognizes common patterns and applies best practices:
|
|
|
181
205
|
- Notification systems
|
|
182
206
|
- Integration patterns
|
|
183
207
|
|
|
208
|
+
## ๐ง New MCP Tools (v1.1.44+)
|
|
209
|
+
|
|
210
|
+
### Catalog Item Search with Fuzzy Matching
|
|
211
|
+
Find catalog items even when you don't know the exact name:
|
|
212
|
+
```javascript
|
|
213
|
+
// In Claude Code with MCP tools
|
|
214
|
+
snow_catalog_item_search({
|
|
215
|
+
query: "iPhone", // Finds iPhone 6S, iPhone 7, etc.
|
|
216
|
+
fuzzy_match: true, // Intelligent variations
|
|
217
|
+
category_filter: "mobile devices",
|
|
218
|
+
include_variables: true // Get catalog variables
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Flow Testing with Mock Data
|
|
223
|
+
Test flows without affecting production data:
|
|
224
|
+
```javascript
|
|
225
|
+
snow_test_flow_with_mock({
|
|
226
|
+
flow_id: "equipment_provisioning_flow",
|
|
227
|
+
create_test_user: true, // Auto-creates test user
|
|
228
|
+
mock_catalog_items: true, // Creates test items
|
|
229
|
+
mock_catalog_data: [
|
|
230
|
+
{
|
|
231
|
+
name: "Test iPhone 6S",
|
|
232
|
+
price: "699.00"
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
simulate_approvals: true, // Auto-approves
|
|
236
|
+
cleanup_after_test: true // Removes test data
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Direct Catalog-Flow Linking
|
|
241
|
+
Link catalog items directly to flows for automated fulfillment:
|
|
242
|
+
```javascript
|
|
243
|
+
snow_link_catalog_to_flow({
|
|
244
|
+
catalog_item_id: "iPhone 6S",
|
|
245
|
+
flow_id: "mobile_provisioning_flow",
|
|
246
|
+
link_type: "flow_catalog_process", // Modern approach
|
|
247
|
+
variable_mapping: [
|
|
248
|
+
{
|
|
249
|
+
catalog_variable: "phone_model",
|
|
250
|
+
flow_input: "device_type"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
catalog_variable: "user_department",
|
|
254
|
+
flow_input: "department"
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
trigger_condition: 'current.stage == "request_approved"',
|
|
258
|
+
execution_options: {
|
|
259
|
+
run_as: "system",
|
|
260
|
+
wait_for_completion: true
|
|
261
|
+
},
|
|
262
|
+
test_link: true // Creates test request
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Bulk Deployment
|
|
267
|
+
Deploy multiple artifacts in a single transaction:
|
|
268
|
+
```javascript
|
|
269
|
+
snow_bulk_deploy({
|
|
270
|
+
artifacts: [
|
|
271
|
+
{ type: "widget", data: widgetData },
|
|
272
|
+
{ type: "flow", data: flowData },
|
|
273
|
+
{ type: "script", data: scriptData }
|
|
274
|
+
],
|
|
275
|
+
transaction_mode: true, // All-or-nothing deployment
|
|
276
|
+
parallel: true, // Deploy simultaneously
|
|
277
|
+
dry_run: false
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
184
281
|
## ๐ Project Structure
|
|
185
282
|
|
|
186
283
|
```
|
|
@@ -368,6 +368,35 @@ class ServiceNowDeploymentMCP {
|
|
|
368
368
|
required: ['name'],
|
|
369
369
|
},
|
|
370
370
|
},
|
|
371
|
+
{
|
|
372
|
+
name: 'snow_bulk_deploy',
|
|
373
|
+
description: 'Deploy multiple artifacts in a single operation with transaction support',
|
|
374
|
+
inputSchema: {
|
|
375
|
+
type: 'object',
|
|
376
|
+
properties: {
|
|
377
|
+
artifacts: {
|
|
378
|
+
type: 'array',
|
|
379
|
+
description: 'Array of artifacts to deploy',
|
|
380
|
+
items: {
|
|
381
|
+
type: 'object',
|
|
382
|
+
properties: {
|
|
383
|
+
type: { type: 'string', enum: ['widget', 'flow', 'script', 'business_rule', 'table', 'application'] },
|
|
384
|
+
sys_id: { type: 'string', description: 'Existing artifact sys_id (for updates)' },
|
|
385
|
+
config: { type: 'object', description: 'Artifact configuration' },
|
|
386
|
+
action: { type: 'string', enum: ['create', 'update', 'deploy'], default: 'deploy' },
|
|
387
|
+
},
|
|
388
|
+
required: ['type', 'config'],
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
transaction_mode: { type: 'boolean', description: 'All or nothing deployment', default: true },
|
|
392
|
+
parallel: { type: 'boolean', description: 'Deploy in parallel when possible', default: false },
|
|
393
|
+
dry_run: { type: 'boolean', description: 'Validate without deploying', default: false },
|
|
394
|
+
update_set_name: { type: 'string', description: 'Custom update set name' },
|
|
395
|
+
rollback_on_error: { type: 'boolean', description: 'Rollback all on any failure', default: true },
|
|
396
|
+
},
|
|
397
|
+
required: ['artifacts'],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
371
400
|
],
|
|
372
401
|
}));
|
|
373
402
|
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
@@ -415,6 +444,8 @@ class ServiceNowDeploymentMCP {
|
|
|
415
444
|
return await this.createSolutionPackage(args);
|
|
416
445
|
case 'snow_flow_wizard':
|
|
417
446
|
return await this.flowWizard(args);
|
|
447
|
+
case 'snow_bulk_deploy':
|
|
448
|
+
return await this.bulkDeploy(args);
|
|
418
449
|
default:
|
|
419
450
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
420
451
|
}
|
|
@@ -2625,6 +2656,327 @@ Use \`snow_preview_widget\` to see a detailed preview of the widget rendering.`,
|
|
|
2625
2656
|
throw new Error(`Flow wizard failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2626
2657
|
}
|
|
2627
2658
|
}
|
|
2659
|
+
/**
|
|
2660
|
+
* Bulk Deploy Multiple Artifacts
|
|
2661
|
+
*/
|
|
2662
|
+
async bulkDeploy(args) {
|
|
2663
|
+
try {
|
|
2664
|
+
const { artifacts, transaction_mode = true, parallel = false, dry_run = false, update_set_name, rollback_on_error = true } = args;
|
|
2665
|
+
this.logger.info(`Starting bulk deployment of ${artifacts.length} artifacts`);
|
|
2666
|
+
// Create or ensure update set
|
|
2667
|
+
if (update_set_name) {
|
|
2668
|
+
await this.client.createUpdateSet({
|
|
2669
|
+
name: update_set_name,
|
|
2670
|
+
description: 'Bulk deployment from Snow-Flow',
|
|
2671
|
+
state: 'in_progress'
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
else {
|
|
2675
|
+
await this.client.ensureUpdateSet();
|
|
2676
|
+
}
|
|
2677
|
+
const results = {
|
|
2678
|
+
total: artifacts.length,
|
|
2679
|
+
successful: 0,
|
|
2680
|
+
failed: 0,
|
|
2681
|
+
skipped: 0,
|
|
2682
|
+
details: []
|
|
2683
|
+
};
|
|
2684
|
+
// Track deployed artifacts for rollback
|
|
2685
|
+
const deployedArtifacts = [];
|
|
2686
|
+
try {
|
|
2687
|
+
if (dry_run) {
|
|
2688
|
+
// Validation only
|
|
2689
|
+
for (const artifact of artifacts) {
|
|
2690
|
+
try {
|
|
2691
|
+
const validation = await this.validateArtifact(artifact);
|
|
2692
|
+
results.details.push({
|
|
2693
|
+
type: artifact.type,
|
|
2694
|
+
name: artifact.config?.name || 'Unknown',
|
|
2695
|
+
status: validation.valid ? 'โ
Valid' : 'โ Invalid',
|
|
2696
|
+
message: validation.message
|
|
2697
|
+
});
|
|
2698
|
+
if (validation.valid) {
|
|
2699
|
+
results.successful++;
|
|
2700
|
+
}
|
|
2701
|
+
else {
|
|
2702
|
+
results.failed++;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
catch (error) {
|
|
2706
|
+
results.failed++;
|
|
2707
|
+
results.details.push({
|
|
2708
|
+
type: artifact.type,
|
|
2709
|
+
name: artifact.config?.name || 'Unknown',
|
|
2710
|
+
status: 'โ Error',
|
|
2711
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2712
|
+
});
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
else {
|
|
2717
|
+
// Actual deployment
|
|
2718
|
+
if (parallel && !transaction_mode) {
|
|
2719
|
+
// Parallel deployment (no transaction support)
|
|
2720
|
+
const deploymentPromises = artifacts.map(async (artifact) => {
|
|
2721
|
+
try {
|
|
2722
|
+
const result = await this.deployArtifact(artifact);
|
|
2723
|
+
if (result.success) {
|
|
2724
|
+
deployedArtifacts.push({ type: artifact.type, sys_id: result.sys_id });
|
|
2725
|
+
results.successful++;
|
|
2726
|
+
results.details.push({
|
|
2727
|
+
type: artifact.type,
|
|
2728
|
+
name: artifact.config?.name || 'Unknown',
|
|
2729
|
+
sys_id: result.sys_id,
|
|
2730
|
+
status: 'โ
Deployed',
|
|
2731
|
+
message: result.message
|
|
2732
|
+
});
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
throw new Error(result.message);
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
catch (error) {
|
|
2739
|
+
results.failed++;
|
|
2740
|
+
results.details.push({
|
|
2741
|
+
type: artifact.type,
|
|
2742
|
+
name: artifact.config?.name || 'Unknown',
|
|
2743
|
+
status: 'โ Failed',
|
|
2744
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2745
|
+
});
|
|
2746
|
+
if (transaction_mode && rollback_on_error) {
|
|
2747
|
+
throw error; // Will trigger rollback
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
});
|
|
2751
|
+
await Promise.all(deploymentPromises);
|
|
2752
|
+
}
|
|
2753
|
+
else {
|
|
2754
|
+
// Sequential deployment (supports transactions)
|
|
2755
|
+
for (const artifact of artifacts) {
|
|
2756
|
+
try {
|
|
2757
|
+
const result = await this.deployArtifact(artifact);
|
|
2758
|
+
if (result.success) {
|
|
2759
|
+
deployedArtifacts.push({ type: artifact.type, sys_id: result.sys_id });
|
|
2760
|
+
results.successful++;
|
|
2761
|
+
results.details.push({
|
|
2762
|
+
type: artifact.type,
|
|
2763
|
+
name: artifact.config?.name || 'Unknown',
|
|
2764
|
+
sys_id: result.sys_id,
|
|
2765
|
+
status: 'โ
Deployed',
|
|
2766
|
+
message: result.message
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
else {
|
|
2770
|
+
throw new Error(result.message);
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
catch (error) {
|
|
2774
|
+
results.failed++;
|
|
2775
|
+
results.details.push({
|
|
2776
|
+
type: artifact.type,
|
|
2777
|
+
name: artifact.config?.name || 'Unknown',
|
|
2778
|
+
status: 'โ Failed',
|
|
2779
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2780
|
+
});
|
|
2781
|
+
if (transaction_mode && rollback_on_error) {
|
|
2782
|
+
throw error; // Will trigger rollback
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
catch (error) {
|
|
2790
|
+
// Rollback if needed
|
|
2791
|
+
if (rollback_on_error && deployedArtifacts.length > 0) {
|
|
2792
|
+
this.logger.info(`Rolling back ${deployedArtifacts.length} deployed artifacts`);
|
|
2793
|
+
for (const deployed of deployedArtifacts) {
|
|
2794
|
+
try {
|
|
2795
|
+
await this.rollbackArtifact(deployed);
|
|
2796
|
+
results.details.push({
|
|
2797
|
+
type: deployed.type,
|
|
2798
|
+
sys_id: deployed.sys_id,
|
|
2799
|
+
status: '๐ Rolled back',
|
|
2800
|
+
message: 'Artifact rolled back due to deployment failure'
|
|
2801
|
+
});
|
|
2802
|
+
}
|
|
2803
|
+
catch (rollbackError) {
|
|
2804
|
+
this.logger.error(`Failed to rollback ${deployed.type} ${deployed.sys_id}:`, rollbackError);
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
throw error;
|
|
2809
|
+
}
|
|
2810
|
+
// Generate summary
|
|
2811
|
+
let summary = `๐ Bulk Deployment ${dry_run ? 'Validation' : 'Complete'}\n\n`;
|
|
2812
|
+
summary += `๐ Summary:\n`;
|
|
2813
|
+
summary += ` Total: ${results.total}\n`;
|
|
2814
|
+
summary += ` โ
Successful: ${results.successful}\n`;
|
|
2815
|
+
summary += ` โ Failed: ${results.failed}\n`;
|
|
2816
|
+
if (results.skipped > 0) {
|
|
2817
|
+
summary += ` โญ๏ธ Skipped: ${results.skipped}\n`;
|
|
2818
|
+
}
|
|
2819
|
+
summary += `\n๐ Details:\n`;
|
|
2820
|
+
for (const detail of results.details) {
|
|
2821
|
+
summary += `\n${detail.status} ${detail.type}: ${detail.name}`;
|
|
2822
|
+
if (detail.sys_id) {
|
|
2823
|
+
summary += ` (${detail.sys_id})`;
|
|
2824
|
+
}
|
|
2825
|
+
if (detail.message) {
|
|
2826
|
+
summary += `\n ${detail.message}`;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
if (transaction_mode && !dry_run) {
|
|
2830
|
+
summary += `\n\n๐ Transaction Mode: ${results.failed === 0 ? 'All deployed successfully' : 'Rolled back due to failures'}`;
|
|
2831
|
+
}
|
|
2832
|
+
return {
|
|
2833
|
+
content: [{
|
|
2834
|
+
type: 'text',
|
|
2835
|
+
text: summary
|
|
2836
|
+
}]
|
|
2837
|
+
};
|
|
2838
|
+
}
|
|
2839
|
+
catch (error) {
|
|
2840
|
+
throw new Error(`Bulk deployment failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Deploy a single artifact
|
|
2845
|
+
*/
|
|
2846
|
+
async deployArtifact(artifact) {
|
|
2847
|
+
const { type, sys_id, config, action = 'deploy' } = artifact;
|
|
2848
|
+
try {
|
|
2849
|
+
switch (type) {
|
|
2850
|
+
case 'widget':
|
|
2851
|
+
if (action === 'update' && sys_id) {
|
|
2852
|
+
const result = await this.client.updateRecord('sp_widget', sys_id, config);
|
|
2853
|
+
return {
|
|
2854
|
+
success: result.success,
|
|
2855
|
+
sys_id: sys_id,
|
|
2856
|
+
message: result.success ? 'Widget updated' : result.error
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
else {
|
|
2860
|
+
const result = await this.deployWidget(config);
|
|
2861
|
+
return {
|
|
2862
|
+
success: result.content[0].text.includes('โ
'),
|
|
2863
|
+
sys_id: result.content[0].text.match(/sys_id: ([a-f0-9]+)/)?.[1],
|
|
2864
|
+
message: 'Widget deployed'
|
|
2865
|
+
};
|
|
2866
|
+
}
|
|
2867
|
+
case 'flow':
|
|
2868
|
+
const flowResult = await this.deployFlow(config);
|
|
2869
|
+
return {
|
|
2870
|
+
success: flowResult.content[0].text.includes('โ
'),
|
|
2871
|
+
sys_id: flowResult.content[0].text.match(/sys_id: ([a-f0-9]+)/)?.[1],
|
|
2872
|
+
message: 'Flow deployed'
|
|
2873
|
+
};
|
|
2874
|
+
case 'script':
|
|
2875
|
+
case 'script_include':
|
|
2876
|
+
const scriptResult = await this.client.createRecord('sys_script_include', config);
|
|
2877
|
+
return {
|
|
2878
|
+
success: scriptResult.success,
|
|
2879
|
+
sys_id: scriptResult.data?.sys_id,
|
|
2880
|
+
message: scriptResult.success ? 'Script deployed' : scriptResult.error
|
|
2881
|
+
};
|
|
2882
|
+
case 'business_rule':
|
|
2883
|
+
const ruleResult = await this.client.createRecord('sys_script', config);
|
|
2884
|
+
return {
|
|
2885
|
+
success: ruleResult.success,
|
|
2886
|
+
sys_id: ruleResult.data?.sys_id,
|
|
2887
|
+
message: ruleResult.success ? 'Business rule deployed' : ruleResult.error
|
|
2888
|
+
};
|
|
2889
|
+
case 'table':
|
|
2890
|
+
const tableResult = await this.client.createRecord('sys_db_object', config);
|
|
2891
|
+
return {
|
|
2892
|
+
success: tableResult.success,
|
|
2893
|
+
sys_id: tableResult.data?.sys_id,
|
|
2894
|
+
message: tableResult.success ? 'Table created' : tableResult.error
|
|
2895
|
+
};
|
|
2896
|
+
case 'application':
|
|
2897
|
+
const appResult = await this.deployApplication(config);
|
|
2898
|
+
return {
|
|
2899
|
+
success: appResult.content[0].text.includes('โ
'),
|
|
2900
|
+
sys_id: appResult.content[0].text.match(/sys_id: ([a-f0-9]+)/)?.[1],
|
|
2901
|
+
message: 'Application deployed'
|
|
2902
|
+
};
|
|
2903
|
+
default:
|
|
2904
|
+
return {
|
|
2905
|
+
success: false,
|
|
2906
|
+
message: `Unknown artifact type: ${type}`
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
catch (error) {
|
|
2911
|
+
return {
|
|
2912
|
+
success: false,
|
|
2913
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2914
|
+
};
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* Validate artifact before deployment
|
|
2919
|
+
*/
|
|
2920
|
+
async validateArtifact(artifact) {
|
|
2921
|
+
const { type, config } = artifact;
|
|
2922
|
+
// Basic validation
|
|
2923
|
+
if (!type || !config) {
|
|
2924
|
+
return { valid: false, message: 'Missing type or config' };
|
|
2925
|
+
}
|
|
2926
|
+
// Type-specific validation
|
|
2927
|
+
switch (type) {
|
|
2928
|
+
case 'widget':
|
|
2929
|
+
if (!config.name || !config.template) {
|
|
2930
|
+
return { valid: false, message: 'Widget requires name and template' };
|
|
2931
|
+
}
|
|
2932
|
+
break;
|
|
2933
|
+
case 'flow':
|
|
2934
|
+
if (!config.name || !config.definition) {
|
|
2935
|
+
return { valid: false, message: 'Flow requires name and definition' };
|
|
2936
|
+
}
|
|
2937
|
+
break;
|
|
2938
|
+
case 'script':
|
|
2939
|
+
case 'script_include':
|
|
2940
|
+
if (!config.name || !config.script) {
|
|
2941
|
+
return { valid: false, message: 'Script requires name and script content' };
|
|
2942
|
+
}
|
|
2943
|
+
break;
|
|
2944
|
+
case 'business_rule':
|
|
2945
|
+
if (!config.name || !config.collection || !config.script) {
|
|
2946
|
+
return { valid: false, message: 'Business rule requires name, collection, and script' };
|
|
2947
|
+
}
|
|
2948
|
+
break;
|
|
2949
|
+
case 'table':
|
|
2950
|
+
if (!config.name || !config.label) {
|
|
2951
|
+
return { valid: false, message: 'Table requires name and label' };
|
|
2952
|
+
}
|
|
2953
|
+
break;
|
|
2954
|
+
case 'application':
|
|
2955
|
+
if (!config.name || !config.scope) {
|
|
2956
|
+
return { valid: false, message: 'Application requires name and scope' };
|
|
2957
|
+
}
|
|
2958
|
+
break;
|
|
2959
|
+
}
|
|
2960
|
+
return { valid: true, message: 'Validation passed' };
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Rollback deployed artifact
|
|
2964
|
+
*/
|
|
2965
|
+
async rollbackArtifact(artifact) {
|
|
2966
|
+
const tableMap = {
|
|
2967
|
+
'widget': 'sp_widget',
|
|
2968
|
+
'flow': 'sys_hub_flow',
|
|
2969
|
+
'script': 'sys_script_include',
|
|
2970
|
+
'script_include': 'sys_script_include',
|
|
2971
|
+
'business_rule': 'sys_script',
|
|
2972
|
+
'table': 'sys_db_object',
|
|
2973
|
+
'application': 'sys_app'
|
|
2974
|
+
};
|
|
2975
|
+
const table = tableMap[artifact.type];
|
|
2976
|
+
if (table) {
|
|
2977
|
+
await this.client.deleteRecord(table, artifact.sys_id);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2628
2980
|
/**
|
|
2629
2981
|
* Extract dependencies from flow definition
|
|
2630
2982
|
*/
|