@jterrats/smart-deployment 1.0.3 → 1.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/LICENSE +29 -0
- package/README.md +6 -0
- package/lib/ai/wave-validation-service.d.ts +21 -0
- package/lib/ai/wave-validation-service.js +189 -114
- package/lib/ai/wave-validation-service.js.map +1 -1
- package/lib/analysis/analysis-reporter.d.ts +12 -0
- package/lib/analysis/analysis-reporter.js +61 -0
- package/lib/analysis/analysis-reporter.js.map +1 -1
- package/lib/analysis/analyze-artifact-service.d.ts +25 -0
- package/lib/analysis/analyze-artifact-service.js +50 -0
- package/lib/analysis/analyze-artifact-service.js.map +1 -0
- package/lib/analysis/analyze-context-service.d.ts +25 -0
- package/lib/analysis/analyze-context-service.js +28 -0
- package/lib/analysis/analyze-context-service.js.map +1 -0
- package/lib/analysis/project-analysis-service.d.ts +48 -0
- package/lib/analysis/project-analysis-service.js +134 -0
- package/lib/analysis/project-analysis-service.js.map +1 -0
- package/lib/commands/analyze.d.ts +0 -2
- package/lib/commands/analyze.js +31 -162
- package/lib/commands/analyze.js.map +1 -1
- package/lib/commands/config.d.ts +0 -4
- package/lib/commands/config.js +25 -95
- package/lib/commands/config.js.map +1 -1
- package/lib/commands/resume.js +6 -16
- package/lib/commands/resume.js.map +1 -1
- package/lib/commands/start.d.ts +0 -11
- package/lib/commands/start.js +38 -550
- package/lib/commands/start.js.map +1 -1
- package/lib/commands/status.js +36 -12
- package/lib/commands/status.js.map +1 -1
- package/lib/commands/validate.d.ts +3 -0
- package/lib/commands/validate.js +5 -7
- package/lib/commands/validate.js.map +1 -1
- package/lib/config/config-mutation-service.d.ts +21 -0
- package/lib/config/config-mutation-service.js +61 -0
- package/lib/config/config-mutation-service.js.map +1 -0
- package/lib/dependencies/circular-dependency-detector.d.ts +5 -0
- package/lib/dependencies/circular-dependency-detector.js +67 -72
- package/lib/dependencies/circular-dependency-detector.js.map +1 -1
- package/lib/dependencies/dependency-depth-calculator.d.ts +28 -0
- package/lib/dependencies/dependency-depth-calculator.js +86 -39
- package/lib/dependencies/dependency-depth-calculator.js.map +1 -1
- package/lib/dependencies/dependency-graph-builder.d.ts +45 -13
- package/lib/dependencies/dependency-graph-builder.js +228 -123
- package/lib/dependencies/dependency-graph-builder.js.map +1 -1
- package/lib/dependencies/dependency-impact-analyzer.d.ts +13 -0
- package/lib/dependencies/dependency-impact-analyzer.js +146 -102
- package/lib/dependencies/dependency-impact-analyzer.js.map +1 -1
- package/lib/dependencies/dependency-merger.d.ts +10 -0
- package/lib/dependencies/dependency-merger.js +123 -61
- package/lib/dependencies/dependency-merger.js.map +1 -1
- package/lib/dependencies/dependency-resolver.d.ts +34 -9
- package/lib/dependencies/dependency-resolver.js +181 -112
- package/lib/dependencies/dependency-resolver.js.map +1 -1
- package/lib/dependencies/dependency-semantics.d.ts +20 -0
- package/lib/dependencies/dependency-semantics.js +55 -0
- package/lib/dependencies/dependency-semantics.js.map +1 -0
- package/lib/dependencies/graph-visualizer.d.ts +6 -1
- package/lib/dependencies/graph-visualizer.js +38 -4
- package/lib/dependencies/graph-visualizer.js.map +1 -1
- package/lib/dependencies/heuristic-inference.d.ts +2 -53
- package/lib/dependencies/heuristic-inference.js +8 -317
- package/lib/dependencies/heuristic-inference.js.map +1 -1
- package/lib/dependencies/heuristic-patterns.d.ts +14 -0
- package/lib/dependencies/heuristic-patterns.js +247 -0
- package/lib/dependencies/heuristic-patterns.js.map +1 -0
- package/lib/deployment/cycle-remediation-runner.d.ts +36 -0
- package/lib/deployment/cycle-remediation-runner.js +262 -0
- package/lib/deployment/cycle-remediation-runner.js.map +1 -0
- package/lib/deployment/deployment-context-service.d.ts +24 -0
- package/lib/deployment/deployment-context-service.js +17 -0
- package/lib/deployment/deployment-context-service.js.map +1 -0
- package/lib/deployment/deployment-runner.d.ts +37 -0
- package/lib/deployment/deployment-runner.js +94 -0
- package/lib/deployment/deployment-runner.js.map +1 -0
- package/lib/deployment/deployment-status-service.d.ts +5 -0
- package/lib/deployment/deployment-status-service.js +39 -18
- package/lib/deployment/deployment-status-service.js.map +1 -1
- package/lib/deployment/deployment-validation-service.d.ts +5 -2
- package/lib/deployment/deployment-validation-service.js +48 -45
- package/lib/deployment/deployment-validation-service.js.map +1 -1
- package/lib/deployment/resume-deployment-service.d.ts +14 -0
- package/lib/deployment/resume-deployment-service.js +25 -0
- package/lib/deployment/resume-deployment-service.js.map +1 -0
- package/lib/deployment/start-execution-service.d.ts +44 -0
- package/lib/deployment/start-execution-service.js +94 -0
- package/lib/deployment/start-execution-service.js.map +1 -0
- package/lib/deployment/test-executor.d.ts +60 -1
- package/lib/deployment/test-executor.js +180 -12
- package/lib/deployment/test-executor.js.map +1 -1
- package/lib/deployment/test-plan-service.d.ts +8 -0
- package/lib/deployment/test-plan-service.js +26 -0
- package/lib/deployment/test-plan-service.js.map +1 -0
- package/lib/deployment/wave-manifest-service.d.ts +11 -0
- package/lib/deployment/wave-manifest-service.js +41 -0
- package/lib/deployment/wave-manifest-service.js.map +1 -0
- package/lib/parsers/apex-class-parser.js +180 -98
- package/lib/parsers/apex-class-parser.js.map +1 -1
- package/lib/parsers/apex-trigger-parser.js +56 -7
- package/lib/parsers/apex-trigger-parser.js.map +1 -1
- package/lib/parsers/aura-parser.js +2 -2
- package/lib/parsers/aura-parser.js.map +1 -1
- package/lib/parsers/bot-parser.js +31 -4
- package/lib/parsers/bot-parser.js.map +1 -1
- package/lib/parsers/custom-metadata-parser.js +37 -3
- package/lib/parsers/custom-metadata-parser.js.map +1 -1
- package/lib/parsers/custom-object-parser.js +284 -150
- package/lib/parsers/custom-object-parser.js.map +1 -1
- package/lib/parsers/email-template-parser.js +115 -58
- package/lib/parsers/email-template-parser.js.map +1 -1
- package/lib/parsers/flexipage-parser.js +41 -16
- package/lib/parsers/flexipage-parser.js.map +1 -1
- package/lib/parsers/flow-parser.js +73 -63
- package/lib/parsers/flow-parser.js.map +1 -1
- package/lib/parsers/genai-prompt-parser.js +16 -4
- package/lib/parsers/genai-prompt-parser.js.map +1 -1
- package/lib/parsers/layout-parser.d.ts +11 -0
- package/lib/parsers/layout-parser.js +143 -68
- package/lib/parsers/layout-parser.js.map +1 -1
- package/lib/parsers/lwc-parser.d.ts +0 -9
- package/lib/parsers/lwc-parser.js +245 -100
- package/lib/parsers/lwc-parser.js.map +1 -1
- package/lib/parsers/parser-utils.d.ts +3 -0
- package/lib/parsers/parser-utils.js +16 -0
- package/lib/parsers/parser-utils.js.map +1 -0
- package/lib/parsers/permission-set-parser.d.ts +6 -0
- package/lib/parsers/permission-set-parser.js +31 -40
- package/lib/parsers/permission-set-parser.js.map +1 -1
- package/lib/parsers/profile-parser.d.ts +13 -0
- package/lib/parsers/profile-parser.js +39 -34
- package/lib/parsers/profile-parser.js.map +1 -1
- package/lib/parsers/visualforce-parser.js +2 -1
- package/lib/parsers/visualforce-parser.js.map +1 -1
- package/lib/presentation/analyze-command-presenter.d.ts +10 -0
- package/lib/presentation/analyze-command-presenter.js +30 -0
- package/lib/presentation/analyze-command-presenter.js.map +1 -0
- package/lib/presentation/config-command-presenter.d.ts +15 -0
- package/lib/presentation/config-command-presenter.js +50 -0
- package/lib/presentation/config-command-presenter.js.map +1 -0
- package/lib/presentation/project-analysis-presenter.d.ts +9 -0
- package/lib/presentation/project-analysis-presenter.js +9 -0
- package/lib/presentation/project-analysis-presenter.js.map +1 -0
- package/lib/presentation/resume-command-presenter.d.ts +7 -0
- package/lib/presentation/resume-command-presenter.js +12 -0
- package/lib/presentation/resume-command-presenter.js.map +1 -0
- package/lib/presentation/start-command-presenter.d.ts +15 -0
- package/lib/presentation/start-command-presenter.js +29 -0
- package/lib/presentation/start-command-presenter.js.map +1 -0
- package/lib/presentation/status-command-presenter.d.ts +7 -0
- package/lib/presentation/status-command-presenter.js +16 -0
- package/lib/presentation/status-command-presenter.js.map +1 -0
- package/lib/presentation/validate-command-presenter.d.ts +9 -0
- package/lib/presentation/validate-command-presenter.js +50 -0
- package/lib/presentation/validate-command-presenter.js.map +1 -0
- package/lib/services/metadata-scanner-service.d.ts +8 -12
- package/lib/services/metadata-scanner-service.js +55 -533
- package/lib/services/metadata-scanner-service.js.map +1 -1
- package/lib/services/scanners/automation-ai-metadata-scanner.d.ts +4 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.js +61 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.js.map +1 -0
- package/lib/services/scanners/code-metadata-scanner.d.ts +23 -0
- package/lib/services/scanners/code-metadata-scanner.js +149 -0
- package/lib/services/scanners/code-metadata-scanner.js.map +1 -0
- package/lib/services/scanners/data-metadata-scanner.d.ts +3 -0
- package/lib/services/scanners/data-metadata-scanner.js +82 -0
- package/lib/services/scanners/data-metadata-scanner.js.map +1 -0
- package/lib/services/scanners/experience-metadata-scanner.d.ts +5 -0
- package/lib/services/scanners/experience-metadata-scanner.js +123 -0
- package/lib/services/scanners/experience-metadata-scanner.js.map +1 -0
- package/lib/services/scanners/scanner-runtime.d.ts +11 -0
- package/lib/services/scanners/scanner-runtime.js +115 -0
- package/lib/services/scanners/scanner-runtime.js.map +1 -0
- package/lib/services/scanners/security-metadata-scanner.d.ts +3 -0
- package/lib/services/scanners/security-metadata-scanner.js +71 -0
- package/lib/services/scanners/security-metadata-scanner.js.map +1 -0
- package/lib/types/dependency.d.ts +11 -1
- package/lib/types/metadata.d.ts +17 -0
- package/lib/types/salesforce/flow/actions.d.ts +108 -0
- package/lib/types/salesforce/flow/actions.js +2 -0
- package/lib/types/salesforce/flow/actions.js.map +1 -0
- package/lib/types/salesforce/flow/common.d.ts +36 -0
- package/lib/types/salesforce/flow/common.js +5 -0
- package/lib/types/salesforce/flow/common.js.map +1 -0
- package/lib/types/salesforce/flow/metadata.d.ts +37 -0
- package/lib/types/salesforce/flow/metadata.js +2 -0
- package/lib/types/salesforce/flow/metadata.js.map +1 -0
- package/lib/types/salesforce/flow/records.d.ts +38 -0
- package/lib/types/salesforce/flow/records.js +2 -0
- package/lib/types/salesforce/flow/records.js.map +1 -0
- package/lib/types/salesforce/flow/resources.d.ts +44 -0
- package/lib/types/salesforce/flow/resources.js +2 -0
- package/lib/types/salesforce/flow/resources.js.map +1 -0
- package/lib/types/salesforce/flow/screens.d.ts +56 -0
- package/lib/types/salesforce/flow/screens.js +2 -0
- package/lib/types/salesforce/flow/screens.js.map +1 -0
- package/lib/types/salesforce/flow/start.d.ts +24 -0
- package/lib/types/salesforce/flow/start.js +2 -0
- package/lib/types/salesforce/flow/start.js.map +1 -0
- package/lib/types/salesforce/flow.d.ts +9 -514
- package/lib/types/salesforce/flow.js +1 -1
- package/lib/types/salesforce/object/core.d.ts +68 -0
- package/lib/types/salesforce/object/core.js +5 -0
- package/lib/types/salesforce/object/core.js.map +1 -0
- package/lib/types/salesforce/object/field.d.ts +155 -0
- package/lib/types/salesforce/object/field.js +5 -0
- package/lib/types/salesforce/object/field.js.map +1 -0
- package/lib/types/salesforce/object/filter.d.ts +16 -0
- package/lib/types/salesforce/object/filter.js +5 -0
- package/lib/types/salesforce/object/filter.js.map +1 -0
- package/lib/types/salesforce/object/policy.d.ts +27 -0
- package/lib/types/salesforce/object/policy.js +5 -0
- package/lib/types/salesforce/object/policy.js.map +1 -0
- package/lib/types/salesforce/object/record.d.ts +44 -0
- package/lib/types/salesforce/object/record.js +5 -0
- package/lib/types/salesforce/object/record.js.map +1 -0
- package/lib/types/salesforce/object/view.d.ts +71 -0
- package/lib/types/salesforce/object/view.js +5 -0
- package/lib/types/salesforce/object/view.js.map +1 -0
- package/lib/types/salesforce/object/weblink.d.ts +70 -0
- package/lib/types/salesforce/object/weblink.js +5 -0
- package/lib/types/salesforce/object/weblink.js.map +1 -0
- package/lib/types/salesforce/object.d.ts +7 -423
- package/lib/types/salesforce/object.js +7 -1
- package/lib/types/salesforce/object.js.map +1 -1
- package/lib/utils/cache-manager.d.ts +16 -15
- package/lib/utils/cache-manager.js +290 -188
- package/lib/utils/cache-manager.js.map +1 -1
- package/lib/utils/logger.d.ts +8 -0
- package/lib/utils/logger.js +82 -69
- package/lib/utils/logger.js.map +1 -1
- package/lib/validators/xml/xml-reference-rules.d.ts +3 -0
- package/lib/validators/xml/xml-reference-rules.js +173 -0
- package/lib/validators/xml/xml-reference-rules.js.map +1 -0
- package/lib/validators/xml/xml-report-formatter.d.ts +2 -0
- package/lib/validators/xml/xml-report-formatter.js +47 -0
- package/lib/validators/xml/xml-report-formatter.js.map +1 -0
- package/lib/validators/xml/xml-schema-rules.d.ts +3 -0
- package/lib/validators/xml/xml-schema-rules.js +75 -0
- package/lib/validators/xml/xml-schema-rules.js.map +1 -0
- package/lib/validators/xml/xml-validation-types.d.ts +25 -0
- package/lib/validators/xml/xml-validation-types.js +2 -0
- package/lib/validators/xml/xml-validation-types.js.map +1 -0
- package/lib/validators/xml-metadata-validator.d.ts +2 -63
- package/lib/validators/xml-metadata-validator.js +7 -338
- package/lib/validators/xml-metadata-validator.js.map +1 -1
- package/lib/waves/test-optimizer.d.ts +13 -0
- package/lib/waves/test-optimizer.js +124 -63
- package/lib/waves/test-optimizer.js.map +1 -1
- package/lib/waves/wave-builder.d.ts +17 -21
- package/lib/waves/wave-builder.js +199 -135
- package/lib/waves/wave-builder.js.map +1 -1
- package/lib/waves/wave-splitter.d.ts +12 -8
- package/lib/waves/wave-splitter.js +156 -115
- package/lib/waves/wave-splitter.js.map +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -8,35 +8,18 @@
|
|
|
8
8
|
* - Metadata parsers (all types)
|
|
9
9
|
* - DependencyGraphBuilder
|
|
10
10
|
*/
|
|
11
|
-
import * as fs from 'node:fs/promises';
|
|
12
11
|
import * as path from 'node:path';
|
|
13
|
-
import { glob as globAsync } from 'glob';
|
|
14
12
|
import { DependencyGraphBuilder } from '../dependencies/dependency-graph-builder.js';
|
|
15
|
-
import { parseAura } from '../parsers/aura-parser.js';
|
|
16
|
-
import { parseApexClass } from '../parsers/apex-class-parser.js';
|
|
17
|
-
import { parseApexTrigger } from '../parsers/apex-trigger-parser.js';
|
|
18
|
-
import { parseBot } from '../parsers/bot-parser.js';
|
|
19
|
-
import { parseCustomMetadataType } from '../parsers/custom-metadata-parser.js';
|
|
20
|
-
import { parseCustomObject } from '../parsers/custom-object-parser.js';
|
|
21
|
-
import { parseEmailTemplate } from '../parsers/email-template-parser.js';
|
|
22
|
-
import { parseFlexiPage } from '../parsers/flexipage-parser.js';
|
|
23
|
-
import { parseFlow } from '../parsers/flow-parser.js';
|
|
24
|
-
import { parseGenAiPrompt } from '../parsers/genai-prompt-parser.js';
|
|
25
|
-
import { parseLayout } from '../parsers/layout-parser.js';
|
|
26
|
-
import { parseLWC } from '../parsers/lwc-parser.js';
|
|
27
|
-
import { parsePermissionSet } from '../parsers/permission-set-parser.js';
|
|
28
|
-
import { parseProfile } from '../parsers/profile-parser.js';
|
|
29
|
-
import { parseVisualforce } from '../parsers/visualforce-parser.js';
|
|
30
13
|
import { ForceIgnoreParser } from '../scanner/forceignore-parser.js';
|
|
31
14
|
import { SfdxProjectDetector } from '../scanner/sfdx-project-detector.js';
|
|
32
15
|
import { getLogger } from '../utils/logger.js';
|
|
16
|
+
import { parseBotComponent, parseFlowComponent, parseGenAiPromptComponent, } from './scanners/automation-ai-metadata-scanner.js';
|
|
17
|
+
import { CODE_DIRECTORY_SCANNERS, CODE_FILE_SCANNERS } from './scanners/code-metadata-scanner.js';
|
|
18
|
+
import { parseCustomMetadataComponents, parseCustomObjectComponent } from './scanners/data-metadata-scanner.js';
|
|
19
|
+
import { parseEmailTemplateComponent, parseFlexiPageComponent, parseLayoutComponent, parseVisualforceComponent, } from './scanners/experience-metadata-scanner.js';
|
|
20
|
+
import { fileExists, scanMetadataDirectories, scanMetadataFiles, scanRegisteredDirectoryMetadata, scanRegisteredFileMetadata, } from './scanners/scanner-runtime.js';
|
|
21
|
+
import { parsePermissionSetComponent, parseProfileComponent } from './scanners/security-metadata-scanner.js';
|
|
33
22
|
const logger = getLogger('MetadataScannerService');
|
|
34
|
-
function toNodeIds(dependencies, defaultType) {
|
|
35
|
-
return new Set([...dependencies].map((dependency) => (dependency.includes(':') ? dependency : `${defaultType}:${dependency}`)));
|
|
36
|
-
}
|
|
37
|
-
function isDefined(value) {
|
|
38
|
-
return value !== undefined;
|
|
39
|
-
}
|
|
40
23
|
/**
|
|
41
24
|
* Metadata file pattern matcher
|
|
42
25
|
* TODO: Use when implementing pattern-based metadata detection
|
|
@@ -53,6 +36,7 @@ function isDefined(value) {
|
|
|
53
36
|
*/
|
|
54
37
|
export class MetadataScannerService {
|
|
55
38
|
forceIgnoreParser;
|
|
39
|
+
shouldIgnorePath = (filePath) => this.shouldIgnore(filePath);
|
|
56
40
|
/**
|
|
57
41
|
* Scan project and analyze dependencies
|
|
58
42
|
*/
|
|
@@ -72,7 +56,7 @@ export class MetadataScannerService {
|
|
|
72
56
|
});
|
|
73
57
|
// Parse .forceignore
|
|
74
58
|
const forceIgnorePath = path.join(projectInfo.projectRoot, '.forceignore');
|
|
75
|
-
if (await
|
|
59
|
+
if (await fileExists(forceIgnorePath)) {
|
|
76
60
|
this.forceIgnoreParser = new ForceIgnoreParser();
|
|
77
61
|
const loadResult = await this.forceIgnoreParser.load(projectInfo.projectRoot);
|
|
78
62
|
logger.info('Loaded .forceignore', {
|
|
@@ -110,7 +94,7 @@ export class MetadataScannerService {
|
|
|
110
94
|
async scanMetadata(projectRoot, packageDirs, errors, warnings) {
|
|
111
95
|
const scannedPackages = await Promise.all(packageDirs.map(async (packageDir) => {
|
|
112
96
|
const packagePath = path.isAbsolute(packageDir) ? packageDir : path.join(projectRoot, packageDir);
|
|
113
|
-
if (!(await
|
|
97
|
+
if (!(await fileExists(packagePath))) {
|
|
114
98
|
logger.warn('Package directory not found', { packagePath });
|
|
115
99
|
warnings.push(`Package directory not found: ${packagePath}`);
|
|
116
100
|
return [];
|
|
@@ -124,507 +108,57 @@ export class MetadataScannerService {
|
|
|
124
108
|
*/
|
|
125
109
|
async scanPackageDirectory(packagePath, errors, warnings) {
|
|
126
110
|
void warnings;
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
const errorMsg = `Failed to parse Apex class ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
147
|
-
logger.warn(errorMsg);
|
|
148
|
-
errors.push(errorMsg);
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
}));
|
|
152
|
-
components.push(...apexComponents.filter(isDefined));
|
|
153
|
-
// Scan Apex Triggers
|
|
154
|
-
const triggerFiles = await this.findFiles(packagePath, '**/triggers/**/*.trigger');
|
|
155
|
-
const triggerComponents = await Promise.all(triggerFiles
|
|
156
|
-
.filter((filePath) => !this.shouldIgnore(filePath) && !filePath.endsWith('.trigger-meta.xml'))
|
|
157
|
-
.map(async (filePath) => {
|
|
158
|
-
try {
|
|
159
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
160
|
-
const parsed = parseApexTrigger(filePath, content);
|
|
161
|
-
return {
|
|
162
|
-
name: parsed.triggerName,
|
|
163
|
-
type: 'ApexTrigger',
|
|
164
|
-
filePath,
|
|
165
|
-
dependencies: toNodeIds(parsed.dependencies.map((d) => d.className), 'ApexClass'),
|
|
166
|
-
dependents: new Set(),
|
|
167
|
-
priorityBoost: 0,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
const errorMsg = `Failed to parse Apex trigger ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
172
|
-
logger.warn(errorMsg);
|
|
173
|
-
errors.push(errorMsg);
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
}));
|
|
177
|
-
components.push(...triggerComponents.filter(isDefined));
|
|
178
|
-
// Scan LWC Components (container-based)
|
|
179
|
-
const lwcDirs = await this.findDirectories(packagePath, '**/lwc/*');
|
|
180
|
-
const lwcComponents = await Promise.all(lwcDirs
|
|
181
|
-
.filter((lwcDir) => !this.shouldIgnore(lwcDir))
|
|
182
|
-
.map(async (lwcDir) => {
|
|
183
|
-
const componentName = path.basename(lwcDir);
|
|
184
|
-
const jsFile = path.join(lwcDir, `${componentName}.js`);
|
|
185
|
-
const tsFile = path.join(lwcDir, `${componentName}.ts`);
|
|
186
|
-
const metaFile = path.join(lwcDir, `${componentName}.js-meta.xml`);
|
|
187
|
-
const jsExists = await this.fileExists(jsFile);
|
|
188
|
-
const tsExists = jsExists ? false : await this.fileExists(tsFile);
|
|
189
|
-
const codeFile = jsExists ? jsFile : tsExists ? tsFile : null;
|
|
190
|
-
if (!codeFile) {
|
|
191
|
-
return undefined;
|
|
192
|
-
}
|
|
193
|
-
try {
|
|
194
|
-
const jsContent = await fs.readFile(codeFile, 'utf-8');
|
|
195
|
-
const metaContent = (await this.fileExists(metaFile)) ? await fs.readFile(metaFile, 'utf-8') : undefined;
|
|
196
|
-
const parsed = parseLWC(componentName, jsContent, metaContent);
|
|
197
|
-
return {
|
|
198
|
-
name: componentName,
|
|
199
|
-
type: 'LightningComponentBundle',
|
|
200
|
-
filePath: codeFile,
|
|
201
|
-
dependencies: new Set([...parsed.apexImports, ...parsed.lwcImports.map((imp) => `c:${imp}`)]),
|
|
202
|
-
dependents: new Set(),
|
|
203
|
-
priorityBoost: 0,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
const errorMsg = `Failed to parse LWC ${componentName}: ${error instanceof Error ? error.message : String(error)}`;
|
|
208
|
-
logger.warn(errorMsg);
|
|
209
|
-
errors.push(errorMsg);
|
|
210
|
-
return undefined;
|
|
211
|
-
}
|
|
212
|
-
}));
|
|
213
|
-
components.push(...lwcComponents.filter(isDefined));
|
|
214
|
-
// Scan Aura Components (container-based)
|
|
215
|
-
const auraDirs = await this.findDirectories(packagePath, '**/aura/*');
|
|
216
|
-
const auraComponents = await Promise.all(auraDirs
|
|
217
|
-
.filter((auraDir) => !this.shouldIgnore(auraDir))
|
|
218
|
-
.map(async (auraDir) => {
|
|
219
|
-
const componentName = path.basename(auraDir);
|
|
220
|
-
const cmpFile = path.join(auraDir, `${componentName}.cmp`);
|
|
221
|
-
if (!(await this.fileExists(cmpFile))) {
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
try {
|
|
225
|
-
const cmpContent = await fs.readFile(cmpFile, 'utf-8');
|
|
226
|
-
const parsed = parseAura(componentName, cmpContent);
|
|
227
|
-
const deps = new Set();
|
|
228
|
-
if (parsed.apexController)
|
|
229
|
-
deps.add(parsed.apexController);
|
|
230
|
-
if (parsed.extendsComponent)
|
|
231
|
-
deps.add(parsed.extendsComponent);
|
|
232
|
-
parsed.implementsInterfaces.forEach((i) => deps.add(i));
|
|
233
|
-
parsed.childComponents.forEach((c) => deps.add(`c:${c}`));
|
|
234
|
-
return {
|
|
235
|
-
name: componentName,
|
|
236
|
-
type: 'AuraDefinitionBundle',
|
|
237
|
-
filePath: cmpFile,
|
|
238
|
-
dependencies: deps,
|
|
239
|
-
dependents: new Set(),
|
|
240
|
-
priorityBoost: 0,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
catch (error) {
|
|
244
|
-
const errorMsg = `Failed to parse Aura component ${componentName}: ${error instanceof Error ? error.message : String(error)}`;
|
|
245
|
-
logger.warn(errorMsg);
|
|
246
|
-
errors.push(errorMsg);
|
|
247
|
-
return undefined;
|
|
248
|
-
}
|
|
249
|
-
}));
|
|
250
|
-
components.push(...auraComponents.filter(isDefined));
|
|
251
|
-
// Scan Flows
|
|
252
|
-
const flowFiles = await this.findFiles(packagePath, '**/flows/**/*.flow-meta.xml');
|
|
253
|
-
const flowComponents = await Promise.all(flowFiles
|
|
254
|
-
.filter((filePath) => !this.shouldIgnore(filePath))
|
|
255
|
-
.map(async (filePath) => {
|
|
256
|
-
try {
|
|
257
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
258
|
-
const parsed = parseFlow(filePath, content);
|
|
259
|
-
const deps = new Set();
|
|
260
|
-
parsed.dependencies.forEach((d) => {
|
|
261
|
-
if (d.type === 'apex_action' || d.type === 'subflow') {
|
|
262
|
-
deps.add(d.name);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
return {
|
|
266
|
-
name: parsed.flowName,
|
|
267
|
-
type: 'Flow',
|
|
268
|
-
filePath,
|
|
269
|
-
dependencies: deps,
|
|
270
|
-
dependents: new Set(),
|
|
271
|
-
priorityBoost: 0,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
catch (error) {
|
|
275
|
-
const errorMsg = `Failed to parse Flow ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
276
|
-
logger.warn(errorMsg);
|
|
277
|
-
errors.push(errorMsg);
|
|
278
|
-
return undefined;
|
|
279
|
-
}
|
|
280
|
-
}));
|
|
281
|
-
components.push(...flowComponents.filter(isDefined));
|
|
282
|
-
// Scan Custom Objects
|
|
283
|
-
const objectDirs = await this.findDirectories(packagePath, '**/objects/*');
|
|
284
|
-
const objectComponents = await Promise.all(objectDirs.map(async (objectDir) => {
|
|
285
|
-
if (this.shouldIgnore(objectDir)) {
|
|
286
|
-
return undefined;
|
|
287
|
-
}
|
|
288
|
-
const objectName = path.basename(objectDir);
|
|
289
|
-
const objectFile = path.join(objectDir, `${objectName}.object-meta.xml`);
|
|
290
|
-
if (!(await this.fileExists(objectFile))) {
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
try {
|
|
294
|
-
const content = await fs.readFile(objectFile, 'utf-8');
|
|
295
|
-
const parsed = await parseCustomObject(objectName, content);
|
|
296
|
-
const deps = new Set();
|
|
297
|
-
parsed.dependencies.forEach((dependency) => {
|
|
298
|
-
if ((dependency.type === 'lookup_field' || dependency.type === 'master_detail_field') &&
|
|
299
|
-
dependency.referencedObject) {
|
|
300
|
-
deps.add(dependency.referencedObject);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
return {
|
|
304
|
-
name: objectName,
|
|
305
|
-
type: 'CustomObject',
|
|
306
|
-
filePath: objectFile,
|
|
307
|
-
dependencies: deps,
|
|
308
|
-
dependents: new Set(),
|
|
309
|
-
priorityBoost: 0,
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
catch (error) {
|
|
313
|
-
const errorMsg = `Failed to parse Custom Object ${objectName}: ${error instanceof Error ? error.message : String(error)}`;
|
|
314
|
-
logger.warn(errorMsg);
|
|
315
|
-
errors.push(errorMsg);
|
|
316
|
-
return undefined;
|
|
317
|
-
}
|
|
318
|
-
}));
|
|
319
|
-
components.push(...objectComponents.filter(isDefined));
|
|
320
|
-
// Scan Custom Metadata Types
|
|
321
|
-
const cmtDirs = await this.findDirectories(packagePath, '**/customMetadata/*');
|
|
322
|
-
const customMetadataComponents = await Promise.all(cmtDirs.map(async (cmtDir) => {
|
|
323
|
-
if (this.shouldIgnore(cmtDir)) {
|
|
324
|
-
return undefined;
|
|
325
|
-
}
|
|
111
|
+
const componentGroups = await Promise.all([
|
|
112
|
+
this.scanRegisteredFileMetadata(packagePath, errors),
|
|
113
|
+
this.scanRegisteredDirectoryMetadata(packagePath, errors),
|
|
114
|
+
this.scanAutomationMetadata(packagePath, errors),
|
|
115
|
+
this.scanDataMetadata(packagePath, errors),
|
|
116
|
+
this.scanSecurityMetadata(packagePath, errors),
|
|
117
|
+
this.scanExperienceMetadata(packagePath, errors),
|
|
118
|
+
this.scanAIMetadata(packagePath, errors),
|
|
119
|
+
]);
|
|
120
|
+
return componentGroups.flat();
|
|
121
|
+
}
|
|
122
|
+
async scanAutomationMetadata(packagePath, errors) {
|
|
123
|
+
return scanMetadataFiles(packagePath, '**/flows/**/*.flow-meta.xml', errors, 'Flow', this.shouldIgnorePath, parseFlowComponent);
|
|
124
|
+
}
|
|
125
|
+
async scanDataMetadata(packagePath, errors) {
|
|
126
|
+
const objectComponents = await scanMetadataDirectories(packagePath, '**/objects/*', errors, 'Custom Object', this.shouldIgnorePath, parseCustomObjectComponent);
|
|
127
|
+
const customMetadataComponents = await scanMetadataDirectories(packagePath, '**/customMetadata/*', errors, 'Custom Metadata Type', this.shouldIgnorePath, async (cmtDir) => {
|
|
326
128
|
const typeName = path.basename(cmtDir);
|
|
327
129
|
const typeFile = path.join(cmtDir, `${typeName}.md-meta.xml`);
|
|
328
|
-
if (!(await
|
|
329
|
-
return
|
|
330
|
-
}
|
|
331
|
-
try {
|
|
332
|
-
const content = await fs.readFile(typeFile, 'utf-8');
|
|
333
|
-
await parseCustomMetadataType(typeName, content);
|
|
334
|
-
return {
|
|
335
|
-
name: typeName,
|
|
336
|
-
type: 'CustomMetadata',
|
|
337
|
-
filePath: typeFile,
|
|
338
|
-
dependencies: new Set(),
|
|
339
|
-
dependents: new Set(),
|
|
340
|
-
priorityBoost: 0,
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
catch (error) {
|
|
344
|
-
const errorMsg = `Failed to parse Custom Metadata Type ${typeName}: ${error instanceof Error ? error.message : String(error)}`;
|
|
345
|
-
logger.warn(errorMsg);
|
|
346
|
-
errors.push(errorMsg);
|
|
347
|
-
return undefined;
|
|
348
|
-
}
|
|
349
|
-
}));
|
|
350
|
-
components.push(...customMetadataComponents.filter(isDefined));
|
|
351
|
-
// Scan Profiles
|
|
352
|
-
const profileFiles = await this.findFiles(packagePath, '**/profiles/**/*.profile-meta.xml');
|
|
353
|
-
const profileComponents = await Promise.all(profileFiles.map(async (filePath) => {
|
|
354
|
-
if (this.shouldIgnore(filePath)) {
|
|
355
|
-
return undefined;
|
|
356
|
-
}
|
|
357
|
-
try {
|
|
358
|
-
const profileName = path.basename(filePath, '.profile-meta.xml');
|
|
359
|
-
const parsed = await parseProfile(filePath, profileName);
|
|
360
|
-
const deps = new Set();
|
|
361
|
-
parsed.objectPermissions.forEach((permission) => deps.add(permission));
|
|
362
|
-
parsed.apexClassAccesses.forEach((classAccess) => deps.add(classAccess));
|
|
363
|
-
parsed.layoutAssignments.forEach((layoutAssignment) => deps.add(layoutAssignment));
|
|
364
|
-
return {
|
|
365
|
-
name: profileName,
|
|
366
|
-
type: 'Profile',
|
|
367
|
-
filePath,
|
|
368
|
-
dependencies: deps,
|
|
369
|
-
dependents: new Set(),
|
|
370
|
-
priorityBoost: 0,
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
const errorMsg = `Failed to parse Profile ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
375
|
-
logger.warn(errorMsg);
|
|
376
|
-
errors.push(errorMsg);
|
|
377
|
-
return undefined;
|
|
378
|
-
}
|
|
379
|
-
}));
|
|
380
|
-
components.push(...profileComponents.filter(isDefined));
|
|
381
|
-
// Scan Permission Sets
|
|
382
|
-
const permSetFiles = await this.findFiles(packagePath, '**/permissionsets/**/*.permissionset-meta.xml');
|
|
383
|
-
const permissionSetComponents = await Promise.all(permSetFiles.map(async (filePath) => {
|
|
384
|
-
if (this.shouldIgnore(filePath)) {
|
|
385
|
-
return undefined;
|
|
386
|
-
}
|
|
387
|
-
try {
|
|
388
|
-
const permSetName = path.basename(filePath, '.permissionset-meta.xml');
|
|
389
|
-
const parsed = await parsePermissionSet(filePath, permSetName);
|
|
390
|
-
const deps = new Set();
|
|
391
|
-
parsed.objectPermissions.forEach((permission) => deps.add(permission));
|
|
392
|
-
parsed.apexClassAccesses.forEach((classAccess) => deps.add(classAccess));
|
|
393
|
-
parsed.customPermissions.forEach((customPermission) => deps.add(customPermission));
|
|
394
|
-
return {
|
|
395
|
-
name: permSetName,
|
|
396
|
-
type: 'PermissionSet',
|
|
397
|
-
filePath,
|
|
398
|
-
dependencies: deps,
|
|
399
|
-
dependents: new Set(),
|
|
400
|
-
priorityBoost: 0,
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
catch (error) {
|
|
404
|
-
const errorMsg = `Failed to parse Permission Set ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
405
|
-
logger.warn(errorMsg);
|
|
406
|
-
errors.push(errorMsg);
|
|
407
|
-
return undefined;
|
|
408
|
-
}
|
|
409
|
-
}));
|
|
410
|
-
components.push(...permissionSetComponents.filter(isDefined));
|
|
411
|
-
// Scan FlexiPages
|
|
412
|
-
const flexipageFiles = await this.findFiles(packagePath, '**/flexipages/**/*.flexipage-meta.xml');
|
|
413
|
-
const flexipageComponents = await Promise.all(flexipageFiles.map(async (filePath) => {
|
|
414
|
-
if (this.shouldIgnore(filePath)) {
|
|
415
|
-
return undefined;
|
|
416
|
-
}
|
|
417
|
-
try {
|
|
418
|
-
const flexipageName = path.basename(filePath, '.flexipage-meta.xml');
|
|
419
|
-
const parsed = await parseFlexiPage(filePath, flexipageName);
|
|
420
|
-
const deps = new Set();
|
|
421
|
-
parsed.lwcComponents.forEach((componentName) => deps.add(`c:${componentName}`));
|
|
422
|
-
parsed.auraComponents.forEach((componentName) => deps.add(`c:${componentName}`));
|
|
423
|
-
parsed.objects.forEach((objectName) => deps.add(objectName));
|
|
424
|
-
return {
|
|
425
|
-
name: flexipageName,
|
|
426
|
-
type: 'FlexiPage',
|
|
427
|
-
filePath,
|
|
428
|
-
dependencies: deps,
|
|
429
|
-
dependents: new Set(),
|
|
430
|
-
priorityBoost: 0,
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
catch (error) {
|
|
434
|
-
const errorMsg = `Failed to parse FlexiPage ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
435
|
-
logger.warn(errorMsg);
|
|
436
|
-
errors.push(errorMsg);
|
|
437
|
-
return undefined;
|
|
438
|
-
}
|
|
439
|
-
}));
|
|
440
|
-
components.push(...flexipageComponents.filter(isDefined));
|
|
441
|
-
// Scan Layouts
|
|
442
|
-
const layoutFiles = await this.findFiles(packagePath, '**/layouts/**/*.layout-meta.xml');
|
|
443
|
-
const layoutComponents = await Promise.all(layoutFiles.map(async (filePath) => {
|
|
444
|
-
if (this.shouldIgnore(filePath)) {
|
|
445
|
-
return undefined;
|
|
446
|
-
}
|
|
447
|
-
try {
|
|
448
|
-
const layoutName = path.basename(filePath, '.layout-meta.xml');
|
|
449
|
-
const parsed = await parseLayout(filePath, layoutName);
|
|
450
|
-
const deps = new Set();
|
|
451
|
-
deps.add(parsed.object);
|
|
452
|
-
parsed.customButtons.forEach((buttonName) => deps.add(buttonName));
|
|
453
|
-
parsed.visualforcePages.forEach((pageName) => deps.add(pageName));
|
|
454
|
-
return {
|
|
455
|
-
name: layoutName,
|
|
456
|
-
type: 'Layout',
|
|
457
|
-
filePath,
|
|
458
|
-
dependencies: deps,
|
|
459
|
-
dependents: new Set(),
|
|
460
|
-
priorityBoost: 0,
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
catch (error) {
|
|
464
|
-
const errorMsg = `Failed to parse Layout ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
465
|
-
logger.warn(errorMsg);
|
|
466
|
-
errors.push(errorMsg);
|
|
467
|
-
return undefined;
|
|
468
|
-
}
|
|
469
|
-
}));
|
|
470
|
-
components.push(...layoutComponents.filter(isDefined));
|
|
471
|
-
// Scan Email Templates
|
|
472
|
-
const emailTemplateFiles = await this.findFiles(packagePath, '**/email/**/*.email-meta.xml');
|
|
473
|
-
const emailTemplateComponents = await Promise.all(emailTemplateFiles.map(async (filePath) => {
|
|
474
|
-
if (this.shouldIgnore(filePath)) {
|
|
475
|
-
return undefined;
|
|
476
|
-
}
|
|
477
|
-
try {
|
|
478
|
-
const templateName = path.basename(filePath, '.email-meta.xml');
|
|
479
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
480
|
-
const parsed = await parseEmailTemplate(templateName, content, content);
|
|
481
|
-
const deps = new Set();
|
|
482
|
-
parsed.dependencies.forEach((dependency) => {
|
|
483
|
-
if (dependency.type === 'visualforce_page') {
|
|
484
|
-
deps.add(dependency.name);
|
|
485
|
-
}
|
|
486
|
-
});
|
|
487
|
-
return {
|
|
488
|
-
name: templateName,
|
|
489
|
-
type: 'EmailTemplate',
|
|
490
|
-
filePath,
|
|
491
|
-
dependencies: deps,
|
|
492
|
-
dependents: new Set(),
|
|
493
|
-
priorityBoost: 0,
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
catch (error) {
|
|
497
|
-
const errorMsg = `Failed to parse Email Template ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
498
|
-
logger.warn(errorMsg);
|
|
499
|
-
errors.push(errorMsg);
|
|
500
|
-
return undefined;
|
|
501
|
-
}
|
|
502
|
-
}));
|
|
503
|
-
components.push(...emailTemplateComponents.filter(isDefined));
|
|
504
|
-
// Scan Bots
|
|
505
|
-
const botFiles = await this.findFiles(packagePath, '**/bots/**/*.bot-meta.xml');
|
|
506
|
-
const botComponents = await Promise.all(botFiles.map(async (filePath) => {
|
|
507
|
-
if (this.shouldIgnore(filePath)) {
|
|
508
|
-
return undefined;
|
|
509
|
-
}
|
|
510
|
-
try {
|
|
511
|
-
const botName = path.basename(filePath, '.bot-meta.xml');
|
|
512
|
-
const parsed = await parseBot(filePath, botName);
|
|
513
|
-
const deps = new Set();
|
|
514
|
-
parsed.flows.forEach((flowName) => deps.add(flowName));
|
|
515
|
-
parsed.apexActions.forEach((actionName) => deps.add(actionName));
|
|
516
|
-
parsed.genAiPrompts.forEach((promptName) => deps.add(promptName));
|
|
517
|
-
return {
|
|
518
|
-
name: botName,
|
|
519
|
-
type: 'Bot',
|
|
520
|
-
filePath,
|
|
521
|
-
dependencies: deps,
|
|
522
|
-
dependents: new Set(),
|
|
523
|
-
priorityBoost: 0,
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
catch (error) {
|
|
527
|
-
const errorMsg = `Failed to parse Bot ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
528
|
-
logger.warn(errorMsg);
|
|
529
|
-
errors.push(errorMsg);
|
|
530
|
-
return undefined;
|
|
531
|
-
}
|
|
532
|
-
}));
|
|
533
|
-
components.push(...botComponents.filter(isDefined));
|
|
534
|
-
// Scan GenAI Prompts
|
|
535
|
-
const genaiFiles = await this.findFiles(packagePath, '**/genaiPromptTemplates/**/*.genAiPromptTemplate-meta.xml');
|
|
536
|
-
const genAiPromptComponents = await Promise.all(genaiFiles.map(async (filePath) => {
|
|
537
|
-
if (this.shouldIgnore(filePath)) {
|
|
538
|
-
return undefined;
|
|
539
|
-
}
|
|
540
|
-
try {
|
|
541
|
-
const promptName = path.basename(filePath, '.genAiPromptTemplate-meta.xml');
|
|
542
|
-
const parsed = await parseGenAiPrompt(filePath, promptName);
|
|
543
|
-
const deps = new Set();
|
|
544
|
-
parsed.sobjects.forEach((sObjectName) => deps.add(sObjectName));
|
|
545
|
-
parsed.dependencies.sobjects.forEach((sObjectName) => deps.add(sObjectName));
|
|
546
|
-
return {
|
|
547
|
-
name: promptName,
|
|
548
|
-
type: 'GenAiPromptTemplate',
|
|
549
|
-
filePath,
|
|
550
|
-
dependencies: deps,
|
|
551
|
-
dependents: new Set(),
|
|
552
|
-
priorityBoost: 0,
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
catch (error) {
|
|
556
|
-
const errorMsg = `Failed to parse GenAI Prompt ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
557
|
-
logger.warn(errorMsg);
|
|
558
|
-
errors.push(errorMsg);
|
|
559
|
-
return undefined;
|
|
560
|
-
}
|
|
561
|
-
}));
|
|
562
|
-
components.push(...genAiPromptComponents.filter(isDefined));
|
|
563
|
-
// Scan Visualforce Pages/Components
|
|
564
|
-
const vfPageFiles = await this.findFiles(packagePath, '**/pages/**/*.page');
|
|
565
|
-
const vfComponentFiles = await this.findFiles(packagePath, '**/components/**/*.component');
|
|
566
|
-
const visualforceComponents = await Promise.all([...vfPageFiles, ...vfComponentFiles].map(async (filePath) => {
|
|
567
|
-
if (this.shouldIgnore(filePath)) {
|
|
568
|
-
return undefined;
|
|
569
|
-
}
|
|
570
|
-
try {
|
|
571
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
572
|
-
const fileName = path.basename(filePath);
|
|
573
|
-
const parsed = parseVisualforce(fileName, content);
|
|
574
|
-
const deps = new Set();
|
|
575
|
-
parsed.dependencies.forEach((dependency) => {
|
|
576
|
-
if (dependency.type === 'apex_controller' || dependency.type === 'apex_extension') {
|
|
577
|
-
deps.add(dependency.name);
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
const componentType = parsed.type === 'page' ? 'VisualforcePage' : 'VisualforceComponent';
|
|
581
|
-
return {
|
|
582
|
-
name: parsed.name,
|
|
583
|
-
type: componentType,
|
|
584
|
-
filePath,
|
|
585
|
-
dependencies: deps,
|
|
586
|
-
dependents: new Set(),
|
|
587
|
-
priorityBoost: 0,
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
catch (error) {
|
|
591
|
-
const errorMsg = `Failed to parse Visualforce ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
592
|
-
logger.warn(errorMsg);
|
|
593
|
-
errors.push(errorMsg);
|
|
594
|
-
return undefined;
|
|
130
|
+
if (!(await fileExists(typeFile))) {
|
|
131
|
+
return [];
|
|
595
132
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
return
|
|
133
|
+
return parseCustomMetadataComponents(cmtDir);
|
|
134
|
+
}, (directoryPath) => path.basename(directoryPath));
|
|
135
|
+
return [...objectComponents, ...customMetadataComponents];
|
|
599
136
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const fullPattern = path.join(rootPath, pattern);
|
|
605
|
-
const files = await globAsync(fullPattern, {
|
|
606
|
-
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
607
|
-
});
|
|
608
|
-
return files;
|
|
137
|
+
async scanSecurityMetadata(packagePath, errors) {
|
|
138
|
+
const profileComponents = await scanMetadataFiles(packagePath, '**/profiles/**/*.profile-meta.xml', errors, 'Profile', this.shouldIgnorePath, parseProfileComponent);
|
|
139
|
+
const permissionSetComponents = await scanMetadataFiles(packagePath, '**/permissionsets/**/*.permissionset-meta.xml', errors, 'Permission Set', this.shouldIgnorePath, parsePermissionSetComponent);
|
|
140
|
+
return [...profileComponents, ...permissionSetComponents];
|
|
609
141
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
142
|
+
async scanExperienceMetadata(packagePath, errors) {
|
|
143
|
+
const flexipageComponents = await scanMetadataFiles(packagePath, '**/flexipages/**/*.flexipage-meta.xml', errors, 'FlexiPage', this.shouldIgnorePath, parseFlexiPageComponent);
|
|
144
|
+
const layoutComponents = await scanMetadataFiles(packagePath, '**/layouts/**/*.layout-meta.xml', errors, 'Layout', this.shouldIgnorePath, parseLayoutComponent);
|
|
145
|
+
const emailTemplateComponents = await scanMetadataFiles(packagePath, '**/email/**/*.email-meta.xml', errors, 'Email Template', this.shouldIgnorePath, (filePath) => parseEmailTemplateComponent(filePath, fileExists));
|
|
146
|
+
const visualforceComponents = await Promise.all([
|
|
147
|
+
scanMetadataFiles(packagePath, '**/pages/**/*.page', errors, 'Visualforce', this.shouldIgnorePath, parseVisualforceComponent),
|
|
148
|
+
scanMetadataFiles(packagePath, '**/components/**/*.component', errors, 'Visualforce', this.shouldIgnorePath, parseVisualforceComponent),
|
|
149
|
+
]);
|
|
150
|
+
return [...flexipageComponents, ...layoutComponents, ...emailTemplateComponents, ...visualforceComponents.flat()];
|
|
151
|
+
}
|
|
152
|
+
async scanAIMetadata(packagePath, errors) {
|
|
153
|
+
const botComponents = await scanMetadataFiles(packagePath, '**/bots/**/*.bot-meta.xml', errors, 'Bot', this.shouldIgnorePath, parseBotComponent);
|
|
154
|
+
const genAiPromptComponents = await scanMetadataFiles(packagePath, '**/genaiPromptTemplates/**/*.genAiPromptTemplate-meta.xml', errors, 'GenAI Prompt', this.shouldIgnorePath, parseGenAiPromptComponent);
|
|
155
|
+
return [...botComponents, ...genAiPromptComponents];
|
|
156
|
+
}
|
|
157
|
+
async scanRegisteredFileMetadata(packagePath, errors) {
|
|
158
|
+
return scanRegisteredFileMetadata(packagePath, errors, this.shouldIgnorePath, CODE_FILE_SCANNERS);
|
|
159
|
+
}
|
|
160
|
+
async scanRegisteredDirectoryMetadata(packagePath, errors) {
|
|
161
|
+
return scanRegisteredDirectoryMetadata(packagePath, errors, this.shouldIgnorePath, CODE_DIRECTORY_SCANNERS);
|
|
628
162
|
}
|
|
629
163
|
/**
|
|
630
164
|
* Check if file should be ignored by .forceignore
|
|
@@ -635,17 +169,5 @@ export class MetadataScannerService {
|
|
|
635
169
|
}
|
|
636
170
|
return this.forceIgnoreParser.isIgnored(filePath);
|
|
637
171
|
}
|
|
638
|
-
/**
|
|
639
|
-
* Check if file/directory exists
|
|
640
|
-
*/
|
|
641
|
-
async fileExists(filePath) {
|
|
642
|
-
try {
|
|
643
|
-
await fs.access(filePath);
|
|
644
|
-
return true;
|
|
645
|
-
}
|
|
646
|
-
catch {
|
|
647
|
-
return false;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
172
|
}
|
|
651
173
|
//# sourceMappingURL=metadata-scanner-service.js.map
|